From 8cbadb61604667b407b53ee1258433994fa4765a Mon Sep 17 00:00:00 2001 From: coasteen Date: Thu, 9 Jul 2026 10:42:28 +0330 Subject: init --- .Xresources | 20 + .bash.d/aliasrc | 28 + .bash.d/export | 1 + .bashrc | 21 + .emacs.d/init.el | 248 + .gitignore | 10 + .mpdconf | 16 + .ssh/config | 46 + .ssh/id_ed25519.pub | 1 + .vimrc | 67 + .wezterm.lua | 16 + .xinitrc | 28 + .zprofile | 143 + .zsh.d/zsh-autosuggestions.zsh | 867 ++ .zshrc | 21 + .zshrc.root | 33 + LICENSE | 674 ++ README.md | 21 + colorlist.palette | 10 + config/alacritty/alacritty.toml | 16 + config/bspwm/bspwmrc | 82 + config/btop/btop.conf | 254 + config/btop/themes/coasteen.theme | 89 + config/btop/themes/dracula.theme | 89 + config/btop/themes/gruvbox.theme | 92 + config/btop/themes/kyli0x.theme | 92 + config/dunst/dunst/dunstrc | 48 + config/dunst/dunstrc | 48 + config/dunst/dunstrc~ | 48 + config/eww/eww.scss | 63 + config/eww/eww.yuck | 58 + config/eww/eww_vars.yuck | 4 + config/eww/eww_widgets.yuck | 21 + config/eww/images/gif1.gif | Bin 0 -> 169253 bytes config/eww/images/gif2.gif | Bin 0 -> 36996 bytes config/eww/scripts/calendar.sh | 2 + config/eww/scripts/day_format.sh | 14 + config/eww/scripts/daytype.sh | 3 + config/eww/scripts/month_format.sh | 3 + config/eww/scripts/start.sh | 9 + config/eww/scripts/year_format.sh | 3 + config/foot/foot.ini | 1 + config/foot/foot.ini.home-backup | 40 + config/home-manager/README.md | 4 + config/home-manager/flake.lock | 47 + config/home-manager/flake.nix | 26 + config/home-manager/home.nix | 195 + config/hypr/hypridle.conf | 14 + config/hypr/hyprland.conf | 217 + config/hypr/hyprlock.conf | 35 + config/hypr/hyprpaper.conf | 3 + config/kitty/.#kitty.conf | 1 + config/kitty/kitty.conf | 52 + config/mako/.github/issue_template.md | 1 + config/mako/.github/pull_request_template.md | 1 + config/mako/config | 12 + config/micro/bindings.json | 35 + config/micro/buffers/history | Bin 0 -> 52 bytes config/micro/settings.json | 3 + config/mksymlink.conf | 16 + config/mutt/color.muttrc | 68 + config/mutt/muttrc | 18 + config/neofetch/config.conf | 864 ++ config/niri-2/config.kdl | 269 + config/niri/config.kdl | 265 + config/nushell/config.nu | 99 + config/nushell/starship.nu | 35 + config/nvim-1/init.lua | 11 + config/nvim-1/lazy-lock.json | 40 + config/nvim-1/lua/config.lua | 86 + config/nvim-1/lua/plugins/catppuccin/init.lua | 84 + config/nvim-1/lua/plugins/lazy/init.lua | 17 + config/nvim-1/lua/plugins/lazy/plugins.lua | 128 + config/nvim-1/lua/plugins/lsp/init.lua | 120 + config/nvim-1/lua/plugins/lualine/init.lua | 42 + config/nvim-1/lua/plugins/nvim-tree/init.lua | 2 + config/nvim-1/lua/plugins/render-markdown/init.lua | 139 + config/nvim-1/lua/plugins/telescope/init.lua | 3 + config/nvim-1/lua/plugins/treesitter/init.lua | 10 + config/nvim-1/lua/plugins/whichkey/init.lua | 2 + config/nvim-1/lua/status_line/init.lua | 102 + config/nvim-1/undo/%home%coast%.Xdefaults | Bin 0 -> 759 bytes ...home%coast%.config%Element%electron-config.json | Bin 0 -> 1274 bytes .../%home%coast%.config%alacritty%alacritty.toml | Bin 0 -> 16787 bytes .../nvim-1/undo/%home%coast%.config%dunst%dunstrc | Bin 0 -> 5122 bytes .../undo/%home%coast%.config%eww%_colors.scss | Bin 0 -> 673 bytes .../nvim-1/undo/%home%coast%.config%eww%eww.scss | Bin 0 -> 7618 bytes .../nvim-1/undo/%home%coast%.config%eww%eww.yuck | Bin 0 -> 7041 bytes ...ast%.config%eww%scripts%get-active-workspace.sh | Bin 0 -> 4312 bytes ...ome%coast%.config%eww%scripts%get-workspaces.sh | Bin 0 -> 2727 bytes .../undo/%home%coast%.config%fht%compositor.toml | Bin 0 -> 26843 bytes .../nvim-1/undo/%home%coast%.config%foot%foot.ini | Bin 0 -> 4112 bytes .../undo/%home%coast%.config%hypr%hypridle.conf | Bin 0 -> 1643 bytes .../undo/%home%coast%.config%hypr%hyprland.conf | Bin 0 -> 249399 bytes .../undo/%home%coast%.config%hypr%hyprlock.conf | Bin 0 -> 2702 bytes .../nvim-1/undo/%home%coast%.config%kwm%config.zon | Bin 0 -> 62767 bytes config/nvim-1/undo/%home%coast%.config%mako%config | Bin 0 -> 7057 bytes ...%8kysq72s.default-release%chrome%userChrome.css | Bin 0 -> 597 bytes .../undo/%home%coast%.config%neofetch%config.conf | Bin 0 -> 82882 bytes ...st%.config%nvim%lua%plugins%catppuccin%init.lua | Bin 0 -> 83907 bytes ...coast%.config%nvim%lua%plugins%lazy%plugins.lua | Bin 0 -> 1620 bytes ...%home%coast%.config%picom%picom-animations.conf | Bin 0 -> 16678 bytes .../undo/%home%coast%.config%picom%picom.conf | Bin 0 -> 39955 bytes config/nvim-1/undo/%home%coast%.config%piss%pissrc | Bin 0 -> 23848 bytes .../undo/%home%coast%.config%quickshell%clock.qml | Bin 0 -> 597 bytes .../%home%coast%.config%quickshell%currentsong.qml | Bin 0 -> 597 bytes .../%home%coast%.config%quickshell%separator.qml | Bin 0 -> 639 bytes .../undo/%home%coast%.config%quickshell%shell.qml | Bin 0 -> 401330 bytes .../%home%coast%.config%quickshell%workspaces.qml | Bin 0 -> 639 bytes config/nvim-1/undo/%home%coast%.config%river%init | Bin 0 -> 1243 bytes .../undo/%home%coast%.config%rofi%config.rasi | Bin 0 -> 13071 bytes .../undo/%home%coast%.config%scrobbler%config.ini | Bin 0 -> 2630 bytes config/nvim-1/undo/%home%coast%.config%sway%config | Bin 0 -> 36011 bytes .../nvim-1/undo/%home%coast%.config%tym%config.lua | Bin 0 -> 13438 bytes .../nvim-1/undo/%home%coast%.config%tym%theme.lua | Bin 0 -> 1256 bytes .../undo/%home%coast%.config%waybar%config.jsonc | Bin 0 -> 77709 bytes .../undo/%home%coast%.config%waybar%style.css | Bin 0 -> 125219 bytes config/nvim-1/undo/%home%coast%.curlrc | Bin 0 -> 669 bytes ...local%share%American Truck Simulator%config.cfg | Bin 0 -> 17100 bytes ...ocal%share%applications%element-desktop.desktop | Bin 0 -> 1083 bytes ...t%.local%share%applications%firefox-bin.desktop | Bin 0 -> 631 bytes ...%.local%share%applications%im.riot.Riot.desktop | Bin 0 -> 2761 bytes ...%export%share%applications%im.riot.Riot.desktop | Bin 0 -> 825 bytes .../%home%coast%.local%src%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes ...ome%coast%.local%src%config%nvim%lua%config.lua | Bin 0 -> 75458 bytes .../undo/%home%coast%.local%src%config%sway%config | Bin 0 -> 1065 bytes ...ome%coast%.local%src%config%waybar%config.jsonc | Bin 0 -> 122714 bytes .../%home%coast%.local%src%config%waybar%style.css | Bin 0 -> 203469 bytes .../undo/%home%coast%.local%src%dmenu%config.h | Bin 0 -> 3785 bytes .../undo/%home%coast%.local%src%dmenu%config.mk | Bin 0 -> 3914 bytes .../undo/%home%coast%.local%src%dmenu%dmenu.c | Bin 0 -> 85514 bytes .../nvim-1/undo/%home%coast%.local%src%dmenu%drw.c | Bin 0 -> 19034 bytes .../undo/%home%coast%.local%src%dwm%config.h | Bin 0 -> 45698 bytes .../undo/%home%coast%.local%src%dwm%config.mk | Bin 0 -> 8711 bytes .../undo/%home%coast%.local%src%dwm%patches.h | Bin 0 -> 6749 bytes .../%home%coast%.local%src%local%bin%mpc-shuf.sh | Bin 0 -> 137909 bytes .../%home%coast%.local%src%local%bin%screenie-wlr | Bin 0 -> 4808 bytes .../undo/%home%coast%.local%src%local%bin%sober | Bin 0 -> 2783 bytes .../%home%coast%.local%src%local%bin%swap.start | Bin 0 -> 3996 bytes .../%home%coast%.local%src%local%bin%swap.stop | Bin 0 -> 2435 bytes .../%home%coast%.local%src%local%bin%updateriver | Bin 0 -> 16783 bytes ...%home%coast%.local%src%local%bin%updateriver.sh | Bin 0 -> 11196 bytes .../undo/%home%coast%.local%src%local%bin%upl | Bin 0 -> 12725 bytes .../%home%coast%.local%src%local%bin%uwuify.awk | Bin 0 -> 28108 bytes .../undo/%home%coast%.local%src%slstatus%config.h | Bin 0 -> 15831 bytes .../undo/%home%coast%.local%src%slstatus%config.mk | Bin 0 -> 2230 bytes .../nvim-1/undo/%home%coast%.local%src%st%config.h | Bin 0 -> 3487 bytes .../undo/%home%coast%.local%src%st%config.mk | Bin 0 -> 599 bytes config/nvim-1/undo/%home%coast%.mpdconf | Bin 0 -> 2438 bytes config/nvim-1/undo/%home%coast%.rtorrent.rc | Bin 0 -> 2008 bytes ...pp%org.vinegarhq.Sober%config%sober%config.json | Bin 0 -> 4597 bytes config/nvim-1/undo/%home%coast%.wezterm.lua | Bin 0 -> 14460 bytes config/nvim-1/undo/%home%coast%.xinitrc | Bin 0 -> 45032 bytes config/nvim-1/undo/%home%coast%.zprofile | Bin 0 -> 31474 bytes config/nvim-1/undo/%home%coast%.zshrc | Bin 0 -> 707 bytes ...ome%coast%Games%Red Dead Redemption 2%launch.sh | Bin 0 -> 28213 bytes config/nvim-1/undo/%home%coast%NOTES | Bin 0 -> 2029 bytes .../nvim-1/undo/%home%coast%Projects%X%term%term | Bin 0 -> 5968 bytes .../undo/%home%coast%Projects%X%term%xterm.c | Bin 0 -> 75232 bytes .../nvim-1/undo/%home%coast%Projects%abcl%main.cl | Bin 0 -> 33977 bytes config/nvim-1/undo/%home%coast%Projects%gtk%main.c | Bin 0 -> 8793 bytes .../undo/%home%coast%Projects%py%ashscrobble | Bin 0 -> 52479 bytes ...ast%Projects%py%ashscrobble%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes .../%home%coast%Projects%py%ashscrobble%LICENSE | Bin 0 -> 3517 bytes ...me%coast%Projects%py%ashscrobble%ashscrobble.py | Bin 0 -> 2182 bytes .../nvim-1/undo/%home%coast%Projects%py%dmenu.lua | Bin 0 -> 32913 bytes .../nvim-1/undo/%home%coast%Projects%py%dmenu.py | Bin 0 -> 23716 bytes .../undo/%home%coast%Projects%pylua%dmenu.lua | Bin 0 -> 10292 bytes .../%home%coast%Projects%river%kwm%config.def.zon | Bin 0 -> 20522 bytes .../%home%coast%Projects%river%river%build.zig.zon | Bin 0 -> 2669 bytes ...home%coast%Projects%rs%guessing_game%.gitignore | Bin 0 -> 1116 bytes .../undo/%home%coast%Projects%wayland%config.h | Bin 0 -> 12548 bytes .../undo/%home%coast%Projects%wayland%main.py | Bin 0 -> 56288 bytes .../undo/%home%coast%Projects%wayland%window.c | Bin 0 -> 145974 bytes .../undo/%home%coast%Projects%wayland%wlbar%main.c | Bin 0 -> 6042 bytes ...st%Projects%wayland%wlclock%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes ...%home%coast%Projects%wayland%wlclock%.gitignore | Bin 0 -> 2753 bytes .../%home%coast%Projects%wayland%wlclock%config.h | Bin 0 -> 12291 bytes .../%home%coast%Projects%wayland%wlclock%main.c | Bin 0 -> 43975 bytes .../%home%coast%Projects%wayland%wlclock%makefile | Bin 0 -> 10669 bytes .../undo/%home%coast%Projects%wayland%wlclock.c | Bin 0 -> 579319 bytes ...coast%Projects%wayland%wled%.git%COMMIT_EDITMSG | Bin 0 -> 687 bytes .../%home%coast%Projects%wayland%wled%.gitignore | Bin 0 -> 2769 bytes .../undo/%home%coast%Projects%wayland%wled%LICENSE | Bin 0 -> 2735 bytes .../undo/%home%coast%Projects%wayland%wled%README | Bin 0 -> 9610 bytes .../%home%coast%Projects%wayland%wled%build.sh | Bin 0 -> 79779 bytes .../%home%coast%Projects%wayland%wled%client.c | Bin 0 -> 258378 bytes .../%home%coast%Projects%wayland%wled%config.h | Bin 0 -> 26398 bytes .../%home%coast%Projects%wayland%wlindow%client.c | Bin 0 -> 2146 bytes .../undo/%home%coast%Projects%wayland%x11alt.c | Bin 0 -> 25803 bytes config/nvim-1/undo/%home%coast%ashos%linux%.config | Bin 0 -> 1626 bytes config/nvim-1/undo/%home%coast%ashos%syslinux.cfg | Bin 0 -> 6204 bytes config/nvim-1/undo/%home%coast%conduwuit | Bin 0 -> 15428 bytes config/nvim-1/undo/%home%coast%driver%driver.c | Bin 0 -> 6721 bytes .../%home%coast%git%compositor%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes .../undo/%home%coast%git%compositor%.gitignore | Bin 0 -> 1677 bytes .../undo/%home%coast%git%compositor%Makefile | Bin 0 -> 2410 bytes .../undo/%home%coast%git%compositor%build.sh | Bin 0 -> 1667 bytes .../undo/%home%coast%git%compositor%makefile | Bin 0 -> 14145 bytes .../%home%coast%git%compositor%src%compositor.c | Bin 0 -> 259361 bytes .../undo/%home%coast%git%compositor%src%config.h | Bin 0 -> 27929 bytes ...e%coast%git%compositor%src%include%compositor.h | Bin 0 -> 16690 bytes ...ome%coast%git%compositor%src%include%keybinds.h | Bin 0 -> 1712 bytes ...e%coast%git%compositor%src%include%screenshot.h | Bin 0 -> 5210 bytes .../undo/%home%coast%git%compositor%src%keybinds.c | Bin 0 -> 3599 bytes .../undo/%home%coast%git%compositor%src%keybinds.h | Bin 0 -> 4422 bytes .../%home%coast%git%compositor%src%screenshot.c | Bin 0 -> 17605 bytes .../undo/%home%coast%git%compositor%src%util.c | Bin 0 -> 2861 bytes config/nvim-1/undo/%home%coast%git%hst%config.h | Bin 0 -> 60894 bytes .../nvim-1/undo/%home%coast%git%neuswc%config.mk | Bin 0 -> 2849 bytes .../%home%coast%git%neuswc%libswc%compositor.h | Bin 0 -> 671 bytes .../undo/%home%coast%git%neuswc%libswc%output.h | Bin 0 -> 671 bytes .../undo/%home%coast%git%neuswc%libswc%pointer.h | Bin 0 -> 1736 bytes .../undo/%home%coast%git%neuswc%libswc%util.h | Bin 0 -> 617 bytes .../nvim-1/undo/%home%coast%git%neuwld%config.mk | Bin 0 -> 629 bytes config/nvim-1/undo/%home%coast%git%swc%config.mk | Bin 0 -> 2305 bytes config/nvim-1/undo/%home%coast%git%swcshot%main.c | Bin 0 -> 14583 bytes .../nvim-1/undo/%home%coast%git%terminal%Makefile | Bin 0 -> 1489 bytes config/nvim-1/undo/%home%coast%git%terminal%main.c | Bin 0 -> 60353 bytes config/nvim-1/undo/%home%coast%git%wld%config.mk | Bin 0 -> 649 bytes config/nvim-1/undo/%home%coast%git%wsxwm%Makefile | Bin 0 -> 5006 bytes .../%home%coast%git%wsxwm%source%include%wsxwm.h | Bin 0 -> 1770 bytes .../undo/%home%coast%git%wsxwm%source%test.diff | Bin 0 -> 1223 bytes .../undo/%home%coast%git%wsxwm%source%wsxwm.c | Bin 0 -> 70249 bytes config/nvim-1/undo/%home%coast%hwfetch | Bin 0 -> 27128 bytes config/nvim-1/undo/%home%coast%main.bash | Bin 0 -> 4076 bytes config/nvim-1/undo/%home%coast%main.c | Bin 0 -> 5019 bytes config/nvim-1/undo/%home%coast%main.lua | Bin 0 -> 3328 bytes config/nvim-1/undo/%home%coast%royal | Bin 0 -> 1348 bytes config/nvim-1/undo/%home%coast%shared%loader.c | Bin 0 -> 7191 bytes config/nvim-1/undo/%home%coast%shared%shared.c | Bin 0 -> 7551 bytes config/nvim-1/undo/%home%coast%test.py | Bin 0 -> 597 bytes config/nvim-2/graft | 1 + config/nvim-2/init.vim | 12 + config/nvim-2/nvim/init.vim | 12 + config/nvim-2/nvim/pack-bak/graft/start/LuaSnip | 1 + config/nvim-2/nvim/pack-bak/graft/start/cmp-buffer | 1 + .../nvim-2/nvim/pack-bak/graft/start/cmp-nvim-lsp | 1 + .../nvim/pack-bak/graft/start/nvim-autopairs | 1 + config/nvim-2/nvim/pack-bak/graft/start/nvim-cmp | 1 + .../nvim/pack-bak/graft/start/nvim-lspconfig | 1 + .../nvim-2/nvim/pack-bak/graft/start/vim-closetag | 1 + .../nvim/pack-bak/graft/start/vim-commentary | 1 + .../nvim-2/nvim/pack-bak/graft/start/vim-endwise | 1 + .../nvim-2/nvim/pack-bak/graft/start/vim-fugitive | 1 + .../nvim-2/nvim/pack-bak/graft/start/vim-polyglot | 1 + .../nvim-2/nvim/pack-bak/graft/start/vim-sensible | 1 + .../nvim-2/nvim/pack-bak/graft/start/vim-surround | 1 + .../nvim-2/nvim/pack-bak/graft/start/vim-vinegar | 1 + config/nvim-2/nvim/pack/scion/start/LuaSnip | 1 + config/nvim-2/nvim/pack/scion/start/cmp-buffer | 1 + config/nvim-2/nvim/pack/scion/start/cmp-nvim-lsp | 1 + config/nvim-2/nvim/pack/scion/start/nvim-autopairs | 1 + config/nvim-2/nvim/pack/scion/start/nvim-cmp | 1 + .../nvim/pack/scion/start/nvim-colorizer.lua | 1 + config/nvim-2/nvim/pack/scion/start/nvim-lspconfig | 1 + .../nvim-2/nvim/pack/scion/start/nvim-treesitter | 1 + config/nvim-2/nvim/pack/scion/start/vim-closetag | 1 + config/nvim-2/nvim/pack/scion/start/vim-commentary | 1 + config/nvim-2/nvim/pack/scion/start/vim-endwise | 1 + config/nvim-2/nvim/pack/scion/start/vim-fugitive | 1 + config/nvim-2/nvim/pack/scion/start/vim-polyglot | 1 + config/nvim-2/nvim/pack/scion/start/vim-sensible | 1 + config/nvim-2/nvim/pack/scion/start/vim-surround | 1 + config/nvim-2/nvim/pack/scion/start/vim-vinegar | 1 + config/nvim-2/nvim/scion | 1 + config/nvim-2/nvim/scion_state.json | 21 + .../%home%coast%.config%alacritty%alacritty.toml | Bin 0 -> 44499 bytes .../%home%coast%.config%fastfetch%config.jsonc | Bin 0 -> 20002 bytes .../undodir/%home%coast%.config%niri%config.kdl | Bin 0 -> 16110 bytes .../%home%coast%.config%nvim%graft%config.rb | Bin 0 -> 18913 bytes .../nvim/undodir/%home%coast%.config%nvim%init.vim | Bin 0 -> 103754 bytes .../nvim/undodir/%home%coast%.config%nvim%key.vim | Bin 0 -> 5683 bytes .../%home%coast%.config%nvim%scion%config.rb | Bin 0 -> 4430 bytes .../%home%coast%.config%nvim%scion%scion.rb | Bin 0 -> 58552 bytes .../nvim/undodir/%home%coast%.config%nvim%test.sh | Bin 0 -> 3475 bytes .../%home%coast%.config%nvim%vscript%lsp.vim | Bin 0 -> 5713 bytes .../%home%coast%.config%nvim%vscript%lua.vim | Bin 0 -> 50636 bytes .../%home%coast%.config%nvim%vscript%scp.vim | Bin 0 -> 30059 bytes .../%home%coast%.config%nvim%vscript%theme.vim | Bin 0 -> 22051 bytes .../undodir/%home%coast%.config%rofi%config.rasi | Bin 0 -> 19085 bytes .../nvim/undodir/%home%coast%.config%starship.toml | Bin 0 -> 10728 bytes ...r%.#plasma-polkit-agent.servicec252b1882abfd1a3 | Bin 0 -> 2796 bytes .../%home%coast%.config%waybar%config.jsonc | Bin 0 -> 171458 bytes .../undodir/%home%coast%.config%waybar%style.css | Bin 0 -> 101843 bytes .../undodir/%home%coast%.config%waybar%window.sh | Bin 0 -> 597 bytes ...e%coast%.config%xdg-desktop-portal%portals.conf | Bin 0 -> 2165 bytes ....local%share%applications%prismlauncher.desktop | Bin 0 -> 5079 bytes ...%coast%.local%share%applications%throne.desktop | Bin 0 -> 5299 bytes .../%home%coast%.zsh.d%zsh-syntaxhighlighting.zsh | Bin 0 -> 1309 bytes config/nvim-2/nvim/undodir/%home%coast%.zshrc | Bin 0 -> 5619 bytes config/nvim-2/nvim/undodir/%home%coast%DEVLIST | Bin 0 -> 7935 bytes .../%home%coast%Downloads%snispoof%config.json | Bin 0 -> 1169 bytes ...es%26.1.2%minecraft%config%DistantHorizons.toml | Bin 0 -> 35630 bytes .../nvim/undodir/%home%coast%Xray%config.json | Bin 0 -> 2583 bytes config/nvim-2/nvim/undodir/%home%coast%bash.sh | Bin 0 -> 6749 bytes .../nvim/undodir/%home%coast%copyparty-setup.py | Bin 0 -> 695 bytes .../nvim/undodir/%home%coast%dlhub%goodlinks.txt | Bin 0 -> 1238 bytes .../nvim/undodir/%home%coast%dlhub%script.py | Bin 0 -> 19927 bytes config/nvim-2/nvim/undodir/%home%coast%main.c | Bin 0 -> 17686 bytes .../nvim/undodir/%home%coast%mhr-cfw%config.json | Bin 0 -> 4736 bytes config/nvim-2/nvim/undodir/%home%coast%pertree | Bin 0 -> 5517 bytes .../undodir/%home%coast%piss%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes .../nvim-2/nvim/undodir/%home%coast%piss%LICENSE | Bin 0 -> 1614 bytes .../nvim-2/nvim/undodir/%home%coast%piss%README.md | Bin 0 -> 6650 bytes .../nvim-2/nvim/undodir/%home%coast%piss%makefile | Bin 0 -> 2156 bytes .../undodir/%home%coast%piss%pissrc.example.lua | Bin 0 -> 1013 bytes .../nvim-2/nvim/undodir/%home%coast%piss%src%chd.1 | Bin 0 -> 1185 bytes .../nvim/undodir/%home%coast%piss%src%daemon.c | Bin 0 -> 9783 bytes .../nvim/undodir/%home%coast%piss%src%piss.1 | Bin 0 -> 3604 bytes ...ome%coast%projects%c%catter%.git%COMMIT_EDITMSG | Bin 0 -> 633 bytes .../%home%coast%projects%c%catter%.gitignore | Bin 0 -> 2099 bytes .../undodir/%home%coast%projects%c%catter%README | Bin 0 -> 2145 bytes .../undodir/%home%coast%projects%c%catter%main.c | Bin 0 -> 733 bytes .../undodir/%home%coast%projects%c%catter%makefile | Bin 0 -> 7122 bytes .../%home%coast%projects%c%catter%src%main.c | Bin 0 -> 10220 bytes ...e%coast%projects%c%compteur%.git%COMMIT_EDITMSG | Bin 0 -> 1333 bytes .../%home%coast%projects%c%compteur%.gitignore | Bin 0 -> 849 bytes .../%home%coast%projects%c%compteur%LICENSE | Bin 0 -> 14067 bytes .../undodir/%home%coast%projects%c%compteur%README | Bin 0 -> 3124 bytes .../%home%coast%projects%c%compteur%src%main.c | Bin 0 -> 104815 bytes .../nvim/undodir/%home%coast%projects%c%ct%main.c | Bin 0 -> 77446 bytes .../undodir/%home%coast%projects%c%ct%makefile | Bin 0 -> 597 bytes .../nvim/undodir/%home%coast%projects%c%ct%rand | Bin 0 -> 7854 bytes .../undodir/%home%coast%projects%c%ct%src%input.c | Bin 0 -> 13032 bytes .../undodir/%home%coast%projects%c%ct%src%main.c | Bin 0 -> 20231 bytes .../undodir/%home%coast%projects%c%cterm%cterm.c | Bin 0 -> 137301 bytes ...oast%projects%c%gl%Valkhaus%.git%COMMIT_EDITMSG | Bin 0 -> 1116 bytes .../%home%coast%projects%c%gl%Valkhaus%.gitignore | Bin 0 -> 1611 bytes .../%home%coast%projects%c%gl%Valkhaus%build.sh | Bin 0 -> 943 bytes .../%home%coast%projects%c%gl%Valkhaus%main.c | Bin 0 -> 100477 bytes .../nvim/undodir/%home%coast%projects%c%makefile | Bin 0 -> 1084 bytes .../undodir/%home%coast%projects%c%makefile-opt | Bin 0 -> 21347 bytes .../undodir/%home%coast%projects%c%template-opt.c | Bin 0 -> 8003 bytes .../undodir/%home%coast%projects%c%vk%Valk%main.c | Bin 0 -> 30066 bytes .../%home%coast%projects%c%vk%Valk%makefile | Bin 0 -> 2525 bytes .../%home%coast%projects%c%vk%Valk%shader.frag | Bin 0 -> 6075 bytes .../%home%coast%projects%c%vk%Valk%shader.vert | Bin 0 -> 4684 bytes .../undodir/%home%coast%projects%eul-license%v1 | Bin 0 -> 2183 bytes ...projects%ruby%vim-asifaiusf%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes ...ome%coast%projects%ruby%vim-asifaiusf%README.md | Bin 0 -> 2694 bytes ...ast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes .../%home%coast%projects%ruby%vim-scion%README | Bin 0 -> 8145 bytes .../%home%coast%projects%ruby%vim-scion%README.md | Bin 0 -> 19866 bytes .../%home%coast%projects%ruby%vim-scion%Rakefile | Bin 0 -> 2638 bytes .../%home%coast%projects%ruby%vim-scion%config.rb | Bin 0 -> 4470 bytes .../%home%coast%projects%ruby%vim-scion%scion.rb | Bin 0 -> 7612 bytes ...%home%coast%projects%ruby%wayland-rec%config.rb | Bin 0 -> 1796 bytes .../%home%coast%projects%ruby%wayland-rec%main.rb | Bin 0 -> 16216 bytes config/nvim-2/nvim/undodir/%home%coast%shit.sh | Bin 0 -> 1676 bytes .../nvim/undodir/%mnt%Home%dotfiles%.gitignore | Bin 0 -> 921 bytes config/nvim-2/nvim/vscript/key.vim | 2 + config/nvim-2/nvim/vscript/lua.vim | 87 + config/nvim-2/nvim/vscript/scp.vim | 29 + config/nvim-2/nvim/vscript/theme.vim | 61 + config/nvim-2/pack-bak/graft/start/LuaSnip | 1 + config/nvim-2/pack-bak/graft/start/cmp-buffer | 1 + config/nvim-2/pack-bak/graft/start/cmp-nvim-lsp | 1 + config/nvim-2/pack-bak/graft/start/nvim-autopairs | 1 + config/nvim-2/pack-bak/graft/start/nvim-cmp | 1 + config/nvim-2/pack-bak/graft/start/nvim-lspconfig | 1 + config/nvim-2/pack-bak/graft/start/vim-closetag | 1 + config/nvim-2/pack-bak/graft/start/vim-commentary | 1 + config/nvim-2/pack-bak/graft/start/vim-endwise | 1 + config/nvim-2/pack-bak/graft/start/vim-fugitive | 1 + config/nvim-2/pack-bak/graft/start/vim-polyglot | 1 + config/nvim-2/pack-bak/graft/start/vim-sensible | 1 + config/nvim-2/pack-bak/graft/start/vim-surround | 1 + config/nvim-2/pack-bak/graft/start/vim-vinegar | 1 + config/nvim-2/scion | 1 + config/nvim-2/scion_state.json | 19 + .../%home%coast%.config%alacritty%alacritty.toml | Bin 0 -> 6436 bytes .../%home%coast%.config%fastfetch%config.jsonc | Bin 0 -> 7709 bytes .../undodir/%home%coast%.config%niri%config.kdl | Bin 0 -> 1409 bytes .../%home%coast%.config%nvim%graft%config.rb | Bin 0 -> 18913 bytes .../undodir/%home%coast%.config%nvim%init.vim | Bin 0 -> 100132 bytes .../undodir/%home%coast%.config%nvim%key.vim | Bin 0 -> 5683 bytes .../undodir/%home%coast%.config%nvim%test.sh | Bin 0 -> 3475 bytes .../%home%coast%.config%nvim%vscript%lsp.vim | Bin 0 -> 5713 bytes .../%home%coast%.config%nvim%vscript%lua.vim | Bin 0 -> 17917 bytes .../%home%coast%.config%nvim%vscript%scp.vim | Bin 0 -> 30059 bytes .../%home%coast%.config%waybar%config.jsonc | Bin 0 -> 1630 bytes ...e%coast%.config%xdg-desktop-portal%portals.conf | Bin 0 -> 2165 bytes config/nvim-2/undodir/%home%coast%.zshrc | Bin 0 -> 1821 bytes config/nvim-2/undodir/%home%coast%DEVLIST | Bin 0 -> 4767 bytes config/nvim-2/undodir/%home%coast%main.c | Bin 0 -> 42611 bytes config/nvim-2/undodir/%home%coast%pertree | Bin 0 -> 5517 bytes ...ome%coast%projects%c%catter%.git%COMMIT_EDITMSG | Bin 0 -> 633 bytes .../%home%coast%projects%c%catter%.gitignore | Bin 0 -> 2099 bytes .../undodir/%home%coast%projects%c%catter%README | Bin 0 -> 2145 bytes .../undodir/%home%coast%projects%c%catter%main.c | Bin 0 -> 733 bytes .../undodir/%home%coast%projects%c%catter%makefile | Bin 0 -> 7122 bytes .../%home%coast%projects%c%catter%src%main.c | Bin 0 -> 10220 bytes .../undodir/%home%coast%projects%c%makefile-opt | Bin 0 -> 21347 bytes .../undodir/%home%coast%projects%c%template-opt.c | Bin 0 -> 8003 bytes ...ast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG | Bin 0 -> 579 bytes .../%home%coast%projects%ruby%vim-scion%README | Bin 0 -> 8145 bytes .../%home%coast%projects%ruby%vim-scion%README.md | Bin 0 -> 19866 bytes .../%home%coast%projects%ruby%vim-scion%Rakefile | Bin 0 -> 2638 bytes .../%home%coast%projects%ruby%vim-scion%config.rb | Bin 0 -> 4470 bytes .../%home%coast%projects%ruby%vim-scion%scion.rb | Bin 0 -> 7612 bytes ...%home%coast%projects%ruby%wayland-rec%config.rb | Bin 0 -> 1796 bytes .../%home%coast%projects%ruby%wayland-rec%main.rb | Bin 0 -> 16216 bytes config/nvim-2/vscript/key.vim | 2 + config/nvim-2/vscript/lua.vim | 122 + config/nvim-2/vscript/scp.vim | 29 + config/nvim-root/init.lua | 168 + config/picom/picom-animations.conf | 310 + config/picom/picom.conf | 151 + config/piss/pissrc | 4 + config/plugged/plug.vim | 2877 +++++++ config/plugin/config.vim | 1 + config/qtile/config.py | 154 + config/qutebrowser/autoconfig.yml | 10 + config/qutebrowser/bookmarks/urls | 0 config/qutebrowser/config.py | 47 + config/qutebrowser/greasemonkey/yt-ads.js | 19 + config/qutebrowser/quickmarks | 0 config/rofi/config.rasi | 64 + config/rofi/gruvbox.rasi | 61 + config/rofi/rofi/config.rasi | 61 + config/shell/aliases | 45 + config/shell/exports | 7 + config/shell/shell/aliases | 53 + config/shell/shell/aliases.backup | 27 + config/shell/shell/exports | 8 + config/shell/shell/exports.backup | 4 + config/starship.toml | 36 + config/sway/config | 131 + config/sxhkd/sxhkdrc | 18 + config/systemd/emacsd.service | 11 + config/tmux/tmux.conf | 67 + config/waybar-2/config.jsonc | 27 + config/waybar-2/style.css | 42 + config/waybar-2/waybar/config.jsonc | 154 + config/waybar-2/waybar/style.css | 207 + config/waybar-2/waybar/window.sh | 77 + config/waybar/config.jsonc | 107 + config/waybar/style.css | 82 + config/wofi/config | 32 + config/wofi/style.css | 59 + config/xmobar/xmobarrc | 13 + config/xmonad/xmonad.hs | 51 + dmenu | 1 + dwl/.gitea/issue_template/bug_report.yml | 62 + dwl/.gitea/issue_template/enhancement-idea.yml | 9 + dwl/.gitignore | 6 + dwl/.mailmap | 1 + dwl/CHANGELOG.md | 200 + dwl/LICENSE | 692 ++ dwl/LICENSE.dwm | 39 + dwl/LICENSE.sway | 19 + dwl/LICENSE.tinywl | 127 + dwl/Makefile | 78 + dwl/README.md | 201 + dwl/client.h | 408 + dwl/config.def.h | 212 + dwl/config.def.h.orig | 210 + dwl/config.mk | 17 + dwl/drwl.h | 311 + dwl/dwl-patches/LICENSE | 692 ++ dwl/dwl-patches/LICENSE.dwm | 39 + dwl/dwl-patches/LICENSE.sway | 19 + dwl/dwl-patches/LICENSE.tinywl | 127 + dwl/dwl-patches/README.md | 87 + dwl/dwl-patches/patches/accessnthmon/README.md | 9 + .../patches/accessnthmon/accessnthmon.patch | 122 + dwl/dwl-patches/patches/alwayscenter/README.md | 9 + .../patches/alwayscenter/alwayscenter.patch | 39 + dwl/dwl-patches/patches/attachbottom/README.md | 10 + .../patches/attachbottom/attachbottom.patch | 29 + dwl/dwl-patches/patches/attachfocused/README.md | 11 + .../patches/attachfocused/attachfocused.patch | 29 + dwl/dwl-patches/patches/attachtop/README.md | 13 + dwl/dwl-patches/patches/attachtop/attachtop.patch | 36 + dwl/dwl-patches/patches/autostart/README.md | 14 + .../patches/autostart/autostart-0.7.patch | 154 + dwl/dwl-patches/patches/autostart/autostart.patch | 148 + dwl/dwl-patches/patches/bar-systray/README.md | 19 + .../patches/bar-systray/bar-systray-0.7.patch | 3023 +++++++ dwl/dwl-patches/patches/bar/README.md | 34 + dwl/dwl-patches/patches/bar/bar-0.6.patch | 1245 +++ dwl/dwl-patches/patches/bar/bar-0.7.patch | 1245 +++ dwl/dwl-patches/patches/bar/bar.patch | 1266 +++ dwl/dwl-patches/patches/bar/bar.png | Bin 0 -> 3486 bytes dwl/dwl-patches/patches/barborder/README.md | 10 + dwl/dwl-patches/patches/barborder/barborder.patch | 136 + dwl/dwl-patches/patches/barcolors/README.md | 9 + dwl/dwl-patches/patches/barcolors/barcolors.patch | 144 + dwl/dwl-patches/patches/barpadding/README.md | 10 + .../patches/barpadding/barpadding.patch | 73 + .../patches/bartruecenteredtitle/README.md | 11 + .../bartruecenteredtitle.patch | 46 + .../bartruecenteredtitle/centeredtitle.webp | Bin 0 -> 25596 bytes dwl/dwl-patches/patches/better-resize/README.md | 48 + .../patches/better-resize/better-resize-0.7.patch | 107 + dwl/dwl-patches/patches/borders/README.md | 37 + dwl/dwl-patches/patches/borders/borders.patch | 213 + dwl/dwl-patches/patches/bottomstack/README.md | 27 + .../patches/bottomstack/bottomstack.patch | 140 + dwl/dwl-patches/patches/btrtile/README.md | 103 + .../patches/btrtile/btrtile-v0.7-gaps.patch | 922 +++ dwl/dwl-patches/patches/btrtile/btrtile-v0.7.patch | 903 ++ dwl/dwl-patches/patches/buttonbystate/README.md | 10 + .../patches/buttonbystate/buttonbystate.patch | 78 + dwl/dwl-patches/patches/center-terminal/README.md | 13 + .../patches/center-terminal/center-terminal.patch | 103 + dwl/dwl-patches/patches/centeredmaster/README.md | 33 + .../patches/centeredmaster/centeredmaster.patch | 135 + dwl/dwl-patches/patches/cfact-snail/README.md | 13 + .../patches/cfact-snail/cfact-snail.patch | 68 + dwl/dwl-patches/patches/cfact/README.md | 25 + dwl/dwl-patches/patches/cfact/cfact-v0.6.patch | 121 + .../patches/cfact/cfact-v0.7-gaps.patch | 155 + dwl/dwl-patches/patches/cfact/cfact-v0.7.patch | 121 + dwl/dwl-patches/patches/cfact/cfact.patch | 121 + dwl/dwl-patches/patches/chainkeys/README.md | 15 + dwl/dwl-patches/patches/chainkeys/chainkeys.patch | 157 + dwl/dwl-patches/patches/client-opacity/README.md | 18 + .../patches/client-opacity/client-opacity.patch | 181 + dwl/dwl-patches/patches/column/README.md | 9 + dwl/dwl-patches/patches/column/column.patch | 79 + dwl/dwl-patches/patches/coredump/README.md | 11 + .../patches/coredump/coredump-0.7.patch | 65 + dwl/dwl-patches/patches/coredump/coredump.patch | 65 + dwl/dwl-patches/patches/cursortheme/README.md | 17 + .../patches/cursortheme/cursortheme.patch | 46 + dwl/dwl-patches/patches/customfloat/README.md | 24 + .../patches/customfloat/customfloat.patch | 93 + dwl/dwl-patches/patches/dim-unfocused/README.md | 19 + .../dim-unfocused/dim-unfocused-20230516.patch | 213 + .../dim-unfocused/dim-unfocused-20240416.patch | 177 + .../dim-unfocused/dim-unfocused-20240714.patch | 199 + .../dim-unfocused/dim-unfocused-20240903.patch | 216 + .../patches/dim-unfocused/dim-unfocused.patch | 216 + .../README.md | 11 + ...able-keybindings-on-fullscreen-toggle-0.7.patch | 71 + .../disable-keybindings-on-fullscreen/README.md | 9 + .../disable-keybindings-on-fullscreen.patch | 82 + dwl/dwl-patches/patches/dragmfact/README.md | 11 + .../patches/dragmfact/dragmfact-v0.6.patch | 59 + .../patches/dragmfact/dragmfact-v0.7.patch | 59 + dwl/dwl-patches/patches/dragmfact/dragmfact.patch | 59 + dwl/dwl-patches/patches/dragresize/README.md | 12 + .../patches/dragresize/dragresize.patch | 210 + dwl/dwl-patches/patches/en-keycodes/README.md | 11 + .../patches/en-keycodes/en-keycodes.patch | 73 + dwl/dwl-patches/patches/envcfg/README.md | 8 + dwl/dwl-patches/patches/envcfg/envcfg.patch | 302 + .../patches/fakefullscreenclient/README.md | 8 + .../fakefullscreenclient.patch | 87 + dwl/dwl-patches/patches/fallback/README.md | 8 + dwl/dwl-patches/patches/fallback/fallback.patch | 44 + dwl/dwl-patches/patches/focusdir/README.md | 9 + dwl/dwl-patches/patches/focusdir/focusdir.patch | 98 + dwl/dwl-patches/patches/follow/README.md | 10 + dwl/dwl-patches/patches/follow/follow.patch | 38 + dwl/dwl-patches/patches/follow/follow.webp | Bin 0 -> 621614 bytes .../patches/foreign-toplevel-management/README.md | 9 + .../foreign-toplevel-management.patch | 507 ++ .../patches/fullscreenadaptivesync/README.md | 29 + .../fullscreenadaptivesync-v0.7.patch | 122 + dwl/dwl-patches/patches/gaplessgrid/README.md | 19 + .../patches/gaplessgrid/gaplessgrid-20230801.patch | 97 + .../patches/gaplessgrid/gaplessgrid-20240714.patch | 89 + .../patches/gaplessgrid/gaplessgrid.patch | 89 + dwl/dwl-patches/patches/gaps/README.md | 14 + dwl/dwl-patches/patches/gaps/gaps.patch | 127 + dwl/dwl-patches/patches/genericgaps/README.md | 25 + .../patches/genericgaps/genericgaps-0.7.patch | 375 + .../patches/genericgaps/genericgaps.patch | 350 + dwl/dwl-patches/patches/gestures/README.md | 23 + dwl/dwl-patches/patches/gestures/gestures.patch | 169 + dwl/dwl-patches/patches/globalkey/README.md | 33 + dwl/dwl-patches/patches/globalkey/globalkey.patch | 131 + dwl/dwl-patches/patches/headless/README.md | 11 + dwl/dwl-patches/patches/headless/headless.patch | 130 + .../patches/hide-behind-fullscreen/README.md | 12 + .../hide-behind-fullscreen-0.7.patch | 73 + .../hide-behind-fullscreen.patch | 73 + .../patches/hide-behind-monocle/README.md | 10 + .../hide-behind-monocle-0.7.patch | 332 + .../hide-behind-monocle/hide-behind-monocle.patch | 332 + dwl/dwl-patches/patches/hide_vacant_tags/README.md | 11 + .../hide_vacant_tags/hide_vacant_tags.patch | 69 + dwl/dwl-patches/patches/hiderule/README.md | 9 + dwl/dwl-patches/patches/hiderule/hiderule.patch | 57 + dwl/dwl-patches/patches/hot-reload/README.md | 110 + .../patches/hot-reload/hot-reload-0.7.patch | 770 ++ .../patches/hot-reload/hot-reload.patch | 1029 +++ dwl/dwl-patches/patches/inputdevicerules/README.md | 18 + .../inputdevicerules/inputdevicerules-v0.6.patch | 173 + .../inputdevicerules/inputdevicerules-v0.7.patch | 173 + dwl/dwl-patches/patches/ipc/README.md | 28 + .../patches/ipc/focus-tagset-output.patch | 24 + dwl/dwl-patches/patches/ipc/ipc.patch | 597 ++ dwl/dwl-patches/patches/ipc/ipcpertag.patch | 97 + dwl/dwl-patches/patches/kblayout/README.md | 32 + dwl/dwl-patches/patches/kblayout/kblayout.patch | 187 + .../patches/keyboardshortcutsinhibit/README.md | 11 + .../keyboardshortcutsinhibit.patch | 101 + dwl/dwl-patches/patches/keycodes/README.md | 20 + .../patches/keycodes/keycodes-0.7.patch | 883 ++ dwl/dwl-patches/patches/keycodes/keycodes.patch | 883 ++ dwl/dwl-patches/patches/launchtag/README.md | 12 + dwl/dwl-patches/patches/launchtag/launchtag.patch | 49 + dwl/dwl-patches/patches/limitnmaster/README.md | 8 + .../patches/limitnmaster/limitnmaster.patch | 33 + dwl/dwl-patches/patches/lockedkeys/README.md | 23 + .../patches/lockedkeys/lockedkeys.patch | 79 + dwl/dwl-patches/patches/mastercolumn/README.md | 16 + .../patches/mastercolumn/mastercolumn-gaps.patch | 63 + .../patches/mastercolumn/mastercolumn.patch | 87 + dwl/dwl-patches/patches/menu/README.md | 18 + dwl/dwl-patches/patches/menu/menu.patch | 227 + dwl/dwl-patches/patches/menurule/README.md | 70 + dwl/dwl-patches/patches/menurule/menurule.patch | 167 + dwl/dwl-patches/patches/menurule/menurule.png | Bin 0 -> 179351 bytes dwl/dwl-patches/patches/meson/README.md | 19 + dwl/dwl-patches/patches/meson/meson.patch | 135 + dwl/dwl-patches/patches/minimalborders/README.md | 34 + .../patches/minimalborders/minimalborders.patch | 161 + dwl/dwl-patches/patches/modes/README.md | 35 + dwl/dwl-patches/patches/modes/modes.patch | 165 + dwl/dwl-patches/patches/monitorconfig/README.md | 9 + .../patches/monitorconfig/monitorconfig.patch | 95 + .../patches/mouse-trackpad-split/README.md | 8 + .../mouse-trackpad-split-0.7.patch | 96 + dwl/dwl-patches/patches/movecenter/README.md | 28 + .../patches/movecenter/movecenter.patch | 82 + dwl/dwl-patches/patches/moveresizekb/README.md | 20 + .../patches/moveresizekb/moveresizekb.patch | 70 + dwl/dwl-patches/patches/movestack/README.md | 13 + dwl/dwl-patches/patches/movestack/movestack.patch | 87 + dwl/dwl-patches/patches/namedscratchpads/README.md | 19 + .../namedscratchpads/namedscratchpads.patch | 278 + dwl/dwl-patches/patches/nextlayout/README.md | 9 + .../patches/nextlayout/nextlayout.patch | 65 + dwl/dwl-patches/patches/numlock-capslock/README.md | 10 + .../numlock-capslock/numlock-capslock-0.7.patch | 84 + .../numlock-capslock/numlock-capslock.patch | 84 + dwl/dwl-patches/patches/passthrough/README.md | 13 + .../patches/passthrough/passthrough.patch | 82 + dwl/dwl-patches/patches/perinputconfig/README.md | 12 + .../perinputconfig/perinputconfig-v0.5.patch | 173 + .../patches/perinputconfig/perinputconfig.patch | 295 + dwl/dwl-patches/patches/pertag/README.md | 12 + dwl/dwl-patches/patches/pertag/pertag.patch | 170 + .../patches/pointer-gestures-unstable-v1/README.md | 16 + .../pointer-gestures-unstable-v1.patch | 186 + dwl/dwl-patches/patches/primaryselection/README.md | 10 + .../primaryselection/primaryselection.patch | 50 + dwl/dwl-patches/patches/push/README.md | 11 + dwl/dwl-patches/patches/push/push-0.7.patch | 127 + dwl/dwl-patches/patches/push/push.patch | 127 + dwl/dwl-patches/patches/regexrules/README.md | 19 + .../patches/regexrules/regexrules.patch | 76 + dwl/dwl-patches/patches/regions/README.md | 11 + dwl/dwl-patches/patches/regions/regions.patch | 71 + .../patches/relative-mouse-resize/README.md | 13 + .../relative-mouse-resize.patch | 102 + dwl/dwl-patches/patches/restore-monitor/README.md | 8 + .../patches/restore-monitor/restore-monitor.patch | 82 + dwl/dwl-patches/patches/right/README.md | 8 + dwl/dwl-patches/patches/right/right.patch | 50 + dwl/dwl-patches/patches/rlimit_max/README.md | 11 + .../patches/rlimit_max/rlimit_max.patch | 91 + dwl/dwl-patches/patches/rotate-clients/README.md | 14 + .../patches/rotate-clients/rotate-clients.patch | 56 + dwl/dwl-patches/patches/rotatetags/README.md | 9 + .../patches/rotatetags/rotatetags.patch | 91 + dwl/dwl-patches/patches/scenefx/README.md | 113 + dwl/dwl-patches/patches/scenefx/scenefx.patch | 700 ++ dwl/dwl-patches/patches/setrule/README.md | 46 + dwl/dwl-patches/patches/setrule/setrule.patch | 155 + dwl/dwl-patches/patches/setupenv/README.md | 8 + dwl/dwl-patches/patches/setupenv/setupenv.patch | 54 + dwl/dwl-patches/patches/shiftview/README.md | 9 + dwl/dwl-patches/patches/shiftview/shiftview.patch | 76 + .../patches/simple_scratchpad/README.md | 25 + .../simple_scratchpad/simple_scratchpad-v0.7.patch | 211 + dwl/dwl-patches/patches/simpleborders/README.md | 13 + .../patches/simpleborders/simpleborders-v0.6.patch | 73 + .../patches/simpleborders/simpleborders-v0.7.patch | 73 + dwl/dwl-patches/patches/singlemaster/README.md | 9 + .../patches/singlemaster/singlemaster.patch | 155 + .../patches/singletagset-pertag/README.md | 22 + .../singletagset-pertag/singletagset-pertag.patch | 261 + .../patches/singletagset-sticky/README.md | 13 + .../singletagset-sticky/singletagset-sticky.patch | 27 + dwl/dwl-patches/patches/singletagset/README.md | 19 + .../patches/singletagset/singletagset-v0.6.patch | 293 + .../patches/singletagset/singletagset-v0.7.patch | 312 + dwl/dwl-patches/patches/skipfocus/README.md | 18 + .../patches/skipfocus/skipfocus-20240714.patch | 81 + dwl/dwl-patches/patches/skipfocus/skipfocus.patch | 81 + .../patches/skipfocus/skipfocus20240108.patch | 62 + dwl/dwl-patches/patches/smartborders/README.md | 14 + .../patches/smartborders/smartborders-0.7.patch | 204 + .../patches/smartborders/smartborders.patch | 203 + dwl/dwl-patches/patches/snail-gaps/README.md | 15 + .../patches/snail-gaps/snail-gaps.patch | 160 + dwl/dwl-patches/patches/snail/README.md | 9 + dwl/dwl-patches/patches/snail/snail.patch | 250 + dwl/dwl-patches/patches/spawninfo/README.md | 41 + dwl/dwl-patches/patches/spawninfo/pamixerc | 134 + dwl/dwl-patches/patches/spawninfo/screenshotwin | 21 + dwl/dwl-patches/patches/spawninfo/spawninfo.patch | 110 + dwl/dwl-patches/patches/stacker/README.md | 28 + dwl/dwl-patches/patches/stacker/stacker.patch | 212 + dwl/dwl-patches/patches/stairs/README.md | 42 + dwl/dwl-patches/patches/stairs/stairs.patch | 136 + dwl/dwl-patches/patches/startargv/README.md | 13 + dwl/dwl-patches/patches/startargv/startargv.patch | 58 + dwl/dwl-patches/patches/sticky/README.md | 13 + dwl/dwl-patches/patches/sticky/sticky.patch | 85 + dwl/dwl-patches/patches/swallow/README.md | 53 + .../patches/swallow/swallow-freebsd.patch | 54 + dwl/dwl-patches/patches/swallow/swallow.patch | 351 + dwl/dwl-patches/patches/swapandfocusdir/README.md | 14 + .../patches/swapandfocusdir/swapandfocusdir.patch | 221 + dwl/dwl-patches/patches/switchtotag/README.md | 9 + .../patches/switchtotag/switchtotag.patch | 116 + dwl/dwl-patches/patches/systemd/README.md | 33 + dwl/dwl-patches/patches/systemd/systemd-0.7.patch | 64 + dwl/dwl-patches/patches/tab/README.md | 24 + dwl/dwl-patches/patches/tab/tab-0.7-bar.patch | 767 ++ dwl/dwl-patches/patches/tab/tab-0.7.patch | 1252 +++ dwl/dwl-patches/patches/tab/tab.patch | 1252 +++ dwl/dwl-patches/patches/tablet-input/README.md | 25 + .../patches/tablet-input/tablet-input-0.7.patch | 355 + .../patches/tablet-input/tablet-input.patch | 372 + dwl/dwl-patches/patches/tagshift/README.md | 10 + dwl/dwl-patches/patches/tagshift/tagshift.patch | 83 + dwl/dwl-patches/patches/tearing/README.md | 17 + dwl/dwl-patches/patches/tearing/tearing.patch | 362 + dwl/dwl-patches/patches/titleurgent/README.md | 11 + .../patches/titleurgent/titleurgent.patch | 80 + dwl/dwl-patches/patches/tmux-borders/README.md | 15 + .../patches/tmux-borders/screenshot1.png | Bin 0 -> 483118 bytes .../patches/tmux-borders/screenshot2.png | Bin 0 -> 492963 bytes .../patches/tmux-borders/tmux-borders-0.7.patch | 489 ++ .../patches/toggle_constraints/README.md | 17 + .../toggle_constraints/toggle_constraints.patch | 86 + .../patches/togglekblayoutandoptions/README.md | 9 + .../togglekblayoutandoptions.patch | 160 + dwl/dwl-patches/patches/touch-input/README.md | 20 + .../patches/touch-input/touch-input.patch | 260 + dwl/dwl-patches/patches/unclutter/README.md | 11 + dwl/dwl-patches/patches/unclutter/unclutter.patch | 192 + .../patches/ungroup-keyboards/README.md | 15 + .../ungroup-keyboards/ungroup-keyboards.patch | 97 + dwl/dwl-patches/patches/vanitygaps/README.md | 12 + .../patches/vanitygaps/vanitygaps-0.7.patch | 358 + .../patches/vanitygaps/vanitygaps.patch | 357 + dwl/dwl-patches/patches/varcol/README.md | 15 + dwl/dwl-patches/patches/varcol/varcol.patch | 618 ++ dwl/dwl-patches/patches/viewnextocctag/README.md | 9 + .../patches/viewnextocctag/viewnextocctag.patch | 92 + dwl/dwl-patches/patches/virtual-pointer/README.md | 12 + .../patches/virtual-pointer/virtual-pointer.patch | 126 + dwl/dwl-patches/patches/warpcursor/README.md | 15 + .../patches/warpcursor/warpcursor.patch | 71 + .../patches/wayland-socket-handover/README.md | 21 + .../wayland-socket-handover.patch | 81 + dwl/dwl-patches/patches/winview/README.md | 35 + .../patches/winview/winview-20240606.patch | 42 + dwl/dwl-patches/patches/winview/winview.patch | 42 + .../patches/xwayland-handle-minimize/README.md | 9 + .../xwayland-handle-minimize.patch | 91 + dwl/dwl-patches/patches/zoomswap/README.md | 54 + .../patches/zoomswap/zoomswap-v0.6.patch | 55 + .../patches/zoomswap/zoomswap-v0.7.patch | 55 + dwl/dwl-patches/patches/zoomswap/zoomswap.patch | 55 + .../stale-patches/bar-systray-old/README.md | 33 + .../bar-systray-old/bar-systray-0.7.patch | 398 + .../stale-patches/bar-systray-old/systray.png | Bin 0 -> 22944 bytes .../stale-patches/master-right/README.md | 13 + .../master-right/master-right-0.7.patch | 35 + .../stale-patches/master-right/master-right.patch | 35 + .../stale-patches/press_repeat_release/README.md | 15 + .../press_repeat_release.patch | 108 + .../stale-patches/remembertags/README.md | 16 + .../stale-patches/remembertags/remembertags.patch | 105 + dwl/dwl-patches/stale-patches/tab-pango/README.md | 10 + dwl/dwl-patches/stale-patches/tab-pango/tab.patch | 461 ++ .../stale-patches/togglekblayout/README.md | 14 + .../togglekblayout/togglekblayout.patch | 107 + dwl/dwl.1 | 158 + dwl/dwl.c | 3645 +++++++++ dwl/dwl.c.orig | 3618 ++++++++ dwl/dwl.desktop | 5 + dwl/protocols/wlr-layer-shell-unstable-v1.xml | 390 + .../wlr-output-power-management-unstable-v1.xml | 128 + dwl/util.c | 51 + dwl/util.h | 5 + dwm/.github/FUNDING.yml | 3 + dwm/.gitignore | 5 + dwm/LICENSE | 38 + dwm/Makefile | 71 + dwm/README | 48 + dwm/README.md | 972 +++ dwm/config.def.h | 2257 +++++ dwm/config.mk | 76 + dwm/drw.c | 775 ++ dwm/drw.h | 106 + dwm/dwm.1 | 176 + dwm/dwm.c | 5512 +++++++++++++ dwm/dwm.desktop | 7 + dwm/dwm.png | Bin 0 -> 373 bytes dwm/patch/alttab.c | 223 + dwm/patch/alttab.h | 5 + dwm/patch/alwaysontop.c | 20 + dwm/patch/alwaysontop.h | 1 + dwm/patch/aspectresize.c | 25 + dwm/patch/aspectresize.h | 2 + dwm/patch/attachx.c | 59 + dwm/patch/attachx.h | 2 + dwm/patch/autostart.c | 76 + dwm/patch/autostart.h | 2 + dwm/patch/banish.c | 71 + dwm/patch/banish.h | 8 + dwm/patch/bar.c | 39 + dwm/patch/bar.h | 2 + dwm/patch/bar_alpha.c | 43 + dwm/patch/bar_alpha.h | 4 + dwm/patch/bar_alternativetags.c | 7 + dwm/patch/bar_alternativetags.h | 2 + dwm/patch/bar_anybar.c | 94 + dwm/patch/bar_anybar.h | 5 + dwm/patch/bar_awesomebar.c | 123 + dwm/patch/bar_awesomebar.h | 4 + dwm/patch/bar_dwmblocks.c | 51 + dwm/patch/bar_dwmblocks.h | 3 + dwm/patch/bar_ewmhtags.c | 52 + dwm/patch/bar_ewmhtags.h | 7 + dwm/patch/bar_fancybar.c | 103 + dwm/patch/bar_fancybar.h | 4 + dwm/patch/bar_flexwintitle.c | 482 ++ dwm/patch/bar_flexwintitle.h | 11 + dwm/patch/bar_holdbar.c | 43 + dwm/patch/bar_holdbar.h | 3 + dwm/patch/bar_indicators.c | 115 + dwm/patch/bar_indicators.h | 21 + dwm/patch/bar_launcher.c | 81 + dwm/patch/bar_launcher.h | 8 + dwm/patch/bar_layoutmenu.c | 18 + dwm/patch/bar_layoutmenu.h | 2 + dwm/patch/bar_ltsymbol.c | 20 + dwm/patch/bar_ltsymbol.h | 3 + dwm/patch/bar_powerline_status.c | 122 + dwm/patch/bar_powerline_status.h | 12 + dwm/patch/bar_powerline_tags.c | 166 + dwm/patch/bar_powerline_tags.h | 4 + dwm/patch/bar_status.c | 34 + dwm/patch/bar_status.h | 10 + dwm/patch/bar_status2d.c | 263 + dwm/patch/bar_status2d.h | 14 + dwm/patch/bar_statusbutton.c | 18 + dwm/patch/bar_statusbutton.h | 4 + dwm/patch/bar_statuscmd.c | 79 + dwm/patch/bar_statuscmd.h | 12 + dwm/patch/bar_statuscolors.c | 102 + dwm/patch/bar_statuscolors.h | 13 + dwm/patch/bar_systray.c | 208 + dwm/patch/bar_systray.h | 41 + dwm/patch/bar_tabgroups.c | 258 + dwm/patch/bar_tabgroups.h | 8 + dwm/patch/bar_taggrid.c | 150 + dwm/patch/bar_taggrid.h | 5 + dwm/patch/bar_tagicons.c | 21 + dwm/patch/bar_tagicons.h | 8 + dwm/patch/bar_taglabels.c | 141 + dwm/patch/bar_taglabels.h | 6 + dwm/patch/bar_tagpreview.c | 112 + dwm/patch/bar_tagpreview.h | 4 + dwm/patch/bar_tags.c | 151 + dwm/patch/bar_tags.h | 4 + dwm/patch/bar_vtcolors.c | 69 + dwm/patch/bar_vtcolors.h | 3 + dwm/patch/bar_winicon.c | 145 + dwm/patch/bar_winicon.h | 9 + dwm/patch/bar_wintitle.c | 88 + dwm/patch/bar_wintitle.h | 4 + dwm/patch/bar_wintitle_floating.c | 46 + dwm/patch/bar_wintitle_floating.h | 9 + dwm/patch/bar_wintitle_hidden.c | 46 + dwm/patch/bar_wintitle_hidden.h | 9 + dwm/patch/bar_wintitleactions.c | 106 + dwm/patch/bar_wintitleactions.h | 7 + dwm/patch/cfacts.c | 24 + dwm/patch/cfacts.h | 2 + dwm/patch/cmdcustomize.c | 6 + dwm/patch/cmdcustomize.h | 2 + dwm/patch/combo.c | 39 + dwm/patch/combo.h | 6 + dwm/patch/cool_autostart.c | 37 + dwm/patch/cool_autostart.h | 2 + dwm/patch/cyclelayouts.c | 10 + dwm/patch/cyclelayouts.h | 2 + dwm/patch/decorationhints.c | 39 + dwm/patch/decorationhints.h | 9 + dwm/patch/distributetags.c | 31 + dwm/patch/distributetags.h | 2 + dwm/patch/dragcfact.c | 83 + dwm/patch/dragcfact.h | 2 + dwm/patch/dragmfact.c | 232 + dwm/patch/dragmfact.h | 2 + dwm/patch/dwmc | 136 + dwm/patch/dwmc.c | 103 + dwm/patch/dwmc.h | 14 + dwm/patch/exresize.c | 196 + dwm/patch/exresize.h | 9 + dwm/patch/fakefullscreenclient.c | 19 + dwm/patch/fakefullscreenclient.h | 2 + dwm/patch/floatpos.c | 195 + dwm/patch/floatpos.h | 4 + dwm/patch/focusadjacenttag.c | 69 + dwm/patch/focusadjacenttag.h | 7 + dwm/patch/focusdir.c | 66 + dwm/patch/focusdir.h | 2 + dwm/patch/focusfollowmouse.c | 9 + dwm/patch/focusfollowmouse.h | 1 + dwm/patch/focusmaster.c | 42 + dwm/patch/focusmaster.h | 2 + dwm/patch/focusurgent.c | 16 + dwm/patch/focusurgent.h | 2 + dwm/patch/fsignal.c | 41 + dwm/patch/fsignal.h | 8 + dwm/patch/fullscreen.c | 18 + dwm/patch/fullscreen.h | 2 + dwm/patch/games.c | 32 + dwm/patch/games.h | 2 + dwm/patch/include.c | 421 + dwm/patch/include.h | 414 + dwm/patch/inplacerotate.c | 84 + dwm/patch/inplacerotate.h | 2 + dwm/patch/insets.c | 19 + dwm/patch/insets.h | 3 + dwm/patch/ipc.c | 111 + dwm/patch/ipc.h | 7 + dwm/patch/ipc/IPCClient.c | 67 + dwm/patch/ipc/IPCClient.h | 62 + dwm/patch/ipc/dwm-msg.c | 549 ++ dwm/patch/ipc/ipc.c | 1202 +++ dwm/patch/ipc/ipc.h | 320 + dwm/patch/ipc/util.c | 136 + dwm/patch/ipc/util.h | 5 + dwm/patch/ipc/yajl_dumps.c | 356 + dwm/patch/ipc/yajl_dumps.h | 66 + dwm/patch/keymodes.c | 144 + dwm/patch/keymodes.h | 22 + dwm/patch/killunsel.c | 28 + dwm/patch/killunsel.h | 2 + dwm/patch/layout_bstack.c | 75 + dwm/patch/layout_bstack.h | 2 + dwm/patch/layout_bstackhoriz.c | 77 + dwm/patch/layout_bstackhoriz.h | 2 + dwm/patch/layout_centeredfloatingmaster.c | 95 + dwm/patch/layout_centeredfloatingmaster.h | 2 + dwm/patch/layout_centeredmaster.c | 160 + dwm/patch/layout_centeredmaster.h | 2 + dwm/patch/layout_columns.c | 74 + dwm/patch/layout_columns.h | 2 + dwm/patch/layout_deck.c | 67 + dwm/patch/layout_deck.h | 2 + dwm/patch/layout_facts.c | 52 + dwm/patch/layout_fibonacci.c | 191 + dwm/patch/layout_fibonacci.h | 8 + dwm/patch/layout_flextile-deluxe.c | 891 ++ dwm/patch/layout_flextile-deluxe.h | 121 + dwm/patch/layout_gapplessgrid.c | 99 + dwm/patch/layout_gapplessgrid.h | 2 + dwm/patch/layout_grid.c | 61 + dwm/patch/layout_grid.h | 2 + dwm/patch/layout_horizgrid.c | 104 + dwm/patch/layout_horizgrid.h | 2 + dwm/patch/layout_monocle.c | 38 + dwm/patch/layout_monocle.h | 2 + dwm/patch/layout_nrowgrid.c | 104 + dwm/patch/layout_nrowgrid.h | 2 + dwm/patch/layout_tile.c | 74 + dwm/patch/layout_tile.h | 2 + dwm/patch/layoutmenu.sh | 8 + dwm/patch/maximize.c | 70 + dwm/patch/maximize.h | 5 + dwm/patch/movecenter.c | 15 + dwm/patch/movecenter.h | 1 + dwm/patch/moveplace.c | 30 + dwm/patch/moveplace.h | 4 + dwm/patch/moveresize.c | 65 + dwm/patch/moveresize.h | 2 + dwm/patch/movestack.c | 51 + dwm/patch/movestack.h | 2 + dwm/patch/mpdcontrol.c | 145 + dwm/patch/mpdcontrol.h | 3 + dwm/patch/nametag.c | 61 + dwm/patch/nametag.h | 1 + dwm/patch/nomodbuttons.c | 8 + dwm/patch/nomodbuttons.h | 2 + dwm/patch/pertag.c | 71 + dwm/patch/pertag.h | 2 + dwm/patch/placedir.c | 96 + dwm/patch/placedir.h | 1 + dwm/patch/placemouse.c | 139 + dwm/patch/placemouse.h | 2 + dwm/patch/push.c | 74 + dwm/patch/push.h | 5 + dwm/patch/push_no_master.c | 44 + dwm/patch/push_no_master.h | 4 + dwm/patch/recttoclient.c | 16 + dwm/patch/recttoclient.h | 4 + dwm/patch/renamed_scratchpads.c | 138 + dwm/patch/renamed_scratchpads.h | 3 + dwm/patch/reorganizetags.c | 42 + dwm/patch/reorganizetags.h | 2 + dwm/patch/restartsig.c | 16 + dwm/patch/restartsig.h | 3 + dwm/patch/riodraw.c | 105 + dwm/patch/riodraw.h | 6 + dwm/patch/rotatestack.c | 53 + dwm/patch/rotatestack.h | 4 + dwm/patch/roundedcorners.c | 53 + dwm/patch/roundedcorners.h | 2 + dwm/patch/scratchpad.c | 77 + dwm/patch/scratchpad.h | 9 + dwm/patch/scratchpad_alt_1.c | 72 + dwm/patch/scratchpad_alt_1.h | 9 + dwm/patch/seamless_restart.c | 478 ++ dwm/patch/seamless_restart.h | 19 + dwm/patch/selfrestart.c | 69 + dwm/patch/selfrestart.h | 3 + dwm/patch/setborderpx.c | 58 + dwm/patch/setborderpx.h | 2 + dwm/patch/shift.c | 50 + dwm/patch/shift.h | 1 + dwm/patch/shiftboth.c | 7 + dwm/patch/shiftboth.h | 1 + dwm/patch/shiftswaptags.c | 7 + dwm/patch/shiftswaptags.h | 1 + dwm/patch/shifttag.c | 7 + dwm/patch/shifttag.h | 1 + dwm/patch/shifttagclients.c | 7 + dwm/patch/shifttagclients.h | 1 + dwm/patch/shiftview.c | 6 + dwm/patch/shiftview.h | 1 + dwm/patch/shiftviewclients.c | 6 + dwm/patch/shiftviewclients.h | 1 + dwm/patch/sizehints_ruled.c | 39 + dwm/patch/sizehints_ruled.h | 2 + dwm/patch/sortscreens.c | 16 + dwm/patch/sortscreens.h | 4 + dwm/patch/stacker.c | 113 + dwm/patch/stacker.h | 11 + dwm/patch/sticky.c | 9 + dwm/patch/sticky.h | 2 + dwm/patch/swallow.c | 257 + dwm/patch/swallow.h | 8 + dwm/patch/swapfocus.c | 22 + dwm/patch/swapfocus.h | 2 + dwm/patch/swaptags.c | 30 + dwm/patch/swaptags.h | 2 + dwm/patch/switchcol.c | 29 + dwm/patch/switchcol.h | 2 + dwm/patch/tab.c | 133 + dwm/patch/tab.h | 5 + dwm/patch/tagall.c | 26 + dwm/patch/tagall.h | 2 + dwm/patch/tagallmon.c | 49 + dwm/patch/tagallmon.h | 2 + dwm/patch/tagothermonitor.c | 44 + dwm/patch/tagothermonitor.h | 9 + dwm/patch/tagswapmon.c | 75 + dwm/patch/tagswapmon.h | 2 + dwm/patch/tapresize.c | 46 + dwm/patch/tapresize.h | 2 + dwm/patch/togglefullscreen.c | 18 + dwm/patch/togglefullscreen.h | 2 + dwm/patch/toggletopbar.c | 20 + dwm/patch/toggletopbar.h | 1 + dwm/patch/transfer.c | 34 + dwm/patch/transfer.h | 2 + dwm/patch/transferall.c | 26 + dwm/patch/transferall.h | 2 + dwm/patch/unfloatvisible.c | 15 + dwm/patch/unfloatvisible.h | 2 + dwm/patch/vanitygaps.c | 228 + dwm/patch/vanitygaps.h | 20 + dwm/patch/warp.c | 46 + dwm/patch/warp.h | 2 + dwm/patch/winview.c | 21 + dwm/patch/winview.h | 2 + dwm/patch/xkb.c | 68 + dwm/patch/xkb.h | 8 + dwm/patch/xrdb.c | 146 + dwm/patch/xrdb.h | 20 + dwm/patch/xresources.c | 74 + dwm/patch/xresources.h | 18 + dwm/patch/zoomswap.c | 14 + dwm/patch/zoomswap.h | 2 + dwm/patches.def.h | 1630 ++++ dwm/transient.c | 43 + dwm/util.c | 36 + dwm/util.h | 20 + local/bin/README.md | 3 + local/bin/Xrec | 32 + local/bin/aurtest.sh | 10 + local/bin/bat-symbol | 41 + local/bin/brwmenu | 118 + local/bin/cotray | Bin 0 -> 26904 bytes local/bin/define | 37 + local/bin/discord | 39 + local/bin/dmenu.py | 161 + local/bin/ecop | 2 + local/bin/edsc | 13 + local/bin/emacsd | 2 + local/bin/emacsd~ | 2 + local/bin/f2py | 8 + local/bin/firemenu | 43 + local/bin/fzfse | 3 + local/bin/grubfk | 29 + local/bin/hyfetch | 7 + local/bin/hyfetch.rs | 7 + local/bin/hyfetch.v1 | 7 + local/bin/killradio | 20 + local/bin/math | 124 + local/bin/mksymlink | 57 + local/bin/mpc-shuf.sh | 126 + local/bin/nodeenv | 7 + local/bin/numpy-config | 8 + local/bin/pyright | 7 + local/bin/pyright-langserver | 7 + local/bin/pyright-python | 7 + local/bin/pyright-python-langserver | 7 + local/bin/qr | 8 + local/bin/radio | 75 + local/bin/resmacs | 2 + local/bin/rimworld | 3 + local/bin/sb-battery | 35 + local/bin/sb-cputemp | 20 + local/bin/sb-cpuusage | 30 + local/bin/sb-liisten | 38 + local/bin/sb-memory | 27 + local/bin/sb-network | 8 + local/bin/sb-swap | 7 + local/bin/sb-volume | 14 + local/bin/screencast | 22 + local/bin/screenie | 8 + local/bin/screenie-active | 3 + local/bin/screenie-wlr | 13 + local/bin/setwall.py | 20 + local/bin/setwall.sh | 8 + local/bin/sober | 2 + local/bin/stacki3 | 8 + local/bin/start-meowgun.sh | 2 + local/bin/start-wq.sh | 2 + local/bin/start_qtile.sh | 39 + local/bin/startniri | 8 + local/bin/startw | 3 + local/bin/swallow | 13 + local/bin/swap.start | 5 + local/bin/swap.stop | 5 + local/bin/sway-status | 35 + local/bin/tabulate | 8 + local/bin/toggle-screens.sh | 13 + local/bin/tun2socks | Bin 0 -> 10412167 bytes local/bin/updateriver | 79 + local/bin/upim | 21 + local/bin/usbmount | 29 + local/bin/usbumount | 31 + local/bin/uwuify.awk | 75 + local/bin/vesktop.sh | 2 + local/bin/win2xcur | 8 + local/bin/wsdump | 8 + local/bin/x2wincur | 8 + local/bin/yellusb | 14 + local/share/color-schemes/Monochrome.colors | 123 + local/share/emoji | 1630 ++++ .../cinnamon/assets/add-workspace-active.svg | 111 + .../cinnamon/assets/add-workspace-hover.svg | 112 + .../cinnamon/assets/add-workspace.svg | 113 + .../cinnamon/assets/calendar-arrow-left.svg | 56 + .../cinnamon/assets/calendar-arrow-right.svg | 56 + .../cinnamon/assets/checkbox-dark.svg | 75 + .../cinnamon/assets/checkbox-off.svg | 3 + .../cinnamon/assets/checkbox.svg | 85 + .../cinnamon/assets/close-active.svg | 72 + .../cinnamon/assets/close-hover.svg | 72 + .../Catppuccin-B-LB-Dark/cinnamon/assets/close.svg | 72 + .../cinnamon/assets/corner-ripple.svg | 46 + .../cinnamon/assets/radiobutton-dark.svg | 71 + .../cinnamon/assets/radiobutton-off.svg | 3 + .../cinnamon/assets/radiobutton.svg | 81 + .../cinnamon/assets/toggle-off.svg | 65 + .../cinnamon/assets/toggle-on-dark.svg | 94 + .../cinnamon/assets/toggle-on.svg | 91 + .../cinnamon/assets/trash-icon.svg | 6 + .../Catppuccin-B-LB-Dark/cinnamon/cinnamon.css | 2594 ++++++ .../Catppuccin-B-LB-Dark/cinnamon/thumbnail.png | Bin 0 -> 5871 bytes .../gnome-shell/assets/calendar-arrow-left.svg | 3 + .../gnome-shell/assets/calendar-arrow-right.svg | 3 + .../gnome-shell/assets/calendar-today.svg | 55 + .../gnome-shell/assets/checkbox-dark.svg | 75 + .../gnome-shell/assets/checkbox-off-active.svg | 3 + .../gnome-shell/assets/checkbox-off-hover.svg | 3 + .../gnome-shell/assets/checkbox-off.svg | 3 + .../gnome-shell/assets/checkbox.svg | 85 + .../gnome-shell/assets/dash-placeholder.svg | 4 + .../gnome-shell/assets/no-events.svg | 82 + .../gnome-shell/assets/no-notifications.svg | 3 + .../gnome-shell/assets/noise-texture.svg | 78 + .../gnome-shell/assets/process-working.svg | 72 + .../gnome-shell/assets/toggle-off.svg | 59 + .../gnome-shell/assets/toggle-on-dark.svg | 94 + .../gnome-shell/assets/toggle-on.svg | 91 + .../gnome-shell/gnome-shell.css | 6084 ++++++++++++++ .../Catppuccin-B-LB-Dark/gnome-shell/no-events.svg | 1 + .../gnome-shell/no-notifications.svg | 1 + .../Catppuccin-B-LB-Dark/gnome-shell/pad-osd.css | 31 + .../gnome-shell/process-working.svg | 1 + .../themes/Catppuccin-B-LB-Dark/gtk-2.0/apps.rc | 92 + .../Catppuccin-B-LB-Dark/gtk-2.0/assets/border.png | Bin 0 -> 126 bytes .../gtk-2.0/assets/button-active.png | Bin 0 -> 267 bytes .../gtk-2.0/assets/button-disabled.png | Bin 0 -> 229 bytes .../gtk-2.0/assets/button-hover.png | Bin 0 -> 252 bytes .../Catppuccin-B-LB-Dark/gtk-2.0/assets/button.png | Bin 0 -> 239 bytes .../gtk-2.0/assets/checkbox-checked-active.png | Bin 0 -> 517 bytes .../gtk-2.0/assets/checkbox-checked-disabled.png | Bin 0 -> 453 bytes .../gtk-2.0/assets/checkbox-checked-hover.png | Bin 0 -> 517 bytes .../gtk-2.0/assets/checkbox-checked.png | Bin 0 -> 512 bytes .../gtk-2.0/assets/checkbox-mixed-active.png | Bin 0 -> 445 bytes .../gtk-2.0/assets/checkbox-mixed-disabled.png | Bin 0 -> 384 bytes .../gtk-2.0/assets/checkbox-mixed-hover.png | Bin 0 -> 445 bytes .../gtk-2.0/assets/checkbox-mixed.png | Bin 0 -> 439 bytes .../gtk-2.0/assets/checkbox-unchecked-active.png | Bin 0 -> 298 bytes .../gtk-2.0/assets/checkbox-unchecked-disabled.png | Bin 0 -> 267 bytes .../gtk-2.0/assets/checkbox-unchecked-hover.png | Bin 0 -> 291 bytes .../gtk-2.0/assets/checkbox-unchecked.png | Bin 0 -> 292 bytes .../gtk-2.0/assets/combo-left-entry-active.png | Bin 0 -> 327 bytes .../gtk-2.0/assets/combo-left-entry-disabled.png | Bin 0 -> 209 bytes .../gtk-2.0/assets/combo-left-entry-hover.png | Bin 0 -> 282 bytes .../gtk-2.0/assets/combo-left-entry.png | Bin 0 -> 216 bytes .../gtk-2.0/assets/combo-right-entry-active.png | Bin 0 -> 337 bytes .../gtk-2.0/assets/combo-right-entry-disabled.png | Bin 0 -> 208 bytes .../gtk-2.0/assets/combo-right-entry-hover.png | Bin 0 -> 296 bytes .../gtk-2.0/assets/combo-right-entry.png | Bin 0 -> 217 bytes .../gtk-2.0/assets/entry-active.png | Bin 0 -> 423 bytes .../gtk-2.0/assets/entry-background-disabled.png | Bin 0 -> 136 bytes .../gtk-2.0/assets/entry-background.png | Bin 0 -> 136 bytes .../gtk-2.0/assets/entry-disabled.png | Bin 0 -> 229 bytes .../gtk-2.0/assets/entry-hover.png | Bin 0 -> 347 bytes .../Catppuccin-B-LB-Dark/gtk-2.0/assets/entry.png | Bin 0 -> 239 bytes .../gtk-2.0/assets/flat-button-active.png | Bin 0 -> 267 bytes .../gtk-2.0/assets/flat-button-disabled.png | Bin 0 -> 195 bytes .../gtk-2.0/assets/flat-button-hover.png | Bin 0 -> 252 bytes .../gtk-2.0/assets/flat-button.png | Bin 0 -> 195 bytes .../Catppuccin-B-LB-Dark/gtk-2.0/assets/focus.png | Bin 0 -> 221 bytes .../gtk-2.0/assets/frame-inline.png | Bin 0 -> 144 bytes .../gtk-2.0/assets/frame-notebook.png | Bin 0 -> 147 bytes .../Catppuccin-B-LB-Dark/gtk-2.0/assets/frame.png | Bin 0 -> 147 bytes .../gtk-2.0/assets/handle-horz-active.png | Bin 0 -> 182 bytes .../gtk-2.0/assets/handle-horz-hover.png | Bin 0 -> 183 bytes .../gtk-2.0/assets/handle-horz.png | Bin 0 -> 180 bytes .../gtk-2.0/assets/handle-vert-active.png | Bin 0 -> 172 bytes .../gtk-2.0/assets/handle-vert-hover.png | Bin 0 -> 177 bytes .../gtk-2.0/assets/handle-vert.png | Bin 0 -> 178 bytes .../assets/menu-checkbox-checked-disabled.png | Bin 0 -> 438 bytes .../gtk-2.0/assets/menu-checkbox-checked.png | Bin 0 -> 461 bytes .../assets/menu-checkbox-mixed-disabled.png | Bin 0 -> 351 bytes .../gtk-2.0/assets/menu-checkbox-mixed.png | Bin 0 -> 363 bytes .../assets/menu-checkbox-unchecked-disabled.png | Bin 0 -> 232 bytes .../gtk-2.0/assets/menu-checkbox-unchecked.png | Bin 0 -> 255 bytes .../gtk-2.0/assets/menu-radio-checked-disabled.png | Bin 0 -> 374 bytes .../gtk-2.0/assets/menu-radio-checked.png | Bin 0 -> 398 bytes .../gtk-2.0/assets/menu-radio-mixed-disabled.png | Bin 0 -> 351 bytes .../gtk-2.0/assets/menu-radio-mixed.png | Bin 0 -> 363 bytes .../assets/menu-radio-unchecked-disabled.png | Bin 0 -> 232 bytes .../gtk-2.0/assets/menu-radio-unchecked.png | Bin 0 -> 255 bytes .../gtk-2.0/assets/pan-down-alt-disabled.png | Bin 0 -> 188 bytes .../gtk-2.0/assets/pan-down-alt.png | Bin 0 -> 194 bytes .../gtk-2.0/assets/pan-down-disabled.png | Bin 0 -> 188 bytes .../gtk-2.0/assets/pan-down.png | Bin 0 -> 193 bytes .../gtk-2.0/assets/pan-left-alt-disabled.png | Bin 0 -> 194 bytes .../gtk-2.0/assets/pan-left-alt.png | Bin 0 -> 194 bytes .../gtk-2.0/assets/pan-left-disabled.png | Bin 0 -> 194 bytes .../gtk-2.0/assets/pan-left-semi.png | Bin 0 -> 205 bytes .../gtk-2.0/assets/pan-left.png | Bin 0 -> 193 bytes .../gtk-2.0/assets/pan-right-alt-disabled.png | Bin 0 -> 195 bytes .../gtk-2.0/assets/pan-right-alt.png | Bin 0 -> 196 bytes .../gtk-2.0/assets/pan-right-disabled.png | Bin 0 -> 195 bytes .../gtk-2.0/assets/pan-right-semi.png | Bin 0 -> 211 bytes .../gtk-2.0/assets/pan-right.png | Bin 0 -> 196 bytes .../gtk-2.0/assets/pan-up-alt-disabled.png | Bin 0 -> 188 bytes .../gtk-2.0/assets/pan-up-alt.png | Bin 0 -> 188 bytes .../gtk-2.0/assets/pan-up-disabled.png | Bin 0 -> 188 bytes .../Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up.png | Bin 0 -> 187 bytes .../gtk-2.0/assets/progressbar-progress.png | Bin 0 -> 136 bytes .../gtk-2.0/assets/progressbar-trough.png | Bin 0 -> 136 bytes .../gtk-2.0/assets/radio-checked-active.png | Bin 0 -> 478 bytes .../gtk-2.0/assets/radio-checked-disabled.png | Bin 0 -> 409 bytes .../gtk-2.0/assets/radio-checked-hover.png | Bin 0 -> 478 bytes .../gtk-2.0/assets/radio-checked.png | Bin 0 -> 473 bytes .../gtk-2.0/assets/radio-mixed-active.png | Bin 0 -> 445 bytes .../gtk-2.0/assets/radio-mixed-disabled.png | Bin 0 -> 384 bytes .../gtk-2.0/assets/radio-mixed-hover.png | Bin 0 -> 445 bytes .../gtk-2.0/assets/radio-mixed.png | Bin 0 -> 439 bytes .../gtk-2.0/assets/radio-unchecked-active.png | Bin 0 -> 298 bytes .../gtk-2.0/assets/radio-unchecked-disabled.png | Bin 0 -> 267 bytes .../gtk-2.0/assets/radio-unchecked-hover.png | Bin 0 -> 291 bytes .../gtk-2.0/assets/radio-unchecked.png | Bin 0 -> 292 bytes .../gtk-2.0/assets/scale-horz-trough-active.png | Bin 0 -> 164 bytes .../gtk-2.0/assets/scale-horz-trough-disabled.png | Bin 0 -> 165 bytes .../gtk-2.0/assets/scale-horz-trough.png | Bin 0 -> 165 bytes .../gtk-2.0/assets/scale-slider-active.png | Bin 0 -> 537 bytes .../gtk-2.0/assets/scale-slider-disabled.png | Bin 0 -> 250 bytes .../gtk-2.0/assets/scale-slider-hover.png | Bin 0 -> 472 bytes .../gtk-2.0/assets/scale-slider.png | Bin 0 -> 290 bytes .../gtk-2.0/assets/scale-vert-trough-active.png | Bin 0 -> 162 bytes .../gtk-2.0/assets/scale-vert-trough-disabled.png | Bin 0 -> 163 bytes .../gtk-2.0/assets/scale-vert-trough.png | Bin 0 -> 163 bytes .../assets/scrollbar-horz-slider-active.png | Bin 0 -> 258 bytes .../assets/scrollbar-horz-slider-disabled.png | Bin 0 -> 224 bytes .../gtk-2.0/assets/scrollbar-horz-slider-hover.png | Bin 0 -> 255 bytes .../gtk-2.0/assets/scrollbar-horz-slider.png | Bin 0 -> 232 bytes .../gtk-2.0/assets/scrollbar-horz-trough.png | Bin 0 -> 129 bytes .../assets/scrollbar-vert-ltr-slider-active.png | Bin 0 -> 262 bytes .../assets/scrollbar-vert-ltr-slider-disabled.png | Bin 0 -> 229 bytes .../assets/scrollbar-vert-ltr-slider-hover.png | Bin 0 -> 259 bytes .../gtk-2.0/assets/scrollbar-vert-ltr-slider.png | Bin 0 -> 236 bytes .../gtk-2.0/assets/scrollbar-vert-ltr-trough.png | Bin 0 -> 128 bytes .../assets/scrollbar-vert-rtl-slider-active.png | Bin 0 -> 261 bytes .../assets/scrollbar-vert-rtl-slider-disabled.png | Bin 0 -> 228 bytes .../assets/scrollbar-vert-rtl-slider-hover.png | Bin 0 -> 258 bytes .../gtk-2.0/assets/scrollbar-vert-rtl-slider.png | Bin 0 -> 235 bytes .../gtk-2.0/assets/scrollbar-vert-rtl-trough.png | Bin 0 -> 128 bytes .../gtk-2.0/assets/spin-ltr-down-active.png | Bin 0 -> 243 bytes .../gtk-2.0/assets/spin-ltr-down-disabled.png | Bin 0 -> 176 bytes .../gtk-2.0/assets/spin-ltr-down-hover.png | Bin 0 -> 222 bytes .../gtk-2.0/assets/spin-ltr-down.png | Bin 0 -> 182 bytes .../gtk-2.0/assets/spin-ltr-up-active.png | Bin 0 -> 262 bytes .../gtk-2.0/assets/spin-ltr-up-disabled.png | Bin 0 -> 185 bytes .../gtk-2.0/assets/spin-ltr-up-hover.png | Bin 0 -> 237 bytes .../gtk-2.0/assets/spin-ltr-up.png | Bin 0 -> 193 bytes .../gtk-2.0/assets/spin-rtl-down-active.png | Bin 0 -> 258 bytes .../gtk-2.0/assets/spin-rtl-down-disabled.png | Bin 0 -> 178 bytes .../gtk-2.0/assets/spin-rtl-down-hover.png | Bin 0 -> 232 bytes .../gtk-2.0/assets/spin-rtl-down.png | Bin 0 -> 186 bytes .../gtk-2.0/assets/spin-rtl-up-active.png | Bin 0 -> 246 bytes .../gtk-2.0/assets/spin-rtl-up-disabled.png | Bin 0 -> 188 bytes .../gtk-2.0/assets/spin-rtl-up-hover.png | Bin 0 -> 233 bytes .../gtk-2.0/assets/spin-rtl-up.png | Bin 0 -> 191 bytes .../Catppuccin-B-LB-Dark/gtk-2.0/assets/tab.png | Bin 0 -> 127 bytes .../gtk-2.0/assets/treeview-ltr-button-active.png | Bin 0 -> 133 bytes .../gtk-2.0/assets/treeview-ltr-button-hover.png | Bin 0 -> 133 bytes .../gtk-2.0/assets/treeview-ltr-button.png | Bin 0 -> 135 bytes .../gtk-2.0/assets/treeview-rtl-button-active.png | Bin 0 -> 133 bytes .../gtk-2.0/assets/treeview-rtl-button-hover.png | Bin 0 -> 133 bytes .../gtk-2.0/assets/treeview-rtl-button.png | Bin 0 -> 135 bytes .../themes/Catppuccin-B-LB-Dark/gtk-2.0/gtkrc | 36 + .../themes/Catppuccin-B-LB-Dark/gtk-2.0/hacks.rc | 36 + .../themes/Catppuccin-B-LB-Dark/gtk-2.0/main.rc | 2708 ++++++ .../assets/scalable/checkbox-checked-symbolic.svg | 44 + .../scalable/checkbox-checked-symbolic@2.svg | 45 + .../assets/scalable/checkbox-mixed-symbolic.svg | 49 + .../assets/scalable/checkbox-mixed-symbolic@2.svg | 50 + .../gtk-3.0/assets/scalable/close.svg | 38 + .../assets/scalable/cursor-handle-symbolic.svg | 3 + .../gtk-3.0/assets/scalable/maximize.svg | 38 + .../gtk-3.0/assets/scalable/minimize.svg | 43 + .../assets/scalable/radio-checked-symbolic.svg | 45 + .../assets/scalable/radio-checked-symbolic@2.svg | 45 + .../assets/scalable/radio-mixed-symbolic.svg | 1 + .../assets/scalable/radio-mixed-symbolic@2.svg | 1 + .../scale-horz-marks-after-slider-symbolic.svg | 53 + .../scale-horz-marks-before-slider-symbolic.svg | 47 + .../scalable/scale-slider-hover-symbolic.svg | 41 + .../scalable/scale-slider-hover-symbolic@2.svg | 41 + .../assets/scalable/scale-slider-symbolic.svg | 40 + .../assets/scalable/scale-slider-symbolic@2.svg | 41 + .../scale-vert-marks-after-slider-symbolic.svg | 52 + .../scale-vert-marks-before-slider-symbolic.svg | 55 + .../scalable/small-checkbox-checked-symbolic.svg | 45 + .../scalable/small-checkbox-checked-symbolic@2.svg | 46 + .../scalable/small-checkbox-mixed-symbolic.svg | 49 + .../scalable/small-checkbox-mixed-symbolic@2.svg | 49 + .../scalable/small-radio-checked-symbolic.svg | 41 + .../scalable/small-radio-checked-symbolic@2.svg | 41 + .../assets/scalable/small-radio-mixed-symbolic.svg | 1 + .../scalable/small-radio-mixed-symbolic@2.svg | 1 + .../gtk-3.0/assets/scalable/unmaximize.svg | 46 + .../assets/scale-horz-marks-after-slider-dark.png | Bin 0 -> 1024 bytes .../scale-horz-marks-after-slider-dark@2.png | Bin 0 -> 2047 bytes ...scale-horz-marks-after-slider-disabled-dark.png | Bin 0 -> 884 bytes ...ale-horz-marks-after-slider-disabled-dark@2.png | Bin 0 -> 1774 bytes .../scale-horz-marks-after-slider-disabled.png | Bin 0 -> 932 bytes .../scale-horz-marks-after-slider-disabled@2.png | Bin 0 -> 1873 bytes .../assets/scale-horz-marks-after-slider.png | Bin 0 -> 1007 bytes .../assets/scale-horz-marks-after-slider@2.png | Bin 0 -> 1984 bytes .../assets/scale-horz-marks-before-slider-dark.png | Bin 0 -> 994 bytes .../scale-horz-marks-before-slider-dark@2.png | Bin 0 -> 2035 bytes ...cale-horz-marks-before-slider-disabled-dark.png | Bin 0 -> 863 bytes ...le-horz-marks-before-slider-disabled-dark@2.png | Bin 0 -> 1791 bytes .../scale-horz-marks-before-slider-disabled.png | Bin 0 -> 898 bytes .../scale-horz-marks-before-slider-disabled@2.png | Bin 0 -> 1836 bytes .../assets/scale-horz-marks-before-slider.png | Bin 0 -> 960 bytes .../assets/scale-horz-marks-before-slider@2.png | Bin 0 -> 1979 bytes .../assets/scale-vert-marks-after-slider-dark.png | Bin 0 -> 894 bytes .../scale-vert-marks-after-slider-dark@2.png | Bin 0 -> 1780 bytes ...scale-vert-marks-after-slider-disabled-dark.png | Bin 0 -> 799 bytes ...ale-vert-marks-after-slider-disabled-dark@2.png | Bin 0 -> 1559 bytes .../scale-vert-marks-after-slider-disabled.png | Bin 0 -> 834 bytes .../scale-vert-marks-after-slider-disabled@2.png | Bin 0 -> 1595 bytes .../assets/scale-vert-marks-after-slider.png | Bin 0 -> 879 bytes .../assets/scale-vert-marks-after-slider@2.png | Bin 0 -> 1680 bytes .../assets/scale-vert-marks-before-slider-dark.png | Bin 0 -> 929 bytes .../scale-vert-marks-before-slider-dark@2.png | Bin 0 -> 1794 bytes ...cale-vert-marks-before-slider-disabled-dark.png | Bin 0 -> 822 bytes ...le-vert-marks-before-slider-disabled-dark@2.png | Bin 0 -> 1562 bytes .../scale-vert-marks-before-slider-disabled.png | Bin 0 -> 844 bytes .../scale-vert-marks-before-slider-disabled@2.png | Bin 0 -> 1582 bytes .../assets/scale-vert-marks-before-slider.png | Bin 0 -> 892 bytes .../assets/scale-vert-marks-before-slider@2.png | Bin 0 -> 1685 bytes .../assets/selectionmode-checkbox-checked-dark.png | Bin 0 -> 458 bytes .../selectionmode-checkbox-checked-dark@2.png | Bin 0 -> 704 bytes .../assets/selectionmode-checkbox-checked.png | Bin 0 -> 471 bytes .../assets/selectionmode-checkbox-checked@2.png | Bin 0 -> 721 bytes .../selectionmode-checkbox-unchecked-dark.png | Bin 0 -> 273 bytes .../selectionmode-checkbox-unchecked-dark@2.png | Bin 0 -> 415 bytes .../assets/selectionmode-checkbox-unchecked.png | Bin 0 -> 273 bytes .../assets/selectionmode-checkbox-unchecked@2.png | Bin 0 -> 415 bytes .../Catppuccin-B-LB-Dark/gtk-3.0/gtk-dark.css | 8598 ++++++++++++++++++++ .../themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk.css | 8598 ++++++++++++++++++++ .../Catppuccin-B-LB-Dark/gtk-3.0/thumbnail.png | Bin 0 -> 2769 bytes .../gtk-4.0/assets/checkbox-checked-symbolic.svg | 44 + .../gtk-4.0/assets/checkbox-checked-symbolic@2.svg | 45 + .../gtk-4.0/assets/checkbox-mixed-symbolic.svg | 49 + .../gtk-4.0/assets/checkbox-mixed-symbolic@2.svg | 50 + .../Catppuccin-B-LB-Dark/gtk-4.0/assets/close.svg | 38 + .../gtk-4.0/assets/cursor-handle-symbolic.svg | 3 + .../gtk-4.0/assets/maximize.svg | 38 + .../gtk-4.0/assets/minimize.svg | 43 + .../gtk-4.0/assets/radio-checked-symbolic.svg | 45 + .../gtk-4.0/assets/radio-checked-symbolic@2.svg | 45 + .../gtk-4.0/assets/radio-mixed-symbolic.svg | 1 + .../gtk-4.0/assets/radio-mixed-symbolic@2.svg | 1 + .../scale-horz-marks-after-slider-symbolic.svg | 53 + .../scale-horz-marks-before-slider-symbolic.svg | 47 + .../gtk-4.0/assets/scale-slider-hover-symbolic.svg | 41 + .../assets/scale-slider-hover-symbolic@2.svg | 41 + .../gtk-4.0/assets/scale-slider-symbolic.svg | 40 + .../gtk-4.0/assets/scale-slider-symbolic@2.svg | 41 + .../scale-vert-marks-after-slider-symbolic.svg | 52 + .../scale-vert-marks-before-slider-symbolic.svg | 55 + .../assets/small-checkbox-checked-symbolic.svg | 45 + .../assets/small-checkbox-checked-symbolic@2.svg | 46 + .../assets/small-checkbox-mixed-symbolic.svg | 49 + .../assets/small-checkbox-mixed-symbolic@2.svg | 49 + .../assets/small-radio-checked-symbolic.svg | 41 + .../assets/small-radio-checked-symbolic@2.svg | 41 + .../gtk-4.0/assets/small-radio-mixed-symbolic.svg | 1 + .../assets/small-radio-mixed-symbolic@2.svg | 1 + .../gtk-4.0/assets/unmaximize.svg | 46 + .../Catppuccin-B-LB-Dark/gtk-4.0/gtk-dark.css | 8518 +++++++++++++++++++ .../themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk.css | 8518 +++++++++++++++++++ .../Catppuccin-B-LB-Dark/gtk-4.0/thumbnail.png | Bin 0 -> 2769 bytes .../share/themes/Catppuccin-B-LB-Dark/index.theme | 12 + .../metacity-1/assets/button.svg | 41 + .../metacity-1/assets/close.svg | 38 + .../metacity-1/assets/maximize.svg | 38 + .../metacity-1/assets/menu.svg | 40 + .../metacity-1/assets/minimize.svg | 47 + .../metacity-1/assets/shade.svg | 38 + .../metacity-1/assets/unmaximize.svg | 67 + .../metacity-1/assets/unshade.svg | 38 + .../metacity-1/metacity-theme-1.xml | 1 + .../metacity-1/metacity-theme-2.xml | 1 + .../metacity-1/metacity-theme-3.xml | 820 ++ .../Catppuccin-B-LB-Dark/metacity-1/thumbnail.png | Bin 0 -> 1542 bytes .../themes/Catppuccin-B-LB-Dark/plank/dock.theme | 64 + .../Catppuccin-B-LB-Dark/xfwm4/bottom-active.png | Bin 0 -> 138 bytes .../Catppuccin-B-LB-Dark/xfwm4/bottom-inactive.png | Bin 0 -> 138 bytes .../xfwm4/bottom-left-active.png | Bin 0 -> 167 bytes .../xfwm4/bottom-left-inactive.png | Bin 0 -> 154 bytes .../xfwm4/bottom-right-active.png | Bin 0 -> 163 bytes .../xfwm4/bottom-right-inactive.png | Bin 0 -> 157 bytes .../Catppuccin-B-LB-Dark/xfwm4/close-active.png | Bin 0 -> 339 bytes .../Catppuccin-B-LB-Dark/xfwm4/close-inactive.png | Bin 0 -> 300 bytes .../Catppuccin-B-LB-Dark/xfwm4/close-prelight.png | Bin 0 -> 354 bytes .../Catppuccin-B-LB-Dark/xfwm4/close-pressed.png | Bin 0 -> 372 bytes .../Catppuccin-B-LB-Dark/xfwm4/hide-active.png | Bin 0 -> 345 bytes .../Catppuccin-B-LB-Dark/xfwm4/hide-inactive.png | Bin 0 -> 277 bytes .../Catppuccin-B-LB-Dark/xfwm4/hide-prelight.png | Bin 0 -> 320 bytes .../Catppuccin-B-LB-Dark/xfwm4/hide-pressed.png | Bin 0 -> 338 bytes .../Catppuccin-B-LB-Dark/xfwm4/left-active.png | Bin 0 -> 138 bytes .../Catppuccin-B-LB-Dark/xfwm4/left-inactive.png | Bin 0 -> 138 bytes .../Catppuccin-B-LB-Dark/xfwm4/maximize-active.png | Bin 0 -> 352 bytes .../xfwm4/maximize-inactive.png | Bin 0 -> 305 bytes .../xfwm4/maximize-prelight.png | Bin 0 -> 376 bytes .../xfwm4/maximize-pressed.png | Bin 0 -> 383 bytes .../xfwm4/maximize-toggled-active.png | Bin 0 -> 394 bytes .../xfwm4/maximize-toggled-inactive.png | Bin 0 -> 349 bytes .../xfwm4/maximize-toggled-prelight.png | Bin 0 -> 419 bytes .../xfwm4/maximize-toggled-pressed.png | Bin 0 -> 424 bytes .../Catppuccin-B-LB-Dark/xfwm4/menu-active.png | Bin 0 -> 174 bytes .../Catppuccin-B-LB-Dark/xfwm4/menu-inactive.png | Bin 0 -> 159 bytes .../Catppuccin-B-LB-Dark/xfwm4/menu-prelight.png | Bin 0 -> 327 bytes .../Catppuccin-B-LB-Dark/xfwm4/menu-pressed.png | Bin 0 -> 348 bytes .../Catppuccin-B-LB-Dark/xfwm4/right-active.png | Bin 0 -> 138 bytes .../Catppuccin-B-LB-Dark/xfwm4/right-inactive.png | Bin 0 -> 138 bytes .../Catppuccin-B-LB-Dark/xfwm4/shade-active.png | Bin 0 -> 228 bytes .../Catppuccin-B-LB-Dark/xfwm4/shade-inactive.png | Bin 0 -> 215 bytes .../Catppuccin-B-LB-Dark/xfwm4/shade-prelight.png | Bin 0 -> 387 bytes .../Catppuccin-B-LB-Dark/xfwm4/shade-pressed.png | Bin 0 -> 404 bytes .../xfwm4/shade-toggled-active.png | Bin 0 -> 226 bytes .../xfwm4/shade-toggled-inactive.png | Bin 0 -> 220 bytes .../xfwm4/shade-toggled-prelight.png | Bin 0 -> 380 bytes .../xfwm4/shade-toggled-pressed.png | Bin 0 -> 396 bytes .../Catppuccin-B-LB-Dark/xfwm4/stick-active.png | Bin 0 -> 327 bytes .../Catppuccin-B-LB-Dark/xfwm4/stick-inactive.png | Bin 0 -> 289 bytes .../Catppuccin-B-LB-Dark/xfwm4/stick-prelight.png | Bin 0 -> 476 bytes .../Catppuccin-B-LB-Dark/xfwm4/stick-pressed.png | Bin 0 -> 485 bytes .../xfwm4/stick-toggled-active.png | Bin 0 -> 364 bytes .../xfwm4/stick-toggled-inactive.png | Bin 0 -> 319 bytes .../xfwm4/stick-toggled-prelight.png | Bin 0 -> 513 bytes .../xfwm4/stick-toggled-pressed.png | Bin 0 -> 515 bytes .../themes/Catppuccin-B-LB-Dark/xfwm4/themerc | 23 + .../Catppuccin-B-LB-Dark/xfwm4/title-1-active.png | Bin 0 -> 146 bytes .../xfwm4/title-1-inactive.png | Bin 0 -> 141 bytes .../Catppuccin-B-LB-Dark/xfwm4/title-2-active.png | Bin 0 -> 146 bytes .../xfwm4/title-2-inactive.png | Bin 0 -> 141 bytes .../Catppuccin-B-LB-Dark/xfwm4/title-3-active.png | Bin 0 -> 146 bytes .../xfwm4/title-3-inactive.png | Bin 0 -> 141 bytes .../Catppuccin-B-LB-Dark/xfwm4/title-4-active.png | Bin 0 -> 146 bytes .../xfwm4/title-4-inactive.png | Bin 0 -> 141 bytes .../Catppuccin-B-LB-Dark/xfwm4/title-5-active.png | Bin 0 -> 146 bytes .../xfwm4/title-5-inactive.png | Bin 0 -> 141 bytes .../Catppuccin-B-LB-Dark/xfwm4/top-left-active.png | Bin 0 -> 182 bytes .../xfwm4/top-left-inactive.png | Bin 0 -> 176 bytes .../xfwm4/top-right-active.png | Bin 0 -> 179 bytes .../xfwm4/top-right-inactive.png | Bin 0 -> 172 bytes .../cinnamon/assets/add-workspace-active.svg | 111 + .../cinnamon/assets/add-workspace-hover.svg | 112 + .../cinnamon/assets/add-workspace.svg | 113 + .../cinnamon/assets/calendar-arrow-left.svg | 56 + .../cinnamon/assets/calendar-arrow-right.svg | 56 + .../cinnamon/assets/checkbox-dark.svg | 75 + .../cinnamon/assets/checkbox-off.svg | 3 + .../cinnamon/assets/checkbox.svg | 85 + .../cinnamon/assets/close-active.svg | 72 + .../cinnamon/assets/close-hover.svg | 72 + .../cinnamon/assets/close.svg | 72 + .../cinnamon/assets/corner-ripple.svg | 46 + .../cinnamon/assets/radiobutton-dark.svg | 71 + .../cinnamon/assets/radiobutton-off.svg | 3 + .../cinnamon/assets/radiobutton.svg | 81 + .../cinnamon/assets/toggle-off.svg | 69 + .../cinnamon/assets/toggle-on-dark.svg | 94 + .../cinnamon/assets/toggle-on.svg | 91 + .../cinnamon/assets/trash-icon.svg | 6 + .../Gruvbox-B-LB-Dark-Medium/cinnamon/cinnamon.css | 2594 ++++++ .../cinnamon/thumbnail.png | Bin 0 -> 5822 bytes .../gnome-shell/assets/calendar-arrow-left.svg | 3 + .../gnome-shell/assets/calendar-arrow-right.svg | 3 + .../gnome-shell/assets/calendar-today.svg | 55 + .../gnome-shell/assets/checkbox-dark.svg | 75 + .../gnome-shell/assets/checkbox-off-active.svg | 3 + .../gnome-shell/assets/checkbox-off-hover.svg | 3 + .../gnome-shell/assets/checkbox-off.svg | 3 + .../gnome-shell/assets/checkbox.svg | 85 + .../gnome-shell/assets/dash-placeholder.svg | 4 + .../gnome-shell/assets/no-events.svg | 82 + .../gnome-shell/assets/no-notifications.svg | 3 + .../gnome-shell/assets/noise-texture.svg | 78 + .../gnome-shell/assets/process-working.svg | 72 + .../gnome-shell/assets/toggle-off.svg | 59 + .../gnome-shell/assets/toggle-on-dark.svg | 94 + .../gnome-shell/assets/toggle-on.svg | 91 + .../gnome-shell/gnome-shell.css | 6084 ++++++++++++++ .../gnome-shell/no-events.svg | 1 + .../gnome-shell/no-notifications.svg | 1 + .../gnome-shell/pad-osd.css | 31 + .../gnome-shell/process-working.svg | 1 + .../Gruvbox-B-LB-Dark-Medium/gtk-2.0/apps.rc | 92 + .../gtk-2.0/assets/border.png | Bin 0 -> 123 bytes .../gtk-2.0/assets/button-active.png | Bin 0 -> 320 bytes .../gtk-2.0/assets/button-disabled.png | Bin 0 -> 323 bytes .../gtk-2.0/assets/button-hover.png | Bin 0 -> 331 bytes .../gtk-2.0/assets/button.png | Bin 0 -> 342 bytes .../gtk-2.0/assets/checkbox-checked-active.png | Bin 0 -> 619 bytes .../gtk-2.0/assets/checkbox-checked-disabled.png | Bin 0 -> 595 bytes .../gtk-2.0/assets/checkbox-checked-hover.png | Bin 0 -> 580 bytes .../gtk-2.0/assets/checkbox-checked.png | Bin 0 -> 497 bytes .../gtk-2.0/assets/checkbox-mixed-active.png | Bin 0 -> 527 bytes .../gtk-2.0/assets/checkbox-mixed-disabled.png | Bin 0 -> 545 bytes .../gtk-2.0/assets/checkbox-mixed-hover.png | Bin 0 -> 510 bytes .../gtk-2.0/assets/checkbox-mixed.png | Bin 0 -> 472 bytes .../gtk-2.0/assets/checkbox-unchecked-active.png | Bin 0 -> 442 bytes .../gtk-2.0/assets/checkbox-unchecked-disabled.png | Bin 0 -> 448 bytes .../gtk-2.0/assets/checkbox-unchecked-hover.png | Bin 0 -> 440 bytes .../gtk-2.0/assets/checkbox-unchecked.png | Bin 0 -> 484 bytes .../gtk-2.0/assets/combo-left-entry-active.png | Bin 0 -> 325 bytes .../gtk-2.0/assets/combo-left-entry-disabled.png | Bin 0 -> 241 bytes .../gtk-2.0/assets/combo-left-entry-hover.png | Bin 0 -> 314 bytes .../gtk-2.0/assets/combo-left-entry.png | Bin 0 -> 258 bytes .../gtk-2.0/assets/combo-right-entry-active.png | Bin 0 -> 343 bytes .../gtk-2.0/assets/combo-right-entry-disabled.png | Bin 0 -> 242 bytes .../gtk-2.0/assets/combo-right-entry-hover.png | Bin 0 -> 349 bytes .../gtk-2.0/assets/combo-right-entry.png | Bin 0 -> 246 bytes .../gtk-2.0/assets/entry-active.png | Bin 0 -> 470 bytes .../gtk-2.0/assets/entry-background-disabled.png | Bin 0 -> 126 bytes .../gtk-2.0/assets/entry-background.png | Bin 0 -> 126 bytes .../gtk-2.0/assets/entry-disabled.png | Bin 0 -> 323 bytes .../gtk-2.0/assets/entry-hover.png | Bin 0 -> 478 bytes .../gtk-2.0/assets/entry.png | Bin 0 -> 342 bytes .../gtk-2.0/assets/flat-button-active.png | Bin 0 -> 320 bytes .../gtk-2.0/assets/flat-button-disabled.png | Bin 0 -> 290 bytes .../gtk-2.0/assets/flat-button-hover.png | Bin 0 -> 331 bytes .../gtk-2.0/assets/flat-button.png | Bin 0 -> 290 bytes .../gtk-2.0/assets/focus.png | Bin 0 -> 288 bytes .../gtk-2.0/assets/frame-inline.png | Bin 0 -> 128 bytes .../gtk-2.0/assets/frame-notebook.png | Bin 0 -> 134 bytes .../gtk-2.0/assets/frame.png | Bin 0 -> 134 bytes .../gtk-2.0/assets/handle-horz-active.png | Bin 0 -> 190 bytes .../gtk-2.0/assets/handle-horz-hover.png | Bin 0 -> 196 bytes .../gtk-2.0/assets/handle-horz.png | Bin 0 -> 197 bytes .../gtk-2.0/assets/handle-vert-active.png | Bin 0 -> 182 bytes .../gtk-2.0/assets/handle-vert-hover.png | Bin 0 -> 181 bytes .../gtk-2.0/assets/handle-vert.png | Bin 0 -> 180 bytes .../assets/menu-checkbox-checked-disabled.png | Bin 0 -> 469 bytes .../gtk-2.0/assets/menu-checkbox-checked.png | Bin 0 -> 416 bytes .../assets/menu-checkbox-mixed-disabled.png | Bin 0 -> 420 bytes .../gtk-2.0/assets/menu-checkbox-mixed.png | Bin 0 -> 371 bytes .../assets/menu-checkbox-unchecked-disabled.png | Bin 0 -> 330 bytes .../gtk-2.0/assets/menu-checkbox-unchecked.png | Bin 0 -> 389 bytes .../gtk-2.0/assets/menu-radio-checked-disabled.png | Bin 0 -> 471 bytes .../gtk-2.0/assets/menu-radio-checked.png | Bin 0 -> 421 bytes .../gtk-2.0/assets/menu-radio-mixed-disabled.png | Bin 0 -> 420 bytes .../gtk-2.0/assets/menu-radio-mixed.png | Bin 0 -> 371 bytes .../assets/menu-radio-unchecked-disabled.png | Bin 0 -> 330 bytes .../gtk-2.0/assets/menu-radio-unchecked.png | Bin 0 -> 389 bytes .../gtk-2.0/assets/pan-down-alt-disabled.png | Bin 0 -> 180 bytes .../gtk-2.0/assets/pan-down-alt.png | Bin 0 -> 181 bytes .../gtk-2.0/assets/pan-down-disabled.png | Bin 0 -> 178 bytes .../gtk-2.0/assets/pan-down.png | Bin 0 -> 181 bytes .../gtk-2.0/assets/pan-left-alt-disabled.png | Bin 0 -> 190 bytes .../gtk-2.0/assets/pan-left-alt.png | Bin 0 -> 183 bytes .../gtk-2.0/assets/pan-left-disabled.png | Bin 0 -> 183 bytes .../gtk-2.0/assets/pan-left-semi.png | Bin 0 -> 185 bytes .../gtk-2.0/assets/pan-left.png | Bin 0 -> 194 bytes .../gtk-2.0/assets/pan-right-alt-disabled.png | Bin 0 -> 187 bytes .../gtk-2.0/assets/pan-right-alt.png | Bin 0 -> 182 bytes .../gtk-2.0/assets/pan-right-disabled.png | Bin 0 -> 180 bytes .../gtk-2.0/assets/pan-right-semi.png | Bin 0 -> 187 bytes .../gtk-2.0/assets/pan-right.png | Bin 0 -> 188 bytes .../gtk-2.0/assets/pan-up-alt-disabled.png | Bin 0 -> 175 bytes .../gtk-2.0/assets/pan-up-alt.png | Bin 0 -> 182 bytes .../gtk-2.0/assets/pan-up-disabled.png | Bin 0 -> 175 bytes .../gtk-2.0/assets/pan-up.png | Bin 0 -> 180 bytes .../gtk-2.0/assets/progressbar-progress.png | Bin 0 -> 140 bytes .../gtk-2.0/assets/progressbar-trough.png | Bin 0 -> 139 bytes .../gtk-2.0/assets/radio-checked-active.png | Bin 0 -> 595 bytes .../gtk-2.0/assets/radio-checked-disabled.png | Bin 0 -> 592 bytes .../gtk-2.0/assets/radio-checked-hover.png | Bin 0 -> 568 bytes .../gtk-2.0/assets/radio-checked.png | Bin 0 -> 500 bytes .../gtk-2.0/assets/radio-mixed-active.png | Bin 0 -> 527 bytes .../gtk-2.0/assets/radio-mixed-disabled.png | Bin 0 -> 545 bytes .../gtk-2.0/assets/radio-mixed-hover.png | Bin 0 -> 510 bytes .../gtk-2.0/assets/radio-mixed.png | Bin 0 -> 472 bytes .../gtk-2.0/assets/radio-unchecked-active.png | Bin 0 -> 442 bytes .../gtk-2.0/assets/radio-unchecked-disabled.png | Bin 0 -> 448 bytes .../gtk-2.0/assets/radio-unchecked-hover.png | Bin 0 -> 440 bytes .../gtk-2.0/assets/radio-unchecked.png | Bin 0 -> 484 bytes .../gtk-2.0/assets/scale-horz-trough-active.png | Bin 0 -> 157 bytes .../gtk-2.0/assets/scale-horz-trough-disabled.png | Bin 0 -> 155 bytes .../gtk-2.0/assets/scale-horz-trough.png | Bin 0 -> 157 bytes .../gtk-2.0/assets/scale-slider-active.png | Bin 0 -> 742 bytes .../gtk-2.0/assets/scale-slider-disabled.png | Bin 0 -> 332 bytes .../gtk-2.0/assets/scale-slider-hover.png | Bin 0 -> 700 bytes .../gtk-2.0/assets/scale-slider.png | Bin 0 -> 328 bytes .../gtk-2.0/assets/scale-vert-trough-active.png | Bin 0 -> 156 bytes .../gtk-2.0/assets/scale-vert-trough-disabled.png | Bin 0 -> 155 bytes .../gtk-2.0/assets/scale-vert-trough.png | Bin 0 -> 156 bytes .../assets/scrollbar-horz-slider-active.png | Bin 0 -> 258 bytes .../assets/scrollbar-horz-slider-disabled.png | Bin 0 -> 272 bytes .../gtk-2.0/assets/scrollbar-horz-slider-hover.png | Bin 0 -> 260 bytes .../gtk-2.0/assets/scrollbar-horz-slider.png | Bin 0 -> 274 bytes .../gtk-2.0/assets/scrollbar-horz-trough.png | Bin 0 -> 128 bytes .../assets/scrollbar-vert-ltr-slider-active.png | Bin 0 -> 263 bytes .../assets/scrollbar-vert-ltr-slider-disabled.png | Bin 0 -> 271 bytes .../assets/scrollbar-vert-ltr-slider-hover.png | Bin 0 -> 260 bytes .../gtk-2.0/assets/scrollbar-vert-ltr-slider.png | Bin 0 -> 272 bytes .../gtk-2.0/assets/scrollbar-vert-ltr-trough.png | Bin 0 -> 127 bytes .../assets/scrollbar-vert-rtl-slider-active.png | Bin 0 -> 261 bytes .../assets/scrollbar-vert-rtl-slider-disabled.png | Bin 0 -> 272 bytes .../assets/scrollbar-vert-rtl-slider-hover.png | Bin 0 -> 261 bytes .../gtk-2.0/assets/scrollbar-vert-rtl-slider.png | Bin 0 -> 272 bytes .../gtk-2.0/assets/scrollbar-vert-rtl-trough.png | Bin 0 -> 127 bytes .../gtk-2.0/assets/spin-ltr-down-active.png | Bin 0 -> 248 bytes .../gtk-2.0/assets/spin-ltr-down-disabled.png | Bin 0 -> 186 bytes .../gtk-2.0/assets/spin-ltr-down-hover.png | Bin 0 -> 242 bytes .../gtk-2.0/assets/spin-ltr-down.png | Bin 0 -> 190 bytes .../gtk-2.0/assets/spin-ltr-up-active.png | Bin 0 -> 264 bytes .../gtk-2.0/assets/spin-ltr-up-disabled.png | Bin 0 -> 202 bytes .../gtk-2.0/assets/spin-ltr-up-hover.png | Bin 0 -> 263 bytes .../gtk-2.0/assets/spin-ltr-up.png | Bin 0 -> 203 bytes .../gtk-2.0/assets/spin-rtl-down-active.png | Bin 0 -> 250 bytes .../gtk-2.0/assets/spin-rtl-down-disabled.png | Bin 0 -> 192 bytes .../gtk-2.0/assets/spin-rtl-down-hover.png | Bin 0 -> 234 bytes .../gtk-2.0/assets/spin-rtl-down.png | Bin 0 -> 194 bytes .../gtk-2.0/assets/spin-rtl-up-active.png | Bin 0 -> 243 bytes .../gtk-2.0/assets/spin-rtl-up-disabled.png | Bin 0 -> 191 bytes .../gtk-2.0/assets/spin-rtl-up-hover.png | Bin 0 -> 236 bytes .../gtk-2.0/assets/spin-rtl-up.png | Bin 0 -> 205 bytes .../gtk-2.0/assets/tab.png | Bin 0 -> 123 bytes .../gtk-2.0/assets/treeview-ltr-button-active.png | Bin 0 -> 129 bytes .../gtk-2.0/assets/treeview-ltr-button-hover.png | Bin 0 -> 129 bytes .../gtk-2.0/assets/treeview-ltr-button.png | Bin 0 -> 118 bytes .../gtk-2.0/assets/treeview-rtl-button-active.png | Bin 0 -> 129 bytes .../gtk-2.0/assets/treeview-rtl-button-hover.png | Bin 0 -> 129 bytes .../gtk-2.0/assets/treeview-rtl-button.png | Bin 0 -> 118 bytes .../themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/gtkrc | 36 + .../Gruvbox-B-LB-Dark-Medium/gtk-2.0/hacks.rc | 36 + .../Gruvbox-B-LB-Dark-Medium/gtk-2.0/main.rc | 2708 ++++++ .../assets/scalable/checkbox-checked-symbolic.svg | 44 + .../scalable/checkbox-checked-symbolic@2.svg | 45 + .../assets/scalable/checkbox-mixed-symbolic.svg | 49 + .../assets/scalable/checkbox-mixed-symbolic@2.svg | 50 + .../gtk-3.0/assets/scalable/close.svg | 38 + .../assets/scalable/cursor-handle-symbolic.svg | 3 + .../gtk-3.0/assets/scalable/maximize.svg | 38 + .../gtk-3.0/assets/scalable/minimize.svg | 43 + .../assets/scalable/radio-checked-symbolic.svg | 45 + .../assets/scalable/radio-checked-symbolic@2.svg | 45 + .../assets/scalable/radio-mixed-symbolic.svg | 1 + .../assets/scalable/radio-mixed-symbolic@2.svg | 1 + .../scale-horz-marks-after-slider-symbolic.svg | 53 + .../scale-horz-marks-before-slider-symbolic.svg | 47 + .../scalable/scale-slider-hover-symbolic.svg | 41 + .../scalable/scale-slider-hover-symbolic@2.svg | 41 + .../assets/scalable/scale-slider-symbolic.svg | 40 + .../assets/scalable/scale-slider-symbolic@2.svg | 41 + .../scale-vert-marks-after-slider-symbolic.svg | 52 + .../scale-vert-marks-before-slider-symbolic.svg | 55 + .../scalable/small-checkbox-checked-symbolic.svg | 45 + .../scalable/small-checkbox-checked-symbolic@2.svg | 46 + .../scalable/small-checkbox-mixed-symbolic.svg | 49 + .../scalable/small-checkbox-mixed-symbolic@2.svg | 49 + .../scalable/small-radio-checked-symbolic.svg | 41 + .../scalable/small-radio-checked-symbolic@2.svg | 41 + .../assets/scalable/small-radio-mixed-symbolic.svg | 1 + .../scalable/small-radio-mixed-symbolic@2.svg | 1 + .../gtk-3.0/assets/scalable/unmaximize.svg | 46 + .../assets/scale-horz-marks-after-slider-dark.png | Bin 0 -> 1137 bytes .../scale-horz-marks-after-slider-dark@2.png | Bin 0 -> 2568 bytes ...scale-horz-marks-after-slider-disabled-dark.png | Bin 0 -> 1064 bytes ...ale-horz-marks-after-slider-disabled-dark@2.png | Bin 0 -> 2372 bytes .../scale-horz-marks-after-slider-disabled.png | Bin 0 -> 1071 bytes .../scale-horz-marks-after-slider-disabled@2.png | Bin 0 -> 2318 bytes .../assets/scale-horz-marks-after-slider.png | Bin 0 -> 1042 bytes .../assets/scale-horz-marks-after-slider@2.png | Bin 0 -> 2289 bytes .../assets/scale-horz-marks-before-slider-dark.png | Bin 0 -> 1114 bytes .../scale-horz-marks-before-slider-dark@2.png | Bin 0 -> 2547 bytes ...cale-horz-marks-before-slider-disabled-dark.png | Bin 0 -> 1057 bytes ...le-horz-marks-before-slider-disabled-dark@2.png | Bin 0 -> 2339 bytes .../scale-horz-marks-before-slider-disabled.png | Bin 0 -> 1046 bytes .../scale-horz-marks-before-slider-disabled@2.png | Bin 0 -> 2302 bytes .../assets/scale-horz-marks-before-slider.png | Bin 0 -> 1019 bytes .../assets/scale-horz-marks-before-slider@2.png | Bin 0 -> 2270 bytes .../assets/scale-vert-marks-after-slider-dark.png | Bin 0 -> 1112 bytes .../scale-vert-marks-after-slider-dark@2.png | Bin 0 -> 2550 bytes ...scale-vert-marks-after-slider-disabled-dark.png | Bin 0 -> 1044 bytes ...ale-vert-marks-after-slider-disabled-dark@2.png | Bin 0 -> 2363 bytes .../scale-vert-marks-after-slider-disabled.png | Bin 0 -> 1053 bytes .../scale-vert-marks-after-slider-disabled@2.png | Bin 0 -> 2339 bytes .../assets/scale-vert-marks-after-slider.png | Bin 0 -> 1006 bytes .../assets/scale-vert-marks-after-slider@2.png | Bin 0 -> 2283 bytes .../assets/scale-vert-marks-before-slider-dark.png | Bin 0 -> 1096 bytes .../scale-vert-marks-before-slider-dark@2.png | Bin 0 -> 2465 bytes ...cale-vert-marks-before-slider-disabled-dark.png | Bin 0 -> 1039 bytes ...le-vert-marks-before-slider-disabled-dark@2.png | Bin 0 -> 2244 bytes .../scale-vert-marks-before-slider-disabled.png | Bin 0 -> 1038 bytes .../scale-vert-marks-before-slider-disabled@2.png | Bin 0 -> 2210 bytes .../assets/scale-vert-marks-before-slider.png | Bin 0 -> 996 bytes .../assets/scale-vert-marks-before-slider@2.png | Bin 0 -> 2154 bytes .../assets/selectionmode-checkbox-checked-dark.png | Bin 0 -> 516 bytes .../selectionmode-checkbox-checked-dark@2.png | Bin 0 -> 853 bytes .../assets/selectionmode-checkbox-checked.png | Bin 0 -> 528 bytes .../assets/selectionmode-checkbox-checked@2.png | Bin 0 -> 892 bytes .../selectionmode-checkbox-unchecked-dark.png | Bin 0 -> 304 bytes .../selectionmode-checkbox-unchecked-dark@2.png | Bin 0 -> 555 bytes .../assets/selectionmode-checkbox-unchecked.png | Bin 0 -> 306 bytes .../assets/selectionmode-checkbox-unchecked@2.png | Bin 0 -> 562 bytes .../Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk-dark.css | 8576 +++++++++++++++++++ .../Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk.css | 8576 +++++++++++++++++++ .../Gruvbox-B-LB-Dark-Medium/gtk-3.0/thumbnail.png | Bin 0 -> 1562 bytes .../gtk-4.0/assets/checkbox-checked-symbolic.svg | 44 + .../gtk-4.0/assets/checkbox-checked-symbolic@2.svg | 45 + .../gtk-4.0/assets/checkbox-mixed-symbolic.svg | 49 + .../gtk-4.0/assets/checkbox-mixed-symbolic@2.svg | 50 + .../gtk-4.0/assets/close.svg | 38 + .../gtk-4.0/assets/cursor-handle-symbolic.svg | 3 + .../gtk-4.0/assets/maximize.svg | 38 + .../gtk-4.0/assets/minimize.svg | 43 + .../gtk-4.0/assets/radio-checked-symbolic.svg | 45 + .../gtk-4.0/assets/radio-checked-symbolic@2.svg | 45 + .../gtk-4.0/assets/radio-mixed-symbolic.svg | 1 + .../gtk-4.0/assets/radio-mixed-symbolic@2.svg | 1 + .../scale-horz-marks-after-slider-symbolic.svg | 53 + .../scale-horz-marks-before-slider-symbolic.svg | 47 + .../gtk-4.0/assets/scale-slider-hover-symbolic.svg | 41 + .../assets/scale-slider-hover-symbolic@2.svg | 41 + .../gtk-4.0/assets/scale-slider-symbolic.svg | 40 + .../gtk-4.0/assets/scale-slider-symbolic@2.svg | 41 + .../scale-vert-marks-after-slider-symbolic.svg | 52 + .../scale-vert-marks-before-slider-symbolic.svg | 55 + .../assets/small-checkbox-checked-symbolic.svg | 45 + .../assets/small-checkbox-checked-symbolic@2.svg | 46 + .../assets/small-checkbox-mixed-symbolic.svg | 49 + .../assets/small-checkbox-mixed-symbolic@2.svg | 49 + .../assets/small-radio-checked-symbolic.svg | 41 + .../assets/small-radio-checked-symbolic@2.svg | 41 + .../gtk-4.0/assets/small-radio-mixed-symbolic.svg | 1 + .../assets/small-radio-mixed-symbolic@2.svg | 1 + .../gtk-4.0/assets/unmaximize.svg | 46 + .../Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk-dark.css | 8519 +++++++++++++++++++ .../Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk.css | 8519 +++++++++++++++++++ .../Gruvbox-B-LB-Dark-Medium/gtk-4.0/thumbnail.png | Bin 0 -> 1562 bytes .../themes/Gruvbox-B-LB-Dark-Medium/index.theme | 12 + .../metacity-1/assets/button.svg | 41 + .../metacity-1/assets/close.svg | 38 + .../metacity-1/assets/maximize.svg | 38 + .../metacity-1/assets/menu.svg | 40 + .../metacity-1/assets/minimize.svg | 47 + .../metacity-1/assets/shade.svg | 38 + .../metacity-1/assets/unmaximize.svg | 67 + .../metacity-1/assets/unshade.svg | 38 + .../metacity-1/metacity-theme-1.xml | 1 + .../metacity-1/metacity-theme-2.xml | 1 + .../metacity-1/metacity-theme-3.xml | 820 ++ .../metacity-1/thumbnail.png | Bin 0 -> 1596 bytes .../Gruvbox-B-LB-Dark-Medium/plank/dock.theme | 64 + .../xfwm4/bottom-active.png | Bin 0 -> 139 bytes .../xfwm4/bottom-inactive.png | Bin 0 -> 135 bytes .../xfwm4/bottom-left-active.png | Bin 0 -> 157 bytes .../xfwm4/bottom-left-inactive.png | Bin 0 -> 150 bytes .../xfwm4/bottom-right-active.png | Bin 0 -> 159 bytes .../xfwm4/bottom-right-inactive.png | Bin 0 -> 156 bytes .../xfwm4/close-active.png | Bin 0 -> 600 bytes .../xfwm4/close-inactive.png | Bin 0 -> 553 bytes .../xfwm4/close-prelight.png | Bin 0 -> 618 bytes .../xfwm4/close-pressed.png | Bin 0 -> 617 bytes .../Gruvbox-B-LB-Dark-Medium/xfwm4/hide-active.png | Bin 0 -> 547 bytes .../xfwm4/hide-inactive.png | Bin 0 -> 487 bytes .../xfwm4/hide-prelight.png | Bin 0 -> 518 bytes .../xfwm4/hide-pressed.png | Bin 0 -> 554 bytes .../Gruvbox-B-LB-Dark-Medium/xfwm4/left-active.png | Bin 0 -> 143 bytes .../xfwm4/left-inactive.png | Bin 0 -> 139 bytes .../xfwm4/maximize-active.png | Bin 0 -> 630 bytes .../xfwm4/maximize-inactive.png | Bin 0 -> 571 bytes .../xfwm4/maximize-prelight.png | Bin 0 -> 612 bytes .../xfwm4/maximize-pressed.png | Bin 0 -> 637 bytes .../xfwm4/maximize-toggled-active.png | Bin 0 -> 691 bytes .../xfwm4/maximize-toggled-inactive.png | Bin 0 -> 626 bytes .../xfwm4/maximize-toggled-prelight.png | Bin 0 -> 665 bytes .../xfwm4/maximize-toggled-pressed.png | Bin 0 -> 702 bytes .../Gruvbox-B-LB-Dark-Medium/xfwm4/menu-active.png | Bin 0 -> 206 bytes .../xfwm4/menu-inactive.png | Bin 0 -> 197 bytes .../xfwm4/menu-prelight.png | Bin 0 -> 508 bytes .../xfwm4/menu-pressed.png | Bin 0 -> 545 bytes .../xfwm4/right-active.png | Bin 0 -> 141 bytes .../xfwm4/right-inactive.png | Bin 0 -> 139 bytes .../xfwm4/shade-active.png | Bin 0 -> 323 bytes .../xfwm4/shade-inactive.png | Bin 0 -> 283 bytes .../xfwm4/shade-prelight.png | Bin 0 -> 586 bytes .../xfwm4/shade-pressed.png | Bin 0 -> 608 bytes .../xfwm4/shade-toggled-active.png | Bin 0 -> 332 bytes .../xfwm4/shade-toggled-inactive.png | Bin 0 -> 290 bytes .../xfwm4/shade-toggled-prelight.png | Bin 0 -> 603 bytes .../xfwm4/shade-toggled-pressed.png | Bin 0 -> 618 bytes .../xfwm4/stick-active.png | Bin 0 -> 492 bytes .../xfwm4/stick-inactive.png | Bin 0 -> 433 bytes .../xfwm4/stick-prelight.png | Bin 0 -> 786 bytes .../xfwm4/stick-pressed.png | Bin 0 -> 818 bytes .../xfwm4/stick-toggled-active.png | Bin 0 -> 551 bytes .../xfwm4/stick-toggled-inactive.png | Bin 0 -> 486 bytes .../xfwm4/stick-toggled-prelight.png | Bin 0 -> 842 bytes .../xfwm4/stick-toggled-pressed.png | Bin 0 -> 885 bytes .../themes/Gruvbox-B-LB-Dark-Medium/xfwm4/themerc | 23 + .../xfwm4/title-1-active.png | Bin 0 -> 141 bytes .../xfwm4/title-1-inactive.png | Bin 0 -> 142 bytes .../xfwm4/title-2-active.png | Bin 0 -> 141 bytes .../xfwm4/title-2-inactive.png | Bin 0 -> 142 bytes .../xfwm4/title-3-active.png | Bin 0 -> 141 bytes .../xfwm4/title-3-inactive.png | Bin 0 -> 142 bytes .../xfwm4/title-4-active.png | Bin 0 -> 141 bytes .../xfwm4/title-4-inactive.png | Bin 0 -> 142 bytes .../xfwm4/title-5-active.png | Bin 0 -> 141 bytes .../xfwm4/title-5-inactive.png | Bin 0 -> 142 bytes .../xfwm4/top-left-active.png | Bin 0 -> 180 bytes .../xfwm4/top-left-inactive.png | Bin 0 -> 174 bytes .../xfwm4/top-right-active.png | Bin 0 -> 203 bytes .../xfwm4/top-right-inactive.png | Bin 0 -> 179 bytes nixos/configuration/configuration.nix | 132 + .../configuration/sys/coreutils-configuration.nix | 48 + nixos/configuration/sys/swap.nix | 11 + nixos/configuration/sys/zram.nix | 10 + nixos/flake.lock | 135 + nixos/flake.nix | 56 + nixos/home-configuration/apps/alacritty.nix | 28 + nixos/home-configuration/apps/foot.nix | 31 + nixos/home-configuration/apps/nushell.nix | 13 + nixos/home-configuration/apps/sway.nix | 111 + nixos/home-configuration/apps/zsh.nix | 59 + nixos/home-configuration/configuration.nix | 99 + portage/make.conf | 20 + slock | 1 + slstatus/LICENSE | 43 + slstatus/Makefile | 69 + slstatus/arg.h | 33 + slstatus/components/battery.c | 247 + slstatus/components/battery.o | Bin 0 -> 5264 bytes slstatus/components/cat.c | 32 + slstatus/components/cat.o | Bin 0 -> 2160 bytes slstatus/components/cpu.c | 157 + slstatus/components/cpu.o | Bin 0 -> 3184 bytes slstatus/components/datetime.c | 20 + slstatus/components/datetime.o | Bin 0 -> 2000 bytes slstatus/components/disk.c | 59 + slstatus/components/disk.o | Bin 0 -> 3192 bytes slstatus/components/entropy.c | 29 + slstatus/components/entropy.o | Bin 0 -> 1856 bytes slstatus/components/hostname.c | 17 + slstatus/components/hostname.o | Bin 0 -> 1712 bytes slstatus/components/ip.c | 61 + slstatus/components/ip.o | Bin 0 -> 2616 bytes slstatus/components/kernel_release.c | 19 + slstatus/components/kernel_release.o | Bin 0 -> 1888 bytes slstatus/components/keyboard_indicators.c | 50 + slstatus/components/keyboard_indicators.o | Bin 0 -> 2480 bytes slstatus/components/keymap.c | 86 + slstatus/components/keymap.o | Bin 0 -> 4080 bytes slstatus/components/load_avg.c | 19 + slstatus/components/load_avg.o | Bin 0 -> 1920 bytes slstatus/components/netspeeds.c | 129 + slstatus/components/netspeeds.o | Bin 0 -> 2848 bytes slstatus/components/num_files.c | 32 + slstatus/components/num_files.o | Bin 0 -> 2176 bytes slstatus/components/pixVol.sh | 10 + slstatus/components/ram.c | 212 + slstatus/components/ram.o | Bin 0 -> 3144 bytes slstatus/components/run_command.c | 31 + slstatus/components/run_command.o | Bin 0 -> 2176 bytes slstatus/components/swap.c | 274 + slstatus/components/swap.o | Bin 0 -> 3952 bytes slstatus/components/temperature.c | 73 + slstatus/components/temperature.o | Bin 0 -> 1776 bytes slstatus/components/uptime.c | 34 + slstatus/components/uptime.o | Bin 0 -> 2040 bytes slstatus/components/user.c | 33 + slstatus/components/user.o | Bin 0 -> 2256 bytes slstatus/components/volume.c | 219 + slstatus/components/volume.o | Bin 0 -> 3640 bytes slstatus/components/wifi.c | 267 + slstatus/components/wifi.o | Bin 0 -> 4392 bytes slstatus/config.def.h | 81 + slstatus/config.h | 74 + slstatus/config.mk | 22 + slstatus/slstatus | Bin 0 -> 31408 bytes slstatus/slstatus.1 | 47 + slstatus/slstatus.c | 134 + slstatus/slstatus.h | 84 + slstatus/slstatus.o | Bin 0 -> 6304 bytes slstatus/util.c | 141 + slstatus/util.h | 16 + slstatus/util.o | Bin 0 -> 5648 bytes sober/config.json | 24 + st/LEGACY | 17 + st/LICENSE | 34 + st/Makefile | 52 + st/README | 34 + st/TODO | 28 + st/arg.h | 50 + st/boxdraw.c | 194 + st/boxdraw_data.h | 214 + st/config.def.h | 517 ++ st/config.h | 336 + st/config.h.save | 486 ++ st/config.h.save.1 | 486 ++ st/config.h.save.2 | 486 ++ st/config.h.save.3 | 486 ++ st/config.mk | 38 + st/graphics.c | 3812 +++++++++ st/graphics.h | 107 + st/hb.c | 125 + st/hb.h | 14 + st/icat-mini.sh | 800 ++ st/khash.h | 627 ++ st/kvec.h | 90 + st/rowcolumn_diacritics_helpers.c | 391 + st/st-alpha-changealpha-20230519-b44f2ad.diff | 194 + st/st.1 | 177 + st/st.c | 2584 ++++++ st/st.core | Bin 0 -> 22913024 bytes st/st.h | 130 + st/st.info | 243 + st/win.h | 41 + st/x.c | 2319 ++++++ wmenu/.gitignore | 1 + wmenu/LICENSE | 32 + wmenu/README.md | 32 + wmenu/docs/meson.build | 26 + wmenu/docs/wmenu.1.scd | 186 + wmenu/menu.c | 692 ++ wmenu/menu.h | 95 + wmenu/meson.build | 80 + wmenu/pango.c | 71 + wmenu/pango.h | 16 + wmenu/pool-buffer.c | 146 + wmenu/pool-buffer.h | 26 + wmenu/protocols/meson.build | 47 + wmenu/protocols/wlr-layer-shell-unstable-v1.xml | 285 + wmenu/render.c | 212 + wmenu/render.h | 9 + wmenu/wayland.c | 510 ++ wmenu/wayland.h | 19 + wmenu/wmenu-run.c | 78 + wmenu/wmenu.c | 35 + 2027 files changed, 221388 insertions(+) create mode 100755 .Xresources create mode 100755 .bash.d/aliasrc create mode 100755 .bash.d/export create mode 100755 .bashrc create mode 100755 .emacs.d/init.el create mode 100755 .gitignore create mode 100755 .mpdconf create mode 100755 .ssh/config create mode 100644 .ssh/id_ed25519.pub create mode 100755 .vimrc create mode 100755 .wezterm.lua create mode 100755 .xinitrc create mode 100755 .zprofile create mode 100755 .zsh.d/zsh-autosuggestions.zsh create mode 100755 .zshrc create mode 100755 .zshrc.root create mode 100755 LICENSE create mode 100755 README.md create mode 100755 colorlist.palette create mode 100644 config/alacritty/alacritty.toml create mode 100755 config/bspwm/bspwmrc create mode 100755 config/btop/btop.conf create mode 100755 config/btop/themes/coasteen.theme create mode 100755 config/btop/themes/dracula.theme create mode 100755 config/btop/themes/gruvbox.theme create mode 100755 config/btop/themes/kyli0x.theme create mode 100755 config/dunst/dunst/dunstrc create mode 100755 config/dunst/dunstrc create mode 100755 config/dunst/dunstrc~ create mode 100755 config/eww/eww.scss create mode 100755 config/eww/eww.yuck create mode 100755 config/eww/eww_vars.yuck create mode 100755 config/eww/eww_widgets.yuck create mode 100755 config/eww/images/gif1.gif create mode 100755 config/eww/images/gif2.gif create mode 100755 config/eww/scripts/calendar.sh create mode 100755 config/eww/scripts/day_format.sh create mode 100755 config/eww/scripts/daytype.sh create mode 100755 config/eww/scripts/month_format.sh create mode 100755 config/eww/scripts/start.sh create mode 100755 config/eww/scripts/year_format.sh create mode 120000 config/foot/foot.ini create mode 100755 config/foot/foot.ini.home-backup create mode 100755 config/home-manager/README.md create mode 100755 config/home-manager/flake.lock create mode 100755 config/home-manager/flake.nix create mode 100755 config/home-manager/home.nix create mode 100644 config/hypr/hypridle.conf create mode 100755 config/hypr/hyprland.conf create mode 100644 config/hypr/hyprlock.conf create mode 100755 config/hypr/hyprpaper.conf create mode 120000 config/kitty/.#kitty.conf create mode 100755 config/kitty/kitty.conf create mode 100755 config/mako/.github/issue_template.md create mode 100755 config/mako/.github/pull_request_template.md create mode 100755 config/mako/config create mode 100755 config/micro/bindings.json create mode 100755 config/micro/buffers/history create mode 100755 config/micro/settings.json create mode 100755 config/mksymlink.conf create mode 100755 config/mutt/color.muttrc create mode 100755 config/mutt/muttrc create mode 100755 config/neofetch/config.conf create mode 100644 config/niri-2/config.kdl create mode 100755 config/niri/config.kdl create mode 100755 config/nushell/config.nu create mode 100755 config/nushell/starship.nu create mode 100755 config/nvim-1/init.lua create mode 100755 config/nvim-1/lazy-lock.json create mode 100755 config/nvim-1/lua/config.lua create mode 100755 config/nvim-1/lua/plugins/catppuccin/init.lua create mode 100755 config/nvim-1/lua/plugins/lazy/init.lua create mode 100755 config/nvim-1/lua/plugins/lazy/plugins.lua create mode 100755 config/nvim-1/lua/plugins/lsp/init.lua create mode 100755 config/nvim-1/lua/plugins/lualine/init.lua create mode 100755 config/nvim-1/lua/plugins/nvim-tree/init.lua create mode 100755 config/nvim-1/lua/plugins/render-markdown/init.lua create mode 100755 config/nvim-1/lua/plugins/telescope/init.lua create mode 100755 config/nvim-1/lua/plugins/treesitter/init.lua create mode 100755 config/nvim-1/lua/plugins/whichkey/init.lua create mode 100755 config/nvim-1/lua/status_line/init.lua create mode 100644 config/nvim-1/undo/%home%coast%.Xdefaults create mode 100644 config/nvim-1/undo/%home%coast%.config%Element%electron-config.json create mode 100644 config/nvim-1/undo/%home%coast%.config%alacritty%alacritty.toml create mode 100644 config/nvim-1/undo/%home%coast%.config%dunst%dunstrc create mode 100644 config/nvim-1/undo/%home%coast%.config%eww%_colors.scss create mode 100644 config/nvim-1/undo/%home%coast%.config%eww%eww.scss create mode 100644 config/nvim-1/undo/%home%coast%.config%eww%eww.yuck create mode 100644 config/nvim-1/undo/%home%coast%.config%eww%scripts%get-active-workspace.sh create mode 100644 config/nvim-1/undo/%home%coast%.config%eww%scripts%get-workspaces.sh create mode 100644 config/nvim-1/undo/%home%coast%.config%fht%compositor.toml create mode 100644 config/nvim-1/undo/%home%coast%.config%foot%foot.ini create mode 100644 config/nvim-1/undo/%home%coast%.config%hypr%hypridle.conf create mode 100644 config/nvim-1/undo/%home%coast%.config%hypr%hyprland.conf create mode 100644 config/nvim-1/undo/%home%coast%.config%hypr%hyprlock.conf create mode 100644 config/nvim-1/undo/%home%coast%.config%kwm%config.zon create mode 100644 config/nvim-1/undo/%home%coast%.config%mako%config create mode 100644 config/nvim-1/undo/%home%coast%.config%mozilla%firefox%8kysq72s.default-release%chrome%userChrome.css create mode 100644 config/nvim-1/undo/%home%coast%.config%neofetch%config.conf create mode 100644 config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%catppuccin%init.lua create mode 100644 config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%lazy%plugins.lua create mode 100644 config/nvim-1/undo/%home%coast%.config%picom%picom-animations.conf create mode 100644 config/nvim-1/undo/%home%coast%.config%picom%picom.conf create mode 100644 config/nvim-1/undo/%home%coast%.config%piss%pissrc create mode 100644 config/nvim-1/undo/%home%coast%.config%quickshell%clock.qml create mode 100644 config/nvim-1/undo/%home%coast%.config%quickshell%currentsong.qml create mode 100644 config/nvim-1/undo/%home%coast%.config%quickshell%separator.qml create mode 100644 config/nvim-1/undo/%home%coast%.config%quickshell%shell.qml create mode 100644 config/nvim-1/undo/%home%coast%.config%quickshell%workspaces.qml create mode 100644 config/nvim-1/undo/%home%coast%.config%river%init create mode 100644 config/nvim-1/undo/%home%coast%.config%rofi%config.rasi create mode 100644 config/nvim-1/undo/%home%coast%.config%scrobbler%config.ini create mode 100644 config/nvim-1/undo/%home%coast%.config%sway%config create mode 100644 config/nvim-1/undo/%home%coast%.config%tym%config.lua create mode 100644 config/nvim-1/undo/%home%coast%.config%tym%theme.lua create mode 100644 config/nvim-1/undo/%home%coast%.config%waybar%config.jsonc create mode 100644 config/nvim-1/undo/%home%coast%.config%waybar%style.css create mode 100644 config/nvim-1/undo/%home%coast%.curlrc create mode 100644 config/nvim-1/undo/%home%coast%.local%share%American Truck Simulator%config.cfg create mode 100644 config/nvim-1/undo/%home%coast%.local%share%applications%element-desktop.desktop create mode 100644 config/nvim-1/undo/%home%coast%.local%share%applications%firefox-bin.desktop create mode 100644 config/nvim-1/undo/%home%coast%.local%share%applications%im.riot.Riot.desktop create mode 100644 config/nvim-1/undo/%home%coast%.local%share%flatpak%app%im.riot.Riot%x86_64%stable%42f010911a82616b14d9f36a8341652b349552a67ba14b8e67fd432e18c37561%export%share%applications%im.riot.Riot.desktop create mode 100644 config/nvim-1/undo/%home%coast%.local%src%.git%COMMIT_EDITMSG create mode 100755 config/nvim-1/undo/%home%coast%.local%src%config%nvim%lua%config.lua create mode 100644 config/nvim-1/undo/%home%coast%.local%src%config%sway%config create mode 100755 config/nvim-1/undo/%home%coast%.local%src%config%waybar%config.jsonc create mode 100755 config/nvim-1/undo/%home%coast%.local%src%config%waybar%style.css create mode 100644 config/nvim-1/undo/%home%coast%.local%src%dmenu%config.h create mode 100644 config/nvim-1/undo/%home%coast%.local%src%dmenu%config.mk create mode 100644 config/nvim-1/undo/%home%coast%.local%src%dmenu%dmenu.c create mode 100644 config/nvim-1/undo/%home%coast%.local%src%dmenu%drw.c create mode 100644 config/nvim-1/undo/%home%coast%.local%src%dwm%config.h create mode 100644 config/nvim-1/undo/%home%coast%.local%src%dwm%config.mk create mode 100644 config/nvim-1/undo/%home%coast%.local%src%dwm%patches.h create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%mpc-shuf.sh create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%screenie-wlr create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%sober create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.start create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.stop create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver.sh create mode 100644 config/nvim-1/undo/%home%coast%.local%src%local%bin%upl create mode 100755 config/nvim-1/undo/%home%coast%.local%src%local%bin%uwuify.awk create mode 100644 config/nvim-1/undo/%home%coast%.local%src%slstatus%config.h create mode 100644 config/nvim-1/undo/%home%coast%.local%src%slstatus%config.mk create mode 100644 config/nvim-1/undo/%home%coast%.local%src%st%config.h create mode 100644 config/nvim-1/undo/%home%coast%.local%src%st%config.mk create mode 100644 config/nvim-1/undo/%home%coast%.mpdconf create mode 100644 config/nvim-1/undo/%home%coast%.rtorrent.rc create mode 100644 config/nvim-1/undo/%home%coast%.var%app%org.vinegarhq.Sober%config%sober%config.json create mode 100755 config/nvim-1/undo/%home%coast%.wezterm.lua create mode 100644 config/nvim-1/undo/%home%coast%.xinitrc create mode 100644 config/nvim-1/undo/%home%coast%.zprofile create mode 100644 config/nvim-1/undo/%home%coast%.zshrc create mode 100644 config/nvim-1/undo/%home%coast%Games%Red Dead Redemption 2%launch.sh create mode 100644 config/nvim-1/undo/%home%coast%NOTES create mode 100644 config/nvim-1/undo/%home%coast%Projects%X%term%term create mode 100644 config/nvim-1/undo/%home%coast%Projects%X%term%xterm.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%abcl%main.cl create mode 100644 config/nvim-1/undo/%home%coast%Projects%gtk%main.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%py%ashscrobble create mode 100644 config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%.git%COMMIT_EDITMSG create mode 100644 config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%LICENSE create mode 100644 config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%ashscrobble.py create mode 100644 config/nvim-1/undo/%home%coast%Projects%py%dmenu.lua create mode 100644 config/nvim-1/undo/%home%coast%Projects%py%dmenu.py create mode 100644 config/nvim-1/undo/%home%coast%Projects%pylua%dmenu.lua create mode 100644 config/nvim-1/undo/%home%coast%Projects%river%kwm%config.def.zon create mode 100644 config/nvim-1/undo/%home%coast%Projects%river%river%build.zig.zon create mode 100755 config/nvim-1/undo/%home%coast%Projects%rs%guessing_game%.gitignore create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%config.h create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%main.py create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%window.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlbar%main.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.git%COMMIT_EDITMSG create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.gitignore create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%config.h create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%main.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%makefile create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlclock.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wled%.git%COMMIT_EDITMSG create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wled%.gitignore create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wled%LICENSE create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wled%README create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wled%build.sh create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wled%client.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wled%config.h create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%wlindow%client.c create mode 100644 config/nvim-1/undo/%home%coast%Projects%wayland%x11alt.c create mode 100644 config/nvim-1/undo/%home%coast%ashos%linux%.config create mode 100644 config/nvim-1/undo/%home%coast%ashos%syslinux.cfg create mode 100644 config/nvim-1/undo/%home%coast%conduwuit create mode 100644 config/nvim-1/undo/%home%coast%driver%driver.c create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%.git%COMMIT_EDITMSG create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%.gitignore create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%Makefile create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%build.sh create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%makefile create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%compositor.c create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%config.h create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%include%compositor.h create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%include%keybinds.h create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%include%screenshot.h create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.c create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.h create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%screenshot.c create mode 100644 config/nvim-1/undo/%home%coast%git%compositor%src%util.c create mode 100644 config/nvim-1/undo/%home%coast%git%hst%config.h create mode 100644 config/nvim-1/undo/%home%coast%git%neuswc%config.mk create mode 100644 config/nvim-1/undo/%home%coast%git%neuswc%libswc%compositor.h create mode 100644 config/nvim-1/undo/%home%coast%git%neuswc%libswc%output.h create mode 100644 config/nvim-1/undo/%home%coast%git%neuswc%libswc%pointer.h create mode 100644 config/nvim-1/undo/%home%coast%git%neuswc%libswc%util.h create mode 100644 config/nvim-1/undo/%home%coast%git%neuwld%config.mk create mode 100644 config/nvim-1/undo/%home%coast%git%swc%config.mk create mode 100644 config/nvim-1/undo/%home%coast%git%swcshot%main.c create mode 100644 config/nvim-1/undo/%home%coast%git%terminal%Makefile create mode 100644 config/nvim-1/undo/%home%coast%git%terminal%main.c create mode 100644 config/nvim-1/undo/%home%coast%git%wld%config.mk create mode 100644 config/nvim-1/undo/%home%coast%git%wsxwm%Makefile create mode 100644 config/nvim-1/undo/%home%coast%git%wsxwm%source%include%wsxwm.h create mode 100644 config/nvim-1/undo/%home%coast%git%wsxwm%source%test.diff create mode 100644 config/nvim-1/undo/%home%coast%git%wsxwm%source%wsxwm.c create mode 100644 config/nvim-1/undo/%home%coast%hwfetch create mode 100644 config/nvim-1/undo/%home%coast%main.bash create mode 100644 config/nvim-1/undo/%home%coast%main.c create mode 100644 config/nvim-1/undo/%home%coast%main.lua create mode 100644 config/nvim-1/undo/%home%coast%royal create mode 100644 config/nvim-1/undo/%home%coast%shared%loader.c create mode 100644 config/nvim-1/undo/%home%coast%shared%shared.c create mode 100644 config/nvim-1/undo/%home%coast%test.py create mode 160000 config/nvim-2/graft create mode 100644 config/nvim-2/init.vim create mode 100644 config/nvim-2/nvim/init.vim create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/LuaSnip create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/cmp-buffer create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/cmp-nvim-lsp create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/nvim-autopairs create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/nvim-cmp create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/nvim-lspconfig create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-closetag create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-commentary create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-endwise create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-fugitive create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-polyglot create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-sensible create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-surround create mode 160000 config/nvim-2/nvim/pack-bak/graft/start/vim-vinegar create mode 160000 config/nvim-2/nvim/pack/scion/start/LuaSnip create mode 160000 config/nvim-2/nvim/pack/scion/start/cmp-buffer create mode 160000 config/nvim-2/nvim/pack/scion/start/cmp-nvim-lsp create mode 160000 config/nvim-2/nvim/pack/scion/start/nvim-autopairs create mode 160000 config/nvim-2/nvim/pack/scion/start/nvim-cmp create mode 160000 config/nvim-2/nvim/pack/scion/start/nvim-colorizer.lua create mode 160000 config/nvim-2/nvim/pack/scion/start/nvim-lspconfig create mode 160000 config/nvim-2/nvim/pack/scion/start/nvim-treesitter create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-closetag create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-commentary create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-endwise create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-fugitive create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-polyglot create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-sensible create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-surround create mode 160000 config/nvim-2/nvim/pack/scion/start/vim-vinegar create mode 160000 config/nvim-2/nvim/scion create mode 100644 config/nvim-2/nvim/scion_state.json create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%alacritty%alacritty.toml create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%fastfetch%config.jsonc create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%niri%config.kdl create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%graft%config.rb create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%init.vim create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%key.vim create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%config.rb create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%scion.rb create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%test.sh create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lsp.vim create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lua.vim create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%scp.vim create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%theme.vim create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%rofi%config.rasi create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%starship.toml create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%systemd%user%.#plasma-polkit-agent.servicec252b1882abfd1a3 create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%waybar%config.jsonc create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%waybar%style.css create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%waybar%window.sh create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%prismlauncher.desktop create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%throne.desktop create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.zsh.d%zsh-syntaxhighlighting.zsh create mode 100644 config/nvim-2/nvim/undodir/%home%coast%.zshrc create mode 100644 config/nvim-2/nvim/undodir/%home%coast%DEVLIST create mode 100644 config/nvim-2/nvim/undodir/%home%coast%Downloads%snispoof%config.json create mode 100644 config/nvim-2/nvim/undodir/%home%coast%PRISMLAUNCHER%instances%26.1.2%minecraft%config%DistantHorizons.toml create mode 100644 config/nvim-2/nvim/undodir/%home%coast%Xray%config.json create mode 100644 config/nvim-2/nvim/undodir/%home%coast%bash.sh create mode 100644 config/nvim-2/nvim/undodir/%home%coast%copyparty-setup.py create mode 100644 config/nvim-2/nvim/undodir/%home%coast%dlhub%goodlinks.txt create mode 100644 config/nvim-2/nvim/undodir/%home%coast%dlhub%script.py create mode 100644 config/nvim-2/nvim/undodir/%home%coast%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%mhr-cfw%config.json create mode 100644 config/nvim-2/nvim/undodir/%home%coast%pertree create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%LICENSE create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%README.md create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%makefile create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%pissrc.example.lua create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%src%chd.1 create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%src%daemon.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%piss%src%piss.1 create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.gitignore create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%README create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%makefile create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%src%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.gitignore create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%LICENSE create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%README create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%src%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%makefile create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%rand create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%input.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%cterm%cterm.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.gitignore create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%build.sh create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile-opt create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%template-opt.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%main.c create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%makefile create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.frag create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.vert create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%eul-license%v1 create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%README.md create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README.md create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%Rakefile create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%config.rb create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%scion.rb create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%config.rb create mode 100644 config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%main.rb create mode 100644 config/nvim-2/nvim/undodir/%home%coast%shit.sh create mode 100644 config/nvim-2/nvim/undodir/%mnt%Home%dotfiles%.gitignore create mode 100644 config/nvim-2/nvim/vscript/key.vim create mode 100644 config/nvim-2/nvim/vscript/lua.vim create mode 100644 config/nvim-2/nvim/vscript/scp.vim create mode 100644 config/nvim-2/nvim/vscript/theme.vim create mode 160000 config/nvim-2/pack-bak/graft/start/LuaSnip create mode 160000 config/nvim-2/pack-bak/graft/start/cmp-buffer create mode 160000 config/nvim-2/pack-bak/graft/start/cmp-nvim-lsp create mode 160000 config/nvim-2/pack-bak/graft/start/nvim-autopairs create mode 160000 config/nvim-2/pack-bak/graft/start/nvim-cmp create mode 160000 config/nvim-2/pack-bak/graft/start/nvim-lspconfig create mode 160000 config/nvim-2/pack-bak/graft/start/vim-closetag create mode 160000 config/nvim-2/pack-bak/graft/start/vim-commentary create mode 160000 config/nvim-2/pack-bak/graft/start/vim-endwise create mode 160000 config/nvim-2/pack-bak/graft/start/vim-fugitive create mode 160000 config/nvim-2/pack-bak/graft/start/vim-polyglot create mode 160000 config/nvim-2/pack-bak/graft/start/vim-sensible create mode 160000 config/nvim-2/pack-bak/graft/start/vim-surround create mode 160000 config/nvim-2/pack-bak/graft/start/vim-vinegar create mode 160000 config/nvim-2/scion create mode 100644 config/nvim-2/scion_state.json create mode 100644 config/nvim-2/undodir/%home%coast%.config%alacritty%alacritty.toml create mode 100644 config/nvim-2/undodir/%home%coast%.config%fastfetch%config.jsonc create mode 100644 config/nvim-2/undodir/%home%coast%.config%niri%config.kdl create mode 100644 config/nvim-2/undodir/%home%coast%.config%nvim%graft%config.rb create mode 100644 config/nvim-2/undodir/%home%coast%.config%nvim%init.vim create mode 100644 config/nvim-2/undodir/%home%coast%.config%nvim%key.vim create mode 100644 config/nvim-2/undodir/%home%coast%.config%nvim%test.sh create mode 100644 config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lsp.vim create mode 100644 config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lua.vim create mode 100644 config/nvim-2/undodir/%home%coast%.config%nvim%vscript%scp.vim create mode 100644 config/nvim-2/undodir/%home%coast%.config%waybar%config.jsonc create mode 100644 config/nvim-2/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf create mode 100644 config/nvim-2/undodir/%home%coast%.zshrc create mode 100644 config/nvim-2/undodir/%home%coast%DEVLIST create mode 100644 config/nvim-2/undodir/%home%coast%main.c create mode 100644 config/nvim-2/undodir/%home%coast%pertree create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%catter%.gitignore create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%catter%README create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%catter%main.c create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%catter%makefile create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%catter%src%main.c create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%makefile-opt create mode 100644 config/nvim-2/undodir/%home%coast%projects%c%template-opt.c create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README.md create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%Rakefile create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%config.rb create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%scion.rb create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%config.rb create mode 100644 config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%main.rb create mode 100644 config/nvim-2/vscript/key.vim create mode 100644 config/nvim-2/vscript/lua.vim create mode 100644 config/nvim-2/vscript/scp.vim create mode 100755 config/nvim-root/init.lua create mode 100755 config/picom/picom-animations.conf create mode 100755 config/picom/picom.conf create mode 100755 config/piss/pissrc create mode 100755 config/plugged/plug.vim create mode 100755 config/plugin/config.vim create mode 100755 config/qtile/config.py create mode 100755 config/qutebrowser/autoconfig.yml create mode 100755 config/qutebrowser/bookmarks/urls create mode 100755 config/qutebrowser/config.py create mode 100755 config/qutebrowser/greasemonkey/yt-ads.js create mode 100755 config/qutebrowser/quickmarks create mode 100755 config/rofi/config.rasi create mode 100755 config/rofi/gruvbox.rasi create mode 100755 config/rofi/rofi/config.rasi create mode 100755 config/shell/aliases create mode 100755 config/shell/exports create mode 100755 config/shell/shell/aliases create mode 100755 config/shell/shell/aliases.backup create mode 100755 config/shell/shell/exports create mode 100755 config/shell/shell/exports.backup create mode 100755 config/starship.toml create mode 100755 config/sway/config create mode 100755 config/sxhkd/sxhkdrc create mode 100755 config/systemd/emacsd.service create mode 100755 config/tmux/tmux.conf create mode 100644 config/waybar-2/config.jsonc create mode 100644 config/waybar-2/style.css create mode 100755 config/waybar-2/waybar/config.jsonc create mode 100755 config/waybar-2/waybar/style.css create mode 100755 config/waybar-2/waybar/window.sh create mode 100755 config/waybar/config.jsonc create mode 100755 config/waybar/style.css create mode 100755 config/wofi/config create mode 100755 config/wofi/style.css create mode 100755 config/xmobar/xmobarrc create mode 100755 config/xmonad/xmonad.hs create mode 160000 dmenu create mode 100755 dwl/.gitea/issue_template/bug_report.yml create mode 100755 dwl/.gitea/issue_template/enhancement-idea.yml create mode 100755 dwl/.gitignore create mode 100755 dwl/.mailmap create mode 100755 dwl/CHANGELOG.md create mode 100755 dwl/LICENSE create mode 100755 dwl/LICENSE.dwm create mode 100755 dwl/LICENSE.sway create mode 100755 dwl/LICENSE.tinywl create mode 100755 dwl/Makefile create mode 100755 dwl/README.md create mode 100755 dwl/client.h create mode 100755 dwl/config.def.h create mode 100755 dwl/config.def.h.orig create mode 100755 dwl/config.mk create mode 100755 dwl/drwl.h create mode 100755 dwl/dwl-patches/LICENSE create mode 100755 dwl/dwl-patches/LICENSE.dwm create mode 100755 dwl/dwl-patches/LICENSE.sway create mode 100755 dwl/dwl-patches/LICENSE.tinywl create mode 100755 dwl/dwl-patches/README.md create mode 100755 dwl/dwl-patches/patches/accessnthmon/README.md create mode 100755 dwl/dwl-patches/patches/accessnthmon/accessnthmon.patch create mode 100755 dwl/dwl-patches/patches/alwayscenter/README.md create mode 100755 dwl/dwl-patches/patches/alwayscenter/alwayscenter.patch create mode 100755 dwl/dwl-patches/patches/attachbottom/README.md create mode 100755 dwl/dwl-patches/patches/attachbottom/attachbottom.patch create mode 100755 dwl/dwl-patches/patches/attachfocused/README.md create mode 100755 dwl/dwl-patches/patches/attachfocused/attachfocused.patch create mode 100755 dwl/dwl-patches/patches/attachtop/README.md create mode 100755 dwl/dwl-patches/patches/attachtop/attachtop.patch create mode 100755 dwl/dwl-patches/patches/autostart/README.md create mode 100755 dwl/dwl-patches/patches/autostart/autostart-0.7.patch create mode 100755 dwl/dwl-patches/patches/autostart/autostart.patch create mode 100755 dwl/dwl-patches/patches/bar-systray/README.md create mode 100755 dwl/dwl-patches/patches/bar-systray/bar-systray-0.7.patch create mode 100755 dwl/dwl-patches/patches/bar/README.md create mode 100755 dwl/dwl-patches/patches/bar/bar-0.6.patch create mode 100755 dwl/dwl-patches/patches/bar/bar-0.7.patch create mode 100755 dwl/dwl-patches/patches/bar/bar.patch create mode 100755 dwl/dwl-patches/patches/bar/bar.png create mode 100755 dwl/dwl-patches/patches/barborder/README.md create mode 100755 dwl/dwl-patches/patches/barborder/barborder.patch create mode 100755 dwl/dwl-patches/patches/barcolors/README.md create mode 100755 dwl/dwl-patches/patches/barcolors/barcolors.patch create mode 100755 dwl/dwl-patches/patches/barpadding/README.md create mode 100755 dwl/dwl-patches/patches/barpadding/barpadding.patch create mode 100755 dwl/dwl-patches/patches/bartruecenteredtitle/README.md create mode 100755 dwl/dwl-patches/patches/bartruecenteredtitle/bartruecenteredtitle.patch create mode 100755 dwl/dwl-patches/patches/bartruecenteredtitle/centeredtitle.webp create mode 100755 dwl/dwl-patches/patches/better-resize/README.md create mode 100755 dwl/dwl-patches/patches/better-resize/better-resize-0.7.patch create mode 100755 dwl/dwl-patches/patches/borders/README.md create mode 100755 dwl/dwl-patches/patches/borders/borders.patch create mode 100755 dwl/dwl-patches/patches/bottomstack/README.md create mode 100755 dwl/dwl-patches/patches/bottomstack/bottomstack.patch create mode 100755 dwl/dwl-patches/patches/btrtile/README.md create mode 100755 dwl/dwl-patches/patches/btrtile/btrtile-v0.7-gaps.patch create mode 100755 dwl/dwl-patches/patches/btrtile/btrtile-v0.7.patch create mode 100755 dwl/dwl-patches/patches/buttonbystate/README.md create mode 100755 dwl/dwl-patches/patches/buttonbystate/buttonbystate.patch create mode 100755 dwl/dwl-patches/patches/center-terminal/README.md create mode 100755 dwl/dwl-patches/patches/center-terminal/center-terminal.patch create mode 100755 dwl/dwl-patches/patches/centeredmaster/README.md create mode 100755 dwl/dwl-patches/patches/centeredmaster/centeredmaster.patch create mode 100755 dwl/dwl-patches/patches/cfact-snail/README.md create mode 100755 dwl/dwl-patches/patches/cfact-snail/cfact-snail.patch create mode 100755 dwl/dwl-patches/patches/cfact/README.md create mode 100755 dwl/dwl-patches/patches/cfact/cfact-v0.6.patch create mode 100755 dwl/dwl-patches/patches/cfact/cfact-v0.7-gaps.patch create mode 100755 dwl/dwl-patches/patches/cfact/cfact-v0.7.patch create mode 100755 dwl/dwl-patches/patches/cfact/cfact.patch create mode 100755 dwl/dwl-patches/patches/chainkeys/README.md create mode 100755 dwl/dwl-patches/patches/chainkeys/chainkeys.patch create mode 100755 dwl/dwl-patches/patches/client-opacity/README.md create mode 100755 dwl/dwl-patches/patches/client-opacity/client-opacity.patch create mode 100755 dwl/dwl-patches/patches/column/README.md create mode 100755 dwl/dwl-patches/patches/column/column.patch create mode 100755 dwl/dwl-patches/patches/coredump/README.md create mode 100755 dwl/dwl-patches/patches/coredump/coredump-0.7.patch create mode 100755 dwl/dwl-patches/patches/coredump/coredump.patch create mode 100755 dwl/dwl-patches/patches/cursortheme/README.md create mode 100755 dwl/dwl-patches/patches/cursortheme/cursortheme.patch create mode 100755 dwl/dwl-patches/patches/customfloat/README.md create mode 100755 dwl/dwl-patches/patches/customfloat/customfloat.patch create mode 100755 dwl/dwl-patches/patches/dim-unfocused/README.md create mode 100755 dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20230516.patch create mode 100755 dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240416.patch create mode 100755 dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240714.patch create mode 100755 dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240903.patch create mode 100755 dwl/dwl-patches/patches/dim-unfocused/dim-unfocused.patch create mode 100755 dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/README.md create mode 100755 dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/disable-keybindings-on-fullscreen-toggle-0.7.patch create mode 100755 dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/README.md create mode 100755 dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/disable-keybindings-on-fullscreen.patch create mode 100755 dwl/dwl-patches/patches/dragmfact/README.md create mode 100755 dwl/dwl-patches/patches/dragmfact/dragmfact-v0.6.patch create mode 100755 dwl/dwl-patches/patches/dragmfact/dragmfact-v0.7.patch create mode 100755 dwl/dwl-patches/patches/dragmfact/dragmfact.patch create mode 100755 dwl/dwl-patches/patches/dragresize/README.md create mode 100755 dwl/dwl-patches/patches/dragresize/dragresize.patch create mode 100755 dwl/dwl-patches/patches/en-keycodes/README.md create mode 100755 dwl/dwl-patches/patches/en-keycodes/en-keycodes.patch create mode 100755 dwl/dwl-patches/patches/envcfg/README.md create mode 100755 dwl/dwl-patches/patches/envcfg/envcfg.patch create mode 100755 dwl/dwl-patches/patches/fakefullscreenclient/README.md create mode 100755 dwl/dwl-patches/patches/fakefullscreenclient/fakefullscreenclient.patch create mode 100755 dwl/dwl-patches/patches/fallback/README.md create mode 100755 dwl/dwl-patches/patches/fallback/fallback.patch create mode 100755 dwl/dwl-patches/patches/focusdir/README.md create mode 100755 dwl/dwl-patches/patches/focusdir/focusdir.patch create mode 100755 dwl/dwl-patches/patches/follow/README.md create mode 100755 dwl/dwl-patches/patches/follow/follow.patch create mode 100755 dwl/dwl-patches/patches/follow/follow.webp create mode 100755 dwl/dwl-patches/patches/foreign-toplevel-management/README.md create mode 100755 dwl/dwl-patches/patches/foreign-toplevel-management/foreign-toplevel-management.patch create mode 100755 dwl/dwl-patches/patches/fullscreenadaptivesync/README.md create mode 100755 dwl/dwl-patches/patches/fullscreenadaptivesync/fullscreenadaptivesync-v0.7.patch create mode 100755 dwl/dwl-patches/patches/gaplessgrid/README.md create mode 100755 dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20230801.patch create mode 100755 dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20240714.patch create mode 100755 dwl/dwl-patches/patches/gaplessgrid/gaplessgrid.patch create mode 100755 dwl/dwl-patches/patches/gaps/README.md create mode 100755 dwl/dwl-patches/patches/gaps/gaps.patch create mode 100755 dwl/dwl-patches/patches/genericgaps/README.md create mode 100755 dwl/dwl-patches/patches/genericgaps/genericgaps-0.7.patch create mode 100755 dwl/dwl-patches/patches/genericgaps/genericgaps.patch create mode 100755 dwl/dwl-patches/patches/gestures/README.md create mode 100755 dwl/dwl-patches/patches/gestures/gestures.patch create mode 100755 dwl/dwl-patches/patches/globalkey/README.md create mode 100755 dwl/dwl-patches/patches/globalkey/globalkey.patch create mode 100755 dwl/dwl-patches/patches/headless/README.md create mode 100755 dwl/dwl-patches/patches/headless/headless.patch create mode 100755 dwl/dwl-patches/patches/hide-behind-fullscreen/README.md create mode 100755 dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen-0.7.patch create mode 100755 dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen.patch create mode 100755 dwl/dwl-patches/patches/hide-behind-monocle/README.md create mode 100755 dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle-0.7.patch create mode 100755 dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle.patch create mode 100755 dwl/dwl-patches/patches/hide_vacant_tags/README.md create mode 100755 dwl/dwl-patches/patches/hide_vacant_tags/hide_vacant_tags.patch create mode 100755 dwl/dwl-patches/patches/hiderule/README.md create mode 100755 dwl/dwl-patches/patches/hiderule/hiderule.patch create mode 100755 dwl/dwl-patches/patches/hot-reload/README.md create mode 100755 dwl/dwl-patches/patches/hot-reload/hot-reload-0.7.patch create mode 100755 dwl/dwl-patches/patches/hot-reload/hot-reload.patch create mode 100755 dwl/dwl-patches/patches/inputdevicerules/README.md create mode 100755 dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.6.patch create mode 100755 dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.7.patch create mode 100755 dwl/dwl-patches/patches/ipc/README.md create mode 100755 dwl/dwl-patches/patches/ipc/focus-tagset-output.patch create mode 100755 dwl/dwl-patches/patches/ipc/ipc.patch create mode 100755 dwl/dwl-patches/patches/ipc/ipcpertag.patch create mode 100755 dwl/dwl-patches/patches/kblayout/README.md create mode 100755 dwl/dwl-patches/patches/kblayout/kblayout.patch create mode 100755 dwl/dwl-patches/patches/keyboardshortcutsinhibit/README.md create mode 100755 dwl/dwl-patches/patches/keyboardshortcutsinhibit/keyboardshortcutsinhibit.patch create mode 100755 dwl/dwl-patches/patches/keycodes/README.md create mode 100755 dwl/dwl-patches/patches/keycodes/keycodes-0.7.patch create mode 100755 dwl/dwl-patches/patches/keycodes/keycodes.patch create mode 100755 dwl/dwl-patches/patches/launchtag/README.md create mode 100755 dwl/dwl-patches/patches/launchtag/launchtag.patch create mode 100755 dwl/dwl-patches/patches/limitnmaster/README.md create mode 100755 dwl/dwl-patches/patches/limitnmaster/limitnmaster.patch create mode 100755 dwl/dwl-patches/patches/lockedkeys/README.md create mode 100755 dwl/dwl-patches/patches/lockedkeys/lockedkeys.patch create mode 100755 dwl/dwl-patches/patches/mastercolumn/README.md create mode 100755 dwl/dwl-patches/patches/mastercolumn/mastercolumn-gaps.patch create mode 100755 dwl/dwl-patches/patches/mastercolumn/mastercolumn.patch create mode 100755 dwl/dwl-patches/patches/menu/README.md create mode 100755 dwl/dwl-patches/patches/menu/menu.patch create mode 100755 dwl/dwl-patches/patches/menurule/README.md create mode 100755 dwl/dwl-patches/patches/menurule/menurule.patch create mode 100755 dwl/dwl-patches/patches/menurule/menurule.png create mode 100755 dwl/dwl-patches/patches/meson/README.md create mode 100755 dwl/dwl-patches/patches/meson/meson.patch create mode 100755 dwl/dwl-patches/patches/minimalborders/README.md create mode 100755 dwl/dwl-patches/patches/minimalborders/minimalborders.patch create mode 100755 dwl/dwl-patches/patches/modes/README.md create mode 100755 dwl/dwl-patches/patches/modes/modes.patch create mode 100755 dwl/dwl-patches/patches/monitorconfig/README.md create mode 100755 dwl/dwl-patches/patches/monitorconfig/monitorconfig.patch create mode 100755 dwl/dwl-patches/patches/mouse-trackpad-split/README.md create mode 100755 dwl/dwl-patches/patches/mouse-trackpad-split/mouse-trackpad-split-0.7.patch create mode 100755 dwl/dwl-patches/patches/movecenter/README.md create mode 100755 dwl/dwl-patches/patches/movecenter/movecenter.patch create mode 100755 dwl/dwl-patches/patches/moveresizekb/README.md create mode 100755 dwl/dwl-patches/patches/moveresizekb/moveresizekb.patch create mode 100755 dwl/dwl-patches/patches/movestack/README.md create mode 100755 dwl/dwl-patches/patches/movestack/movestack.patch create mode 100755 dwl/dwl-patches/patches/namedscratchpads/README.md create mode 100755 dwl/dwl-patches/patches/namedscratchpads/namedscratchpads.patch create mode 100755 dwl/dwl-patches/patches/nextlayout/README.md create mode 100755 dwl/dwl-patches/patches/nextlayout/nextlayout.patch create mode 100755 dwl/dwl-patches/patches/numlock-capslock/README.md create mode 100755 dwl/dwl-patches/patches/numlock-capslock/numlock-capslock-0.7.patch create mode 100755 dwl/dwl-patches/patches/numlock-capslock/numlock-capslock.patch create mode 100755 dwl/dwl-patches/patches/passthrough/README.md create mode 100755 dwl/dwl-patches/patches/passthrough/passthrough.patch create mode 100755 dwl/dwl-patches/patches/perinputconfig/README.md create mode 100755 dwl/dwl-patches/patches/perinputconfig/perinputconfig-v0.5.patch create mode 100755 dwl/dwl-patches/patches/perinputconfig/perinputconfig.patch create mode 100755 dwl/dwl-patches/patches/pertag/README.md create mode 100755 dwl/dwl-patches/patches/pertag/pertag.patch create mode 100755 dwl/dwl-patches/patches/pointer-gestures-unstable-v1/README.md create mode 100755 dwl/dwl-patches/patches/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch create mode 100755 dwl/dwl-patches/patches/primaryselection/README.md create mode 100755 dwl/dwl-patches/patches/primaryselection/primaryselection.patch create mode 100755 dwl/dwl-patches/patches/push/README.md create mode 100755 dwl/dwl-patches/patches/push/push-0.7.patch create mode 100755 dwl/dwl-patches/patches/push/push.patch create mode 100755 dwl/dwl-patches/patches/regexrules/README.md create mode 100755 dwl/dwl-patches/patches/regexrules/regexrules.patch create mode 100755 dwl/dwl-patches/patches/regions/README.md create mode 100755 dwl/dwl-patches/patches/regions/regions.patch create mode 100755 dwl/dwl-patches/patches/relative-mouse-resize/README.md create mode 100755 dwl/dwl-patches/patches/relative-mouse-resize/relative-mouse-resize.patch create mode 100755 dwl/dwl-patches/patches/restore-monitor/README.md create mode 100755 dwl/dwl-patches/patches/restore-monitor/restore-monitor.patch create mode 100755 dwl/dwl-patches/patches/right/README.md create mode 100755 dwl/dwl-patches/patches/right/right.patch create mode 100755 dwl/dwl-patches/patches/rlimit_max/README.md create mode 100755 dwl/dwl-patches/patches/rlimit_max/rlimit_max.patch create mode 100755 dwl/dwl-patches/patches/rotate-clients/README.md create mode 100755 dwl/dwl-patches/patches/rotate-clients/rotate-clients.patch create mode 100755 dwl/dwl-patches/patches/rotatetags/README.md create mode 100755 dwl/dwl-patches/patches/rotatetags/rotatetags.patch create mode 100755 dwl/dwl-patches/patches/scenefx/README.md create mode 100755 dwl/dwl-patches/patches/scenefx/scenefx.patch create mode 100755 dwl/dwl-patches/patches/setrule/README.md create mode 100755 dwl/dwl-patches/patches/setrule/setrule.patch create mode 100755 dwl/dwl-patches/patches/setupenv/README.md create mode 100755 dwl/dwl-patches/patches/setupenv/setupenv.patch create mode 100755 dwl/dwl-patches/patches/shiftview/README.md create mode 100755 dwl/dwl-patches/patches/shiftview/shiftview.patch create mode 100755 dwl/dwl-patches/patches/simple_scratchpad/README.md create mode 100755 dwl/dwl-patches/patches/simple_scratchpad/simple_scratchpad-v0.7.patch create mode 100755 dwl/dwl-patches/patches/simpleborders/README.md create mode 100755 dwl/dwl-patches/patches/simpleborders/simpleborders-v0.6.patch create mode 100755 dwl/dwl-patches/patches/simpleborders/simpleborders-v0.7.patch create mode 100755 dwl/dwl-patches/patches/singlemaster/README.md create mode 100755 dwl/dwl-patches/patches/singlemaster/singlemaster.patch create mode 100755 dwl/dwl-patches/patches/singletagset-pertag/README.md create mode 100755 dwl/dwl-patches/patches/singletagset-pertag/singletagset-pertag.patch create mode 100755 dwl/dwl-patches/patches/singletagset-sticky/README.md create mode 100755 dwl/dwl-patches/patches/singletagset-sticky/singletagset-sticky.patch create mode 100755 dwl/dwl-patches/patches/singletagset/README.md create mode 100755 dwl/dwl-patches/patches/singletagset/singletagset-v0.6.patch create mode 100755 dwl/dwl-patches/patches/singletagset/singletagset-v0.7.patch create mode 100755 dwl/dwl-patches/patches/skipfocus/README.md create mode 100755 dwl/dwl-patches/patches/skipfocus/skipfocus-20240714.patch create mode 100755 dwl/dwl-patches/patches/skipfocus/skipfocus.patch create mode 100755 dwl/dwl-patches/patches/skipfocus/skipfocus20240108.patch create mode 100755 dwl/dwl-patches/patches/smartborders/README.md create mode 100755 dwl/dwl-patches/patches/smartborders/smartborders-0.7.patch create mode 100755 dwl/dwl-patches/patches/smartborders/smartborders.patch create mode 100755 dwl/dwl-patches/patches/snail-gaps/README.md create mode 100755 dwl/dwl-patches/patches/snail-gaps/snail-gaps.patch create mode 100755 dwl/dwl-patches/patches/snail/README.md create mode 100755 dwl/dwl-patches/patches/snail/snail.patch create mode 100755 dwl/dwl-patches/patches/spawninfo/README.md create mode 100755 dwl/dwl-patches/patches/spawninfo/pamixerc create mode 100755 dwl/dwl-patches/patches/spawninfo/screenshotwin create mode 100755 dwl/dwl-patches/patches/spawninfo/spawninfo.patch create mode 100755 dwl/dwl-patches/patches/stacker/README.md create mode 100755 dwl/dwl-patches/patches/stacker/stacker.patch create mode 100755 dwl/dwl-patches/patches/stairs/README.md create mode 100755 dwl/dwl-patches/patches/stairs/stairs.patch create mode 100755 dwl/dwl-patches/patches/startargv/README.md create mode 100755 dwl/dwl-patches/patches/startargv/startargv.patch create mode 100755 dwl/dwl-patches/patches/sticky/README.md create mode 100755 dwl/dwl-patches/patches/sticky/sticky.patch create mode 100755 dwl/dwl-patches/patches/swallow/README.md create mode 100755 dwl/dwl-patches/patches/swallow/swallow-freebsd.patch create mode 100755 dwl/dwl-patches/patches/swallow/swallow.patch create mode 100755 dwl/dwl-patches/patches/swapandfocusdir/README.md create mode 100755 dwl/dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch create mode 100755 dwl/dwl-patches/patches/switchtotag/README.md create mode 100755 dwl/dwl-patches/patches/switchtotag/switchtotag.patch create mode 100755 dwl/dwl-patches/patches/systemd/README.md create mode 100755 dwl/dwl-patches/patches/systemd/systemd-0.7.patch create mode 100755 dwl/dwl-patches/patches/tab/README.md create mode 100755 dwl/dwl-patches/patches/tab/tab-0.7-bar.patch create mode 100755 dwl/dwl-patches/patches/tab/tab-0.7.patch create mode 100755 dwl/dwl-patches/patches/tab/tab.patch create mode 100755 dwl/dwl-patches/patches/tablet-input/README.md create mode 100755 dwl/dwl-patches/patches/tablet-input/tablet-input-0.7.patch create mode 100755 dwl/dwl-patches/patches/tablet-input/tablet-input.patch create mode 100755 dwl/dwl-patches/patches/tagshift/README.md create mode 100755 dwl/dwl-patches/patches/tagshift/tagshift.patch create mode 100755 dwl/dwl-patches/patches/tearing/README.md create mode 100755 dwl/dwl-patches/patches/tearing/tearing.patch create mode 100755 dwl/dwl-patches/patches/titleurgent/README.md create mode 100755 dwl/dwl-patches/patches/titleurgent/titleurgent.patch create mode 100755 dwl/dwl-patches/patches/tmux-borders/README.md create mode 100755 dwl/dwl-patches/patches/tmux-borders/screenshot1.png create mode 100755 dwl/dwl-patches/patches/tmux-borders/screenshot2.png create mode 100755 dwl/dwl-patches/patches/tmux-borders/tmux-borders-0.7.patch create mode 100755 dwl/dwl-patches/patches/toggle_constraints/README.md create mode 100755 dwl/dwl-patches/patches/toggle_constraints/toggle_constraints.patch create mode 100755 dwl/dwl-patches/patches/togglekblayoutandoptions/README.md create mode 100755 dwl/dwl-patches/patches/togglekblayoutandoptions/togglekblayoutandoptions.patch create mode 100755 dwl/dwl-patches/patches/touch-input/README.md create mode 100755 dwl/dwl-patches/patches/touch-input/touch-input.patch create mode 100755 dwl/dwl-patches/patches/unclutter/README.md create mode 100755 dwl/dwl-patches/patches/unclutter/unclutter.patch create mode 100755 dwl/dwl-patches/patches/ungroup-keyboards/README.md create mode 100755 dwl/dwl-patches/patches/ungroup-keyboards/ungroup-keyboards.patch create mode 100755 dwl/dwl-patches/patches/vanitygaps/README.md create mode 100755 dwl/dwl-patches/patches/vanitygaps/vanitygaps-0.7.patch create mode 100755 dwl/dwl-patches/patches/vanitygaps/vanitygaps.patch create mode 100755 dwl/dwl-patches/patches/varcol/README.md create mode 100755 dwl/dwl-patches/patches/varcol/varcol.patch create mode 100755 dwl/dwl-patches/patches/viewnextocctag/README.md create mode 100755 dwl/dwl-patches/patches/viewnextocctag/viewnextocctag.patch create mode 100755 dwl/dwl-patches/patches/virtual-pointer/README.md create mode 100755 dwl/dwl-patches/patches/virtual-pointer/virtual-pointer.patch create mode 100755 dwl/dwl-patches/patches/warpcursor/README.md create mode 100755 dwl/dwl-patches/patches/warpcursor/warpcursor.patch create mode 100755 dwl/dwl-patches/patches/wayland-socket-handover/README.md create mode 100755 dwl/dwl-patches/patches/wayland-socket-handover/wayland-socket-handover.patch create mode 100755 dwl/dwl-patches/patches/winview/README.md create mode 100755 dwl/dwl-patches/patches/winview/winview-20240606.patch create mode 100755 dwl/dwl-patches/patches/winview/winview.patch create mode 100755 dwl/dwl-patches/patches/xwayland-handle-minimize/README.md create mode 100755 dwl/dwl-patches/patches/xwayland-handle-minimize/xwayland-handle-minimize.patch create mode 100755 dwl/dwl-patches/patches/zoomswap/README.md create mode 100755 dwl/dwl-patches/patches/zoomswap/zoomswap-v0.6.patch create mode 100755 dwl/dwl-patches/patches/zoomswap/zoomswap-v0.7.patch create mode 100755 dwl/dwl-patches/patches/zoomswap/zoomswap.patch create mode 100755 dwl/dwl-patches/stale-patches/bar-systray-old/README.md create mode 100755 dwl/dwl-patches/stale-patches/bar-systray-old/bar-systray-0.7.patch create mode 100755 dwl/dwl-patches/stale-patches/bar-systray-old/systray.png create mode 100755 dwl/dwl-patches/stale-patches/master-right/README.md create mode 100755 dwl/dwl-patches/stale-patches/master-right/master-right-0.7.patch create mode 100755 dwl/dwl-patches/stale-patches/master-right/master-right.patch create mode 100755 dwl/dwl-patches/stale-patches/press_repeat_release/README.md create mode 100755 dwl/dwl-patches/stale-patches/press_repeat_release/press_repeat_release.patch create mode 100755 dwl/dwl-patches/stale-patches/remembertags/README.md create mode 100755 dwl/dwl-patches/stale-patches/remembertags/remembertags.patch create mode 100755 dwl/dwl-patches/stale-patches/tab-pango/README.md create mode 100755 dwl/dwl-patches/stale-patches/tab-pango/tab.patch create mode 100755 dwl/dwl-patches/stale-patches/togglekblayout/README.md create mode 100755 dwl/dwl-patches/stale-patches/togglekblayout/togglekblayout.patch create mode 100755 dwl/dwl.1 create mode 100755 dwl/dwl.c create mode 100755 dwl/dwl.c.orig create mode 100755 dwl/dwl.desktop create mode 100755 dwl/protocols/wlr-layer-shell-unstable-v1.xml create mode 100755 dwl/protocols/wlr-output-power-management-unstable-v1.xml create mode 100755 dwl/util.c create mode 100755 dwl/util.h create mode 100755 dwm/.github/FUNDING.yml create mode 100755 dwm/.gitignore create mode 100755 dwm/LICENSE create mode 100755 dwm/Makefile create mode 100755 dwm/README create mode 100755 dwm/README.md create mode 100755 dwm/config.def.h create mode 100755 dwm/config.mk create mode 100755 dwm/drw.c create mode 100755 dwm/drw.h create mode 100755 dwm/dwm.1 create mode 100755 dwm/dwm.c create mode 100755 dwm/dwm.desktop create mode 100755 dwm/dwm.png create mode 100755 dwm/patch/alttab.c create mode 100755 dwm/patch/alttab.h create mode 100755 dwm/patch/alwaysontop.c create mode 100755 dwm/patch/alwaysontop.h create mode 100755 dwm/patch/aspectresize.c create mode 100755 dwm/patch/aspectresize.h create mode 100755 dwm/patch/attachx.c create mode 100755 dwm/patch/attachx.h create mode 100755 dwm/patch/autostart.c create mode 100755 dwm/patch/autostart.h create mode 100755 dwm/patch/banish.c create mode 100755 dwm/patch/banish.h create mode 100755 dwm/patch/bar.c create mode 100755 dwm/patch/bar.h create mode 100755 dwm/patch/bar_alpha.c create mode 100755 dwm/patch/bar_alpha.h create mode 100755 dwm/patch/bar_alternativetags.c create mode 100755 dwm/patch/bar_alternativetags.h create mode 100755 dwm/patch/bar_anybar.c create mode 100755 dwm/patch/bar_anybar.h create mode 100755 dwm/patch/bar_awesomebar.c create mode 100755 dwm/patch/bar_awesomebar.h create mode 100755 dwm/patch/bar_dwmblocks.c create mode 100755 dwm/patch/bar_dwmblocks.h create mode 100755 dwm/patch/bar_ewmhtags.c create mode 100755 dwm/patch/bar_ewmhtags.h create mode 100755 dwm/patch/bar_fancybar.c create mode 100755 dwm/patch/bar_fancybar.h create mode 100755 dwm/patch/bar_flexwintitle.c create mode 100755 dwm/patch/bar_flexwintitle.h create mode 100755 dwm/patch/bar_holdbar.c create mode 100755 dwm/patch/bar_holdbar.h create mode 100755 dwm/patch/bar_indicators.c create mode 100755 dwm/patch/bar_indicators.h create mode 100755 dwm/patch/bar_launcher.c create mode 100755 dwm/patch/bar_launcher.h create mode 100755 dwm/patch/bar_layoutmenu.c create mode 100755 dwm/patch/bar_layoutmenu.h create mode 100755 dwm/patch/bar_ltsymbol.c create mode 100755 dwm/patch/bar_ltsymbol.h create mode 100755 dwm/patch/bar_powerline_status.c create mode 100755 dwm/patch/bar_powerline_status.h create mode 100755 dwm/patch/bar_powerline_tags.c create mode 100755 dwm/patch/bar_powerline_tags.h create mode 100755 dwm/patch/bar_status.c create mode 100755 dwm/patch/bar_status.h create mode 100755 dwm/patch/bar_status2d.c create mode 100755 dwm/patch/bar_status2d.h create mode 100755 dwm/patch/bar_statusbutton.c create mode 100755 dwm/patch/bar_statusbutton.h create mode 100755 dwm/patch/bar_statuscmd.c create mode 100755 dwm/patch/bar_statuscmd.h create mode 100755 dwm/patch/bar_statuscolors.c create mode 100755 dwm/patch/bar_statuscolors.h create mode 100755 dwm/patch/bar_systray.c create mode 100755 dwm/patch/bar_systray.h create mode 100755 dwm/patch/bar_tabgroups.c create mode 100755 dwm/patch/bar_tabgroups.h create mode 100755 dwm/patch/bar_taggrid.c create mode 100755 dwm/patch/bar_taggrid.h create mode 100755 dwm/patch/bar_tagicons.c create mode 100755 dwm/patch/bar_tagicons.h create mode 100755 dwm/patch/bar_taglabels.c create mode 100755 dwm/patch/bar_taglabels.h create mode 100755 dwm/patch/bar_tagpreview.c create mode 100755 dwm/patch/bar_tagpreview.h create mode 100755 dwm/patch/bar_tags.c create mode 100755 dwm/patch/bar_tags.h create mode 100755 dwm/patch/bar_vtcolors.c create mode 100755 dwm/patch/bar_vtcolors.h create mode 100755 dwm/patch/bar_winicon.c create mode 100755 dwm/patch/bar_winicon.h create mode 100755 dwm/patch/bar_wintitle.c create mode 100755 dwm/patch/bar_wintitle.h create mode 100755 dwm/patch/bar_wintitle_floating.c create mode 100755 dwm/patch/bar_wintitle_floating.h create mode 100755 dwm/patch/bar_wintitle_hidden.c create mode 100755 dwm/patch/bar_wintitle_hidden.h create mode 100755 dwm/patch/bar_wintitleactions.c create mode 100755 dwm/patch/bar_wintitleactions.h create mode 100755 dwm/patch/cfacts.c create mode 100755 dwm/patch/cfacts.h create mode 100755 dwm/patch/cmdcustomize.c create mode 100755 dwm/patch/cmdcustomize.h create mode 100755 dwm/patch/combo.c create mode 100755 dwm/patch/combo.h create mode 100755 dwm/patch/cool_autostart.c create mode 100755 dwm/patch/cool_autostart.h create mode 100755 dwm/patch/cyclelayouts.c create mode 100755 dwm/patch/cyclelayouts.h create mode 100755 dwm/patch/decorationhints.c create mode 100755 dwm/patch/decorationhints.h create mode 100755 dwm/patch/distributetags.c create mode 100755 dwm/patch/distributetags.h create mode 100755 dwm/patch/dragcfact.c create mode 100755 dwm/patch/dragcfact.h create mode 100755 dwm/patch/dragmfact.c create mode 100755 dwm/patch/dragmfact.h create mode 100755 dwm/patch/dwmc create mode 100755 dwm/patch/dwmc.c create mode 100755 dwm/patch/dwmc.h create mode 100755 dwm/patch/exresize.c create mode 100755 dwm/patch/exresize.h create mode 100755 dwm/patch/fakefullscreenclient.c create mode 100755 dwm/patch/fakefullscreenclient.h create mode 100755 dwm/patch/floatpos.c create mode 100755 dwm/patch/floatpos.h create mode 100755 dwm/patch/focusadjacenttag.c create mode 100755 dwm/patch/focusadjacenttag.h create mode 100755 dwm/patch/focusdir.c create mode 100755 dwm/patch/focusdir.h create mode 100755 dwm/patch/focusfollowmouse.c create mode 100755 dwm/patch/focusfollowmouse.h create mode 100755 dwm/patch/focusmaster.c create mode 100755 dwm/patch/focusmaster.h create mode 100755 dwm/patch/focusurgent.c create mode 100755 dwm/patch/focusurgent.h create mode 100755 dwm/patch/fsignal.c create mode 100755 dwm/patch/fsignal.h create mode 100755 dwm/patch/fullscreen.c create mode 100755 dwm/patch/fullscreen.h create mode 100755 dwm/patch/games.c create mode 100755 dwm/patch/games.h create mode 100755 dwm/patch/include.c create mode 100755 dwm/patch/include.h create mode 100755 dwm/patch/inplacerotate.c create mode 100755 dwm/patch/inplacerotate.h create mode 100755 dwm/patch/insets.c create mode 100755 dwm/patch/insets.h create mode 100755 dwm/patch/ipc.c create mode 100755 dwm/patch/ipc.h create mode 100755 dwm/patch/ipc/IPCClient.c create mode 100755 dwm/patch/ipc/IPCClient.h create mode 100755 dwm/patch/ipc/dwm-msg.c create mode 100755 dwm/patch/ipc/ipc.c create mode 100755 dwm/patch/ipc/ipc.h create mode 100755 dwm/patch/ipc/util.c create mode 100755 dwm/patch/ipc/util.h create mode 100755 dwm/patch/ipc/yajl_dumps.c create mode 100755 dwm/patch/ipc/yajl_dumps.h create mode 100755 dwm/patch/keymodes.c create mode 100755 dwm/patch/keymodes.h create mode 100755 dwm/patch/killunsel.c create mode 100755 dwm/patch/killunsel.h create mode 100755 dwm/patch/layout_bstack.c create mode 100755 dwm/patch/layout_bstack.h create mode 100755 dwm/patch/layout_bstackhoriz.c create mode 100755 dwm/patch/layout_bstackhoriz.h create mode 100755 dwm/patch/layout_centeredfloatingmaster.c create mode 100755 dwm/patch/layout_centeredfloatingmaster.h create mode 100755 dwm/patch/layout_centeredmaster.c create mode 100755 dwm/patch/layout_centeredmaster.h create mode 100755 dwm/patch/layout_columns.c create mode 100755 dwm/patch/layout_columns.h create mode 100755 dwm/patch/layout_deck.c create mode 100755 dwm/patch/layout_deck.h create mode 100755 dwm/patch/layout_facts.c create mode 100755 dwm/patch/layout_fibonacci.c create mode 100755 dwm/patch/layout_fibonacci.h create mode 100755 dwm/patch/layout_flextile-deluxe.c create mode 100755 dwm/patch/layout_flextile-deluxe.h create mode 100755 dwm/patch/layout_gapplessgrid.c create mode 100755 dwm/patch/layout_gapplessgrid.h create mode 100755 dwm/patch/layout_grid.c create mode 100755 dwm/patch/layout_grid.h create mode 100755 dwm/patch/layout_horizgrid.c create mode 100755 dwm/patch/layout_horizgrid.h create mode 100755 dwm/patch/layout_monocle.c create mode 100755 dwm/patch/layout_monocle.h create mode 100755 dwm/patch/layout_nrowgrid.c create mode 100755 dwm/patch/layout_nrowgrid.h create mode 100755 dwm/patch/layout_tile.c create mode 100755 dwm/patch/layout_tile.h create mode 100755 dwm/patch/layoutmenu.sh create mode 100755 dwm/patch/maximize.c create mode 100755 dwm/patch/maximize.h create mode 100755 dwm/patch/movecenter.c create mode 100755 dwm/patch/movecenter.h create mode 100755 dwm/patch/moveplace.c create mode 100755 dwm/patch/moveplace.h create mode 100755 dwm/patch/moveresize.c create mode 100755 dwm/patch/moveresize.h create mode 100755 dwm/patch/movestack.c create mode 100755 dwm/patch/movestack.h create mode 100755 dwm/patch/mpdcontrol.c create mode 100755 dwm/patch/mpdcontrol.h create mode 100755 dwm/patch/nametag.c create mode 100755 dwm/patch/nametag.h create mode 100755 dwm/patch/nomodbuttons.c create mode 100755 dwm/patch/nomodbuttons.h create mode 100755 dwm/patch/pertag.c create mode 100755 dwm/patch/pertag.h create mode 100755 dwm/patch/placedir.c create mode 100755 dwm/patch/placedir.h create mode 100755 dwm/patch/placemouse.c create mode 100755 dwm/patch/placemouse.h create mode 100755 dwm/patch/push.c create mode 100755 dwm/patch/push.h create mode 100755 dwm/patch/push_no_master.c create mode 100755 dwm/patch/push_no_master.h create mode 100755 dwm/patch/recttoclient.c create mode 100755 dwm/patch/recttoclient.h create mode 100755 dwm/patch/renamed_scratchpads.c create mode 100755 dwm/patch/renamed_scratchpads.h create mode 100755 dwm/patch/reorganizetags.c create mode 100755 dwm/patch/reorganizetags.h create mode 100755 dwm/patch/restartsig.c create mode 100755 dwm/patch/restartsig.h create mode 100755 dwm/patch/riodraw.c create mode 100755 dwm/patch/riodraw.h create mode 100755 dwm/patch/rotatestack.c create mode 100755 dwm/patch/rotatestack.h create mode 100755 dwm/patch/roundedcorners.c create mode 100755 dwm/patch/roundedcorners.h create mode 100755 dwm/patch/scratchpad.c create mode 100755 dwm/patch/scratchpad.h create mode 100755 dwm/patch/scratchpad_alt_1.c create mode 100755 dwm/patch/scratchpad_alt_1.h create mode 100755 dwm/patch/seamless_restart.c create mode 100755 dwm/patch/seamless_restart.h create mode 100755 dwm/patch/selfrestart.c create mode 100755 dwm/patch/selfrestart.h create mode 100755 dwm/patch/setborderpx.c create mode 100755 dwm/patch/setborderpx.h create mode 100755 dwm/patch/shift.c create mode 100755 dwm/patch/shift.h create mode 100755 dwm/patch/shiftboth.c create mode 100755 dwm/patch/shiftboth.h create mode 100755 dwm/patch/shiftswaptags.c create mode 100755 dwm/patch/shiftswaptags.h create mode 100755 dwm/patch/shifttag.c create mode 100755 dwm/patch/shifttag.h create mode 100755 dwm/patch/shifttagclients.c create mode 100755 dwm/patch/shifttagclients.h create mode 100755 dwm/patch/shiftview.c create mode 100755 dwm/patch/shiftview.h create mode 100755 dwm/patch/shiftviewclients.c create mode 100755 dwm/patch/shiftviewclients.h create mode 100755 dwm/patch/sizehints_ruled.c create mode 100755 dwm/patch/sizehints_ruled.h create mode 100755 dwm/patch/sortscreens.c create mode 100755 dwm/patch/sortscreens.h create mode 100755 dwm/patch/stacker.c create mode 100755 dwm/patch/stacker.h create mode 100755 dwm/patch/sticky.c create mode 100755 dwm/patch/sticky.h create mode 100755 dwm/patch/swallow.c create mode 100755 dwm/patch/swallow.h create mode 100755 dwm/patch/swapfocus.c create mode 100755 dwm/patch/swapfocus.h create mode 100755 dwm/patch/swaptags.c create mode 100755 dwm/patch/swaptags.h create mode 100755 dwm/patch/switchcol.c create mode 100755 dwm/patch/switchcol.h create mode 100755 dwm/patch/tab.c create mode 100755 dwm/patch/tab.h create mode 100755 dwm/patch/tagall.c create mode 100755 dwm/patch/tagall.h create mode 100755 dwm/patch/tagallmon.c create mode 100755 dwm/patch/tagallmon.h create mode 100755 dwm/patch/tagothermonitor.c create mode 100755 dwm/patch/tagothermonitor.h create mode 100755 dwm/patch/tagswapmon.c create mode 100755 dwm/patch/tagswapmon.h create mode 100755 dwm/patch/tapresize.c create mode 100755 dwm/patch/tapresize.h create mode 100755 dwm/patch/togglefullscreen.c create mode 100755 dwm/patch/togglefullscreen.h create mode 100755 dwm/patch/toggletopbar.c create mode 100755 dwm/patch/toggletopbar.h create mode 100755 dwm/patch/transfer.c create mode 100755 dwm/patch/transfer.h create mode 100755 dwm/patch/transferall.c create mode 100755 dwm/patch/transferall.h create mode 100755 dwm/patch/unfloatvisible.c create mode 100755 dwm/patch/unfloatvisible.h create mode 100755 dwm/patch/vanitygaps.c create mode 100755 dwm/patch/vanitygaps.h create mode 100755 dwm/patch/warp.c create mode 100755 dwm/patch/warp.h create mode 100755 dwm/patch/winview.c create mode 100755 dwm/patch/winview.h create mode 100755 dwm/patch/xkb.c create mode 100755 dwm/patch/xkb.h create mode 100755 dwm/patch/xrdb.c create mode 100755 dwm/patch/xrdb.h create mode 100755 dwm/patch/xresources.c create mode 100755 dwm/patch/xresources.h create mode 100755 dwm/patch/zoomswap.c create mode 100755 dwm/patch/zoomswap.h create mode 100755 dwm/patches.def.h create mode 100755 dwm/transient.c create mode 100755 dwm/util.c create mode 100755 dwm/util.h create mode 100755 local/bin/README.md create mode 100755 local/bin/Xrec create mode 100755 local/bin/aurtest.sh create mode 100755 local/bin/bat-symbol create mode 100755 local/bin/brwmenu create mode 100755 local/bin/cotray create mode 100755 local/bin/define create mode 100755 local/bin/discord create mode 100755 local/bin/dmenu.py create mode 100755 local/bin/ecop create mode 100755 local/bin/edsc create mode 100755 local/bin/emacsd create mode 100755 local/bin/emacsd~ create mode 100755 local/bin/f2py create mode 100755 local/bin/firemenu create mode 100755 local/bin/fzfse create mode 100755 local/bin/grubfk create mode 100755 local/bin/hyfetch create mode 100755 local/bin/hyfetch.rs create mode 100755 local/bin/hyfetch.v1 create mode 100755 local/bin/killradio create mode 100755 local/bin/math create mode 100755 local/bin/mksymlink create mode 100755 local/bin/mpc-shuf.sh create mode 100755 local/bin/nodeenv create mode 100755 local/bin/numpy-config create mode 100755 local/bin/pyright create mode 100755 local/bin/pyright-langserver create mode 100755 local/bin/pyright-python create mode 100755 local/bin/pyright-python-langserver create mode 100755 local/bin/qr create mode 100755 local/bin/radio create mode 100755 local/bin/resmacs create mode 100755 local/bin/rimworld create mode 100755 local/bin/sb-battery create mode 100755 local/bin/sb-cputemp create mode 100755 local/bin/sb-cpuusage create mode 100755 local/bin/sb-liisten create mode 100755 local/bin/sb-memory create mode 100755 local/bin/sb-network create mode 100755 local/bin/sb-swap create mode 100755 local/bin/sb-volume create mode 100755 local/bin/screencast create mode 100755 local/bin/screenie create mode 100755 local/bin/screenie-active create mode 100755 local/bin/screenie-wlr create mode 100755 local/bin/setwall.py create mode 100755 local/bin/setwall.sh create mode 100644 local/bin/sober create mode 100755 local/bin/stacki3 create mode 100755 local/bin/start-meowgun.sh create mode 100755 local/bin/start-wq.sh create mode 100755 local/bin/start_qtile.sh create mode 100755 local/bin/startniri create mode 100755 local/bin/startw create mode 100755 local/bin/swallow create mode 100755 local/bin/swap.start create mode 100755 local/bin/swap.stop create mode 100755 local/bin/sway-status create mode 100755 local/bin/tabulate create mode 100755 local/bin/toggle-screens.sh create mode 100755 local/bin/tun2socks create mode 100755 local/bin/updateriver create mode 100755 local/bin/upim create mode 100755 local/bin/usbmount create mode 100755 local/bin/usbumount create mode 100755 local/bin/uwuify.awk create mode 100755 local/bin/vesktop.sh create mode 100755 local/bin/win2xcur create mode 100755 local/bin/wsdump create mode 100755 local/bin/x2wincur create mode 100755 local/bin/yellusb create mode 100755 local/share/color-schemes/Monochrome.colors create mode 100755 local/share/emoji create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-active.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-hover.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-left.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-right.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-dark.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-off.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-active.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-hover.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/corner-ripple.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-dark.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-off.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-off.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on-dark.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/trash-icon.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/cinnamon.css create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/cinnamon/thumbnail.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-left.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-right.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-today.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-dark.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-active.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-hover.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/dash-placeholder.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-events.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-notifications.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/noise-texture.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/process-working.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-off.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on-dark.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/gnome-shell.css create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-events.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-notifications.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/pad-osd.css create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/process-working.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/apps.rc create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/border.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/focus.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-inline.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-notebook.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-semi.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-semi.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-progress.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-trough.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-trough.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-trough.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-trough.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/tab.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-hover.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/gtkrc create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/hacks.rc create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/main.rc create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/close.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/maximize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/minimize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/unmaximize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk-dark.css create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk.css create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/thumbnail.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/close.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/cursor-handle-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/maximize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/minimize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/unmaximize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk-dark.css create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk.css create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/thumbnail.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/index.theme create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/button.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/close.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/maximize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/menu.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/minimize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/shade.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unmaximize.svg create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unshade.svg create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-1.xml create mode 120000 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-2.xml create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-3.xml create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/metacity-1/thumbnail.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/plank/dock.theme create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-prelight.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-pressed.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/themerc create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-inactive.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-active.png create mode 100755 local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-active.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-hover.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-left.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-right.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-dark.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-off.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-active.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-hover.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/corner-ripple.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-dark.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-off.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-off.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on-dark.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/trash-icon.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/cinnamon.css create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/thumbnail.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-left.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-right.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-today.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-dark.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-active.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-hover.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/dash-placeholder.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-events.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-notifications.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/noise-texture.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/process-working.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-off.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on-dark.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/gnome-shell.css create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-events.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-notifications.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/pad-osd.css create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/process-working.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/apps.rc create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/border.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/focus.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-inline.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-notebook.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-semi.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-semi.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-progress.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-trough.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-trough.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-trough.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-trough.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/tab.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-hover.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/gtkrc create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/hacks.rc create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/main.rc create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/close.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/maximize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/minimize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/unmaximize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk-dark.css create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk.css create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/thumbnail.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/close.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/cursor-handle-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/maximize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/minimize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic@2.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/unmaximize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk-dark.css create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk.css create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/thumbnail.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/index.theme create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/button.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/close.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/maximize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/menu.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/minimize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/shade.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unmaximize.svg create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unshade.svg create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-1.xml create mode 120000 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-2.xml create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-3.xml create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/thumbnail.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/plank/dock.theme create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-prelight.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-pressed.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/themerc create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-inactive.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-active.png create mode 100755 local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-inactive.png create mode 100755 nixos/configuration/configuration.nix create mode 100755 nixos/configuration/sys/coreutils-configuration.nix create mode 100755 nixos/configuration/sys/swap.nix create mode 100755 nixos/configuration/sys/zram.nix create mode 100755 nixos/flake.lock create mode 100755 nixos/flake.nix create mode 100755 nixos/home-configuration/apps/alacritty.nix create mode 100755 nixos/home-configuration/apps/foot.nix create mode 100755 nixos/home-configuration/apps/nushell.nix create mode 100755 nixos/home-configuration/apps/sway.nix create mode 100755 nixos/home-configuration/apps/zsh.nix create mode 100755 nixos/home-configuration/configuration.nix create mode 100755 portage/make.conf create mode 160000 slock create mode 100755 slstatus/LICENSE create mode 100755 slstatus/Makefile create mode 100755 slstatus/arg.h create mode 100755 slstatus/components/battery.c create mode 100644 slstatus/components/battery.o create mode 100755 slstatus/components/cat.c create mode 100644 slstatus/components/cat.o create mode 100755 slstatus/components/cpu.c create mode 100644 slstatus/components/cpu.o create mode 100755 slstatus/components/datetime.c create mode 100644 slstatus/components/datetime.o create mode 100755 slstatus/components/disk.c create mode 100644 slstatus/components/disk.o create mode 100755 slstatus/components/entropy.c create mode 100644 slstatus/components/entropy.o create mode 100755 slstatus/components/hostname.c create mode 100644 slstatus/components/hostname.o create mode 100755 slstatus/components/ip.c create mode 100644 slstatus/components/ip.o create mode 100755 slstatus/components/kernel_release.c create mode 100644 slstatus/components/kernel_release.o create mode 100755 slstatus/components/keyboard_indicators.c create mode 100644 slstatus/components/keyboard_indicators.o create mode 100755 slstatus/components/keymap.c create mode 100644 slstatus/components/keymap.o create mode 100755 slstatus/components/load_avg.c create mode 100644 slstatus/components/load_avg.o create mode 100755 slstatus/components/netspeeds.c create mode 100644 slstatus/components/netspeeds.o create mode 100755 slstatus/components/num_files.c create mode 100644 slstatus/components/num_files.o create mode 100755 slstatus/components/pixVol.sh create mode 100755 slstatus/components/ram.c create mode 100644 slstatus/components/ram.o create mode 100755 slstatus/components/run_command.c create mode 100644 slstatus/components/run_command.o create mode 100755 slstatus/components/swap.c create mode 100644 slstatus/components/swap.o create mode 100755 slstatus/components/temperature.c create mode 100644 slstatus/components/temperature.o create mode 100755 slstatus/components/uptime.c create mode 100644 slstatus/components/uptime.o create mode 100755 slstatus/components/user.c create mode 100644 slstatus/components/user.o create mode 100755 slstatus/components/volume.c create mode 100644 slstatus/components/volume.o create mode 100755 slstatus/components/wifi.c create mode 100644 slstatus/components/wifi.o create mode 100755 slstatus/config.def.h create mode 100755 slstatus/config.h create mode 100755 slstatus/config.mk create mode 100755 slstatus/slstatus create mode 100755 slstatus/slstatus.1 create mode 100755 slstatus/slstatus.c create mode 100755 slstatus/slstatus.h create mode 100644 slstatus/slstatus.o create mode 100755 slstatus/util.c create mode 100755 slstatus/util.h create mode 100644 slstatus/util.o create mode 100755 sober/config.json create mode 100755 st/LEGACY create mode 100755 st/LICENSE create mode 100755 st/Makefile create mode 100755 st/README create mode 100755 st/TODO create mode 100755 st/arg.h create mode 100755 st/boxdraw.c create mode 100755 st/boxdraw_data.h create mode 100755 st/config.def.h create mode 100755 st/config.h create mode 100755 st/config.h.save create mode 100755 st/config.h.save.1 create mode 100755 st/config.h.save.2 create mode 100755 st/config.h.save.3 create mode 100755 st/config.mk create mode 100755 st/graphics.c create mode 100755 st/graphics.h create mode 100755 st/hb.c create mode 100755 st/hb.h create mode 100755 st/icat-mini.sh create mode 100755 st/khash.h create mode 100755 st/kvec.h create mode 100755 st/rowcolumn_diacritics_helpers.c create mode 100755 st/st-alpha-changealpha-20230519-b44f2ad.diff create mode 100755 st/st.1 create mode 100755 st/st.c create mode 100755 st/st.core create mode 100755 st/st.h create mode 100755 st/st.info create mode 100755 st/win.h create mode 100755 st/x.c create mode 100755 wmenu/.gitignore create mode 100755 wmenu/LICENSE create mode 100755 wmenu/README.md create mode 100755 wmenu/docs/meson.build create mode 100755 wmenu/docs/wmenu.1.scd create mode 100755 wmenu/menu.c create mode 100755 wmenu/menu.h create mode 100755 wmenu/meson.build create mode 100755 wmenu/pango.c create mode 100755 wmenu/pango.h create mode 100755 wmenu/pool-buffer.c create mode 100755 wmenu/pool-buffer.h create mode 100755 wmenu/protocols/meson.build create mode 100755 wmenu/protocols/wlr-layer-shell-unstable-v1.xml create mode 100755 wmenu/render.c create mode 100755 wmenu/render.h create mode 100755 wmenu/wayland.c create mode 100755 wmenu/wayland.h create mode 100755 wmenu/wmenu-run.c create mode 100755 wmenu/wmenu.c diff --git a/.Xresources b/.Xresources new file mode 100755 index 0000000..4ddc51e --- /dev/null +++ b/.Xresources @@ -0,0 +1,20 @@ +Xcursor.theme: Adwaita +Xcursor.size: 24 + +!xterm +XTerm*termName: xterm-256color +XTerm*loginShell: true +XTerm*scrollBar: false +!xtermFont +xterm*font: *-fixed-*-*-*-18-* +!xtermCursor +XTerm*cursorColor: white +XTerm*cursorBlink: false +!xtermSCrollback +XTerm*saveLines: 5000 +!clipboard +XTerm*selectToClipboard: true +XTerm*rightScrollBar: false + +!colors for xterm +XTerm*background: #ffffff diff --git a/.bash.d/aliasrc b/.bash.d/aliasrc new file mode 100755 index 0000000..ee290ce --- /dev/null +++ b/.bash.d/aliasrc @@ -0,0 +1,28 @@ +#!/bin/bash +alias es=eix +alias weather=curl\ wttr.in/masjedsoleyman +alias c="clear" +alias cear="clear" +alias cd..="cd .." +alias ..='echo "cd .."; cd ../' +alias claer="clear" +alias clare="clear" +alias cleae="clear" +alias clera="clear" +alias ls=ls\ --color=auto +alias nf="neofetch" +alias als="vim ~/.bash.d/aliasrc" +alias ac="sudo emerge -ac" +alias suod=sudo +alias srcbash="source ~/.bashrc" +alias smi=nvidia-smi +alias tl="sudo tail -f /var/log/emerge-fetch.log" +alias music="mpv --playlist=/home/coast/Music --shuffle" +alias cmatrix="cmatrix -C white" +fixaud() { + pactl set-card-profile alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic "HiFi (HDMI1, HDMI2, HDMI3, Mic1, Mic2, Speaker)" +} + +fixaud2() { + pactl set-default-sink alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink +} diff --git a/.bash.d/export b/.bash.d/export new file mode 100755 index 0000000..5f7f13c --- /dev/null +++ b/.bash.d/export @@ -0,0 +1 @@ +export PS1="\[\e[01;32m\]\u@\h\[\e[01;34m\] \w \$\[\e[00m\]" diff --git a/.bashrc b/.bashrc new file mode 100755 index 0000000..88d5b9f --- /dev/null +++ b/.bashrc @@ -0,0 +1,21 @@ +# /etc/skel/.bashrc +# +# This file is sourced by all *interactive* bash shells on startup, +# including some apparently interactive shells such as scp and rcp +# that can't tolerate any output. So make sure this doesn't display +# anything or bad things will happen ! + + +# Test for an interactive shell. There is no need to set anything +# past this point for scp and rcp, and it's important to refrain from +# outputting anything in those cases. +if [[ $- != *i* ]] ; then + # Shell is non-interactive. Be done now! + return +fi + +source ~/.bash.d/* +PS1='\[\e[1;37m\]\u@\h \w \$\[\e[0m\] ' + +[[ $PS1 && -f /usr/share/bash-completion/bash_completion ]] && \ + . /usr/share/bash-completion/bash_completion diff --git a/.emacs.d/init.el b/.emacs.d/init.el new file mode 100755 index 0000000..882287d --- /dev/null +++ b/.emacs.d/init.el @@ -0,0 +1,248 @@ +;;; init.el --- Coast's ~/.emacs.d/init.el +;; +;;; Commentary: +;; This is my GNU/Emacs configuration -- +;; It has: +;; - (TEMPORARY) Evil mode; as I've gotten used to Vim binds when I was away from GNU/Emacs for a bit. +;; - Automatic syntax-highlighting. +;; - Has a minimap. +;; - Bad theme; it's fine on my eyes, though -- I like the 'solarized' theme >:3 +;; - It's also gay. +;; +;;; Code: +;; +(require 'package) +(setq package-archives + '(("gnu" . "https://elpa.gnu.org/packages/") + ("melpa" . "https://melpa.org/packages/"))) +(package-initialize) +(unless package-archive-contents + (package-refresh-contents)) +(require 'use-package) + +;;; Message: +;; "run" command (M-x / evil) +(defun coast/run-current-file () + (interactive) + (let ((file (buffer-file-name))) + (cond + ((not file) + (message "No file to run!")) + ((string-match "\\.py\\'" file) + (compile (format "python3 %s" file))) + ((string-match "\\.c\\'" file) + (let* ((out (concat (file-name-sans-extension file) ".out"))) + (compile (format "gcc %s -o %s && %s" file out out)))) + ((string-match "\\.sh\\'" file) + (compile (format "bash %s" file))) + ((string-match "\\.rs\\'" file) + (let* ((out (file-name-sans-extension file))) + (compile (format "rustc %s && %s" file out)))) + ((string-match "\\.lua\\'" file) + (compile (format "lua %s" file))) + ((string-match "\\.js\\'" file) + (compile (format "node %s" file))) + ((coast/file-has-shebang-p file) + (compile (format "%s" file))) + (t (message "Not sure how to run this."))))) + +(defun coast/file-has-shebang-p (file) + (when (and file (file-readable-p file)) + (with-temp-buffer + (insert-file-contents-literally file nil 0 128) + (goto-char (point-min)) + (looking-at "^#!")))) + +(defalias 'run #'coast/run-current-file) + +(menu-bar-mode -1) +(tool-bar-mode -1) +(scroll-bar-mode -1) +(global-display-line-numbers-mode 1) +(global-hl-line-mode 1) +(electric-pair-mode 1) + +(setq-default electric-pair-pairs + '((?\" . ?\") + (?\{ . ?\}) + (?\( . ?\)) + (?\[ . ?\]) + (?\< . ?\>))) + +(setq-default electric-pair-text-pairs electric-pair-pairs) + +(set-frame-parameter (selected-frame) 'alpha '(95 . 95)) +(add-to-list 'default-frame-alist '(alpha . (95 . 95))) + +(set-face-attribute 'default nil :family "Inconsolata" :height 180) + +(setq backup-directory-alist `((".*" . "~/.local/tmp/emacsbackup/"))) +(setq make-backup-files t) +(setq backup-by-copying t) + +(use-package solarized-theme :ensure t) +(load-theme 'solarized-selenized-dark t) + +(use-package all-the-icons :ensure t :if (display-graphic-p)) +(use-package rainbow-mode :ensure t :hook (prog-mode . rainbow-mode)) +(use-package elcord :ensure t :config (elcord-mode 1)) + +(use-package neotree :ensure t :bind ("" . neotree-toggle)) + +(use-package vertico :ensure t :config (vertico-mode 1)) +(use-package marginalia :ensure t :hook (vertico-mode . marginalia-mode)) +(use-package consult + :ensure t + :bind (("C-x b" . consult-buffer) + ("C-s" . consult-line))) + +(use-package which-key :ensure t :config (which-key-mode 1)) + +(use-package company :ensure t :hook (prog-mode . company-mode)) +(use-package yasnippet :ensure t :hook (prog-mode . yas-minor-mode)) +(use-package flycheck :ensure t :hook (prog-mode . flycheck-mode)) + +(global-set-key (kbd "C-c t") 'ansi-term) + +(use-package web-mode + :ensure t + :mode "\\.html?\\'" + :config + (setq web-mode-enable-auto-pairing t + web-mode-enable-auto-closing t + web-mode-enable-auto-expanding t)) + +(use-package emmet-mode + :ensure t + :hook ((web-mode html-mode css-mode) . emmet-mode) + :config + (setq emmet-expand-jsx-className? t)) + +(use-package python :mode "\\.py\\'") +(use-package sh-script :mode "\\.sh\\'") +(use-package cc-mode) +(use-package markdown-mode :ensure t :mode "\\.md\\'") +(use-package yaml-mode :ensure t :mode "\\.ya?ml\\'") +(use-package macrostep :ensure t) + +;;; Message: +;; Language-setup. +(use-package python + :mode ("\\.py\\'" . python-mode) + :interpreter ("python" . python-mode)) + +(use-package rust-mode + :ensure t + :mode ("\\.rs\\'" . rust-mode)) + +(use-package sh-script + :mode (("\\.sh\\'" . sh-mode) + ("\\.bash\\'" . sh-mode) + ("\\.zsh\\'" . sh-mode)) + :interpreter (("bash" . sh-mode) + ("sh" . sh-mode) + ("zsh" . sh-mode))) + +(use-package lua-mode + :ensure t + :mode ("\\.lua\\'" . lua-mode)) + +(use-package cc-mode + :mode (("\\.c\\'" . c-mode) + ("\\.h\\'" . c-mode) + ("\\.cpp\\'" . c++-mode) + ("\\.hpp\\'" . c++-mode)) + :interpreter (("c" . c-mode) + ("cpp" . c++-mode))) + +(use-package markdown-mode + :ensure t + :mode ("\\.md\\'" . markdown-mode)) + +(use-package yaml-mode + :ensure t + :mode ("\\.ya?ml\\'" . yaml-mode)) + +;;; Message +;; -- Set window title -- +(setq frame-title-format '("%b —— GNU/Emacs")) + +;;; Message: +;; -- The below may have been temporarily added -- + +(use-package doom-modeline + :ensure t + :init + (setq doom-modeline-height 25 + doom-modeline-bar-width 3 + doom-modeline-buffer-file-name-style 'truncate-with-project + doom-modeline-icon t + doom-modeline-major-mode-icon t + doom-modeline-enable-word-count t + doom-modeline-vcs-max-length 12 + doom-modeline-minor-modes nil) + :config + (doom-modeline-mode 1)) + +(setq evil-want-keybinding nil) + +(use-package evil + :ensure t + :init (setq evil-want-integration t + evil-want-C-u-scroll t) + :config (evil-mode 1)) + +(use-package evil-collection + :after evil + :ensure t + :config (evil-collection-init)) + +(use-package evil-leader + :ensure t + :config + (global-evil-leader-mode) + (evil-leader/set-leader "") + (evil-leader/set-key + "f" 'find-file + "b" 'switch-to-buffer + "k" 'kill-buffer + "t" 'ansi-term + "e" 'eval-buffer + "r" 'coast/run-current-file)) + +(use-package evil-surround :ensure t :config (global-evil-surround-mode 1)) +(use-package evil-commentary :ensure t :config (evil-commentary-mode 1)) + +(use-package corfu + :ensure t + :custom + (corfu-auto t) + (corfu-cycle t) + (corfu-quit-no-match nil) + :init + (global-corfu-mode)) + +(use-package cape + :ensure t) + +(defun my/evil-ex-corfu-setup () + (setq-local completion-at-point-functions + (list (cape-super-capf #'completion-at-point)))) + +(add-hook 'evil-ex-completion-hook #'my/evil-ex-corfu-setup) + +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(warning-suppress-log-types '((use-package)))) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + ) + +(provide 'init) +;;; init.el ends here diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..a98eb8c --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +config/nvim/plugged +config/nvim/pack +config/nvim/undodir +config/qtile/__pycache__ +etc/nixos/hardware-configuration.nix +nixos/hardware-configuration.nix +config/nvim/nvim +config/nvim/undo +config/nushell/history.txt +config/nvim-2/pack diff --git a/.mpdconf b/.mpdconf new file mode 100755 index 0000000..2655222 --- /dev/null +++ b/.mpdconf @@ -0,0 +1,16 @@ +bind_to_address "127.0.0.1" + +music_directory "/home/coast/Music" +playlist_directory "/home/coast/.mpd/playlists" + +db_file "/home/coast/.mpd/database" +log_file "/home/coast/.mpd/log" +pid_file "/home/coast/.mpd/mpd.pid" + +user "coast" + +audio_output { + type "pulse" + name "PulseAudio Output" + mixer_type "software" +} diff --git a/.ssh/config b/.ssh/config new file mode 100755 index 0000000..7a17d87 --- /dev/null +++ b/.ssh/config @@ -0,0 +1,46 @@ +Host srv + HostName 5.178.107.206 + User coast + DynamicForward 65000 + ExitOnForwardFailure yes + ServerAliveInterval 60 + ServerAliveCountMax 3 + ControlMaster auto + ControlPath ~/.ssh/control-%r@%h:%p-srv1 + ControlPersist 10m +Host srv2 + HostName sx7n8.tech + User coast + DynamicForward 65000 + ExitOnForwardFailure yes + ServerAliveInterval 60 + ServerAliveCountMax 3 + ControlMaster auto + ControlPath ~/.ssh/control-%r@%h:%p-srv2 + ControlPersist 10m +Host srv3 + HostName 75.127.15.21 + User root + DynamicForward 65000 + ExitOnForwardFailure yes + ServerAliveInterval 60 + ServerAliveCountMax 3 + ControlMaster auto + ControlPath ~/.ssh/control-%r@%h:%p-srv3 + ControlPersist 10m +Host srv4 + HostName 74.209.118.150 + User root + Port 65001 + DynamicForward 65000 + ServerAliveInterval 60 + ServerAliveCountMax 3 +Host laptop + HostName 192.168.1.157 + User coast + ForwardX11Trusted yes + ServerAliveInterval 60 + ServerAliveCountMax 3 + ControlMaster auto + ControlPath ~/.ssh/control-%r@%h:%p-laptop + ControlPersist 10m diff --git a/.ssh/id_ed25519.pub b/.ssh/id_ed25519.pub new file mode 100644 index 0000000..0a9f14e --- /dev/null +++ b/.ssh/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA/uTuBIG/d0zfgGJz6boCEeyuz16/t41aWCjN+SK5BF coast@unix diff --git a/.vimrc b/.vimrc new file mode 100755 index 0000000..d929aab --- /dev/null +++ b/.vimrc @@ -0,0 +1,67 @@ +set nocompatible +filetype plugin indent on +syntax enable +set encoding=utf-8 + +set laststatus=2 +set statusline=%l +set statusline+=<< +set statusline+=\ %f\ %* +set statusline+=>> +set statusline+=\ %2*\ %F +set statusline+=\ %m +set statusline+=%= +set statusline+=\ %1*\ << +set statusline+=\ Line:\ %l +set statusline+=\ Col:\ %c +set statusline+=\ :::\ %n +set statusline+=\ >> + +set number +set relativenumber +set numberwidth=4 + +highlight LineNr ctermfg=DarkGray guifg=#3a3a3a +highlight SignColumn ctermbg=NONE guibg=NONE +highlight LineNr cterm=italic gui=italic + +set tabstop=4 +set shiftwidth=4 +set expandtab +set smartindent +set nowrap + +set incsearch +set hlsearch +set ignorecase +set smartcase + +set mouse=a +set scrolloff=5 +set cursorline +set noshowmode +set shortmess+=I +set laststatus=2 + +let mapleader = "\" + +nnoremap w :w +nnoremap q :q + +nnoremap h :nohlsearch + +nnoremap n :set relativenumber! + +nnoremap h +nnoremap j +nnoremap k +nnoremap l + +call plug#begin('~/.vim/plugged') + Plug 'preservim/nerdtree' + Plug 'itchyny/lightline.vim' + Plug 'tpope/vim-commentary' + Plug 'airblade/vim-gitgutter' +call plug#end() + +nnoremap t :NERDTreeToggle diff --git a/.wezterm.lua b/.wezterm.lua new file mode 100755 index 0000000..bdf0257 --- /dev/null +++ b/.wezterm.lua @@ -0,0 +1,16 @@ +local wezterm = require("wezterm") +local config = wezterm.config_builder() +config.font_size = 15 +config.color_scheme = "Mashup Colors (terminal.sexy)" +config.window_padding = { + left = 4, + right = 4, + top = 4, + bottom = 4, +} +config.enable_tab_bar = false +config.font = wezterm.font("JetBrainsMono Nerd Font") +config.window_close_confirmation = "NeverPrompt" +config.window_background_opacity = 0.90 +config.default_cursor_style = "SteadyUnderline" +return config diff --git a/.xinitrc b/.xinitrc new file mode 100755 index 0000000..5b6933b --- /dev/null +++ b/.xinitrc @@ -0,0 +1,28 @@ +#!/bin/zsh + +if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then + exec dbus-launch --sh-syntax --exit-with-session "$0" +fi + +export XDG_SESSION_TYPE=x11 +export XDG_CURRENT_DESKTOP=dwm +export GDK_BACKEND=x11 +export QT_QPA_PLATFORM=xcb +export XCURSOR_THEME=Adwaita +export XCURSOR_SIZE=24 + +xset r rate 200 35 +xinput set-prop "ELAN0709:00 04F3:30A0 Touchpad" "libinput Tapping Enabled" 1 & +xrdb -merge ~/.Xresources +picom --config ~/.config/picom/picom.conf & +sxhkd & +slstatus & +/usr/libexec/polkit-gnome-authentication-agent-1 & +pulseaudio --start & +setxkbmap -option caps:escape & +xwallpaper --zoom files/pics/walls/wallhaven-y8g1el_1920x1080.png & +dunst & +notify-send "test" +brightnessctl -d intel_backlight set 100% + +exec dwm diff --git a/.zprofile b/.zprofile new file mode 100755 index 0000000..be3dbf7 --- /dev/null +++ b/.zprofile @@ -0,0 +1,143 @@ +export TERM=xterm-256color + +grep --color=auto < /dev/null &>/dev/null && alias grep='grep --color=auto' +export PATH="$HOME/.local/bin:$PATH" +export PATH="/usr/pkg/sbin:/usr/pkg/bin:$PATH" +export PATH="$HOME/.cargo/bin:$PATH" +export PATH="$PATH:/home/coast/.spicetify" +export MANPATH="/usr/pkg/man:$MANPATH" +export XDG_DATA_DIRS="/var/lib/flatpak/exports/share:$HOME/.local/share/flatpak/exports/share:/usr/local/share:/usr/share" +export EIX_LIMIT=0 +export EDITOR=vim +#export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" +export EGIT_OVERRIDE_REPO_RIVER_RIVER="https://github.com/riverwm/river.git" + +alias record='wf-recorder -f desktop.mkv -a alsa_output.pci-0000_0b_00.6.analog-stereo.monitor -g "$(slurp)"' + +export XDG_SESSION_TYPE=x11 + +#aliasrc + +#OS-based aliases +[ "$(uname -s)" = "FreeBSD" ] && alias make=gmake + +alias \ + sysrc="doas sysrc"\ + service="doas service"\ + sysctl="doas sysctl"\ + pkg="doas proxychains -q pkg" +#alias \ +# starth="dbus-run-session sway"\ +# startw=starth\ +# startx=starth +alias startx="dbus-run-session startx" + +alias \ + elog="doas tail -f /var/log/emerge-fetch.log"\ + emerge="doas px emerge"\ + eu="doas etc-update" + +alias pgrep="pgrep -a" +alias qb=qbittorrent-nox +alias s=ssh\ laptop +alias s1="ssh coast@seqyusphere.eu" +alias s2="ssh coast@sx7n8.tech" +alias nrs="doas nixos-rebuild switch --flake /etc/nixos#core" +alias nf="clear && neofetch" +alias mutt="neomutt" +alias mt="neomutt" +alias emoji="cat ~/.local/src/local/share/emoji | grep" +alias cst="vi ~/.config/st/config.h" +#alias ls="ls --color=auto" +#alias ll="ls -hl" +#alias l="ls -lh" +alias la="ls -ahl" +alias smi="nvidia-smi" +alias srczsh="source ~/.zshrc" +alias battery="sb-battery" +alias quit="exit" +alias push="git push" +alias weather="curl wttr.in/masjedsoleyman" +alias las="ls" +alias c="clear" +alias cear="clear" +alias cd..="cd .." +alias ..='echo "cd .."; cd ../' +alias claer="clear" +alias clare="clear" +alias cleae="clear" +alias clera="clear" +alias hotp="htop" +alias copykey='cat ~/.local/share/vault1.key | xclip -sel clipboard' +alias mic="micro" +alias nx="nsxiv" +alias e="doas emerge --ask --verbose" +alias es="emerge -s" +alias fe="flatpak search" +alias fei="flatpak install" +alias ac="doas emerge -ac" +alias ls="ls --color=auto" +alias alsamixer="alsamixer -c 0" +alias l="ls -l;" +alias freebsd="qemu-system-x86_64 -m 8048 -smp 2 -hda /home/coast/vm/freebsd/FreeBSD-14.3-RELEASE-amd64.qcow2 -nic user,model=virtio-net-pci -enable-kvm" +alias os="ls --color=auto" +alias lsbc="lsblk | bat -l conf" +alias main=man +alias mian=man +alias su="su -" + +video() { + mpv "$1" --ytdl-format="bestvideo[height>=720]+bestaudio/best[height>=720]" +} +videolow() { + mpv "$1" --ytdl-format="bestvideo[height<=720]+bestaudio/best[height<=720]" +} + +#else +bindkey -e +batstat=$(cat /sys/class/power_supply/BAT1/status 2>/dev/null) +charge=$(cat /sys/class/power_supply/BAT1/capacity 2>/dev/null) +if [[ "$batstat" == "Discharging" && "$charge" -lt 50 ]]; then + echo "Battery: $(sb-battery)" +fi + +noipv6(){ + doas sysctl -w net.ipv6.conf.all.disable_ipv6=1 + doas sysctl -w net.ipv6.conf.default.disable_ipv6=1 + doas sysctl -w net.ipv6.conf.lo.disable_ipv6=1 +} + +#PROXYCHAINS_IGNORE=( +# cd exit clear fg bg jobs history +# ssh scp sftp +# proxychains +#) +# +#autoload -U add-zsh-hook +# +#_proxychains_auto() { +# local cmd="$BUFFER" +# [[ -z "$cmd" ]] && return +# +# # get first word of command +# local first=${cmd%% *} +# +# # ignore listed commands +# for ignore in "${PROXYCHAINS_IGNORE[@]}"; do +# [[ "$first" == "$ignore" ]] && return +# done +# +# # sudo/doas handling +# if [[ "$cmd" == sudo\ * ]]; then +# BUFFER="sudo proxychains ${cmd#sudo }" +# elif [[ "$cmd" == doas\ * ]]; then +# BUFFER="doas proxychains ${cmd#doas }" +# else +# BUFFER="proxychains $cmd" +# fi +#} +# +#add-zsh-hook preexec _proxychains_auto +if test -z "$XDG_RUNTIME_DIR"; then + export XDG_RUNTIME_DIR=$(mktemp -d /tmp/$(id -u)-runtime-dir.XXX) +fi diff --git a/.zsh.d/zsh-autosuggestions.zsh b/.zsh.d/zsh-autosuggestions.zsh new file mode 100755 index 0000000..e780225 --- /dev/null +++ b/.zsh.d/zsh-autosuggestions.zsh @@ -0,0 +1,867 @@ +# Fish-like fast/unobtrusive autosuggestions for zsh. +# https://github.com/zsh-users/zsh-autosuggestions +# v0.7.1 +# Copyright (c) 2013 Thiago de Arruda +# Copyright (c) 2016-2021 Eric Freese +# +# 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. + +#--------------------------------------------------------------------# +# Global Configuration Variables # +#--------------------------------------------------------------------# + +# Color to use when highlighting suggestion +# Uses format of `region_highlight` +# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets +(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) && +typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8' + +# Prefix to use when saving original versions of bound widgets +(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) && +typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig- + +# Strategies to use to fetch a suggestion +# Will try each strategy in order until a suggestion is returned +(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && { + typeset -ga ZSH_AUTOSUGGEST_STRATEGY + ZSH_AUTOSUGGEST_STRATEGY=(history) +} + +# Widgets that clear the suggestion +(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && { + typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS + ZSH_AUTOSUGGEST_CLEAR_WIDGETS=( + history-search-forward + history-search-backward + history-beginning-search-forward + history-beginning-search-backward + history-beginning-search-forward-end + history-beginning-search-backward-end + history-substring-search-up + history-substring-search-down + up-line-or-beginning-search + down-line-or-beginning-search + up-line-or-history + down-line-or-history + accept-line + copy-earlier-word + ) +} + +# Widgets that accept the entire suggestion +(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && { + typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS + ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=( + forward-char + end-of-line + vi-forward-char + vi-end-of-line + vi-add-eol + ) +} + +# Widgets that accept the entire suggestion and execute it +(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && { + typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS + ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=( + ) +} + +# Widgets that accept the suggestion as far as the cursor moves +(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && { + typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS + ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=( + forward-word + emacs-forward-word + vi-forward-word + vi-forward-word-end + vi-forward-blank-word + vi-forward-blank-word-end + vi-find-next-char + vi-find-next-char-skip + ) +} + +# Widgets that should be ignored (globbing supported but must be escaped) +(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && { + typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS + ZSH_AUTOSUGGEST_IGNORE_WIDGETS=( + orig-\* + beep + run-help + set-local-history + which-command + yank + yank-pop + zle-\* + ) +} + +# Pty name for capturing completions for completion suggestion strategy +(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) && +typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty + +#--------------------------------------------------------------------# +# Utility Functions # +#--------------------------------------------------------------------# + +_zsh_autosuggest_escape_command() { + setopt localoptions EXTENDED_GLOB + + # Escape special chars in the string (requires EXTENDED_GLOB) + echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}" +} + +#--------------------------------------------------------------------# +# Widget Helpers # +#--------------------------------------------------------------------# + +_zsh_autosuggest_incr_bind_count() { + typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1)) + _ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count +} + +# Bind a single widget to an autosuggest widget, saving a reference to the original widget +_zsh_autosuggest_bind_widget() { + typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS + + local widget=$1 + local autosuggest_action=$2 + local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX + + local -i bind_count + + # Save a reference to the original widget + case $widgets[$widget] in + # Already bound + user:_zsh_autosuggest_(bound|orig)_*) + bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget])) + ;; + + # User-defined widget + user:*) + _zsh_autosuggest_incr_bind_count $widget + zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:} + ;; + + # Built-in widget + builtin) + _zsh_autosuggest_incr_bind_count $widget + eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }" + zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget + ;; + + # Completion widget + completion:*) + _zsh_autosuggest_incr_bind_count $widget + eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}" + ;; + esac + + # Pass the original widget's name explicitly into the autosuggest + # function. Use this passed in widget name to call the original + # widget instead of relying on the $WIDGET variable being set + # correctly. $WIDGET cannot be trusted because other plugins call + # zle without the `-w` flag (e.g. `zle self-insert` instead of + # `zle self-insert -w`). + eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() { + _zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@ + }" + + # Create the bound widget + zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget +} + +# Map all configured widgets to the right autosuggest widgets +_zsh_autosuggest_bind_widgets() { + emulate -L zsh + + local widget + local ignore_widgets + + ignore_widgets=( + .\* + _\* + ${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-} + $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\* + $ZSH_AUTOSUGGEST_IGNORE_WIDGETS + ) + + # Find every widget we might want to bind and bind it appropriately + for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do + if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then + _zsh_autosuggest_bind_widget $widget clear + elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then + _zsh_autosuggest_bind_widget $widget accept + elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then + _zsh_autosuggest_bind_widget $widget execute + elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then + _zsh_autosuggest_bind_widget $widget partial_accept + else + # Assume any unspecified widget might modify the buffer + _zsh_autosuggest_bind_widget $widget modify + fi + done +} + +# Given the name of an original widget and args, invoke it, if it exists +_zsh_autosuggest_invoke_original_widget() { + # Do nothing unless called with at least one arg + (( $# )) || return 0 + + local original_widget_name="$1" + + shift + + if (( ${+widgets[$original_widget_name]} )); then + zle $original_widget_name -- $@ + fi +} + +#--------------------------------------------------------------------# +# Highlighting # +#--------------------------------------------------------------------# + +# If there was a highlight, remove it +_zsh_autosuggest_highlight_reset() { + typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT + + if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then + region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}") + unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT + fi +} + +# If there's a suggestion, highlight it +_zsh_autosuggest_highlight_apply() { + typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT + + if (( $#POSTDISPLAY )); then + typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" + region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT") + else + unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT + fi +} + +#--------------------------------------------------------------------# +# Autosuggest Widget Implementations # +#--------------------------------------------------------------------# + +# Disable suggestions +_zsh_autosuggest_disable() { + typeset -g _ZSH_AUTOSUGGEST_DISABLED + _zsh_autosuggest_clear +} + +# Enable suggestions +_zsh_autosuggest_enable() { + unset _ZSH_AUTOSUGGEST_DISABLED + + if (( $#BUFFER )); then + _zsh_autosuggest_fetch + fi +} + +# Toggle suggestions (enable/disable) +_zsh_autosuggest_toggle() { + if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then + _zsh_autosuggest_enable + else + _zsh_autosuggest_disable + fi +} + +# Clear the suggestion +_zsh_autosuggest_clear() { + # Remove the suggestion + POSTDISPLAY= + + _zsh_autosuggest_invoke_original_widget $@ +} + +# Modify the buffer and get a new suggestion +_zsh_autosuggest_modify() { + local -i retval + + # Only available in zsh >= 5.4 + local -i KEYS_QUEUED_COUNT + + # Save the contents of the buffer/postdisplay + local orig_buffer="$BUFFER" + local orig_postdisplay="$POSTDISPLAY" + + # Clear suggestion while waiting for next one + POSTDISPLAY= + + # Original widget may modify the buffer + _zsh_autosuggest_invoke_original_widget $@ + retval=$? + + emulate -L zsh + + # Don't fetch a new suggestion if there's more input to be read immediately + if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then + POSTDISPLAY="$orig_postdisplay" + return $retval + fi + + # Optimize if manually typing in the suggestion or if buffer hasn't changed + if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then + POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}" + return $retval + fi + + # Bail out if suggestions are disabled + if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then + return $? + fi + + # Get a new suggestion if the buffer is not empty after modification + if (( $#BUFFER > 0 )); then + if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then + _zsh_autosuggest_fetch + fi + fi + + return $retval +} + +# Fetch a new suggestion based on what's currently in the buffer +_zsh_autosuggest_fetch() { + if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then + _zsh_autosuggest_async_request "$BUFFER" + else + local suggestion + _zsh_autosuggest_fetch_suggestion "$BUFFER" + _zsh_autosuggest_suggest "$suggestion" + fi +} + +# Offer a suggestion +_zsh_autosuggest_suggest() { + emulate -L zsh + + local suggestion="$1" + + if [[ -n "$suggestion" ]] && (( $#BUFFER )); then + POSTDISPLAY="${suggestion#$BUFFER}" + else + POSTDISPLAY= + fi +} + +# Accept the entire suggestion +_zsh_autosuggest_accept() { + local -i retval max_cursor_pos=$#BUFFER + + # When vicmd keymap is active, the cursor can't move all the way + # to the end of the buffer + if [[ "$KEYMAP" = "vicmd" ]]; then + max_cursor_pos=$((max_cursor_pos - 1)) + fi + + # If we're not in a valid state to accept a suggestion, just run the + # original widget and bail out + if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then + _zsh_autosuggest_invoke_original_widget $@ + return + fi + + # Only accept if the cursor is at the end of the buffer + # Add the suggestion to the buffer + BUFFER="$BUFFER$POSTDISPLAY" + + # Remove the suggestion + POSTDISPLAY= + + # Run the original widget before manually moving the cursor so that the + # cursor movement doesn't make the widget do something unexpected + _zsh_autosuggest_invoke_original_widget $@ + retval=$? + + # Move the cursor to the end of the buffer + if [[ "$KEYMAP" = "vicmd" ]]; then + CURSOR=$(($#BUFFER - 1)) + else + CURSOR=$#BUFFER + fi + + return $retval +} + +# Accept the entire suggestion and execute it +_zsh_autosuggest_execute() { + # Add the suggestion to the buffer + BUFFER="$BUFFER$POSTDISPLAY" + + # Remove the suggestion + POSTDISPLAY= + + # Call the original `accept-line` to handle syntax highlighting or + # other potential custom behavior + _zsh_autosuggest_invoke_original_widget "accept-line" +} + +# Partially accept the suggestion +_zsh_autosuggest_partial_accept() { + local -i retval cursor_loc + + # Save the contents of the buffer so we can restore later if needed + local original_buffer="$BUFFER" + + # Temporarily accept the suggestion. + BUFFER="$BUFFER$POSTDISPLAY" + + # Original widget moves the cursor + _zsh_autosuggest_invoke_original_widget $@ + retval=$? + + # Normalize cursor location across vi/emacs modes + cursor_loc=$CURSOR + if [[ "$KEYMAP" = "vicmd" ]]; then + cursor_loc=$((cursor_loc + 1)) + fi + + # If we've moved past the end of the original buffer + if (( $cursor_loc > $#original_buffer )); then + # Set POSTDISPLAY to text right of the cursor + POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}" + + # Clip the buffer at the cursor + BUFFER="${BUFFER[1,$cursor_loc]}" + else + # Restore the original buffer + BUFFER="$original_buffer" + fi + + return $retval +} + +() { + typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS + + _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=( + clear + fetch + suggest + accept + execute + enable + disable + toggle + ) + + local action + for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do + eval "_zsh_autosuggest_widget_$action() { + local -i retval + + _zsh_autosuggest_highlight_reset + + _zsh_autosuggest_$action \$@ + retval=\$? + + _zsh_autosuggest_highlight_apply + + zle -R + + return \$retval + }" + done + + for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do + zle -N autosuggest-$action _zsh_autosuggest_widget_$action + done +} + +#--------------------------------------------------------------------# +# Completion Suggestion Strategy # +#--------------------------------------------------------------------# +# Fetches a suggestion from the completion engine +# + +_zsh_autosuggest_capture_postcompletion() { + # Always insert the first completion into the buffer + compstate[insert]=1 + + # Don't list completions + unset 'compstate[list]' +} + +_zsh_autosuggest_capture_completion_widget() { + # Add a post-completion hook to be called after all completions have been + # gathered. The hook can modify compstate to affect what is done with the + # gathered completions. + local -a +h comppostfuncs + comppostfuncs=(_zsh_autosuggest_capture_postcompletion) + + # Only capture completions at the end of the buffer + CURSOR=$#BUFFER + + # Run the original widget wrapping `.complete-word` so we don't + # recursively try to fetch suggestions, since our pty is forked + # after autosuggestions is initialized. + zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]} + + if is-at-least 5.0.3; then + # Don't do any cr/lf transformations. We need to do this immediately before + # output because if we do it in setup, onlcr will be re-enabled when we enter + # vared in the async code path. There is a bug in zpty module in older versions + # where the tty is not properly attached to the pty slave, resulting in stty + # getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream + # commit f75904a38 + stty -onlcr -ocrnl -F /dev/tty + fi + + # The completion has been added, print the buffer as the suggestion + echo -nE - $'\0'$BUFFER$'\0' +} + +zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget + +_zsh_autosuggest_capture_setup() { + # There is a bug in zpty module in older zsh versions by which a + # zpty that exits will kill all zpty processes that were forked + # before it. Here we set up a zsh exit hook to SIGKILL the zpty + # process immediately, before it has a chance to kill any other + # zpty processes. + if ! is-at-least 5.4; then + zshexit() { + # The zsh builtin `kill` fails sometimes in older versions + # https://unix.stackexchange.com/a/477647/156673 + kill -KILL $$ 2>&- || command kill -KILL $$ + + # Block for long enough for the signal to come through + sleep 1 + } + fi + + # Try to avoid any suggestions that wouldn't match the prefix + zstyle ':completion:*' matcher-list '' + zstyle ':completion:*' path-completion false + zstyle ':completion:*' max-errors 0 not-numeric + + bindkey '^I' autosuggest-capture-completion +} + +_zsh_autosuggest_capture_completion_sync() { + _zsh_autosuggest_capture_setup + + zle autosuggest-capture-completion +} + +_zsh_autosuggest_capture_completion_async() { + _zsh_autosuggest_capture_setup + + zmodload zsh/parameter 2>/dev/null || return # For `$functions` + + # Make vared completion work as if for a normal command line + # https://stackoverflow.com/a/7057118/154703 + autoload +X _complete + functions[_original_complete]=$functions[_complete] + function _complete() { + unset 'compstate[vared]' + _original_complete "$@" + } + + # Open zle with buffer set so we can capture completions for it + vared 1 +} + +_zsh_autosuggest_strategy_completion() { + # Reset options to defaults and enable LOCAL_OPTIONS + emulate -L zsh + + # Enable extended glob for completion ignore pattern + setopt EXTENDED_GLOB + + typeset -g suggestion + local line REPLY + + # Exit if we don't have completions + whence compdef >/dev/null || return + + # Exit if we don't have zpty + zmodload zsh/zpty 2>/dev/null || return + + # Exit if our search string matches the ignore pattern + [[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return + + # Zle will be inactive if we are in async mode + if zle; then + zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync + else + zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1" + zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t' + fi + + { + # The completion result is surrounded by null bytes, so read the + # content between the first two null bytes. + zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0' + + # Extract the suggestion from between the null bytes. On older + # versions of zsh (older than 5.3), we sometimes get extra bytes after + # the second null byte, so trim those off the end. + # See http://www.zsh.org/mla/workers/2015/msg03290.html + suggestion="${${(@0)line}[2]}" + } always { + # Destroy the pty + zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME + } +} + +#--------------------------------------------------------------------# +# History Suggestion Strategy # +#--------------------------------------------------------------------# +# Suggests the most recent history item that matches the given +# prefix. +# + +_zsh_autosuggest_strategy_history() { + # Reset options to defaults and enable LOCAL_OPTIONS + emulate -L zsh + + # Enable globbing flags so that we can use (#m) and (x~y) glob operator + setopt EXTENDED_GLOB + + # Escape backslashes and all of the glob operators so we can use + # this string as a pattern to search the $history associative array. + # - (#m) globbing flag enables setting references for match data + # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 + local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" + + # Get the history items that match the prefix, excluding those that match + # the ignore pattern + local pattern="$prefix*" + if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then + pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" + fi + + # Give the first history item matching the pattern as the suggestion + # - (r) subscript flag makes the pattern match on values + typeset -g suggestion="${history[(r)$pattern]}" +} + +#--------------------------------------------------------------------# +# Match Previous Command Suggestion Strategy # +#--------------------------------------------------------------------# +# Suggests the most recent history item that matches the given +# prefix and whose preceding history item also matches the most +# recently executed command. +# +# For example, suppose your history has the following entries: +# - pwd +# - ls foo +# - ls bar +# - pwd +# +# Given the history list above, when you type 'ls', the suggestion +# will be 'ls foo' rather than 'ls bar' because your most recently +# executed command (pwd) was previously followed by 'ls foo'. +# +# Note that this strategy won't work as expected with ZSH options that don't +# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or +# `HIST_EXPIRE_DUPS_FIRST`. + +_zsh_autosuggest_strategy_match_prev_cmd() { + # Reset options to defaults and enable LOCAL_OPTIONS + emulate -L zsh + + # Enable globbing flags so that we can use (#m) and (x~y) glob operator + setopt EXTENDED_GLOB + + # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 + local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" + + # Get the history items that match the prefix, excluding those that match + # the ignore pattern + local pattern="$prefix*" + if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then + pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" + fi + + # Get all history event numbers that correspond to history + # entries that match the pattern + local history_match_keys + history_match_keys=(${(k)history[(R)$~pattern]}) + + # By default we use the first history number (most recent history entry) + local histkey="${history_match_keys[1]}" + + # Get the previously executed command + local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")" + + # Iterate up to the first 200 history event numbers that match $prefix + for key in "${(@)history_match_keys[1,200]}"; do + # Stop if we ran out of history + [[ $key -gt 1 ]] || break + + # See if the history entry preceding the suggestion matches the + # previous command, and use it if it does + if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then + histkey="$key" + break + fi + done + + # Give back the matched history entry + typeset -g suggestion="$history[$histkey]" +} + +#--------------------------------------------------------------------# +# Fetch Suggestion # +#--------------------------------------------------------------------# +# Loops through all specified strategies and returns a suggestion +# from the first strategy to provide one. +# + +_zsh_autosuggest_fetch_suggestion() { + typeset -g suggestion + local -a strategies + local strategy + + # Ensure we are working with an array + strategies=(${=ZSH_AUTOSUGGEST_STRATEGY}) + + for strategy in $strategies; do + # Try to get a suggestion from this strategy + _zsh_autosuggest_strategy_$strategy "$1" + + # Ensure the suggestion matches the prefix + [[ "$suggestion" != "$1"* ]] && unset suggestion + + # Break once we've found a valid suggestion + [[ -n "$suggestion" ]] && break + done +} + +#--------------------------------------------------------------------# +# Async # +#--------------------------------------------------------------------# + +_zsh_autosuggest_async_request() { + zmodload zsh/system 2>/dev/null # For `$sysparams` + + typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID + + # If we've got a pending request, cancel it + if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then + # Close the file descriptor and remove the handler + builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&- + zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD + + # We won't know the pid unless the user has zsh/system module installed + if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then + # Zsh will make a new process group for the child process only if job + # control is enabled (MONITOR option) + if [[ -o MONITOR ]]; then + # Send the signal to the process group to kill any processes that may + # have been forked by the suggestion strategy + kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null + else + # Kill just the child process since it wasn't placed in a new process + # group. If the suggestion strategy forked any child processes they may + # be orphaned and left behind. + kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null + fi + fi + fi + + # Fork a process to fetch a suggestion and open a pipe to read from it + builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <( + # Tell parent process our pid + echo $sysparams[pid] + + # Fetch and print the suggestion + local suggestion + _zsh_autosuggest_fetch_suggestion "$1" + echo -nE "$suggestion" + ) + + # There's a weird bug here where ^C stops working unless we force a fork + # See https://github.com/zsh-users/zsh-autosuggestions/issues/364 + autoload -Uz is-at-least + is-at-least 5.8 || command true + + # Read the pid from the child process + read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD + + # When the fd is readable, call the response handler + zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response +} + +# Called when new data is ready to be read from the pipe +# First arg will be fd ready for reading +# Second arg will be passed in case of error +_zsh_autosuggest_async_response() { + emulate -L zsh + + local suggestion + + if [[ -z "$2" || "$2" == "hup" ]]; then + # Read everything from the fd and give it as a suggestion + IFS='' read -rd '' -u $1 suggestion + zle autosuggest-suggest -- "$suggestion" + + # Close the fd + builtin exec {1}<&- + fi + + # Always remove the handler + zle -F "$1" + _ZSH_AUTOSUGGEST_ASYNC_FD= +} + +#--------------------------------------------------------------------# +# Start # +#--------------------------------------------------------------------# + +# Start the autosuggestion widgets +_zsh_autosuggest_start() { + # By default we re-bind widgets on every precmd to ensure we wrap other + # wrappers. Specifically, highlighting breaks if our widgets are wrapped by + # zsh-syntax-highlighting widgets. This also allows modifications to the + # widget list variables to take effect on the next precmd. However this has + # a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND + # to disable the automatic re-binding. + if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then + add-zsh-hook -d precmd _zsh_autosuggest_start + fi + + _zsh_autosuggest_bind_widgets +} + +# Mark for auto-loading the functions that we use +autoload -Uz add-zsh-hook is-at-least + +# Automatically enable asynchronous mode in newer versions of zsh. Disable for +# older versions because there is a bug when using async mode where ^C does not +# work immediately after fetching a suggestion. +# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 +if is-at-least 5.0.8; then + typeset -g ZSH_AUTOSUGGEST_USE_ASYNC= +fi + +# Start the autosuggestion widgets on the next precmd +add-zsh-hook precmd _zsh_autosuggest_start diff --git a/.zshrc b/.zshrc new file mode 100755 index 0000000..b0edb53 --- /dev/null +++ b/.zshrc @@ -0,0 +1,21 @@ +#!/bin/zsh +source /etc/profile +HISTFILE=$HOME/.cache/zsh/history +SAVEHIST=100000000 +HISTSIZE=$SAVEHIST +setopt appendhistory +autoload -U compinit +zstyle ':completion:*' menu select +zmodload zsh/complist +compinit +comp_options+=(globdots) +zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' +source ~/.zsh.d/* +autoload -U colors && colors && setopt prompt_subst +ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=5" +ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=12" +LIBCLANG_PATH=/usr/lib/llvm/20/lib64 +source ~/.zprofile +PATH=$PATH:/home/coast/.spicetify + +PROMPT="0 %n %1~ " diff --git a/.zshrc.root b/.zshrc.root new file mode 100755 index 0000000..90b5d36 --- /dev/null +++ b/.zshrc.root @@ -0,0 +1,33 @@ +#!/bin/zsh +#history settings +HISTFILE=$HOME/.cache/zsh/history +SAVEHIST=100000000 +HISTSIZE=$SAVEHIST +setopt appendhistory +#completion +autoload -U compinit +zstyle ':completion:*' menu select +zmodload zsh/complist +compinit +comp_options+=(globdots) +zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' +source /usr/share/zsh/site-functions/zsh-autosuggestions.zsh && fpath=(/usr/share/zsh/site-functions $fpath) && source /usr/share/zsh/site-functions/zsh-syntax-highlighting.zsh +#colors & prompt +autoload -U colors && colors && setopt prompt_subst +ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=5" +ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=12" +#PROMPT="%F{9}[%f%F{9}!root%f%F{9}@%f%F{9}%m%f %F{2}%~%f%F{9}]%f: " +#paths and environment +fpath=(~/.zsh/completions $fpath) +export PATH=$HOME/.local/bin:$PATH +export EDITOR="emacs" +export PATH=/usr/pkg/sbin:/usr/pkg/bin:$PATH +export MANPATH=/usr/pkg/man:$MANPATH +#aliases for root +alias ..='echo "cd .."; cd ../' +alias ls="ls --color=auto" +grep --color=auto < /dev/null &>/dev/null && alias grep='grep --color=auto' +bindkey -e +#export PS1="%F{15}[%f%F{252}%B%n%b%f%F{15}@%f%F{15}%B%m%b%f%F{15}]%f%F{252}[%f%F{15}%B%~%b%f%F{252}]%f#%B%b " + +export PS1="%F{1}[%B!%n@%m%b %F{2}%~%F{1}]%f: " diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100755 index 0000000..5d8bd93 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +## README - Coast's dotfiles + +Most of these dotfiles are oldies — my newer ones live in my home-manager configuration. +If you want shiny, modern dotfiles, make sure you have Nix Home Manager installed, then run: +*Make sure you have Nix Package Manager installed first!* + +```bash +cd ~/.config && mkdir home-manager +git clone https://codeberg.org/coast/home-manager.git +nix run home-manager -- init --switch . +``` + +I think these commands will set up home-manager with my quirky configuration. +But to be brutally honest, please don’t use mine — you deserve way better! :3 Like your own setup! Mine’s kinda ass. I love ass. + +### Disclaimer +*These dotfiles reflect my personal preferences and workflow. They might not be suitable for everyone and could require adjustments to fit your needs.* +*They were set up how I learned how to set it up, you might not like how I've set up my program(s)' configuration files in this repository. I strongly recommend that you write your own configs.* +*Feel free to fork, modify, or use parts of this configuration as an inspiration for your own setup.* + + diff --git a/colorlist.palette b/colorlist.palette new file mode 100755 index 0000000..48f67a0 --- /dev/null +++ b/colorlist.palette @@ -0,0 +1,10 @@ +#66cccc // Soft Cyan +#00cccc // Medium Cyan +#00ffff // Bright Cyan +#33aaaa // Teal Cyan +#009999 // Deep Cyan +#11a8cd // Aqua Glow +#00e5e5 // Electric Cyan + + +#a8dcee // sky cyan diff --git a/config/alacritty/alacritty.toml b/config/alacritty/alacritty.toml new file mode 100644 index 0000000..41959d2 --- /dev/null +++ b/config/alacritty/alacritty.toml @@ -0,0 +1,16 @@ +[window] +dimensions = { columns = 100, lines = 25 } +dynamic_title = true +[terminal.shell] +program = "/usr/bin/zsh" +[font] +normal = { family = "JetBrains Mono Nerd Font", style = "Regular" } +size = 13.0 +[cursor] +style = { shape = "Underline", blinking = "Off" } +[colors] +primary = { background = "#121212", foreground = "#e0e0e0" } +cursor = { cursor = "#e0e0e0", text = "#121212" } +selection = { background = "#e0e0e0", text = "#121212" } +normal = { black = "#121212", red = "#d32f2f", green = "#4caf50", yellow = "#ffeb3b", blue = "#2196f3", magenta = "#9c27b0", cyan = "#00bcd4", white = "#e0e0e0" } +bright = { black = "#757575", red = "#f44336", green = "#8bc34a", yellow = "#ffc107", blue = "#3f51b5", magenta = "#673ab7", cyan = "#009688", white = "#ffffff" } diff --git a/config/bspwm/bspwmrc b/config/bspwm/bspwmrc new file mode 100755 index 0000000..e4a1ca9 --- /dev/null +++ b/config/bspwm/bspwmrc @@ -0,0 +1,82 @@ +#!/bin/sh +# my bspwmrc + +# desktops +bspc monitor -d I II III IV V VI VII VIII IX X + +# borders +bspc config focused_border_color "#383838" +bspc config normal_border_color "#282828" +bspc config border_width 2 + +# layout +bspc config window_gap 10 +bspc config split_ratio 0.5 +bspc config smart_gap true + +# focus behavior +bspc config focus_follows_pointer true +bspc config click_to_focus false +bspc config pointer_follows_monitor true + +# monitor / window behavior +bspc config remove_disabled_monitors true +bspc config auto_cancel true +bspc config auto_alternate true + +# padding +bspc config bottom_padding 0 + + +### {{{ find and stop processes + +pidb() { + pgrep -x "$1" >/dev/null 2>&1 +} + +run() { + proc="$1" + cmd="$2" + + if ! pidb "$proc"; then + sh -c "$cmd" & + fi +} + +### }}} + + +### {{{ rerun/start processes + +# piss +run "piss" "piss" + +# picom +run "picom" "picom --backend glx" + +# dunst +run "dunst" "dunst" + +# bspbar +run "bspbar" "bspbar" + +# polkit gnome +run "polkit-gnome-authentication-agent-1" \ + "/usr/libexec/polkit-gnome-authentication-agent-1" + +# xsettingsd +run "xsettingsd" "xsettingsd" + +# pulseaudio +run "pulseaudio" "pulseaudio --start" + +# pipewire +run "pipewire" "pipewire" + +# xtkhd +run "xtkhd" "xtkhd" + +xrandr --output eDP-1 --off +hsetroot -center "$HOME/Downloads/wall4.png" + +### }}} diff --git a/config/btop/btop.conf b/config/btop/btop.conf new file mode 100755 index 0000000..43cd05d --- /dev/null +++ b/config/btop/btop.conf @@ -0,0 +1,254 @@ +#? Config file for btop v. 1.4.3 + +#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes. +#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes" +color_theme = "dracula" + +#* If the theme set background should be shown, set to False if you want terminal background transparency. +theme_background = False + +#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false. +truecolor = True + +#* Set to true to force tty mode regardless if a real tty has been detected or not. +#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols. +force_tty = False + +#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets. +#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box. +#* Use whitespace " " as separator between different presets. +#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty" +presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty" + +#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists. +#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift. +vim_keys = True + +#* Rounded corners on boxes, is ignored if TTY mode is ON. +rounded_corners = False + +#* Default symbols to use for graph creation, "braille", "block" or "tty". +#* "braille" offers the highest resolution but might not be included in all fonts. +#* "block" has half the resolution of braille but uses more common characters. +#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY. +#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view. +graph_symbol = "braille" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_cpu = "default" + +# Graph symbol to use for graphs in gpu box, "default", "braille", "block" or "tty". +graph_symbol_gpu = "default" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_mem = "default" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_net = "default" + +# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". +graph_symbol_proc = "default" + +#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace. +shown_boxes = "cpu mem net proc" + +#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs. +update_ms = 2000 + +#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct", +#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly. +proc_sorting = "cpu lazy" + +#* Reverse sorting order, True or False. +proc_reversed = False + +#* Show processes as a tree. +proc_tree = False + +#* Use the cpu graph colors in the process list. +proc_colors = True + +#* Use a darkening gradient in the process list. +proc_gradient = True + +#* If process cpu usage should be of the core it's running on or usage of the total available cpu power. +proc_per_core = False + +#* Show process memory as bytes instead of percent. +proc_mem_bytes = True + +#* Show cpu graph for each process. +proc_cpu_graphs = True + +#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate) +proc_info_smaps = False + +#* Show proc box on left side of screen instead of right. +proc_left = False + +#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop). +proc_filter_kernel = False + +#* In tree-view, always accumulate child process resources in the parent process. +proc_aggregate = False + +#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available. +#* Select from a list of detected attributes from the options menu. +cpu_graph_upper = "Auto" + +#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available. +#* Select from a list of detected attributes from the options menu. +cpu_graph_lower = "Auto" + +#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off". +show_gpu_info = "Auto" + +#* Toggles if the lower CPU graph should be inverted. +cpu_invert_lower = True + +#* Set to True to completely disable the lower CPU graph. +cpu_single_graph = False + +#* Show cpu box at bottom of screen instead of top. +cpu_bottom = False + +#* Shows the system uptime in the CPU box. +show_uptime = True + +#* Show cpu temperature. +check_temp = True + +#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors. +cpu_sensor = "Auto" + +#* Show temperatures for cpu cores also if check_temp is True and sensors has been found. +show_coretemp = True + +#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core. +#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine. +#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries. +#* Example: "4:0 5:1 6:3" +cpu_core_map = "" + +#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine". +temp_scale = "celsius" + +#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024. +base_10_sizes = False + +#* Show CPU frequency. +show_cpu_freq = True + +#* Draw a clock at top of screen, formatting according to strftime, empty string to disable. +#* Special formatting: /host = hostname | /user = username | /uptime = system uptime +clock_format = "%X" + +#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort. +background_update = True + +#* Custom cpu model name, empty string to disable. +custom_cpu_name = "" + +#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ". +#* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user". +disks_filter = "" + +#* Show graphs instead of meters for memory values. +mem_graphs = True + +#* Show mem box below net box instead of above. +mem_below_net = False + +#* Count ZFS ARC in cached and available memory. +zfs_arc_cached = True + +#* If swap memory should be shown in memory box. +show_swap = True + +#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk. +swap_disk = True + +#* If mem box should be split to also show disks info. +show_disks = True + +#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar. +only_physical = True + +#* Read disks list from /etc/fstab. This also disables only_physical. +use_fstab = True + +#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool) +zfs_hide_datasets = False + +#* Set to true to show available disk space for privileged users. +disk_free_priv = False + +#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view. +show_io_stat = True + +#* Toggles io mode for disks, showing big graphs for disk read/write speeds. +io_mode = False + +#* Set to True to show combined read/write io graphs in io mode. +io_graph_combined = False + +#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ". +#* Example: "/mnt/media:100 /:20 /boot:1". +io_graph_speeds = "" + +#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False. +net_download = 100 + +net_upload = 100 + +#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest. +net_auto = True + +#* Sync the auto scaling for download and upload to whichever currently has the highest scale. +net_sync = True + +#* Starts with the Network Interface specified here. +net_iface = "" + +#* "True" shows bitrates in base 10 (Kbps, Mbps). "False" shows bitrates in binary sizes (Kibps, Mibps, etc.). "Auto" uses base_10_sizes. +base_10_bitrate = "Auto" + +#* Show battery stats in top right if battery is present. +show_battery = True + +#* Which battery to use if multiple are present. "Auto" for auto detection. +selected_battery = "Auto" + +#* Show power stats of battery next to charge indicator. +show_battery_watts = True + +#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG". +#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info. +log_level = "WARNING" + +#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards. +nvml_measure_pcie_speeds = True + +#* Measure PCIe throughput on AMD cards, may impact performance on certain cards. +rsmi_measure_pcie_speeds = True + +#* Horizontally mirror the GPU graph. +gpu_mirror_graph = True + +#* Custom gpu0 model name, empty string to disable. +custom_gpu_name0 = "" + +#* Custom gpu1 model name, empty string to disable. +custom_gpu_name1 = "" + +#* Custom gpu2 model name, empty string to disable. +custom_gpu_name2 = "" + +#* Custom gpu3 model name, empty string to disable. +custom_gpu_name3 = "" + +#* Custom gpu4 model name, empty string to disable. +custom_gpu_name4 = "" + +#* Custom gpu5 model name, empty string to disable. +custom_gpu_name5 = "" diff --git a/config/btop/themes/coasteen.theme b/config/btop/themes/coasteen.theme new file mode 100755 index 0000000..52e4152 --- /dev/null +++ b/config/btop/themes/coasteen.theme @@ -0,0 +1,89 @@ +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="" + +# Main text color +theme[main_fg]="#f8e8ec" + +# Title color for boxes +theme[title]="#f8e8ec" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#ff8aa0" + +# Background color of selected item in processes box +theme[selected_bg]="#7b3949" + +# Foreground color of selected item in processes box +theme[selected_fg]="#f8e8ec" + +# Color of inactive/disabled text +theme[inactive_fg]="#a56a79" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#c67090" + +# Background color of the percentage meters +theme[meter_bg]="#a65c6c" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#ff8aa0" + +# Cpu box outline color +theme[cpu_box]="#d77189" + +# Memory/disks box outline color +theme[mem_box]="#d77189" + +# Net up/down box outline color +theme[net_box]="#d77189" + +# Processes box outline color +theme[proc_box]="#d77189" + +# Box divider line and small boxes line color +theme[div_line]="#6f3b4a" + +# Temperature graph colors +theme[temp_start]="#ff8aa0" +theme[temp_mid]="#d77189" +theme[temp_end]="#a65c6c" + +# CPU graph colors +theme[cpu_start]="#ff8aa0" +theme[cpu_mid]="#d77189" +theme[cpu_end]="#a65c6c" + +# Mem/Disk free meter +theme[free_start]="#ff8aa0" +theme[free_mid]="#d77189" +theme[free_end]="#a65c6c" + +# Mem/Disk cached meter +theme[cached_start]="#ff8aa0" +theme[cached_mid]="#d77189" +theme[cached_end]="#a65c6c" + +# Mem/Disk available meter +theme[available_start]="#ff8aa0" +theme[available_mid]="#d77189" +theme[available_end]="#a65c6c" + +# Mem/Disk used meter +theme[used_start]="#ff8aa0" +theme[used_mid]="#d77189" +theme[used_end]="#a65c6c" + +# Download graph colors +theme[download_start]="#ff8aa0" +theme[download_mid]="#d77189" +theme[download_end]="#a65c6c" + +# Upload graph colors +theme[upload_start]="#f19bb4" +theme[upload_mid]="#d77189" +theme[upload_end]="#a65c6c" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#ff8aa0" +theme[process_mid]="#d77189" +theme[process_end]="#c67090" diff --git a/config/btop/themes/dracula.theme b/config/btop/themes/dracula.theme new file mode 100755 index 0000000..5768e5f --- /dev/null +++ b/config/btop/themes/dracula.theme @@ -0,0 +1,89 @@ +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#282a36" + +# Main text color +theme[main_fg]="#f8f8f2" + +# Title color for boxes +theme[title]="#f8f8f2" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#6272a4" + +# Background color of selected item in processes box +theme[selected_bg]="#ff79c6" + +# Foreground color of selected item in processes box +theme[selected_fg]="#f8f8f2" + +# Color of inactive/disabled text +theme[inactive_fg]="#44475a" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#f8f8f2" + +# Background color of the percentage meters +theme[meter_bg]="#44475a" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#bd93f9" + +# Cpu box outline color +theme[cpu_box]="#bd93f9" + +# Memory/disks box outline color +theme[mem_box]="#50fa7b" + +# Net up/down box outline color +theme[net_box]="#ff5555" + +# Processes box outline color +theme[proc_box]="#8be9fd" + +# Box divider line and small boxes line color +theme[div_line]="#44475a" + +# Temperature graph colors +theme[temp_start]="#bd93f9" +theme[temp_mid]="#ff79c6" +theme[temp_end]="#ff33a8" + +# CPU graph colors +theme[cpu_start]="#bd93f9" +theme[cpu_mid]="#8be9fd" +theme[cpu_end]="#50fa7b" + +# Mem/Disk free meter +theme[free_start]="#ffa6d9" +theme[free_mid]="#ff79c6" +theme[free_end]="#ff33a8" + +# Mem/Disk cached meter +theme[cached_start]="#b1f0fd" +theme[cached_mid]="#8be9fd" +theme[cached_end]="#26d7fd" + +# Mem/Disk available meter +theme[available_start]="#ffd4a6" +theme[available_mid]="#ffb86c" +theme[available_end]="#ff9c33" + +# Mem/Disk used meter +theme[used_start]="#96faaf" +theme[used_mid]="#50fa7b" +theme[used_end]="#0dfa49" + +# Download graph colors +theme[download_start]="#bd93f9" +theme[download_mid]="#50fa7b" +theme[download_end]="#8be9fd" + +# Upload graph colors +theme[upload_start]="#8c42ab" +theme[upload_mid]="#ff79c6" +theme[upload_end]="#ff33a8" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#50fa7b" +theme[process_mid]="#59b690" +theme[process_end]="#6272a4" diff --git a/config/btop/themes/gruvbox.theme b/config/btop/themes/gruvbox.theme new file mode 100755 index 0000000..8cd9d37 --- /dev/null +++ b/config/btop/themes/gruvbox.theme @@ -0,0 +1,92 @@ +#Bashtop gruvbox (https://github.com/morhetz/gruvbox) theme +#by BachoSeven + +# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" +# example for white: "#FFFFFF", "#ff" or "255 255 255". + +# All graphs and meters can be gradients +# For single color graphs leave "mid" and "end" variable empty. +# Use "start" and "end" variables for two color gradient +# Use "start", "mid" and "end" for three color gradient + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#1d2021" + +# Main text color +theme[main_fg]="#a89984" + +# Title color for boxes +theme[title]="#ebdbb2" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#d79921" + +# Background color of selected items +theme[selected_bg]="#282828" + +# Foreground color of selected items +theme[selected_fg]="#fabd2f" + +# Color of inactive/disabled text +theme[inactive_fg]="#282828" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#585858" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#98971a" + +# Cpu box outline color +theme[cpu_box]="#a89984" + +# Memory/disks box outline color +theme[mem_box]="#a89984" + +# Net up/down box outline color +theme[net_box]="#a89984" + +# Processes box outline color +theme[proc_box]="#a89984" + +# Box divider line and small boxes line color +theme[div_line]="#a89984" + +# Temperature graph colors +theme[temp_start]="#458588" +theme[temp_mid]="#d3869b" +theme[temp_end]="#fb4394" + +# CPU graph colors +theme[cpu_start]="#b8bb26" +theme[cpu_mid]="#d79921" +theme[cpu_end]="#fb4934" + +# Mem/Disk free meter +theme[free_start]="#4e5900" +theme[free_mid]="" +theme[free_end]="#98971a" + +# Mem/Disk cached meter +theme[cached_start]="#458588" +theme[cached_mid]="" +theme[cached_end]="#83a598" + +# Mem/Disk available meter +theme[available_start]="#d79921" +theme[available_mid]="" +theme[available_end]="#fabd2f" + +# Mem/Disk used meter +theme[used_start]="#cc241d" +theme[used_mid]="" +theme[used_end]="#fb4934" + +# Download graph colors +theme[download_start]="#3d4070" +theme[download_mid]="#6c71c4" +theme[download_end]="#a3a8f7" + +# Upload graph colors +theme[upload_start]="#701c45" +theme[upload_mid]="#b16286" +theme[upload_end]="#d3869b" diff --git a/config/btop/themes/kyli0x.theme b/config/btop/themes/kyli0x.theme new file mode 100755 index 0000000..c955287 --- /dev/null +++ b/config/btop/themes/kyli0x.theme @@ -0,0 +1,92 @@ +#Bashtop Kyli0x Theme +#by Kyli0x + +# Main background, empty for terminal default, need to be empty if you want transparent background +theme[main_bg]="#222222" + +# Main text color +theme[main_fg]="#e8f6f5" + +# Title color for boxes +theme[title]="#e8f6f5" + +# Highlight color for keyboard shortcuts +theme[hi_fg]="#21d6c9" + +# Background color of selected item in processes box +theme[selected_bg]="#1aaba0" + +# Foreground color of selected item in processes box +theme[selected_fg]="#e8f6f5" + +# Color of inactive/disabled text +theme[inactive_fg]="#5ec4bc" + +# Color of text appearing on top of graphs, i.e uptime and current network graph scaling +theme[graph_text]="#ba1a84" + +# Background color of the percentage meters +theme[meter_bg]="#5ec4bc" + +# Misc colors for processes box including mini cpu graphs, details memory graph and details status text +theme[proc_misc]="#21d6c9" + +# Cpu box outline color +theme[cpu_box]="#d486d4" + +# Memory/disks box outline color +theme[mem_box]="#d486d4" + +# Net up/down box outline color +theme[net_box]="#d486d4" + +# Processes box outline color +theme[proc_box]="#d486d4" + +# Box divider line and small boxes line color +theme[div_line]="#80638e" + +# Temperature graph colors +theme[temp_start]="#21d6c9" +theme[temp_mid]="#1aaba0" +theme[temp_end]="#5ec4bc" + +# CPU graph colors +theme[cpu_start]="#21d6c9" +theme[cpu_mid]="#1aaba0" +theme[cpu_end]="#5ec4bc" + +# Mem/Disk free meter +theme[free_start]="#21d6c9" +theme[free_mid]="#1aaba0" +theme[free_end]="#5ec4bc" + +# Mem/Disk cached meter +theme[cached_start]="#21d6c9" +theme[cached_mid]="#1aaba0" +theme[cached_end]="#5ec4bc" + +# Mem/Disk available meter +theme[available_start]="#21d6c9" +theme[available_mid]="#1aaba0" +theme[available_end]="#5ec4bc" + +# Mem/Disk used meter +theme[used_start]="#21d6c9" +theme[used_mid]="#1aaba0" +theme[used_end]="#5ec4bc" + +# Download graph colors +theme[download_start]="#21d6c9" +theme[download_mid]="#1aaba0" +theme[download_end]="#5ec4bc" + +# Upload graph colors +theme[upload_start]="#ec95ec" +theme[upload_mid]="#1aaba0" +theme[upload_end]="#5ec4bc" + +# Process box color gradient for threads, mem and cpu usage +theme[process_start]="#21d6c9" +theme[process_mid]="#1aaba0" +theme[process_end]="#ba1a84" diff --git a/config/dunst/dunst/dunstrc b/config/dunst/dunst/dunstrc new file mode 100755 index 0000000..768ba77 --- /dev/null +++ b/config/dunst/dunst/dunstrc @@ -0,0 +1,48 @@ +[global] +# Basic settings +font = Fira Code 10 +geometry = "300x100-10+55" # 10px from right edge, 55px from top +separator_height = 2 +frame_width = 4 +#corner_radius = 8 +grow_direction = up + +[urgency_low] +background = "#222222" # normbgcolor +foreground = "#bbbbbb" # normfgcolor +frame_color = "#444444" # normbordercolor +timeout = 5 +icon_position = left + +[urgency_normal] +background = "#722F37" # selbgcolor wine red yay! +foreground = "#eeeeee" # selfgcolor bright text +frame_color = "#722F37" # selbordercolor same wine red frame +timeout = 8 +icon_position = left + +[urgency_critical] +background = "#7B2D33" # slightly brighter wine red for critical +foreground = "#eeeeee" +frame_color = "#7B2D33" +timeout = 0 # stays until dismissed +icon_position = left + +[frame] +# subtle shadow for modern look +shadow = false +shadow_offset_x = -5 +shadow_offset_y = -5 +#shadow_radius = 12 +shadow_opacity = 0.7 +shadow_color = "#000000" + +[format] +# tweak layout to be modern and clean +title = "%s" +body = "%s" + +[mouse] +# allow click to close +close_on_click = true + diff --git a/config/dunst/dunstrc b/config/dunst/dunstrc new file mode 100755 index 0000000..84722cc --- /dev/null +++ b/config/dunst/dunstrc @@ -0,0 +1,48 @@ +[global] +# Basic settings +font = Fira Code 10 +geometry = "300x100-10+55" # 10px from right edge, 55px from top +separator_height = 2 +frame_width = 4 +#corner_radius = 8 +grow_direction = up + +[urgency_low] +background = "#222222" # normbgcolor +foreground = "#bbbbbb" # normfgcolor +frame_color = "#444444" # normbordercolor +timeout = 5 +icon_position = left + +[urgency_normal] +background = "#DB940A" # selbgcolor wine red yay! +foreground = "#222222" # selfgcolor bright text +frame_color = "#DB940A" # selbordercolor same wine red frame +timeout = 8 +icon_position = left + +[urgency_critical] +background = "#DB940A" # slightly brighter wine red for critical +foreground = "#eeeeee" +frame_color = "#DB940A" +timeout = 0 # stays until dismissed +icon_position = left + +[frame] +# subtle shadow for modern look +shadow = false +shadow_offset_x = -5 +shadow_offset_y = -5 +#shadow_radius = 12 +shadow_opacity = 0.7 +shadow_color = "#000000" + +[format] +# tweak layout to be modern and clean +title = "%s" +body = "%s" + +[mouse] +# allow click to close +close_on_click = true + diff --git a/config/dunst/dunstrc~ b/config/dunst/dunstrc~ new file mode 100755 index 0000000..3c92181 --- /dev/null +++ b/config/dunst/dunstrc~ @@ -0,0 +1,48 @@ +[global] +# Basic settings +font = Fira Code 10 +geometry = "300x100-10+55" # 10px from right edge, 55px from top +separator_height = 2 +frame_width = 4 +#corner_radius = 8 +grow_direction = up + +[urgency_low] +background = "#222222" # normbgcolor +foreground = "#bbbbbb" # normfgcolor +frame_color = "#444444" # normbordercolor +timeout = 5 +icon_position = left + +[urgency_normal] +background = "#DB940A" # selbgcolor wine red yay! +foreground = "#eeeeee" # selfgcolor bright text +frame_color = "#DB940A" # selbordercolor same wine red frame +timeout = 8 +icon_position = left + +[urgency_critical] +background = "#DB940A" # slightly brighter wine red for critical +foreground = "#eeeeee" +frame_color = "#DB940A" +timeout = 0 # stays until dismissed +icon_position = left + +[frame] +# subtle shadow for modern look +shadow = false +shadow_offset_x = -5 +shadow_offset_y = -5 +#shadow_radius = 12 +shadow_opacity = 0.7 +shadow_color = "#000000" + +[format] +# tweak layout to be modern and clean +title = "%s" +body = "%s" + +[mouse] +# allow click to close +close_on_click = true + diff --git a/config/eww/eww.scss b/config/eww/eww.scss new file mode 100755 index 0000000..3975a93 --- /dev/null +++ b/config/eww/eww.scss @@ -0,0 +1,63 @@ +* { + all: unset; + background: transparent; + font-family: "JetBrainsMono Nerd Font"; + border-radius: 10px; +} + +$bg: #111111; +$bg1: #111111; +$bg2: #26233a; +$fg: #ebbcba; +$fgdim: #6e6a86; +$accent: #9ccfd8; +$border: #ebbcba; + +.container { + background-color: $bg1; + border: 1px solid $border; + color: $fg; + border-radius: 10px; + padding: 6px; + opacity: 0.9; +} + +.button-label, .label { + font-size: 24px; + font-weight: bold; + color: $fg; +} + +.completelytrans { + background: none; +} + +.calendar-label { + font-size: 16px; + font-weight: bold; + color: $fg; +} + +window { + all: unset; + background: transparent; +} + +calendar, calendar.view, calendar.header { + all: unset; + background-color: $bg; + color: $fgdim; + font-size: 18px; + border-radius: 10px; +} + +calendar:indeterminate { + color: #665c54; +} + +calendar:selected { + background-color: $bg2; + border: 1px solid $accent; + color: $fg; + border-radius: 4px; +} diff --git a/config/eww/eww.yuck b/config/eww/eww.yuck new file mode 100755 index 0000000..1ab7c4e --- /dev/null +++ b/config/eww/eww.yuck @@ -0,0 +1,58 @@ +(include "eww_widgets.yuck") + +(defwindow calendar + :monitor 'HDMI-A-1' + :stacking "fg" + :geometry (geometry :x "1600" :y "810" :width "320" :height "250" :anchor "top right") + (calendar)) + +(defwindow year + :monitor 'HDMI-A-1' + :stacking "bg" + :geometry (geometry :x "15" :y "15" :width "100" :height "100" :anchor "top right") + (year)) + +(defwindow month + :monitor 'HDMI-A-1' + :stacking "bg" + :geometry (geometry :x "15" :y "125" :width "100" :height "100" :anchor "top right") + (month)) + +(defwindow day + :monitor 'HDMI-A-1' + :stacking "bg" + :geometry (geometry :x "15" :y "235" :width "100" :height "100" :anchor "top right") + (day)) + +(defwindow daytype + :monitor 'HDMI-A-1' + :stacking "bg" + :geometry (geometry :x "1805" :y "345" :width "100" :height "100" :achor "top right") + (daytype)) + +(defwindow gif1 + :monitor 'HDMI-A-1' + :windowtype "dock" + :stacking "bg" + :namespace "eww" + :geometry (geometry + :x "30px" + :y "30px" + :width "70px" + :height "70px" + :anchor "bottom right") + (gif1)) + +(defwindow gif2 + :monitor 'HDMI-A-1' + :windowtype "dock" + :stacking "bg" + :namespace "eww" + :geometry (geometry + :x "30px" + :y "250px" + :width "70px" + :height "70px" + :anchor "bottom right") + (gif2)) + diff --git a/config/eww/eww_vars.yuck b/config/eww/eww_vars.yuck new file mode 100755 index 0000000..35d807b --- /dev/null +++ b/config/eww/eww_vars.yuck @@ -0,0 +1,4 @@ +(defpoll DAY :interval "1s" '~/.config/eww/scripts/day_format.sh') +(defpoll MONTH :interval "1s" '~/.config/eww/scripts/month_format.sh') +(defpoll YEAR :interval "1s" '~/.config/eww/scripts/year_format.sh') +(defpoll DAYTYPE :interval "1s" '~/.config/eww/scripts/daytype.sh') diff --git a/config/eww/eww_widgets.yuck b/config/eww/eww_widgets.yuck new file mode 100755 index 0000000..d3fb0a0 --- /dev/null +++ b/config/eww/eww_widgets.yuck @@ -0,0 +1,21 @@ +(include "eww_vars.yuck") + +(defwidget day [] + (box :height "100" :width "100" :halign "center" :valign "center" :class "container" + (label :class "label" :text DAY))) +(defwidget month [] + (box :height "100" :width "100" :halign "center" :valign "center" :class "container" + (label :class "label" :text MONTH))) +(defwidget year [] + (box :height "100" :width "100" :halign "center" :valign "center" :class "container" + (label :class "label" :text YEAR))) +(defwidget daytype [] + (box :height "100" :width "100" :halign "center" :valign "center" :class "container" + (label :class "label" :text DAYTYPE))) +(defwidget gif1 [] + (box :halign "center" :valign "center" :class "container" + (image :path 'images/gif1.gif'))) + +(defwidget gif2 [] + (box :halign "center" :valign "center" :class "container" + (image :path 'images/gif2.gif'))) diff --git a/config/eww/images/gif1.gif b/config/eww/images/gif1.gif new file mode 100755 index 0000000..013df71 Binary files /dev/null and b/config/eww/images/gif1.gif differ diff --git a/config/eww/images/gif2.gif b/config/eww/images/gif2.gif new file mode 100755 index 0000000..f728b4f Binary files /dev/null and b/config/eww/images/gif2.gif differ diff --git a/config/eww/scripts/calendar.sh b/config/eww/scripts/calendar.sh new file mode 100755 index 0000000..ada469a --- /dev/null +++ b/config/eww/scripts/calendar.sh @@ -0,0 +1,2 @@ +#!bash +cal -m diff --git a/config/eww/scripts/day_format.sh b/config/eww/scripts/day_format.sh new file mode 100755 index 0000000..a3e715a --- /dev/null +++ b/config/eww/scripts/day_format.sh @@ -0,0 +1,14 @@ +#!/bin/sh +day_of_month=$(date +"%d") +day_of_month=$(echo $day_of_month | sed 's/^0*//') +if [[ $day_of_month -ge 11 && $day_of_month -le 13 ]]; then + suffix="th" +else + case $((day_of_month % 10)) in + 1) suffix="st" ;; + 2) suffix="nd" ;; + 3) suffix="rd" ;; + *) suffix="th" ;; + esac +fi +echo "${day_of_month}${suffix}" diff --git a/config/eww/scripts/daytype.sh b/config/eww/scripts/daytype.sh new file mode 100755 index 0000000..aad1cdc --- /dev/null +++ b/config/eww/scripts/daytype.sh @@ -0,0 +1,3 @@ +#!/bin/sh +day_type=$(date +"%a") +echo "$day_type" diff --git a/config/eww/scripts/month_format.sh b/config/eww/scripts/month_format.sh new file mode 100755 index 0000000..2eecb3f --- /dev/null +++ b/config/eww/scripts/month_format.sh @@ -0,0 +1,3 @@ +#!/bin/sh +month=$(date +"%b") +echo "$month" diff --git a/config/eww/scripts/start.sh b/config/eww/scripts/start.sh new file mode 100755 index 0000000..e032918 --- /dev/null +++ b/config/eww/scripts/start.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Reload/Open eww +eww kill +eww daemon + +eww open year +eww open month +eww open day diff --git a/config/eww/scripts/year_format.sh b/config/eww/scripts/year_format.sh new file mode 100755 index 0000000..d8016be --- /dev/null +++ b/config/eww/scripts/year_format.sh @@ -0,0 +1,3 @@ +#!/bin/sh +year=$(date +"%Y") +echo "$year" diff --git a/config/foot/foot.ini b/config/foot/foot.ini new file mode 120000 index 0000000..875ed93 --- /dev/null +++ b/config/foot/foot.ini @@ -0,0 +1 @@ +/nix/store/ya9248ng717qf0ncbn6sbs9bai66g5xn-home-manager-files/.config/foot/foot.ini \ No newline at end of file diff --git a/config/foot/foot.ini.home-backup b/config/foot/foot.ini.home-backup new file mode 100755 index 0000000..351c040 --- /dev/null +++ b/config/foot/foot.ini.home-backup @@ -0,0 +1,40 @@ +font=Maple Mono:size=14 +pad=4x4 + +[colors] +alpha=1.0 +background=111111 + +[colors] +foreground=cdd6f4 +background=1e1e2e + +regular0=45475a +regular1=f38ba8 +regular2=a6e3a1 +regular3=f9e2af +regular4=89b4fa +regular5=f5c2e7 +regular6=94e2d5 +regular7=bac2de + +bright0=585b70 +bright1=f38ba8 +bright2=a6e3a1 +bright3=f9e2af +bright4=89b4fa +bright5=f5c2e7 +bright6=94e2d5 +bright7=a6adc8 + +16=fab387 +17=f5e0dc + +selection-foreground=cdd6f4 +selection-background=414356 + +search-box-no-match=11111b f38ba8 +search-box-match=cdd6f4 313244 + +jump-labels=11111b fab387 +urls=89b4fa diff --git a/config/home-manager/README.md b/config/home-manager/README.md new file mode 100755 index 0000000..edd92b3 --- /dev/null +++ b/config/home-manager/README.md @@ -0,0 +1,4 @@ +flakes are auto-generated by nix + + +by the way; these are for my machine :3 they're poorly written i just wanted to save them somewhere diff --git a/config/home-manager/flake.lock b/config/home-manager/flake.lock new file mode 100755 index 0000000..0935d23 --- /dev/null +++ b/config/home-manager/flake.lock @@ -0,0 +1,47 @@ +{ + "nodes": { + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1748227609, + "narHash": "sha256-SaSdslyo6UGDpPUlmrPA4dWOEuxCy2ihRN9K6BnqYsA=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "d23d20f55d49d8818ac1f1b2783671e8a6725022", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1748190013, + "narHash": "sha256-R5HJFflOfsP5FBtk+zE8FpL8uqE7n62jqOsADvVshhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "62b852f6c6742134ade1abdd2a21685fd617a291", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/config/home-manager/flake.nix b/config/home-manager/flake.nix new file mode 100755 index 0000000..2030861 --- /dev/null +++ b/config/home-manager/flake.nix @@ -0,0 +1,26 @@ +{ + description = "Home Manager configuration of avery"; + + inputs = { + nixpkgs.url = "nixpkgs/nixos-unstable"; + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { nixpkgs, home-manager, ... }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + in + { + homeConfigurations."avery" = home-manager.lib.homeManagerConfiguration { + inherit pkgs; + + modules = [ ./home.nix ]; + + }; + }; +} diff --git a/config/home-manager/home.nix b/config/home-manager/home.nix new file mode 100755 index 0000000..08a103c --- /dev/null +++ b/config/home-manager/home.nix @@ -0,0 +1,195 @@ +# _ _ +#| |__ ___ _ __ ___ ___ _ __ (_)_ __ +#| '_ \ / _ \| '_ ` _ \ / _ \ | '_ \| \ \/ / +#| | | | (_) | | | | | | __/_| | | | |> < +#|_| |_|\___/|_| |_| |_|\___(_)_| |_|_/_/\_\ +#Coast's ~/.config/home-manager/home.nix +{ config, pkgs, ... }: +{ + home.username = "avery"; + home.homeDirectory = "/home/avery"; + home.stateVersion = "25.05"; + home.packages = with pkgs; [ + bat cowsay bat cmatrix bat cava cbonsai bat ksh bat tree hyfetch qutebrowser xonsh elvish openjdk btop htop cpufetch lm_sensors dysk dogdns ]; + home.file = { + }; + home.sessionVariables = { + EDITOR = "emacs"; + BROWSER = "brave"; + }; + programs.eza = { + enable = true; +}; + programs.bash = { + enable = true; + initExtra = '' + if [ "$(id -u)" = 0 ]; then PS1ICON='#'; else PS1ICON='$'; fi +PS1='\[\e[38;2;254;128;25m\][\[\e[38;2;235;219;178m\]\u\[\e[38;2;200;200;200m\]@\[\e[38;2;131;165;152m\]coast \[\e[38;2;235;219;178m\]\w\[\e[38;2;254;128;25m\]]'"$PS1ICON"'\[\e[0m\] ' + source "$HOME/.config/shell/aliases" + source "$HOME/.config/shell/exports" + ''; +}; + home.file.".config/bat/config".text = '' + --theme="Nord" + --style="numbers,changes,grid" + --paging=auto + ''; +#vim conf + home.file.".vimrc".text = '' + set number + set shiftwidth=4 + set tabstop=4 + set wrap + set cursorline + set linebreak + set termguicolors + syntax on + filetype plugin indent on + set ignorecase + set smartcase + set hlsearch + set incsearch + set autoindent + set expandtab + map :setlocal spell! spelllang=en_us + nnoremap :NERDTreeToggle + call plug#begin('~/.vim/plugged') + Plug 'tpope/vim-sensible' + Plug 'preservim/nerdtree' + Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } + Plug 'junegunn/fzf.vim' + Plug 'vim-airline/vim-airline' + Plug 'vim-airline/vim-airline-themes' + call plug#end() + set background=dark + ''; + home.file.".config/shell/exports".text = '' + export PATH=$HOME/.local/bin:$PATH + export PATH=$HOME/.luarocks/bin:$PATH + if [ -n "$ZSH_VERSION" ]; then + export ZSH="/home/avery/.oh-my-zsh" + fi + export NIXPKGS_ALLOW_UNFREE=1 + export EDITOR="emacs" + ''; + home.file.".config/shell/aliases".text = '' + #!/bin/sh + #general aliases + alias xi="doas xbps-install -S $1" + alias nf="clear && fastfetch" + alias ascdis="fastfetch --logo $1" + alias forge="su forgejo" + alias emoji="cat ~/.local/share/emoji | grep $1" + alias cst="emacs ~/.suckless/st/config.h" + alias las="ls" + alias lasa="ls -a" + alias lasal="ls -al" + alias anal="ls -ahl" + alias resmacs="systemctl --user restart emacsd" + alias smi="nvidia-smi" + alias src="source ~/.zshrc" + alias bat="sb-battery" + alias battery="sb-battery" + alias vimrc="vim .vimrc" + alias ri="ranger" + alias rim="ranger" + alias quit="exit" + alias :q="exit" + alias :q!="exit" + alias :Q="exit" + alias :Q!="exit" + alias :quit="exit" + alias :quit!="exit" + alias :QUIT="exit" + alias :QUIT!="exit" + alias q="exit" + alias fnl="fennel" + alias "push"="git push -u origin main" + alias irc="irssi" + alias hsw="home-manager switch --flake ~/.config/home-manager" + alias hsc="emacs ~/.config/home-manager/home.nix" + alias yell="echo" + alias chm="ecop cat ~/.config/home-manager/home.nix" + if [ -n "$ZSH_VERSION" ]; then + alias ed="ed -p '%: '" + else + alias ed="ed -p '$: '" + fi + alias weather="curl wttr.in/masjedsoleyman" + #typo/shortcut + alias c="clear" + alias cear="clear" + alias "cd.."="cd .." + alias claer="clear" + alias claer="clear" + alias clare="clear" + alias cleae="clear" + alias clera="clear" + alias hotp="htop" + ''; + home.file.".zshrc".text = '' + #!/usr/bin/zsh + HISTFILE=$HOME/.cache/zsh/history + SAVEHIST=100000000 + HISTSIZE=$SAVEHIST + setopt appendhistory + #tab completion + autoload -U compinit + zstyle ':completion:*' menu select + zmodload zsh/complist + compinit + _comp_options+=(globdots) + #oh my zsh + ZSH_THEME="gentoo" + plugins=(git) + export ZSH="$HOME/.oh-my-zsh" + source $ZSH/oh-my-zsh.sh + #eval + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + #source + source "$HOME/.config/shell/aliases" + source "$HOME/.config/shell/exports" + source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh + fpath=(/usr/share/zsh/site-functions $fpath) + source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh + #colors + autoload -U colors && colors + setopt prompt_subst + #prompt + [ "$(id -u)" = 0 ] && PS1ICON="#" || PS1ICON='%' + PROMPT='%{$(echo -e "\e[38;2;254;128;25m")%}[%{$(echo -e "\e[38;2;235;219;178m")%}%n%{$(echo -e "\e[38;2;200;200;200m")%}@%{$(echo -e "\e[38;2;131;165;152m")%}coast %{$(echo -e "\e[38;2;235;219;178m")%}%~%{$(echo -e "\e[38;2;254;128;25m")%}]%$PS1ICON%{$(echo -e "\e[0m")%} ' + ''; + + programs.alacritty = { + enable = true; + settings = { + window = { + padding = { + x = 4; + y = 4; + }; + decorations = "transparent"; + blur = true; + opacity = 0.9; + }; + font = { + normal = { + family = "monospace"; + }; + size = 9; + }; + colors = { +# primary = { +# background = "0x1e1e2e"; +# foreground = "0xcdd6f4"; +# }; + cursor = { + text = "0x1e1e2e"; + cursor = "0xcdd6f4"; + }; + }; + }; + }; + + programs.home-manager.enable = true; +} diff --git a/config/hypr/hypridle.conf b/config/hypr/hypridle.conf new file mode 100644 index 0000000..8874a43 --- /dev/null +++ b/config/hypr/hypridle.conf @@ -0,0 +1,14 @@ +general { + lock_cmd = pidof hyprlock || hyprlock +} + +listener { + timeout = 300 + on-timeout = hyprlock +} + +listener { + timeout = 600 + on-timeout = hyprctl dispatch dpms off + on-resume = hyprctl dispatch dpms on +} diff --git a/config/hypr/hyprland.conf b/config/hypr/hyprland.conf new file mode 100755 index 0000000..8efd6ad --- /dev/null +++ b/config/hypr/hyprland.conf @@ -0,0 +1,217 @@ +#monitor=DP-1,1920x1080@75,auto,1 +monitor=HDMI-A-1,1920x1080@100.00,auto,1 + +hide_on_fullscreen = true + +$terminal = footclient +$menu = rofi -show drun -config /home/coast/.config/rofi/config.rasi +$webBrowser = firefox-bin +$discordApp = vesktop-bin --proxy-server="socks5://127.0.0.1:65000" +$restartWaybar = pkill waybar; waybar&disown +$fileManager = pcmanfm + +exec-once = hyprctl setcursor Adwaita 24 & +exec-once = wbg /home/coast/Pictures/walls/wallhaven-yq5dmg_1920x1080.png & +exec-once = hypridle & +exec-once = hyprpm reload -n; +exec-once = dbus-update-activation-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=Hyprland +exec-once = gnome-keyring-daemon --start --components=secrets +exec-once = waybar & +exec-once = mpd ~/.mpdconf & +exec-once = mpc add /; + +exec-once = foot --server; + +exec-once = flatpak override --env=GTK_THEME=Catppuccin-B-MB-Dark --user; + +env = XCURSOR_SIZE,24 +env = HYPRCURSOR_SIZE,24 + +general { + gaps_in = 5 + gaps_out = 15 + border_size = 2 + col.active_border = rgba(6c6c9dee) rgba(1e1e2eee) 45deg + col.inactive_border = rgba(1e1e2eaa) + resize_on_border = false + allow_tearing = false + layout = master +} + +decoration { + rounding = 10 + active_opacity = 1.0 + inactive_opacity = 1.0 + shadow { + enabled = true + range = 4 + render_power = 3 + color = rgba(1a1a1aee) + } + blur { + enabled = true + size = 3 + passes = 1 + vibrancy = 0.1696 + new_optimizations = true + } +} + +animations { + enabled = yes + bezier = shot, 0.2, 1, 0.3, 1 + bezier = swipe, 0.6, 0, 0.4, 1 + bezier = bounce, 0.1, 1.1, 0.3, 1 + animation = windows, 1, 3, bounce, popin 80% + animation = windowsIn, 1, 3, bounce, popin 80% + animation = windowsOut, 1, 2, shot, popin 80% + animation = border, 1, 2, default + animation = fade, 1, 2, default + animation = layers, 1, 4, swipe, slide top + animation = layersIn, 1, 4, swipe, slide top + animation = layersOut, 1, 2, swipe, slide top + animation = workspaces, 1, 3, swipe, slide +} + +master { + new_status = slave +} + +misc { + force_default_wallpaper = 0 + disable_hyprland_logo = true +} + +input { + kb_layout = us + follow_mouse = 1 + sensitivity = 0 +} + +$mainMod = SUPER + +bind = $mainMod, Return, exec, $terminal +bind = $mainMod, S, killactive, +bind = $mainMod, M, exec, killall eww; eww daemon && eww open bar +bind = $mainMod SHIFT, Q, exit +bind = $mainMod, Space, togglefloating +bind = $mainMod, Space, resizeactive, exact 1000 800 +bind = $mainMod, Space, centerwindow +bind = $mainMod, R, exec, $menu + +bind = $mainMod, H, movefocus, l +bind = $mainMod, L, movefocus, r +bind = $mainMod, K, movefocus, u +bind = $mainMod, J, movefocus, d + +bind = $mainMod SHIFT, H, movewindow, l +bind = $mainMod SHIFT, L, movewindow, r +bind = $mainMod SHIFT, K, movewindow, u +bind = $mainMod SHIFT, J, movewindow, d + +binde = $mainMod ALT, H, resizeactive, -30 0 +binde = $mainMod ALT, L, resizeactive, 30 0 +binde = $mainMod ALT, K, resizeactive, 0 -30 +binde = $mainMod ALT, J, resizeactive, 0 30 + +binde = $mainMod, left, moveactive, -40 0 +binde = $mainMod, right, moveactive, 40 0 +binde = $mainMod, up, moveactive, 0 -40 +binde = $mainMod, down, moveactive, 0 40 + +binde = $mainMod SHIFT, left, resizeactive, -40 0 +binde = $mainMod SHIFT, right, resizeactive, 40 0 +binde = $mainMod SHIFT, up, resizeactive, 0 -40 +binde = $mainMod SHIFT, down, resizeactive, 0 40 + +bind = $mainMod, Backslash, centerwindow, + +workspace = 2, monitor:HDMI-A-1 + +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 + +bind = $mainMod SHIFT, 1, movetoworkspace, 1 +bind = $mainMod SHIFT, 2, movetoworkspace, 2 +bind = $mainMod SHIFT, 3, movetoworkspace, 3 +bind = $mainMod SHIFT, 4, movetoworkspace, 4 +bind = $mainMod SHIFT, 5, movetoworkspace, 5 +bind = $mainMod SHIFT, 6, movetoworkspace, 6 +bind = $mainMod SHIFT, 7, movetoworkspace, 7 +bind = $mainMod SHIFT, 8, movetoworkspace, 8 +bind = $mainMod SHIFT, 9, movetoworkspace, 9 + +bind = $mainMod, C, togglespecialworkspace, magic +bind = $mainMod SHIFT, S, exec, grim -g "$(slurp)" - | wl-copy + +bind = $mainMod CONTROL, L, exec, hyprlock + +bind = $mainMod SHIFT, B, exec, $webBrowser +bind = $mainMod SHIFT, V, exec, $discordApp +bind = $mainMod, F, exec, $fileManager + +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow + +bind = $mainMod SHIFT, P, exec, $restartWaybar + +plugin { + hyprbars { + enabled = true + + bar_height = 25 + bar_color = rgba(1e1e2eaa) + bar_blur = true + + bar_title_enabled = true + bar_text_font = "JetBrainsMono Nerd Font" + bar_text_size = 12 + bar_text_align = center + col.text = rgba(ffffffdd) + + bar_buttons_alignment = left + bar_padding = 10 + bar_button_padding = 6 + icon_on_hover = false + + hyprbars-button = rgb(ff5f57), 14, , hyprctl dispatch killactive + hyprbars-button = rgb(febb2e), 14, , hyprctl dispatch togglefloating + hyprbars-button = rgb(28c840), 14, , hyprctl dispatch fullscreen 1 + + on_double_click = hyprctl dispatch fullscreen 1 + } + + hyprexpo { + columns = 3 + gap_size = 5 + bg_col = rgba(1e1e2eaa) + workspace_method = center current + gesture_distance = 300 + } +} + +bind = $mainMod, e, hyprexpo:expo, toggle + +bind = $mainMod ALT, up, exec, /home/coast/.local/bin/mpc-shuf.sh shuf +bind = $mainMod ALT, down, exec, /home/coast/.local/bin/mpc-shuf.sh shufno +bind = $mainMod ALT, right, exec, /home/coast/.local/bin/mpc-shuf.sh next +bind = $mainMod ALT, left, exec, /home/coast/.local/bin/mpc-shuf.sh prev +bind = $mainMod SHIFT, R, exec, /home/coast/.local/bin/mpc-shuf.sh search +bind = $mainMod CONTROL, R, exec, /home/coast/.local/bin/mpc-shuf.sh album +bind = $mainMod ALT, R, exec, /home/coast/.local/bin/mpc-shuf.sh artist +bind = $mainMod, slash, exec, /home/coast/.local/bin/mpc-shuf.sh info +bind = $mainMod, comma, exec, mpc volume -5 +bind = $mainMod, period, exec, mpc volume +5 +bind = $mainMod, bracketright, exec, /home/coast/.local/bin/mpc-shuf.sh toggle +bind = $mainMod CONTROL, up, exec, mpc stop; mpc add /; notify-send "Reset MPC!" + +xwayland { + enabled = true +} diff --git a/config/hypr/hyprlock.conf b/config/hypr/hyprlock.conf new file mode 100644 index 0000000..43216c4 --- /dev/null +++ b/config/hypr/hyprlock.conf @@ -0,0 +1,35 @@ +background { + monitor = + path = screenshot + blur_passes = 3 + blur_size = 12 + dim = 0.4 +} + +input-field { + monitor = + size = 350, 60 + position = 0, -100 + rounding = 0 + border_width = 2 + + font = "JetBrainsMono Nerd Font" + font_size = 22 + font_color = rgb(245, 224, 220) + + inner_color = rgb(30, 24, 36) + outer_color = rgb(58, 52, 70) + border_color = rgb(252, 205, 205) + placeholder_text = "Password..." + fade_on_empty = true +} + +label { + monitor = + text = $TIME + font = "JetBrainsMono Nerd Font" + font_size = 64 + position = 0, 100 + color = rgb(245, 224, 220) +} + diff --git a/config/hypr/hyprpaper.conf b/config/hypr/hyprpaper.conf new file mode 100755 index 0000000..9018554 --- /dev/null +++ b/config/hypr/hyprpaper.conf @@ -0,0 +1,3 @@ +preload = ~/Pictures/Wallpapers/flowers.png +wallpaper = HDMI-A-1,~/Pictures/Wallpapers/flowers.png +wallpaper = eDP-1,~/Pictures/Wallpapers/flowers.png diff --git a/config/kitty/.#kitty.conf b/config/kitty/.#kitty.conf new file mode 120000 index 0000000..7f737a3 --- /dev/null +++ b/config/kitty/.#kitty.conf @@ -0,0 +1 @@ +coast@core.1143:1751344825 \ No newline at end of file diff --git a/config/kitty/kitty.conf b/config/kitty/kitty.conf new file mode 100755 index 0000000..a147494 --- /dev/null +++ b/config/kitty/kitty.conf @@ -0,0 +1,52 @@ +font_family family="Ubuntu Mono" +font_size 15 +bold_font auto +italic_font auto +bold_italic_font auto +background_opacity 0.9 +window_padding_width 8 +confirm_os_window_close 0 + +background #1d1d1d +foreground #deddda + +selection_background #303030 +selection_foreground #c0bfbc + +url_color #1a5fb4 + +wayland_titlebar_color system +macos_titlebar_color system + +cursor #deddda +cursor_text_color #1d1d1d + +active_border_color #4f4f4f +inactive_border_color #282828 +bell_border_color #ed333b +visual_bell_color none + +active_tab_background #242424 +active_tab_foreground #fcfcfc +inactive_tab_background #303030 +inactive_tab_foreground #b0afac +tab_bar_background none +tab_bar_margin_color none + +color0 #1d1d1d +color1 #ed333b +color2 #57e389 +color3 #ff7800 +color4 #62a0ea +color5 #9141ac +color6 #5bc8af +color7 #deddda + +color8 #9a9996 +color9 #f66151 +color10 #8ff0a4 +color11 #ffa348 +color12 #99c1f1 +color13 #dc8add +color14 #93ddc2 +color15 #f6f5f4 diff --git a/config/mako/.github/issue_template.md b/config/mako/.github/issue_template.md new file mode 100755 index 0000000..45a7be3 --- /dev/null +++ b/config/mako/.github/issue_template.md @@ -0,0 +1 @@ +> If you're reporting an UI issue, make sure you take a screenshot that shows the actual bug. \ No newline at end of file diff --git a/config/mako/.github/pull_request_template.md b/config/mako/.github/pull_request_template.md new file mode 100755 index 0000000..622089f --- /dev/null +++ b/config/mako/.github/pull_request_template.md @@ -0,0 +1 @@ +> If you're fixing a UI issue, make sure you take two screenshots. One that shows the actual bug and another that shows how you fixed it. \ No newline at end of file diff --git a/config/mako/config b/config/mako/config new file mode 100755 index 0000000..8fd99fd --- /dev/null +++ b/config/mako/config @@ -0,0 +1,12 @@ +default-timeout=5000 +ignore-timeout=1 +background-color=#1e1e2e +text-color=#cdd6f4 +border-color=#cdd6f4 +progress-color=over #313244 +border-radius=0 + +[urgency=low] +border-color=#a6e3a1 +[urgency=high] +border-color=#f38ba8 diff --git a/config/micro/bindings.json b/config/micro/bindings.json new file mode 100755 index 0000000..58313ff --- /dev/null +++ b/config/micro/bindings.json @@ -0,0 +1,35 @@ +{ + "\u001b\u003c": "CursorStart", + "\u001b\u003e": "CursorEnd", + "\u003cCtrl-x\u003e\u003c0\u003e": "Unsplit", + "\u003cCtrl-x\u003e\u003c2\u003e": "HSplit", + "\u003cCtrl-x\u003e\u003c3\u003e": "VSplit", + "\u003cCtrl-x\u003e\u003cCtrl-c\u003e": "Quit", + "\u003cCtrl-x\u003e\u003cCtrl-f\u003e": "OpenFile", + "\u003cCtrl-x\u003e\u003cCtrl-s\u003e": "Save", + "\u003cCtrl-x\u003e\u003ch\u003e": "SelectAll", + "Alt-/": "lua:comment.comment", + "Alt-[": "PreviousTab", + "Alt-]": "NextTab", + "Alt-b": "WordLeft", + "Alt-f": "WordRight", + "Alt-k": "command:hover", + "Alt-r": "command:references", + "Alt-v": "CursorPageUp", + "Alt-w": "Copy", + "Alt-x": "CommandMode", + "Ctrl-a": "StartOfLine", + "Ctrl-e": "EndOfLine", + "Ctrl-g": "Escape", + "Ctrl-k": "CutLine", + "Ctrl-r": "FindPrevious", + "Ctrl-s": "Find", + "Ctrl-v": "CursorPageDown", + "Ctrl-y": "Paste", + "Ctrl-z": "Undo", + "Ctrl-b": "CursorLeft", + "Ctrl-f": "CursorRight", + "Ctrl-p": "CursorUp", + "Ctrl-n": "CursorDown", + "CtrlUnderscore": "Undo" +} diff --git a/config/micro/buffers/history b/config/micro/buffers/history new file mode 100755 index 0000000..449014c Binary files /dev/null and b/config/micro/buffers/history differ diff --git a/config/micro/settings.json b/config/micro/settings.json new file mode 100755 index 0000000..2b6fe8a --- /dev/null +++ b/config/micro/settings.json @@ -0,0 +1,3 @@ +{ + "colorscheme": "geany" +} diff --git a/config/mksymlink.conf b/config/mksymlink.conf new file mode 100755 index 0000000..f3b5f56 --- /dev/null +++ b/config/mksymlink.conf @@ -0,0 +1,16 @@ +MAIN="$HOME/.local/src/config" + +list="\ +nvim=nvim +qtile=qtile +sway=sway +mutt=mutt +qutebrowser=qutebrowser +wofi=wofi +fastfetch=fastfetch +btop=btop +foot=foot +mako=mako +neofetch=neofetch +mksymlink.conf=mksymlink.conf +" diff --git a/config/mutt/color.muttrc b/config/mutt/color.muttrc new file mode 100755 index 0000000..c964d03 --- /dev/null +++ b/config/mutt/color.muttrc @@ -0,0 +1,68 @@ +# vim: filetype=neomuttrc +# Default index colors: +color index yellow default '.*' +color index_author red default '.*' +color index_number blue default +color index_subject cyan default '.*' + +# For new mail: +color index brightyellow black "~N" +color index_author brightred black "~N" +color index_subject brightcyan black "~N" + +# Header colors: +color header blue default ".*" +color header brightmagenta default "^(From)" +color header brightcyan default "^(Subject)" +color header brightwhite default "^(CC|BCC)" + +mono bold bold +mono underline underline +mono indicator reverse +mono error bold +color normal default default +color indicator brightblack white +color sidebar_highlight red default +color sidebar_divider brightblack black +color sidebar_flagged red black +color sidebar_new green black +color normal brightyellow default +color error red default +color tilde black default +color message cyan default +color markers red white +color attachment white default +color search brightmagenta default +color status brightyellow black +color hdrdefault brightgreen default +color quoted green default +color quoted1 blue default +color quoted2 cyan default +color quoted3 yellow default +color quoted4 red default +color quoted5 brightred default +color signature brightgreen default +color bold black default +color underline black default +color normal default default + +color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses +color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL +color body green default "\`[^\`]*\`" # Green text between ` and ` +color body brightblue default "^# \.*" # Headings as bold blue +color body brightcyan default "^## \.*" # Subheadings as bold cyan +color body brightgreen default "^### \.*" # Subsubheadings as bold green +color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow +color body brightcyan default "[;:][-o][)/(|]" # emoticons +color body brightcyan default "[;:][)(|]" # emoticons +color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon? +color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon? +color body red default "(BAD signature)" +color body cyan default "(Good signature)" +color body brightblack default "^gpg: Good signature .*" +color body brightyellow default "^gpg: " +color body brightyellow red "^gpg: BAD signature from.*" +mono body bold "^gpg: Good signature" +mono body bold "^gpg: BAD signature from.*" +color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]" + diff --git a/config/mutt/muttrc b/config/mutt/muttrc new file mode 100755 index 0000000..9ef2c54 --- /dev/null +++ b/config/mutt/muttrc @@ -0,0 +1,18 @@ +set folder = "imaps://coast@cock.email@mail.cock.li:993" +set smtp_url = "smtps://coast@cock.email@mail.cock.li:587" + +set imap_pass = `cat /home/coast/.local/keys/imap.muttrc` +set smtp_pass = `cat /home/coast/.local/keys/smtp.muttrc` + +set from = "coast@cock.email" +set realname = "Coasteen" + +set spoolfile = "+INBOX" + +set editor = "nvim" +set edit_headers = yes +set include = yes +set indent_str = "> " +set reply_regexp = "^([rR][eE]:[ \t]*)*" + +source color.muttrc diff --git a/config/neofetch/config.conf b/config/neofetch/config.conf new file mode 100755 index 0000000..cdba4c6 --- /dev/null +++ b/config/neofetch/config.conf @@ -0,0 +1,864 @@ +# See this wiki page for more info: +# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info +print_info() { + info title + info underline + + info "OS" distro + info "Host" model + info "Kernel" kernel + info "Uptime" uptime + info "Packages" packages + info "Shell" shell + info "Resolution" resolution + info "DE" de + info "WM" wm + info "WM Theme" wm_theme + info "Theme" theme + info "Icons" icons + info "Terminal" term + info "Terminal Font" term_font + info "CPU" cpu + info "GPU" gpu + info "Memory" memory + + # info "GPU Driver" gpu_driver # Linux/macOS only + # info "CPU Usage" cpu_usage + # info "Disk" disk + # info "Battery" battery + # info "Font" font + # info "Song" song + # [[ "$player" ]] && prin "Music Player" "$player" + # info "Local IP" local_ip + # info "Public IP" public_ip + # info "Users" users + # info "Locale" locale # This only works on glibc systems. + + info cols +} + +# Title + + +# Hide/Show Fully qualified domain name. +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --title_fqdn +title_fqdn="off" + + +# Kernel + + +# Shorten the output of the kernel function. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --kernel_shorthand +# Supports: Everything except *BSDs (except PacBSD and PC-BSD) +# +# Example: +# on: '4.8.9-1-ARCH' +# off: 'Linux 4.8.9-1-ARCH' +kernel_shorthand="on" + + +# Distro + + +# Shorten the output of the distro function +# +# Default: 'off' +# Values: 'on', 'tiny', 'off' +# Flag: --distro_shorthand +# Supports: Everything except Windows and Haiku +distro_shorthand="off" + +# Show/Hide OS Architecture. +# Show 'x86_64', 'x86' and etc in 'Distro:' output. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --os_arch +# +# Example: +# on: 'Arch Linux x86_64' +# off: 'Arch Linux' +os_arch="on" + + +# Uptime + + +# Shorten the output of the uptime function +# +# Default: 'on' +# Values: 'on', 'tiny', 'off' +# Flag: --uptime_shorthand +# +# Example: +# on: '2 days, 10 hours, 3 mins' +# tiny: '2d 10h 3m' +# off: '2 days, 10 hours, 3 minutes' +uptime_shorthand="on" + + +# Memory + + +# Show memory pecentage in output. +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --memory_percent +# +# Example: +# on: '1801MiB / 7881MiB (22%)' +# off: '1801MiB / 7881MiB' +memory_percent="off" + +# Change memory output unit. +# +# Default: 'mib' +# Values: 'kib', 'mib', 'gib' +# Flag: --memory_unit +# +# Example: +# kib '1020928KiB / 7117824KiB' +# mib '1042MiB / 6951MiB' +# gib: ' 0.98GiB / 6.79GiB' +memory_unit="mib" + + +# Packages + + +# Show/Hide Package Manager names. +# +# Default: 'tiny' +# Values: 'on', 'tiny' 'off' +# Flag: --package_managers +# +# Example: +# on: '998 (pacman), 8 (flatpak), 4 (snap)' +# tiny: '908 (pacman, flatpak, snap)' +# off: '908' +package_managers="on" + + +# Shell + + +# Show the path to $SHELL +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --shell_path +# +# Example: +# on: '/bin/bash' +# off: 'bash' +shell_path="off" + +# Show $SHELL version +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --shell_version +# +# Example: +# on: 'bash 4.4.5' +# off: 'bash' +shell_version="on" + + +# CPU + + +# CPU speed type +# +# Default: 'bios_limit' +# Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'. +# Flag: --speed_type +# Supports: Linux with 'cpufreq' +# NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value. +speed_type="bios_limit" + +# CPU speed shorthand +# +# Default: 'off' +# Values: 'on', 'off'. +# Flag: --speed_shorthand +# NOTE: This flag is not supported in systems with CPU speed less than 1 GHz +# +# Example: +# on: 'i7-6500U (4) @ 3.1GHz' +# off: 'i7-6500U (4) @ 3.100GHz' +speed_shorthand="off" + +# Enable/Disable CPU brand in output. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --cpu_brand +# +# Example: +# on: 'Intel i7-6500U' +# off: 'i7-6500U (4)' +cpu_brand="on" + +# CPU Speed +# Hide/Show CPU speed. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --cpu_speed +# +# Example: +# on: 'Intel i7-6500U (4) @ 3.1GHz' +# off: 'Intel i7-6500U (4)' +cpu_speed="on" + +# CPU Cores +# Display CPU cores in output +# +# Default: 'logical' +# Values: 'logical', 'physical', 'off' +# Flag: --cpu_cores +# Support: 'physical' doesn't work on BSD. +# +# Example: +# logical: 'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores) +# physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores) +# off: 'Intel i7-6500U @ 3.1GHz' +cpu_cores="logical" + +# CPU Temperature +# Hide/Show CPU temperature. +# Note the temperature is added to the regular CPU function. +# +# Default: 'off' +# Values: 'C', 'F', 'off' +# Flag: --cpu_temp +# Supports: Linux, BSD +# NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable +# coretemp kernel module. This only supports newer Intel processors. +# +# Example: +# C: 'Intel i7-6500U (4) @ 3.1GHz [27.2°C]' +# F: 'Intel i7-6500U (4) @ 3.1GHz [82.0°F]' +# off: 'Intel i7-6500U (4) @ 3.1GHz' +cpu_temp="off" + + +# GPU + + +# Enable/Disable GPU Brand +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --gpu_brand +# +# Example: +# on: 'AMD HD 7950' +# off: 'HD 7950' +gpu_brand="on" + +# Which GPU to display +# +# Default: 'all' +# Values: 'all', 'dedicated', 'integrated' +# Flag: --gpu_type +# Supports: Linux +# +# Example: +# all: +# GPU1: AMD HD 7950 +# GPU2: Intel Integrated Graphics +# +# dedicated: +# GPU1: AMD HD 7950 +# +# integrated: +# GPU1: Intel Integrated Graphics +gpu_type="all" + + +# Resolution + + +# Display refresh rate next to each monitor +# Default: 'off' +# Values: 'on', 'off' +# Flag: --refresh_rate +# Supports: Doesn't work on Windows. +# +# Example: +# on: '1920x1080 @ 60Hz' +# off: '1920x1080' +refresh_rate="off" + + +# Gtk Theme / Icons / Font + + +# Shorten output of GTK Theme / Icons / Font +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --gtk_shorthand +# +# Example: +# on: 'Numix, Adwaita' +# off: 'Numix [GTK2], Adwaita [GTK3]' +gtk_shorthand="off" + + +# Enable/Disable gtk2 Theme / Icons / Font +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --gtk2 +# +# Example: +# on: 'Numix [GTK2], Adwaita [GTK3]' +# off: 'Adwaita [GTK3]' +gtk2="on" + +# Enable/Disable gtk3 Theme / Icons / Font +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --gtk3 +# +# Example: +# on: 'Numix [GTK2], Adwaita [GTK3]' +# off: 'Numix [GTK2]' +gtk3="on" + + +# IP Address + + +# Website to ping for the public IP +# +# Default: 'http://ident.me' +# Values: 'url' +# Flag: --ip_host +public_ip_host="http://ident.me" + +# Public IP timeout. +# +# Default: '2' +# Values: 'int' +# Flag: --ip_timeout +public_ip_timeout=2 + + +# Desktop Environment + + +# Show Desktop Environment version +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --de_version +de_version="on" + + +# Disk + + +# Which disks to display. +# The values can be any /dev/sdXX, mount point or directory. +# NOTE: By default we only show the disk info for '/'. +# +# Default: '/' +# Values: '/', '/dev/sdXX', '/path/to/drive'. +# Flag: --disk_show +# +# Example: +# disk_show=('/' '/dev/sdb1'): +# 'Disk (/): 74G / 118G (66%)' +# 'Disk (/mnt/Videos): 823G / 893G (93%)' +# +# disk_show=('/'): +# 'Disk (/): 74G / 118G (66%)' +# +disk_show=('/') + +# Disk subtitle. +# What to append to the Disk subtitle. +# +# Default: 'mount' +# Values: 'mount', 'name', 'dir', 'none' +# Flag: --disk_subtitle +# +# Example: +# name: 'Disk (/dev/sda1): 74G / 118G (66%)' +# 'Disk (/dev/sdb2): 74G / 118G (66%)' +# +# mount: 'Disk (/): 74G / 118G (66%)' +# 'Disk (/mnt/Local Disk): 74G / 118G (66%)' +# 'Disk (/mnt/Videos): 74G / 118G (66%)' +# +# dir: 'Disk (/): 74G / 118G (66%)' +# 'Disk (Local Disk): 74G / 118G (66%)' +# 'Disk (Videos): 74G / 118G (66%)' +# +# none: 'Disk: 74G / 118G (66%)' +# 'Disk: 74G / 118G (66%)' +# 'Disk: 74G / 118G (66%)' +disk_subtitle="mount" + +# Disk percent. +# Show/Hide disk percent. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --disk_percent +# +# Example: +# on: 'Disk (/): 74G / 118G (66%)' +# off: 'Disk (/): 74G / 118G' +disk_percent="on" + + +# Song + + +# Manually specify a music player. +# +# Default: 'auto' +# Values: 'auto', 'player-name' +# Flag: --music_player +# +# Available values for 'player-name': +# +# amarok +# audacious +# banshee +# bluemindo +# clementine +# cmus +# deadbeef +# deepin-music +# dragon +# elisa +# exaile +# gnome-music +# gmusicbrowser +# gogglesmm +# guayadeque +# io.elementary.music +# iTunes +# juk +# lollypop +# mocp +# mopidy +# mpd +# muine +# netease-cloud-music +# olivia +# playerctl +# pogo +# pragha +# qmmp +# quodlibet +# rhythmbox +# sayonara +# smplayer +# spotify +# strawberry +# tauonmb +# tomahawk +# vlc +# xmms2d +# xnoise +# yarock +music_player="auto" + +# Format to display song information. +# +# Default: '%artist% - %album% - %title%' +# Values: '%artist%', '%album%', '%title%' +# Flag: --song_format +# +# Example: +# default: 'Song: Jet - Get Born - Sgt Major' +song_format="%artist% - %album% - %title%" + +# Print the Artist, Album and Title on separate lines +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --song_shorthand +# +# Example: +# on: 'Artist: The Fratellis' +# 'Album: Costello Music' +# 'Song: Chelsea Dagger' +# +# off: 'Song: The Fratellis - Costello Music - Chelsea Dagger' +song_shorthand="off" + +# 'mpc' arguments (specify a host, password etc). +# +# Default: '' +# Example: mpc_args=(-h HOST -P PASSWORD) +mpc_args=() + + +# Text Colors + + +# Text Colors +# +# Default: 'distro' +# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num' +# Flag: --colors +# +# Each number represents a different part of the text in +# this order: 'title', '@', 'underline', 'subtitle', 'colon', 'info' +# +# Example: +# colors=(distro) - Text is colored based on Distro colors. +# colors=(4 6 1 8 8 6) - Text is colored in the order above. +colors=(distro) + + +# Text Options + + +# Toggle bold text +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --bold +bold="on" + +# Enable/Disable Underline +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --underline +underline_enabled="on" + +# Underline character +# +# Default: '-' +# Values: 'string' +# Flag: --underline_char +underline_char="-" + + +# Info Separator +# Replace the default separator with the specified string. +# +# Default: ':' +# Flag: --separator +# +# Example: +# separator="->": 'Shell-> bash' +# separator=" =": 'WM = dwm' +separator=":" + + +# Color Blocks + + +# Color block range +# The range of colors to print. +# +# Default: '0', '15' +# Values: 'num' +# Flag: --block_range +# +# Example: +# +# Display colors 0-7 in the blocks. (8 colors) +# neofetch --block_range 0 7 +# +# Display colors 0-15 in the blocks. (16 colors) +# neofetch --block_range 0 15 +block_range=(0 15) + +# Toggle color blocks +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --color_blocks +color_blocks="on" + +# Color block width in spaces +# +# Default: '3' +# Values: 'num' +# Flag: --block_width +block_width=3 + +# Color block height in lines +# +# Default: '1' +# Values: 'num' +# Flag: --block_height +block_height=1 + +# Color Alignment +# +# Default: 'auto' +# Values: 'auto', 'num' +# Flag: --col_offset +# +# Number specifies how far from the left side of the terminal (in spaces) to +# begin printing the columns, in case you want to e.g. center them under your +# text. +# Example: +# col_offset="auto" - Default behavior of neofetch +# col_offset=7 - Leave 7 spaces then print the colors +col_offset="auto" + +# Progress Bars + + +# Bar characters +# +# Default: '-', '=' +# Values: 'string', 'string' +# Flag: --bar_char +# +# Example: +# neofetch --bar_char 'elapsed' 'total' +# neofetch --bar_char '-' '=' +bar_char_elapsed="-" +bar_char_total="=" + +# Toggle Bar border +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --bar_border +bar_border="on" + +# Progress bar length in spaces +# Number of chars long to make the progress bars. +# +# Default: '15' +# Values: 'num' +# Flag: --bar_length +bar_length=15 + +# Progress bar colors +# When set to distro, uses your distro's logo colors. +# +# Default: 'distro', 'distro' +# Values: 'distro', 'num' +# Flag: --bar_colors +# +# Example: +# neofetch --bar_colors 3 4 +# neofetch --bar_colors distro 5 +bar_color_elapsed="distro" +bar_color_total="distro" + + +# Info display +# Display a bar with the info. +# +# Default: 'off' +# Values: 'bar', 'infobar', 'barinfo', 'off' +# Flags: --cpu_display +# --memory_display +# --battery_display +# --disk_display +# +# Example: +# bar: '[---=======]' +# infobar: 'info [---=======]' +# barinfo: '[---=======] info' +# off: 'info' +cpu_display="off" +memory_display="off" +battery_display="off" +disk_display="off" + + +# Backend Settings + + +# Image backend. +# +# Default: 'ascii' +# Values: 'ascii', 'caca', 'chafa', 'jp2a', 'iterm2', 'off', +# 'pot', 'termpix', 'pixterm', 'tycat', 'w3m', 'kitty' +# Flag: --backend +image_backend="ascii" + +# Image Source +# +# Which image or ascii file to display. +# +# Default: 'auto' +# Values: 'auto', 'ascii', 'wallpaper', '/path/to/img', '/path/to/ascii', '/path/to/dir/' +# 'command output (neofetch --ascii "$(fortune | cowsay -W 30)")' +# Flag: --source +# +# NOTE: 'auto' will pick the best image source for whatever image backend is used. +# In ascii mode, distro ascii art will be used and in an image mode, your +# wallpaper will be used. +image_source="auto" + + +# Ascii Options + + +# Ascii distro +# Which distro's ascii art to display. +# +# Default: 'auto' +# Values: 'auto', 'distro_name' +# Flag: --ascii_distro +# NOTE: AIX, Alpine, Anarchy, Android, Antergos, antiX, "AOSC OS", +# "AOSC OS/Retro", Apricity, ArcoLinux, ArchBox, ARCHlabs, +# ArchStrike, XFerience, ArchMerge, Arch, Artix, Arya, Bedrock, +# Bitrig, BlackArch, BLAG, BlankOn, BlueLight, bonsai, BSD, +# BunsenLabs, Calculate, Carbs, CentOS, Chakra, ChaletOS, +# Chapeau, Chrom*, Cleanjaro, ClearOS, Clear_Linux, Clover, +# Condres, Container_Linux, CRUX, Cucumber, Debian, Deepin, +# DesaOS, Devuan, DracOS, DarkOs, DragonFly, Drauger, Elementary, +# EndeavourOS, Endless, EuroLinux, Exherbo, Fedora, Feren, FreeBSD, +# FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, Gentoo, Pentoo, +# gNewSense, GNOME, GNU, GoboLinux, Grombyang, Guix, Haiku, Huayra, +# Hyperbola, janus, Kali, KaOS, KDE_neon, Kibojoe, Kogaion, +# Korora, KSLinux, Kubuntu, LEDE, LFS, Linux_Lite, +# LMDE, Lubuntu, Lunar, macos, Mageia, MagpieOS, Mandriva, +# Manjaro, Maui, Mer, Minix, LinuxMint, MX_Linux, Namib, +# Neptune, NetBSD, Netrunner, Nitrux, NixOS, Nurunner, +# NuTyX, OBRevenge, OpenBSD, openEuler, OpenIndiana, openmamba, +# OpenMandriva, OpenStage, OpenWrt, osmc, Oracle, OS Elbrus, PacBSD, +# Parabola, Pardus, Parrot, Parsix, TrueOS, PCLinuxOS, Peppermint, +# popos, Porteus, PostMarketOS, Proxmox, Puppy, PureOS, Qubes, Radix, +# Raspbian, Reborn_OS, Redstar, Redcore, Redhat, Refracted_Devuan, +# Regata, Rosa, sabotage, Sabayon, Sailfish, SalentOS, Scientific, +# Septor, SereneLinux, SharkLinux, Siduction, Slackware, SliTaz, +# SmartOS, Solus, Source_Mage, Sparky, Star, SteamOS, SunOS, +# openSUSE_Leap, openSUSE_Tumbleweed, openSUSE, SwagArch, Tails, +# Trisquel, Ubuntu-Budgie, Ubuntu-GNOME, Ubuntu-MATE, Ubuntu-Studio, +# Ubuntu, Venom, Void, Obarun, windows10, Windows7, Xubuntu, Zorin, +# and IRIX have ascii logos +# NOTE: Arch, Ubuntu, Redhat, and Dragonfly have 'old' logo variants. +# Use '{distro name}_old' to use the old logos. +# NOTE: Ubuntu has flavor variants. +# Change this to Lubuntu, Kubuntu, Xubuntu, Ubuntu-GNOME, +# Ubuntu-Studio, Ubuntu-Mate or Ubuntu-Budgie to use the flavors. +# NOTE: Arcolinux, Dragonfly, Fedora, Alpine, Arch, Ubuntu, +# CRUX, Debian, Gentoo, FreeBSD, Mac, NixOS, OpenBSD, android, +# Antrix, CentOS, Cleanjaro, ElementaryOS, GUIX, Hyperbola, +# Manjaro, MXLinux, NetBSD, Parabola, POP_OS, PureOS, +# Slackware, SunOS, LinuxLite, OpenSUSE, Raspbian, +# postmarketOS, and Void have a smaller logo variant. +# Use '{distro name}_small' to use the small variants. +ascii_distro="auto" + +# Ascii Colors +# +# Default: 'distro' +# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num' +# Flag: --ascii_colors +# +# Example: +# ascii_colors=(distro) - Ascii is colored based on Distro colors. +# ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors. +ascii_colors=(distro) + +# Bold ascii logo +# Whether or not to bold the ascii logo. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --ascii_bold +ascii_bold="on" + + +# Image Options + + +# Image loop +# Setting this to on will make neofetch redraw the image constantly until +# Ctrl+C is pressed. This fixes display issues in some terminal emulators. +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --loop +image_loop="off" + +# Thumbnail directory +# +# Default: '~/.cache/thumbnails/neofetch' +# Values: 'dir' +thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch" + +# Crop mode +# +# Default: 'normal' +# Values: 'normal', 'fit', 'fill' +# Flag: --crop_mode +# +# See this wiki page to learn about the fit and fill options. +# https://github.com/dylanaraps/neofetch/wiki/What-is-Waifu-Crop%3F +crop_mode="normal" + +# Crop offset +# Note: Only affects 'normal' crop mode. +# +# Default: 'center' +# Values: 'northwest', 'north', 'northeast', 'west', 'center' +# 'east', 'southwest', 'south', 'southeast' +# Flag: --crop_offset +crop_offset="center" + +# Image size +# The image is half the terminal width by default. +# +# Default: 'auto' +# Values: 'auto', '00px', '00%', 'none' +# Flags: --image_size +# --size +image_size="auto" + +# Gap between image and text +# +# Default: '3' +# Values: 'num', '-num' +# Flag: --gap +gap=3 + +# Image offsets +# Only works with the w3m backend. +# +# Default: '0' +# Values: 'px' +# Flags: --xoffset +# --yoffset +yoffset=0 +xoffset=0 + +# Image background color +# Only works with the w3m backend. +# +# Default: '' +# Values: 'color', 'blue' +# Flag: --bg_color +background_color= + + +# Misc Options + +# Stdout mode +# Turn off all colors and disables image backend (ASCII/Image). +# Useful for piping into another command. +# Default: 'off' +# Values: 'on', 'off' +stdout="off" diff --git a/config/niri-2/config.kdl b/config/niri-2/config.kdl new file mode 100644 index 0000000..b536336 --- /dev/null +++ b/config/niri-2/config.kdl @@ -0,0 +1,269 @@ +spawn-at-startup "waybar" +spawn-at-startup "awww-daemon" +spawn-at-startup "awww" "img" "/home/coast/Downloads/wallhaven-3qrol9_1920x1080.png" +input { + mod-key "Super" + keyboard { + xkb { + options "altwin:swap_alt_win" + } + numlock + repeat-delay 600 + repeat-rate 25 + } + + touchpad { + tap + natural-scroll + } + + trackpoint { + } +} + +gestures { + hot-corners { + off + } +} + +cursor { + xcursor-theme "Adwaita" + xcursor-size 24 +} + +output "HDMI-A-1" { + mode "1920x1080@74.973" + scale 1 + transform "normal" +} + +output "eDP-1" { + off + scale 1 + transform "normal" + position x=1280 y=0 +} + +layout { + gaps 10 + center-focused-column "never" + + preset-column-widths { + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + } + + default-column-width { + proportion 0.5; + } + + focus-ring { + width 2.5 + active-color "#0E0F12" + inactive-color "#191724" + } + + border { + off + width 4 + active-color "#0E0F12" + inactive-color "#0E0F12" + urgent-color "#9b0000" + } + + shadow { + on + softness 30 + spread 5 + offset x=0 y=5 + color "#0007" + } + + struts { + } +} + +prefer-no-csd + +screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" + +spawn-at-startup "waybar &" +spawn-at-startup "swww-daemon &" +spawn-at-startup "swww img --outputs HDMI-A-1 ~/Wallpapers/bay.png &" +spawn-at-startup "eww daemon &" +spawn-at-startup "eww open-many year month day daytype &" +spawn-at-startup "foot --server &" + + +window-rule { + match title="Waydroid" + open-fullscreen true +} +window-rule { + match app-id=r#"firefox$"# title="^Picture-in-Picture$" + open-floating true +} + +window-rule { + match app-id=r#"waydroid$"# + open-fullscreen true +} + +window-rule { + geometry-corner-radius 7 + clip-to-geometry true +} + +binds { + Mod+Shift+Slash { show-hotkey-overlay; } + Mod+Return hotkey-overlay-title="Open a Terminal: alacritty" { spawn "alacritty"; } + Mod+R hotkey-overlay-title="Run an Application: rofi" { spawn-sh "rofi -show drun -config ~/.config/rofi/config.rasi"; } + Mod+Shift+Return hotkey-overlay-title="Run an application: rofi (run)" { spawn-sh "rofi -show run -config ~/.config/rofi/config.rasi"; } + Super+Alt+L hotkey-overlay-title="Lock the screen" { spawn "hyprlock"; } + Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; } + + XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+"; } + XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; } + XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; } + XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; } + + XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; } + + Mod+O repeat=false { toggle-overview; } + Mod+S repeat=false { close-window; } + + Mod+Left { focus-column-left; } + Mod+Down { focus-window-down; } + Mod+Up { focus-window-up; } + Mod+Right { focus-column-right; } + Mod+H { focus-column-left; } + Mod+J { focus-window-down; } + Mod+K { focus-window-up; } + Mod+L { focus-column-right; } + + Mod+Ctrl+Left { move-column-left; } + Mod+Ctrl+Down { move-window-down; } + Mod+Ctrl+Up { move-window-up; } + Mod+Ctrl+Right { move-column-right; } + Mod+Shift+H { move-column-left; } + Mod+Shift+J { move-window-down; } + Mod+Shift+K { move-window-up; } + Mod+Shift+L { move-column-right; } + + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + + Mod+Shift+Left { focus-monitor-left; } + Mod+Shift+Down { focus-monitor-down; } + Mod+Shift+Up { focus-monitor-up; } + Mod+Shift+Right { focus-monitor-right; } + Mod+Ctrl+H { focus-monitor-left; } + Mod+Ctrl+J { focus-monitor-down; } + Mod+Ctrl+K { focus-monitor-up; } + Mod+Ctrl+L { focus-monitor-right; } + + Mod+Shift+Ctrl+Left { move-column-to-monitor-left; } + Mod+Shift+Ctrl+Down { move-column-to-monitor-down; } + Mod+Shift+Ctrl+Up { move-column-to-monitor-up; } + Mod+Shift+Ctrl+Right { move-column-to-monitor-right; } + Mod+Shift+Ctrl+H { move-column-to-monitor-left; } + Mod+Shift+Ctrl+J { move-column-to-monitor-down; } + Mod+Shift+Ctrl+K { move-column-to-monitor-up; } + Mod+Shift+Ctrl+L { move-column-to-monitor-right; } + + Mod+Page_Down { focus-workspace-down; } + Mod+Page_Up { focus-workspace-up; } + Mod+N { focus-workspace-down; } + Mod+M { focus-workspace-up; } + Mod+Ctrl+Page_Down { move-column-to-workspace-down; } + Mod+Ctrl+Page_Up { move-column-to-workspace-up; } + Mod+Ctrl+M { move-column-to-workspace-down; } + Mod+Ctrl+N { move-column-to-workspace-up; } + + Mod+Shift+P hotkey-overlay-title="Restart waybar and eww" { spawn-sh "pkill waybar && waybar & disown && eww kill && eww daemon && eww open-many year month day daytype"; } + + Mod+Shift+Page_Down { move-workspace-down; } + Mod+Shift+Page_Up { move-workspace-up; } + Mod+Shift+M { move-workspace-down; } + Mod+Shift+N { move-workspace-up; } + + Mod+1 { focus-workspace 1; } + Mod+2 { focus-workspace 2; } + Mod+3 { focus-workspace 3; } + Mod+4 { focus-workspace 4; } + Mod+5 { focus-workspace 5; } + Mod+6 { focus-workspace 6; } + Mod+7 { focus-workspace 7; } + Mod+8 { focus-workspace 8; } + Mod+9 { focus-workspace 9; } + Mod+Shift+1 { move-column-to-workspace 1; } + Mod+Shift+2 { move-column-to-workspace 2; } + Mod+Shift+3 { move-column-to-workspace 3; } + Mod+Shift+4 { move-column-to-workspace 4; } + Mod+Shift+5 { move-column-to-workspace 5; } + Mod+Shift+6 { move-column-to-workspace 6; } + Mod+Shift+7 { move-column-to-workspace 7; } + Mod+Shift+8 { move-column-to-workspace 8; } + Mod+Shift+9 { move-column-to-workspace 9; } + + Mod+BracketLeft { consume-or-expel-window-left; } + Mod+BracketRight { consume-or-expel-window-right; } + + Mod+Comma { consume-window-into-column; } + Mod+Period { expel-window-from-column; } + + Mod+D { switch-preset-column-width; } + Mod+Shift+R { switch-preset-window-height; } + Mod+Ctrl+R { reset-window-height; } + Mod+W { maximize-column; } + Mod+Shift+W { fullscreen-window; } + + Mod+Ctrl+F { expand-column-to-available-width; } + Mod+C { center-column; } + Mod+Ctrl+C { center-visible-columns; } + + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + + Mod+Shift+Minus { set-window-height "-10%"; } + Mod+Shift+Equal { set-window-height "+10%"; } + + Mod+Space { toggle-window-floating; } + Mod+Shift+V { switch-focus-between-floating-and-tiling; } + + Mod+Shift+F { toggle-column-tabbed-display; } + Mod+F hotkey-overlay-title="Spawn file manager (nautilus)" { spawn "nautilus"; } + + Print { screenshot; } + Super+Shift+S { screenshot; } + Control+Alt+S { screenshot-window; } + Ctrl+Print { screenshot-screen; } + Alt+Print { screenshot-window; } + + Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; } + + Mod+Shift+E { quit; } + Ctrl+Alt+Delete { quit; } + + Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } + Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; } + + Mod+WheelScrollRight { focus-column-right; } + Mod+WheelScrollLeft { focus-column-left; } + Mod+Ctrl+WheelScrollRight { move-column-right; } + Mod+Ctrl+WheelScrollLeft { move-column-left; } + + Mod+Shift+WheelScrollDown { focus-column-right; } + Mod+Shift+WheelScrollUp { focus-column-left; } + Mod+Ctrl+Shift+WheelScrollDown { move-column-right; } + Mod+Ctrl+Shift+WheelScrollUp { move-column-left; } +} + + diff --git a/config/niri/config.kdl b/config/niri/config.kdl new file mode 100755 index 0000000..56782dd --- /dev/null +++ b/config/niri/config.kdl @@ -0,0 +1,265 @@ +input { + mod-key "Super" + keyboard { + xkb { + } + numlock + repeat-delay 600 + repeat-rate 25 + } + + touchpad { + tap + natural-scroll + } + + trackpoint { + } +} + +gestures { + hot-corners { + off + } +} + +cursor { + xcursor-theme "Adwaita" + xcursor-size 24 +} + +output "HDMI-A-1" { + mode "1920x1080@74.973" + scale 1 + transform "normal" +} + +output "eDP-1" { + off + scale 1 + transform "normal" + position x=1280 y=0 +} + +layout { + gaps 5 + center-focused-column "never" + + preset-column-widths { + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + } + + default-column-width { + proportion 0.5; + } + + focus-ring { + width 2.5 + active-color "#211e1e" + inactive-color "#191724" + } + + border { + off + width 4 + active-color "#191724" + inactive-color "#191724" + urgent-color "#9b0000" + } + + shadow { + on + softness 30 + spread 5 + offset x=0 y=5 + color "#0007" + } + + struts { + } +} + +prefer-no-csd + +screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" + +spawn-at-startup "waybar &" +spawn-at-startup "swww-daemon &" +spawn-at-startup "swww img --outputs HDMI-A-1 ~/Wallpapers/bay.png &" +spawn-at-startup "eww daemon &" +spawn-at-startup "eww open-many year month day daytype &" +spawn-at-startup "foot --server &" + + +window-rule { + match title="Waydroid" + open-fullscreen true +} +window-rule { + match app-id=r#"firefox$"# title="^Picture-in-Picture$" + open-floating true +} + +window-rule { + match app-id=r#"waydroid$"# + open-fullscreen true +} + +window-rule { + geometry-corner-radius 7 + clip-to-geometry true +} + +binds { + Mod+Shift+Slash { show-hotkey-overlay; } + Mod+Return hotkey-overlay-title="Open a Terminal: footclient" { spawn "footclient"; } + Mod+R hotkey-overlay-title="Run an Application: rofi" { spawn-sh "rofi -show drun -config ~/.config/rofi/gruvbox.rasi"; } + Mod+Shift+Return hotkey-overlay-title="Run an application: rofi (run)" { spawn-sh "rofi -show run -config ~/.config/rofi/gruvbox.rasi"; } + Super+Alt+L hotkey-overlay-title="Lock the screen" { spawn "swaylock"; } + Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; } + + XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+"; } + XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; } + XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; } + XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; } + + XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; } + + Mod+O repeat=false { toggle-overview; } + Mod+S repeat=false { close-window; } + + Mod+Left { focus-column-left; } + Mod+Down { focus-window-down; } + Mod+Up { focus-window-up; } + Mod+Right { focus-column-right; } + Mod+H { focus-column-left; } + Mod+J { focus-window-down; } + Mod+K { focus-window-up; } + Mod+L { focus-column-right; } + + Mod+Ctrl+Left { move-column-left; } + Mod+Ctrl+Down { move-window-down; } + Mod+Ctrl+Up { move-window-up; } + Mod+Ctrl+Right { move-column-right; } + Mod+Shift+H { move-column-left; } + Mod+Shift+J { move-window-down; } + Mod+Shift+K { move-window-up; } + Mod+Shift+L { move-column-right; } + + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + + Mod+Shift+Left { focus-monitor-left; } + Mod+Shift+Down { focus-monitor-down; } + Mod+Shift+Up { focus-monitor-up; } + Mod+Shift+Right { focus-monitor-right; } + Mod+Ctrl+H { focus-monitor-left; } + Mod+Ctrl+J { focus-monitor-down; } + Mod+Ctrl+K { focus-monitor-up; } + Mod+Ctrl+L { focus-monitor-right; } + + Mod+Shift+Ctrl+Left { move-column-to-monitor-left; } + Mod+Shift+Ctrl+Down { move-column-to-monitor-down; } + Mod+Shift+Ctrl+Up { move-column-to-monitor-up; } + Mod+Shift+Ctrl+Right { move-column-to-monitor-right; } + Mod+Shift+Ctrl+H { move-column-to-monitor-left; } + Mod+Shift+Ctrl+J { move-column-to-monitor-down; } + Mod+Shift+Ctrl+K { move-column-to-monitor-up; } + Mod+Shift+Ctrl+L { move-column-to-monitor-right; } + + Mod+Page_Down { focus-workspace-down; } + Mod+Page_Up { focus-workspace-up; } + Mod+N { focus-workspace-down; } + Mod+M { focus-workspace-up; } + Mod+Ctrl+Page_Down { move-column-to-workspace-down; } + Mod+Ctrl+Page_Up { move-column-to-workspace-up; } + Mod+Ctrl+M { move-column-to-workspace-down; } + Mod+Ctrl+N { move-column-to-workspace-up; } + + Mod+Shift+P hotkey-overlay-title="Restart waybar and eww" { spawn-sh "pkill waybar && waybar & disown && eww kill && eww daemon && eww open-many year month day daytype"; } + + Mod+Shift+Page_Down { move-workspace-down; } + Mod+Shift+Page_Up { move-workspace-up; } + Mod+Shift+M { move-workspace-down; } + Mod+Shift+N { move-workspace-up; } + + Mod+1 { focus-workspace 1; } + Mod+2 { focus-workspace 2; } + Mod+3 { focus-workspace 3; } + Mod+4 { focus-workspace 4; } + Mod+5 { focus-workspace 5; } + Mod+6 { focus-workspace 6; } + Mod+7 { focus-workspace 7; } + Mod+8 { focus-workspace 8; } + Mod+9 { focus-workspace 9; } + Mod+Shift+1 { move-column-to-workspace 1; } + Mod+Shift+2 { move-column-to-workspace 2; } + Mod+Shift+3 { move-column-to-workspace 3; } + Mod+Shift+4 { move-column-to-workspace 4; } + Mod+Shift+5 { move-column-to-workspace 5; } + Mod+Shift+6 { move-column-to-workspace 6; } + Mod+Shift+7 { move-column-to-workspace 7; } + Mod+Shift+8 { move-column-to-workspace 8; } + Mod+Shift+9 { move-column-to-workspace 9; } + + Mod+BracketLeft { consume-or-expel-window-left; } + Mod+BracketRight { consume-or-expel-window-right; } + + Mod+Comma { consume-window-into-column; } + Mod+Period { expel-window-from-column; } + + Mod+D { switch-preset-column-width; } + Mod+Shift+R { switch-preset-window-height; } + Mod+Ctrl+R { reset-window-height; } + Mod+W { maximize-column; } + Mod+Shift+W { fullscreen-window; } + + Mod+Ctrl+F { expand-column-to-available-width; } + Mod+C { center-column; } + Mod+Ctrl+C { center-visible-columns; } + + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + + Mod+Shift+Minus { set-window-height "-10%"; } + Mod+Shift+Equal { set-window-height "+10%"; } + + Mod+Space { toggle-window-floating; } + Mod+Shift+V { switch-focus-between-floating-and-tiling; } + + Mod+Shift+F { toggle-column-tabbed-display; } + Mod+F hotkey-overlay-title="Spawn file manager (nautilus)" { spawn "nautilus"; } + + Print { screenshot; } + Super+Shift+S { screenshot; } + Control+Alt+S { screenshot-window; } + Ctrl+Print { screenshot-screen; } + Alt+Print { screenshot-window; } + + Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; } + + Mod+Shift+E { quit; } + Ctrl+Alt+Delete { quit; } + + Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } + Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; } + + Mod+WheelScrollRight { focus-column-right; } + Mod+WheelScrollLeft { focus-column-left; } + Mod+Ctrl+WheelScrollRight { move-column-right; } + Mod+Ctrl+WheelScrollLeft { move-column-left; } + + Mod+Shift+WheelScrollDown { focus-column-right; } + Mod+Shift+WheelScrollUp { focus-column-left; } + Mod+Ctrl+Shift+WheelScrollDown { move-column-right; } + Mod+Ctrl+Shift+WheelScrollUp { move-column-left; } +} + + diff --git a/config/nushell/config.nu b/config/nushell/config.nu new file mode 100755 index 0000000..1658d14 --- /dev/null +++ b/config/nushell/config.nu @@ -0,0 +1,99 @@ +$env.config.buffer_editor = "vim" +$env.PROMPT_COMMAND_RIGHT = "" +$env.path ++= ["~/.local/bin"] +$env.config.show_banner = false +$env.config.table.mode = 'none' +$env.TERM = "xterm" +$env.USER = "coast" + +$env.PROMPT_COMMAND = { + let dir = (pwd | path basename) + let home_dir = ($dir | str replace "coast" "home") + $"(ansi reset)0 ($env.USER) ($home_dir) " +} + +$env.PROMPT_INDICATOR = "" + +let carapace_completer = {|spans| + carapace $spans.0 nushell ...$spans | from json +} + +$env.config = { + show_banner: false + completions: { + case_sensitive: false + quick: true + partial: true + algorithm: "fuzzy" + external: { + enable: true + max_results: 100 + completer: $carapace_completer + } + } +} + +alias sd = sudo +alias nano = vim +alias suod = sudo +alias sduo = sudo +alias hotp = htop +alias c = clear +alias dir = tree -idA + +let bg0 = "#0f0f0f" +let bg1 = "#1a1a1a" +let bg2 = "#2a2a2a" +let bg3 = "#3a3a3a" +let fg0 = "#e0def4" +let fg1 = "#ebbcba" +let red = "#eb6f92" +let green = "#eb6f92" +let yellow = "#ea9a97" +let blue = "#d7827e" +let purple = "#ea9a97" +let aqua = "#ebbcba" +let orange = "#ea9a97" +let gray = "#6e6a86" + +let dark = { + separator: $gray, + leading_trailing_space_bg: $bg1, + header: $yellow, + datetime: $blue, + filesize: $green, + row_index: $gray, + + bool: $green, + int: $orange, + float: $yellow, + string: $fg1, + nothing: $gray, + binary: $red, + cell-path: $blue, + hints: $gray, + + shape_garbage: { fg: $fg0 bg: $red attr: b }, + shape_bool: $green, + shape_int: { fg: $orange attr: b }, + shape_float: { fg: $yellow attr: b }, + shape_range: { fg: $yellow attr: b }, + shape_internalcall: { fg: $aqua attr: b }, + shape_external: $blue, + shape_externalarg: { fg: $green attr: b }, + shape_literal: $fg1, + shape_operator: $orange, + shape_signature: { fg: $yellow attr: b }, + shape_string: $purple, + shape_filepath: $blue, + shape_globpattern: { fg: $blue attr: b }, + shape_variable: $aqua, + shape_flag: { fg: $yellow attr: b }, + shape_custom: { attr: b } +} + +$env.config.color_config = $dark +$env.config.use_ansi_coloring = true + +source ~/.config/nushell/starship.nu + diff --git a/config/nushell/starship.nu b/config/nushell/starship.nu new file mode 100755 index 0000000..8bef494 --- /dev/null +++ b/config/nushell/starship.nu @@ -0,0 +1,35 @@ +export-env { $env.STARSHIP_SHELL = "nu"; load-env { + STARSHIP_SESSION_KEY: (random chars -l 16) + PROMPT_MULTILINE_INDICATOR: ( + ^/etc/profiles/per-user/coast/bin/starship prompt --continuation + ) + + # Does not play well with default character module. + # TODO: Also Use starship vi mode indicators? + PROMPT_INDICATOR: "" + + PROMPT_COMMAND: {|| + # jobs are not supported + ( + ^/etc/profiles/per-user/coast/bin/starship prompt + --cmd-duration $env.CMD_DURATION_MS + $"--status=($env.LAST_EXIT_CODE)" + --terminal-width (term size).columns + ) + } + + config: ($env.config? | default {} | merge { + render_right_prompt_on_last_line: true + }) + + PROMPT_COMMAND_RIGHT: {|| + ( + ^/etc/profiles/per-user/coast/bin/starship prompt + --right + --cmd-duration $env.CMD_DURATION_MS + $"--status=($env.LAST_EXIT_CODE)" + --terminal-width (term size).columns + ) + } +}} + diff --git a/config/nvim-1/init.lua b/config/nvim-1/init.lua new file mode 100755 index 0000000..d9da61e --- /dev/null +++ b/config/nvim-1/init.lua @@ -0,0 +1,11 @@ +require("plugins/lazy") +require("plugins/lsp") +require("plugins/nvim-tree") +require("plugins/telescope") +require("plugins/treesitter") +require("config") +require("plugins/render-markdown") +--require("status_line").setup() +require("plugins/lualine") +require("plugins/catppuccin") +require("colorizer").setup() -- #ffffff #edb511 diff --git a/config/nvim-1/lazy-lock.json b/config/nvim-1/lazy-lock.json new file mode 100755 index 0000000..27e4c91 --- /dev/null +++ b/config/nvim-1/lazy-lock.json @@ -0,0 +1,40 @@ +{ + "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, + "cmp-cmdline": { "branch": "main", "commit": "d126061b624e0af6c3a556428712dd4d4194ec6d" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "a8912b88ce488f411177fc8aed358b04dc246d7b" }, + "cmp-nvim-lua": { "branch": "main", "commit": "f12408bdb54c39c23e67cab726264c10db33ada8" }, + "cmp-path": { "branch": "main", "commit": "c6635aae33a50d6010bf1aa756ac2398a2d54c32" }, + "cmp-spell": { "branch": "master", "commit": "694a4e50809d6d645c1ea29015dad0c293f019d6" }, + "cmp-vsnip": { "branch": "main", "commit": "989a8a73c44e926199bfd05fa7a516d51f2d2752" }, + "comfy-line-numbers.nvim": { "branch": "main", "commit": "31e2f9287b4491ad72defb9e0185eb2739983799" }, + "fterm.nvim": { "branch": "master", "commit": "d1320892cc2ebab472935242d9d992a2c9570180" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, + "lsp_signature.nvim": { "branch": "master", "commit": "d50e40b3bf9324128e71b0b7e589765ce89466d2" }, + "lualine.nvim": { "branch": "master", "commit": "a94fc68960665e54408fe37dcf573193c4ce82c9" }, + "mason.nvim": { "branch": "main", "commit": "8024d64e1330b86044fed4c8494ef3dcd483a67c" }, + "mini.nvim": { "branch": "main", "commit": "429e5f9dc9cd59bf76cd98b687300f0a384a7f52" }, + "moonfly": { "branch": "master", "commit": "ef85b89739bee184e204c89bc06280d62bd84039" }, + "none-ls-extras.nvim": { "branch": "main", "commit": "924fe88a9983c7d90dbb31fc4e3129a583ea0a90" }, + "none-ls.nvim": { "branch": "main", "commit": "db2a48b79cfcdab8baa5d3f37f21c78b6705c62e" }, + "nvim": { "branch": "main", "commit": "0a5de4da015a175f416d6ef1eda84661623e0500" }, + "nvim-autopairs": { "branch": "master", "commit": "4d74e75913832866aa7de35e4202463ddf6efd1b" }, + "nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" }, + "nvim-colorizer.lua": { "branch": "master", "commit": "a065833f35a3a7cc3ef137ac88b5381da2ba302e" }, + "nvim-lspconfig": { "branch": "master", "commit": "77d3fdfb3554632c7a3b101ded643d422de7626f" }, + "nvim-numbertoggle": { "branch": "main", "commit": "923f9709989605fe2bc4b9de8a3625fa808f5cd6" }, + "nvim-toggler": { "branch": "main", "commit": "467808600882fd6c9e33b9dbc4889b1b80cfd917" }, + "nvim-tree.lua": { "branch": "master", "commit": "1c733e8c1957dc67f47580fe9c458a13b5612d5b" }, + "nvim-treesitter": { "branch": "main", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, + "nvim-web-devicons": { "branch": "master", "commit": "1fb58cca9aebbc4fd32b086cb413548ce132c127" }, + "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, + "presence.nvim": { "branch": "main", "commit": "87c857a56b7703f976d3a5ef15967d80508df6e6" }, + "render-markdown.nvim": { "branch": "main", "commit": "10126effbafb74541b69219711dfb2c631e7ebf8" }, + "telescope-undo.nvim": { "branch": "main", "commit": "928d0c2dc9606e01e2cc547196f48d2eaecf58e5" }, + "telescope.nvim": { "branch": "master", "commit": "d90956833d7c27e73c621a61f20b29fdb7122709" }, + "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, + "twilight.nvim": { "branch": "main", "commit": "664e752f4a219801265cc3fc18782b457b58c1e1" }, + "typst-preview.nvim": { "branch": "master", "commit": "e544812bba84b4f7976590f2b6c0dfbd099e1893" }, + "vim-closetag": { "branch": "master", "commit": "d0a562f8bdb107a50595aefe53b1a690460c3822" }, + "vim-vsnip": { "branch": "master", "commit": "0a4b8419e44f47c57eec4c90df17567ad4b1b36e" }, + "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" } +} diff --git a/config/nvim-1/lua/config.lua b/config/nvim-1/lua/config.lua new file mode 100755 index 0000000..f37534b --- /dev/null +++ b/config/nvim-1/lua/config.lua @@ -0,0 +1,86 @@ +local opt = vim.opt +local map = vim.keymap.set +local g = vim.g + +--filetypes +vim.cmd("autocmd BufRead,BufNewFile *.m set filetype=objc") + +g.mapleader = " " + +opt.shiftwidth = 4 +opt.tabstop = 4 +opt.softtabstop = 4 +opt.smarttab = true +opt.smartindent = true + +opt.undofile = true +opt.undodir = vim.fn.stdpath("config") .. "/undo" + +opt.number = true +opt.relativenumber = true + +opt.fillchars = "eob: " + +g.loaded_netrw = 1 +g.loaded_netrwPlugin = 1 + +opt.termguicolors = true + +opt.spell = false +opt.spelllang = { "en_us" } + +opt.shell = "/usr/bin/zsh" + +vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { + border = "single", +}) +vim.diagnostic.config({ float = { border = "single" } }) + +map("n", "u", ":Telescope") +map("n", "t", ":tabnew") +map("n", "", ":tabn") +map("n", "", ":tabp") +map("n", "", ":bw") + +map("n", ".", vim.diagnostic.open_float) + +map("n", "=", "=") + +map("n", "x", "!chmod +x %") + +vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("UserLspConfig", {}), + callback = function(ev) + vim.bo[ev.buf].omnifunc = "v:lua.vim.lsp.omnifunc" + + local opts = { buffer = ev.buf } + map("n", "K", function() + vim.lsp.buf.hover({ border = "single" }) + end, opts) + map("n", "gi", vim.lsp.buf.implementation, opts) + map("n", "", vim.lsp.buf.signature_help, opts) + map("n", "wa", vim.lsp.buf.add_workspace_folder, opts) + map("n", "wr", vim.lsp.buf.remove_workspace_folder, opts) + map("n", "wl", function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, opts) + map("n", "D", vim.lsp.buf.type_definition, opts) + map("n", "rn", vim.lsp.buf.rename, opts) + map({ "n", "v" }, "ca", vim.lsp.buf.code_action, opts) + map("n", "gr", vim.lsp.buf.references, opts) + map("n", "f", function() + vim.lsp.buf.format({ async = true }) + end, opts) + end, +}) + +local builtin = require("telescope.builtin") +map("n", "ff", builtin.find_files, {}) +map("n", "fg", builtin.live_grep, {}) +map("n", "fb", builtin.buffers, {}) +map("n", "fh", builtin.help_tags, {}) +local treeapi = require("nvim-tree.api") +map("n", "e", treeapi.tree.toggle, {}) + +map("n", "", 'lua require("FTerm").toggle()') +map("t", "", 'lua require("FTerm").toggle()') diff --git a/config/nvim-1/lua/plugins/catppuccin/init.lua b/config/nvim-1/lua/plugins/catppuccin/init.lua new file mode 100755 index 0000000..29afa04 --- /dev/null +++ b/config/nvim-1/lua/plugins/catppuccin/init.lua @@ -0,0 +1,84 @@ +local colors = { + black = "#121212", + white = "#ffffff", + gray = "#7e7e7e", + light_gray = "#d0d0d0", + dark_gray = "#505050", + red = "#ff5c57", + green = "#5af78e", + yellow = "#f3f99d", + blue = "#57c7ff", + purple = "#d183e8", + cyan = "#9aedfe", +} + +local highlights = { + Normal = { fg = colors.light_gray, bg = colors.black }, + Comment = { fg = colors.gray, italic = true }, + Constant = { fg = colors.blue }, + String = { fg = colors.green }, + Identifier = { fg = colors.blue }, + Function = { fg = colors.purple }, + Statement = { fg = colors.yellow }, + PreProc = { fg = colors.cyan }, + Type = { fg = colors.blue }, + Special = { fg = colors.red }, + Underlined = { fg = colors.white, underline = true }, + Todo = { fg = colors.black, bg = colors.yellow, bold = true }, + + StatusLine = { fg = colors.white, bg = colors.dark_gray }, + StatusLineNC = { fg = colors.light_gray, bg = colors.black }, + NvimTreeNormal = { fg = colors.light_gray, bg = colors.black }, + NvimTreeFolderName = { fg = colors.blue, bold = true }, + NvimTreeOpenedFolderName = { fg = colors.green, bold = true }, + NvimTreeRootFolder = { fg = colors.yellow, bold = true, underline = true }, + NvimTreeFileIcon = { fg = colors.light_gray }, + NvimTreeGitDirty = { fg = colors.red }, + NvimTreeGitStaged = { fg = colors.green }, + NvimTreeGitNew = { fg = colors.blue }, + NvimTreeGitRenamed = { fg = colors.purple }, + NvimTreeGitDeleted = { fg = colors.red }, + CursorLine = { bg = colors.dark_gray }, +} + +for group, opts in pairs(highlights) do + vim.api.nvim_set_hl(0, group, opts) +end + +require("lualine").setup({ + options = { + theme = { + normal = { + a = { fg = colors.black, bg = colors.white, gui = "bold" }, + b = { fg = colors.white, bg = colors.dark_gray }, + c = { fg = colors.white, bg = colors.black }, + }, + inactive = { + a = { fg = colors.dark_gray, bg = colors.black, gui = "bold" }, + b = { fg = colors.dark_gray, bg = colors.black }, + c = { fg = colors.dark_gray, bg = colors.black }, + }, + }, + }, +}) + +require("nvim-tree").setup({ + view = { + width = 30, + side = "left", + }, + renderer = { + highlight_git = true, + root_folder_modifier = ":~", + icons = { + show = { + file = true, + folder = true, + git = true, + }, + }, + }, + filters = { + dotfiles = false, + }, +}) diff --git a/config/nvim-1/lua/plugins/lazy/init.lua b/config/nvim-1/lua/plugins/lazy/init.lua new file mode 100755 index 0000000..497cf69 --- /dev/null +++ b/config/nvim-1/lua/plugins/lazy/init.lua @@ -0,0 +1,17 @@ +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +local lazy_plugins = require("plugins/lazy/plugins") + +require("lazy").setup(lazy_plugins) +require("mason").setup() diff --git a/config/nvim-1/lua/plugins/lazy/plugins.lua b/config/nvim-1/lua/plugins/lazy/plugins.lua new file mode 100755 index 0000000..10da3ea --- /dev/null +++ b/config/nvim-1/lua/plugins/lazy/plugins.lua @@ -0,0 +1,128 @@ +return { + { + "andweeb/presence.nvim", + "catppuccin/nvim", + --"morhetz/gruvbox", + "neovim/nvim-lspconfig", + "williamboman/mason.nvim", + { + "nvim-telescope/telescope.nvim", + tag = "0.1.5", + dependencies = { "nvim-lua/plenary.nvim" }, + }, + { + "nvim-tree/nvim-tree.lua", + dependencies = { "nvim-tree/nvim-web-devicons" }, + }, + { + "folke/todo-comments.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + opts = {}, + }, + { + "nvim-lualine/lualine.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + }, + { + "nvimtools/none-ls.nvim", + dependencies = { + "nvimtools/none-ls-extras.nvim", + }, + }, + { + "windwp/nvim-autopairs", + event = "InsertEnter", + }, + { + "hrsh7th/nvim-cmp", + dependencies = { + "neovim/nvim-lspconfig", + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-nvim-lua", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-path", + "hrsh7th/cmp-cmdline", + "hrsh7th/cmp-vsnip", + "hrsh7th/vim-vsnip", + }, + }, + { + "ray-x/lsp_signature.nvim", + event = "VeryLazy", + }, + "nvim-treesitter/nvim-treesitter", + "f3fora/cmp-spell", + { + "debugloop/telescope-undo.nvim", + dependencies = { + { + "nvim-telescope/telescope.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + }, + }, + }, + { + "chomosuke/typst-preview.nvim", + lazy = false, + version = "1.*", + opts = {}, + }, + { + "MeanderingProgrammer/render-markdown.nvim", + dependencies = { + "nvim-treesitter/nvim-treesitter", + "nvim-mini/mini.nvim", + }, + opts = {}, + }, + "sitiom/nvim-numbertoggle", + "mluders/comfy-line-numbers.nvim", + { + "folke/which-key.nvim", + event = "VeryLazy", + init = function() + vim.o.timeout = true + vim.o.timeoutlen = 300 + end, + }, + { + "folke/twilight.nvim", + opts = { + dimming = { + alpha = 0.35, + color = { "Normal" }, + term_bg = "#282828", + inactive = false, + }, + context = 15, + treesitter = true, + expand = { + "function", + "method", + "table", + "if_statement", + }, + exclude = { + "md", + }, + }, + }, + "nguyenvukhang/nvim-toggler", + "alvan/vim-closetag", + "norcalli/nvim-colorizer.lua", + { + "numtostr/fterm.nvim", + border = "double", + dimensions = { + height = 0.9, + width = 0.9, + }, + }, + { + "bluz71/vim-moonfly-colors", + name = "moonfly", + lazy = false, + priority = 1000, + }, + }, +} diff --git a/config/nvim-1/lua/plugins/lsp/init.lua b/config/nvim-1/lua/plugins/lsp/init.lua new file mode 100755 index 0000000..1785d51 --- /dev/null +++ b/config/nvim-1/lua/plugins/lsp/init.lua @@ -0,0 +1,120 @@ +local lsp = require("lspconfig") +local fmt = require("null-ls") +local cmp = require("cmp") + +require("nvim-autopairs").setup({}) +require("lsp_signature").setup({ hint_enable = false }) + +local augroup = vim.api.nvim_create_augroup("LspFormatting", {}) +fmt.setup({ + sources = { + fmt.builtins.formatting.clang_format, + require("none-ls.formatting.rustfmt"), + fmt.builtins.formatting.stylua, + fmt.builtins.formatting.gofmt, + }, + on_attach = function(client, bufnr) + if client.supports_method("textDocument/formatting") then + vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr }) + vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + buffer = bufnr, + callback = function() + vim.lsp.buf.format({ async = false }) + end, + }) + end + end, +}) + +cmp.setup({ + snippet = { + expand = function(args) + vim.fn["vsnip#anonymous"](args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm({ select = true }), + }), + window = { completion = cmp.config.window.bordered(), documentation = cmp.config.window.bordered() }, + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + { name = "vsnip" }, + { name = "spell" }, + }, { + { name = "buffer" }, + { name = "nvim_lua" }, + }), +}) + +local capabilities = require("cmp_nvim_lsp").default_capabilities() + +lsp.html.setup({ + cmd = { "vscode-html-language-server", "--stdio" }, + capabilities = capabilities, + init_options = { + configurationSection = { "html", "css", "javascript" }, + embeddedLanguages = { css = true, javascript = true }, + provideFormatter = true, + }, + settings = { + html = { + format = { + wrapLineLength = 120, + wrapAttributes = "auto", + contentUnformatted = "pre,code,textarea", + }, + hover = { documentation = true, references = true }, + }, + }, +}) + +lsp.cssls.setup({ + capabilities = capabilities, + settings = { css = { validate = true }, scss = { validate = true }, less = { validate = true } }, +}) + +lsp.ts_ls.setup({ + capabilities = capabilities, + on_attach = function(client) + client.server_capabilities.documentFormattingProvider = false + end, +}) + +lsp.rust_analyzer.setup({ capabilities = capabilities }) + +local clangd_capabilities = vim.deepcopy(capabilities) +clangd_capabilities["offsetEncoding"] = "utf-8" +lsp.clangd.setup({ + cmd = { "clangd", "--background-index", "--function-arg-placeholders=0", "-j=12", "--clang-tidy" }, + capabilities = clangd_capabilities, + init_options = { documentFormatting = true }, +}) + +lsp.pyright.setup({ capabilities = capabilities }) +lsp.gopls.setup({ capabilities = capabilities }) +lsp.asm_lsp.setup({ capabilities = capabilities }) +lsp.zls.setup({ capabilities = capabilities }) +lsp.jdtls.setup({ capabilities = capabilities }) +lsp.tinymist.setup({ capabilities = capabilities }) + +lsp.lua_ls.setup({ + on_init = function(client) + local path = client.workspace_folders[1].name + if not vim.loop.fs_stat(path .. "/.luarc.json") and not vim.loop.fs_stat(path .. "/.luarc.jsonc") then + client.config.settings = vim.tbl_deep_extend("force", client.config.settings, { + Lua = { + runtime = { version = "LuaJIT" }, + workspace = { checkThirdParty = false, library = { vim.env.VIMRUNTIME } }, + }, + }) + client.notify("workspace/didChangeConfiguration", { settings = client.config.settings }) + end + return true + end, + capabilities = capabilities, +}) diff --git a/config/nvim-1/lua/plugins/lualine/init.lua b/config/nvim-1/lua/plugins/lualine/init.lua new file mode 100755 index 0000000..8de1ba9 --- /dev/null +++ b/config/nvim-1/lua/plugins/lualine/init.lua @@ -0,0 +1,42 @@ +local lualine = require("lualine") + +lualine.setup({ + options = { + icons_enabled = true, + theme = "auto", + component_separators = { left = "|", right = "|" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = { + statusline = {}, + winbar = {}, + }, + ignore_focus = {}, + always_divide_middle = true, + globalstatus = false, + refresh = { + statusline = 1000, + tabline = 1000, + winbar = 1000, + }, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch", "diff", "diagnostics" }, + lualine_c = { "filename" }, + lualine_x = { "encoding", "fileformat", "filetype" }, + lualine_y = {}, + lualine_z = { "location" }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { "filename" }, + lualine_x = { "location" }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + winbar = {}, + inactive_winbar = {}, + extensions = {}, +}) diff --git a/config/nvim-1/lua/plugins/nvim-tree/init.lua b/config/nvim-1/lua/plugins/nvim-tree/init.lua new file mode 100755 index 0000000..c7174f7 --- /dev/null +++ b/config/nvim-1/lua/plugins/nvim-tree/init.lua @@ -0,0 +1,2 @@ +local tree = require("nvim-tree") +tree.setup() \ No newline at end of file diff --git a/config/nvim-1/lua/plugins/render-markdown/init.lua b/config/nvim-1/lua/plugins/render-markdown/init.lua new file mode 100755 index 0000000..ab078ce --- /dev/null +++ b/config/nvim-1/lua/plugins/render-markdown/init.lua @@ -0,0 +1,139 @@ +require("render-markdown").setup({ + link = { + -- Turn on / off inline link icon rendering. + enabled = true, + -- Additional modes to render links. + render_modes = false, + -- How to handle footnote links, start with a '^'. + footnote = { + -- Turn on / off footnote rendering. + enabled = true, + -- Replace value with superscript equivalent. + superscript = true, + -- Added before link content. + prefix = "", + -- Added after link content. + suffix = "", + }, + -- Inlined with 'image' elements. + image = "󰥶 ", + -- Inlined with 'email_autolink' elements. + email = "󰀓 ", + -- Fallback icon for 'inline_link' and 'uri_autolink' elements. + hyperlink = "󰌹 ", + -- Applies to the inlined icon as a fallback. + highlight = "RenderMarkdownLink", + -- Applies to WikiLink elements. + wiki = { + icon = "󱗖 ", + body = function() + return nil + end, + highlight = "RenderMarkdownWikiLink", + }, + -- Define custom destination patterns so icons can quickly inform you of what a link + -- contains. Applies to 'inline_link', 'uri_autolink', and wikilink nodes. When multiple + -- patterns match a link the one with the longer pattern is used. + -- The key is for healthcheck and to allow users to change its values, value type below. + -- | pattern | matched against the destination text | + -- | icon | gets inlined before the link text | + -- | kind | optional determines how pattern is checked | + -- | | pattern | @see :h lua-patterns, is the default if not set | + -- | | suffix | @see :h vim.endswith() | + -- | priority | optional used when multiple match, uses pattern length if empty | + -- | highlight | optional highlight for 'icon', uses fallback highlight if empty | + custom = { + web = { pattern = "^http", icon = "󰖟 " }, + github = { pattern = "github%.com", icon = "󰊤 " }, + gitlab = { pattern = "gitlab%.com", icon = "󰮠 " }, + stackoverflow = { pattern = "stackoverflow%.com", icon = "󰓌 " }, + wikipedia = { pattern = "wikipedia%.org", icon = "󰖬 " }, + youtube = { pattern = "youtube%.com", icon = "󰗃 " }, + }, + }, + callout = { + -- Callouts are a special instance of a 'block_quote' that start with a 'shortcut_link'. + -- The key is for healthcheck and to allow users to change its values, value type below. + -- | raw | matched against the raw text of a 'shortcut_link', case insensitive | + -- | rendered | replaces the 'raw' value when rendering | + -- | highlight | highlight for the 'rendered' text and quote markers | + -- | quote_icon | optional override for quote.icon value for individual callout | + -- | category | optional metadata useful for filtering | + + note = { raw = "[!NOTE]", rendered = "󰋽 Note", highlight = "RenderMarkdownInfo" }, + tip = { raw = "[!TIP]", rendered = "󰌶 Tip", highlight = "RenderMarkdownSuccess" }, + important = { raw = "[!IMPORTANT]", rendered = "󰅾 Important", highlight = "RenderMarkdownHint" }, + warning = { raw = "[!WARNING]", rendered = "󰀪 Warning", highlight = "RenderMarkdownWarn" }, + caution = { raw = "[!CAUTION]", rendered = "󰳦 Caution", highlight = "RenderMarkdownError" }, + abstract = { raw = "[!ABSTRACT]", rendered = "󰨸 Abstract", highlight = "RenderMarkdownInfo" }, + summary = { raw = "[!SUMMARY]", rendered = "󰨸 Summary", highlight = "RenderMarkdownInfo" }, + tldr = { raw = "[!TLDR]", rendered = "󰨸 Tldr", highlight = "RenderMarkdownInfo" }, + info = { raw = "[!INFO]", rendered = "󰋽 Info", highlight = "RenderMarkdownInfo" }, + todo = { raw = "[!TODO]", rendered = "󰗡 Todo", highlight = "RenderMarkdownInfo" }, + hint = { raw = "[!HINT]", rendered = "󰌶 Hint", highlight = "RenderMarkdownSuccess" }, + success = { raw = "[!SUCCESS]", rendered = "󰄬 Success", highlight = "RenderMarkdownSuccess" }, + check = { raw = "[!CHECK]", rendered = "󰄬 Check", highlight = "RenderMarkdownSuccess" }, + done = { raw = "[!DONE]", rendered = "󰄬 Done", highlight = "RenderMarkdownSuccess" }, + question = { raw = "[!QUESTION]", rendered = "󰘥 Question", highlight = "RenderMarkdownWarn" }, + help = { raw = "[!HELP]", rendered = "󰘥 Help", highlight = "RenderMarkdownWarn" }, + faq = { raw = "[!FAQ]", rendered = "󰘥 Faq", highlight = "RenderMarkdownWarn" }, + attention = { raw = "[!ATTENTION]", rendered = "󰀪 Attention", highlight = "RenderMarkdownWarn" }, + failure = { raw = "[!FAILURE]", rendered = "󰅖 Failure", highlight = "RenderMarkdownError" }, + fail = { raw = "[!FAIL]", rendered = "󰅖 Fail", highlight = "RenderMarkdownError" }, + missing = { raw = "[!MISSING]", rendered = "󰅖 Missing", highlight = "RenderMarkdownError" }, + danger = { raw = "[!DANGER]", rendered = "󱐌 Danger", highlight = "RenderMarkdownError" }, + error = { raw = "[!ERROR]", rendered = "󱐌 Error", highlight = "RenderMarkdownError" }, + bug = { raw = "[!BUG]", rendered = "󰨰 Bug", highlight = "RenderMarkdownError" }, + example = { raw = "[!EXAMPLE]", rendered = "󰉹 Example", highlight = "RenderMarkdownHint" }, + quote = { raw = "[!QUOTE]", rendered = "󱆨 Quote", highlight = "RenderMarkdownQuote" }, + cite = { raw = "[!CITE]", rendered = "󱆨 Cite", highlight = "RenderMarkdownQuote" }, + }, + checkbox = { + enabled = true, + render_modes = false, + bullet = false, + right_pad = 1, + unchecked = { + icon = "󰄱 ", + highlight = "RenderMarkdownUnchecked", + scope_highlight = nil, + }, + checked = { + icon = "󰱒 ", + highlight = "RenderMarkdownChecked", + scope_highlight = nil, + }, + custom = { + todo = { raw = "[-]", rendered = "󰥔 ", highlight = "RenderMarkdownTodo", scope_highlight = nil }, + }, + }, + bullet = { + enabled = true, + render_modes = false, + icons = { "●", "○", "◆", "◇" }, + ordered_icons = function(ctx) + local value = vim.trim(ctx.value) + local index = tonumber(value:sub(1, #value - 1)) + return ("%d."):format(index > 1 and index or ctx.index) + end, + left_pad = 0, + right_pad = 0, + highlight = "RenderMarkdownBullet", + scope_highlight = {}, + }, + quote = { icon = "▋" }, + anti_conceal = { + enabled = true, + -- Which elements to always show, ignoring anti conceal behavior. Values can either be + -- booleans to fix the behavior or string lists representing modes where anti conceal + -- behavior will be ignored. Valid values are: + -- head_icon, head_background, head_border, code_language, code_background, code_border, + -- dash, bullet, check_icon, check_scope, quote, table_border, callout, link, sign + ignore = { + code_background = true, + sign = true, + }, + above = 0, + below = 0, + }, +}) diff --git a/config/nvim-1/lua/plugins/telescope/init.lua b/config/nvim-1/lua/plugins/telescope/init.lua new file mode 100755 index 0000000..2cb0f77 --- /dev/null +++ b/config/nvim-1/lua/plugins/telescope/init.lua @@ -0,0 +1,3 @@ +local tel = require("telescope") +tel.setup({}) +tel.load_extension("undo") diff --git a/config/nvim-1/lua/plugins/treesitter/init.lua b/config/nvim-1/lua/plugins/treesitter/init.lua new file mode 100755 index 0000000..192cab7 --- /dev/null +++ b/config/nvim-1/lua/plugins/treesitter/init.lua @@ -0,0 +1,10 @@ +local ts = require("nvim-treesitter.configs") + +ts.setup({ + ensure_installed = { "c", "cpp", "lua", "go", "gomod", "gowork", "gosum", "rust", "python" }, + auto_install = true, + sync_install = true, + highlight = { + enable = true + } +}) diff --git a/config/nvim-1/lua/plugins/whichkey/init.lua b/config/nvim-1/lua/plugins/whichkey/init.lua new file mode 100755 index 0000000..e6b9906 --- /dev/null +++ b/config/nvim-1/lua/plugins/whichkey/init.lua @@ -0,0 +1,2 @@ +local wk = require("which-key") +wk.setup({}) diff --git a/config/nvim-1/lua/status_line/init.lua b/config/nvim-1/lua/status_line/init.lua new file mode 100755 index 0000000..904684b --- /dev/null +++ b/config/nvim-1/lua/status_line/init.lua @@ -0,0 +1,102 @@ +local colors = { + foreground = "#ebdbb2", + pink = "#b16286", + red = "#cc241d", + green = "#98971a", + yellow = "#d79921", + orange = "#d65d0e", + magenta = "#b16286", + cyan = "#458588", + bg_darken = "#1d2021", + dark_text = "#1d2021", +} + +local M = {} + +function M.setup() + vim.cmd("hi StatusBackground guifg=" .. colors.foreground .. " guibg=" .. colors.bg_darken) + vim.cmd("hi Moden guifg=" .. colors.dark_text .. " guibg=" .. colors.pink .. " gui=bold") + vim.cmd("hi Modei guifg=" .. colors.dark_text .. " guibg=" .. colors.green .. " gui=bold") + vim.cmd("hi Modev guifg=" .. colors.dark_text .. " guibg=" .. colors.yellow .. " gui=bold") + vim.cmd("hi Modet guifg=" .. colors.dark_text .. " guibg=" .. colors.orange .. " gui=bold") + vim.cmd("hi Modec guifg=" .. colors.dark_text .. " guibg=" .. colors.magenta .. " gui=bold") + vim.cmd("hi Moder guifg=" .. colors.dark_text .. " guibg=" .. colors.red .. " gui=bold") + vim.cmd("hi Filetype guifg=" .. colors.cyan .. " guibg=" .. colors.bg_darken .. " gui=bold") + vim.cmd("hi Position guifg=" .. colors.yellow .. " guibg=" .. colors.bg_darken .. " gui=bold") + vim.cmd("hi GitBranch guifg=" .. colors.orange .. " guibg=" .. colors.bg_darken .. " gui=bold") + vim.cmd("hi GitDiff guifg=" .. colors.green .. " guibg=" .. colors.bg_darken) + vim.cmd("hi GitDiffDel guifg=" .. colors.red .. " guibg=" .. colors.bg_darken) + vim.cmd("hi Separator guifg=" .. colors.foreground .. " guibg=" .. colors.bg_darken) + vim.cmd("hi LSPError guifg=" .. colors.red .. " guibg=" .. colors.bg_darken) + vim.cmd("hi LSPWarn guifg=" .. colors.yellow .. " guibg=" .. colors.bg_darken) + vim.cmd("hi LSPInfo guifg=" .. colors.cyan .. " guibg=" .. colors.bg_darken) + vim.cmd("hi LSPOk guifg=" .. colors.green .. " guibg=" .. colors.bg_darken) + + vim.o.statusline = table.concat({ + "%{%v:lua.themeStatuslineMode()%} ", + "%f ", + "%{%v:lua.themeGitBranch()%} ", + "%{%v:lua.themeGitDiff()%} ", + "%{%v:lua.themeLSP()%} ", + "%=", + "%{%v:lua.themeStatuslineFiletype()%} ", + "%{%v:lua.themeStatuslinePosition()%}", + }) +end + +function themeStatuslineMode() + local mode = vim.fn.mode() + local mode_highlight = "Mode" .. mode:sub(1, 1) + return string.format("%%#%s# %s %%#StatusBackground#", mode_highlight, mode:upper()) +end + +function themeStatuslineFiletype() + return string.format("%%#Filetype# %s %%#Separator#│%%#StatusBackground#", vim.bo.filetype) +end + +function themeStatuslinePosition() + local row, col = unpack(vim.api.nvim_win_get_cursor(0)) + return string.format("%%#Position# %03d:%02d ", row, col) +end + +function themeGitBranch() + local branch = vim.fn.systemlist("git rev-parse --abbrev-ref HEAD 2>/dev/null")[1] or "" + if branch ~= "" then + return string.format("%%#GitBranch# %s %%#Separator#│%%#StatusBackground#", branch) + end + return "" +end + +function themeGitDiff() + local diff = vim.fn.systemlist("git diff --shortstat 2>/dev/null")[1] or "" + local added, removed = diff:match("(%d+) insertions?"), diff:match("(%d+) deletions?") + added = added or "0" + removed = removed or "0" + if diff ~= "" then + return string.format("%%#GitDiff#+%s %%#GitDiffDel#-%s %%#StatusBackground#", added, removed) + end + return "" +end + +function themeLSP() + local errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR }) + local warns = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN }) + local info = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO }) + local hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT }) + local str = "" + if errors > 0 then + str = str .. string.format("%%#LSPError#E:%d ", errors) + end + if warns > 0 then + str = str .. string.format("%%#LSPWarn#W:%d ", warns) + end + if info > 0 then + str = str .. string.format("%%#LSPInfo#I:%d ", info) + end + if hints > 0 then + str = str .. string.format("%%#LSPOk#H:%d ", hints) + end + return str +end + +return M diff --git a/config/nvim-1/undo/%home%coast%.Xdefaults b/config/nvim-1/undo/%home%coast%.Xdefaults new file mode 100644 index 0000000..ec94686 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.Xdefaults differ diff --git a/config/nvim-1/undo/%home%coast%.config%Element%electron-config.json b/config/nvim-1/undo/%home%coast%.config%Element%electron-config.json new file mode 100644 index 0000000..c97175a Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%Element%electron-config.json differ diff --git a/config/nvim-1/undo/%home%coast%.config%alacritty%alacritty.toml b/config/nvim-1/undo/%home%coast%.config%alacritty%alacritty.toml new file mode 100644 index 0000000..d3c6a07 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%alacritty%alacritty.toml differ diff --git a/config/nvim-1/undo/%home%coast%.config%dunst%dunstrc b/config/nvim-1/undo/%home%coast%.config%dunst%dunstrc new file mode 100644 index 0000000..f79da8c Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%dunst%dunstrc differ diff --git a/config/nvim-1/undo/%home%coast%.config%eww%_colors.scss b/config/nvim-1/undo/%home%coast%.config%eww%_colors.scss new file mode 100644 index 0000000..a081160 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%eww%_colors.scss differ diff --git a/config/nvim-1/undo/%home%coast%.config%eww%eww.scss b/config/nvim-1/undo/%home%coast%.config%eww%eww.scss new file mode 100644 index 0000000..35c5ada Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%eww%eww.scss differ diff --git a/config/nvim-1/undo/%home%coast%.config%eww%eww.yuck b/config/nvim-1/undo/%home%coast%.config%eww%eww.yuck new file mode 100644 index 0000000..ef847ca Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%eww%eww.yuck differ diff --git a/config/nvim-1/undo/%home%coast%.config%eww%scripts%get-active-workspace.sh b/config/nvim-1/undo/%home%coast%.config%eww%scripts%get-active-workspace.sh new file mode 100644 index 0000000..5b8174a Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%eww%scripts%get-active-workspace.sh differ diff --git a/config/nvim-1/undo/%home%coast%.config%eww%scripts%get-workspaces.sh b/config/nvim-1/undo/%home%coast%.config%eww%scripts%get-workspaces.sh new file mode 100644 index 0000000..b51d1e9 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%eww%scripts%get-workspaces.sh differ diff --git a/config/nvim-1/undo/%home%coast%.config%fht%compositor.toml b/config/nvim-1/undo/%home%coast%.config%fht%compositor.toml new file mode 100644 index 0000000..ddc12da Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%fht%compositor.toml differ diff --git a/config/nvim-1/undo/%home%coast%.config%foot%foot.ini b/config/nvim-1/undo/%home%coast%.config%foot%foot.ini new file mode 100644 index 0000000..da3ee23 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%foot%foot.ini differ diff --git a/config/nvim-1/undo/%home%coast%.config%hypr%hypridle.conf b/config/nvim-1/undo/%home%coast%.config%hypr%hypridle.conf new file mode 100644 index 0000000..9added8 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%hypr%hypridle.conf differ diff --git a/config/nvim-1/undo/%home%coast%.config%hypr%hyprland.conf b/config/nvim-1/undo/%home%coast%.config%hypr%hyprland.conf new file mode 100644 index 0000000..ea2a4f8 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%hypr%hyprland.conf differ diff --git a/config/nvim-1/undo/%home%coast%.config%hypr%hyprlock.conf b/config/nvim-1/undo/%home%coast%.config%hypr%hyprlock.conf new file mode 100644 index 0000000..1ca560c Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%hypr%hyprlock.conf differ diff --git a/config/nvim-1/undo/%home%coast%.config%kwm%config.zon b/config/nvim-1/undo/%home%coast%.config%kwm%config.zon new file mode 100644 index 0000000..16be823 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%kwm%config.zon differ diff --git a/config/nvim-1/undo/%home%coast%.config%mako%config b/config/nvim-1/undo/%home%coast%.config%mako%config new file mode 100644 index 0000000..21d4ef3 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%mako%config differ diff --git a/config/nvim-1/undo/%home%coast%.config%mozilla%firefox%8kysq72s.default-release%chrome%userChrome.css b/config/nvim-1/undo/%home%coast%.config%mozilla%firefox%8kysq72s.default-release%chrome%userChrome.css new file mode 100644 index 0000000..19027c2 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%mozilla%firefox%8kysq72s.default-release%chrome%userChrome.css differ diff --git a/config/nvim-1/undo/%home%coast%.config%neofetch%config.conf b/config/nvim-1/undo/%home%coast%.config%neofetch%config.conf new file mode 100644 index 0000000..c006483 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%neofetch%config.conf differ diff --git a/config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%catppuccin%init.lua b/config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%catppuccin%init.lua new file mode 100644 index 0000000..6a0cc3b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%catppuccin%init.lua differ diff --git a/config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%lazy%plugins.lua b/config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%lazy%plugins.lua new file mode 100644 index 0000000..a514179 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%nvim%lua%plugins%lazy%plugins.lua differ diff --git a/config/nvim-1/undo/%home%coast%.config%picom%picom-animations.conf b/config/nvim-1/undo/%home%coast%.config%picom%picom-animations.conf new file mode 100644 index 0000000..a64107e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%picom%picom-animations.conf differ diff --git a/config/nvim-1/undo/%home%coast%.config%picom%picom.conf b/config/nvim-1/undo/%home%coast%.config%picom%picom.conf new file mode 100644 index 0000000..6143380 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%picom%picom.conf differ diff --git a/config/nvim-1/undo/%home%coast%.config%piss%pissrc b/config/nvim-1/undo/%home%coast%.config%piss%pissrc new file mode 100644 index 0000000..8df5476 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%piss%pissrc differ diff --git a/config/nvim-1/undo/%home%coast%.config%quickshell%clock.qml b/config/nvim-1/undo/%home%coast%.config%quickshell%clock.qml new file mode 100644 index 0000000..2947ae6 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%quickshell%clock.qml differ diff --git a/config/nvim-1/undo/%home%coast%.config%quickshell%currentsong.qml b/config/nvim-1/undo/%home%coast%.config%quickshell%currentsong.qml new file mode 100644 index 0000000..63f404b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%quickshell%currentsong.qml differ diff --git a/config/nvim-1/undo/%home%coast%.config%quickshell%separator.qml b/config/nvim-1/undo/%home%coast%.config%quickshell%separator.qml new file mode 100644 index 0000000..d750c37 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%quickshell%separator.qml differ diff --git a/config/nvim-1/undo/%home%coast%.config%quickshell%shell.qml b/config/nvim-1/undo/%home%coast%.config%quickshell%shell.qml new file mode 100644 index 0000000..e445b2d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%quickshell%shell.qml differ diff --git a/config/nvim-1/undo/%home%coast%.config%quickshell%workspaces.qml b/config/nvim-1/undo/%home%coast%.config%quickshell%workspaces.qml new file mode 100644 index 0000000..a931439 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%quickshell%workspaces.qml differ diff --git a/config/nvim-1/undo/%home%coast%.config%river%init b/config/nvim-1/undo/%home%coast%.config%river%init new file mode 100644 index 0000000..9c07d69 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%river%init differ diff --git a/config/nvim-1/undo/%home%coast%.config%rofi%config.rasi b/config/nvim-1/undo/%home%coast%.config%rofi%config.rasi new file mode 100644 index 0000000..e3999e9 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%rofi%config.rasi differ diff --git a/config/nvim-1/undo/%home%coast%.config%scrobbler%config.ini b/config/nvim-1/undo/%home%coast%.config%scrobbler%config.ini new file mode 100644 index 0000000..a63463d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%scrobbler%config.ini differ diff --git a/config/nvim-1/undo/%home%coast%.config%sway%config b/config/nvim-1/undo/%home%coast%.config%sway%config new file mode 100644 index 0000000..9ea1a0b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%sway%config differ diff --git a/config/nvim-1/undo/%home%coast%.config%tym%config.lua b/config/nvim-1/undo/%home%coast%.config%tym%config.lua new file mode 100644 index 0000000..f7d5ccb Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%tym%config.lua differ diff --git a/config/nvim-1/undo/%home%coast%.config%tym%theme.lua b/config/nvim-1/undo/%home%coast%.config%tym%theme.lua new file mode 100644 index 0000000..b6e4d63 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%tym%theme.lua differ diff --git a/config/nvim-1/undo/%home%coast%.config%waybar%config.jsonc b/config/nvim-1/undo/%home%coast%.config%waybar%config.jsonc new file mode 100644 index 0000000..51d45d0 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%waybar%config.jsonc differ diff --git a/config/nvim-1/undo/%home%coast%.config%waybar%style.css b/config/nvim-1/undo/%home%coast%.config%waybar%style.css new file mode 100644 index 0000000..3467a78 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.config%waybar%style.css differ diff --git a/config/nvim-1/undo/%home%coast%.curlrc b/config/nvim-1/undo/%home%coast%.curlrc new file mode 100644 index 0000000..47e0956 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.curlrc differ diff --git a/config/nvim-1/undo/%home%coast%.local%share%American Truck Simulator%config.cfg b/config/nvim-1/undo/%home%coast%.local%share%American Truck Simulator%config.cfg new file mode 100644 index 0000000..5086657 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%share%American Truck Simulator%config.cfg differ diff --git a/config/nvim-1/undo/%home%coast%.local%share%applications%element-desktop.desktop b/config/nvim-1/undo/%home%coast%.local%share%applications%element-desktop.desktop new file mode 100644 index 0000000..8f58e93 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%share%applications%element-desktop.desktop differ diff --git a/config/nvim-1/undo/%home%coast%.local%share%applications%firefox-bin.desktop b/config/nvim-1/undo/%home%coast%.local%share%applications%firefox-bin.desktop new file mode 100644 index 0000000..7ef4b8d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%share%applications%firefox-bin.desktop differ diff --git a/config/nvim-1/undo/%home%coast%.local%share%applications%im.riot.Riot.desktop b/config/nvim-1/undo/%home%coast%.local%share%applications%im.riot.Riot.desktop new file mode 100644 index 0000000..1535b49 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%share%applications%im.riot.Riot.desktop differ diff --git a/config/nvim-1/undo/%home%coast%.local%share%flatpak%app%im.riot.Riot%x86_64%stable%42f010911a82616b14d9f36a8341652b349552a67ba14b8e67fd432e18c37561%export%share%applications%im.riot.Riot.desktop b/config/nvim-1/undo/%home%coast%.local%share%flatpak%app%im.riot.Riot%x86_64%stable%42f010911a82616b14d9f36a8341652b349552a67ba14b8e67fd432e18c37561%export%share%applications%im.riot.Riot.desktop new file mode 100644 index 0000000..149d27d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%share%flatpak%app%im.riot.Riot%x86_64%stable%42f010911a82616b14d9f36a8341652b349552a67ba14b8e67fd432e18c37561%export%share%applications%im.riot.Riot.desktop differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%.git%COMMIT_EDITMSG b/config/nvim-1/undo/%home%coast%.local%src%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..07596ad Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%config%nvim%lua%config.lua b/config/nvim-1/undo/%home%coast%.local%src%config%nvim%lua%config.lua new file mode 100755 index 0000000..8d1e014 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%config%nvim%lua%config.lua differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%config%sway%config b/config/nvim-1/undo/%home%coast%.local%src%config%sway%config new file mode 100644 index 0000000..bdd8a66 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%config%sway%config differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%config%waybar%config.jsonc b/config/nvim-1/undo/%home%coast%.local%src%config%waybar%config.jsonc new file mode 100755 index 0000000..cbd3adb Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%config%waybar%config.jsonc differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%config%waybar%style.css b/config/nvim-1/undo/%home%coast%.local%src%config%waybar%style.css new file mode 100755 index 0000000..3b6fd1e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%config%waybar%style.css differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%dmenu%config.h b/config/nvim-1/undo/%home%coast%.local%src%dmenu%config.h new file mode 100644 index 0000000..8c2030f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%dmenu%config.h differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%dmenu%config.mk b/config/nvim-1/undo/%home%coast%.local%src%dmenu%config.mk new file mode 100644 index 0000000..13e2940 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%dmenu%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%dmenu%dmenu.c b/config/nvim-1/undo/%home%coast%.local%src%dmenu%dmenu.c new file mode 100644 index 0000000..baea793 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%dmenu%dmenu.c differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%dmenu%drw.c b/config/nvim-1/undo/%home%coast%.local%src%dmenu%drw.c new file mode 100644 index 0000000..33c21ac Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%dmenu%drw.c differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%dwm%config.h b/config/nvim-1/undo/%home%coast%.local%src%dwm%config.h new file mode 100644 index 0000000..f98efb5 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%dwm%config.h differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%dwm%config.mk b/config/nvim-1/undo/%home%coast%.local%src%dwm%config.mk new file mode 100644 index 0000000..60ae5f6 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%dwm%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%dwm%patches.h b/config/nvim-1/undo/%home%coast%.local%src%dwm%patches.h new file mode 100644 index 0000000..f5512c2 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%dwm%patches.h differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%mpc-shuf.sh b/config/nvim-1/undo/%home%coast%.local%src%local%bin%mpc-shuf.sh new file mode 100644 index 0000000..3f01d69 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%mpc-shuf.sh differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%screenie-wlr b/config/nvim-1/undo/%home%coast%.local%src%local%bin%screenie-wlr new file mode 100644 index 0000000..b135c89 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%screenie-wlr differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%sober b/config/nvim-1/undo/%home%coast%.local%src%local%bin%sober new file mode 100644 index 0000000..d88c112 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%sober differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.start b/config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.start new file mode 100644 index 0000000..5c6282d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.start differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.stop b/config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.stop new file mode 100644 index 0000000..299dbdd Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%swap.stop differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver b/config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver new file mode 100644 index 0000000..b9e1ebf Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver.sh b/config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver.sh new file mode 100644 index 0000000..65910ef Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%updateriver.sh differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%upl b/config/nvim-1/undo/%home%coast%.local%src%local%bin%upl new file mode 100644 index 0000000..c5923b9 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%upl differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%local%bin%uwuify.awk b/config/nvim-1/undo/%home%coast%.local%src%local%bin%uwuify.awk new file mode 100755 index 0000000..8fa3bac Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%local%bin%uwuify.awk differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%slstatus%config.h b/config/nvim-1/undo/%home%coast%.local%src%slstatus%config.h new file mode 100644 index 0000000..ac72597 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%slstatus%config.h differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%slstatus%config.mk b/config/nvim-1/undo/%home%coast%.local%src%slstatus%config.mk new file mode 100644 index 0000000..dcebd8e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%slstatus%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%st%config.h b/config/nvim-1/undo/%home%coast%.local%src%st%config.h new file mode 100644 index 0000000..25333d8 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%st%config.h differ diff --git a/config/nvim-1/undo/%home%coast%.local%src%st%config.mk b/config/nvim-1/undo/%home%coast%.local%src%st%config.mk new file mode 100644 index 0000000..b335397 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.local%src%st%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%.mpdconf b/config/nvim-1/undo/%home%coast%.mpdconf new file mode 100644 index 0000000..12bbdf7 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.mpdconf differ diff --git a/config/nvim-1/undo/%home%coast%.rtorrent.rc b/config/nvim-1/undo/%home%coast%.rtorrent.rc new file mode 100644 index 0000000..7d56ef2 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.rtorrent.rc differ diff --git a/config/nvim-1/undo/%home%coast%.var%app%org.vinegarhq.Sober%config%sober%config.json b/config/nvim-1/undo/%home%coast%.var%app%org.vinegarhq.Sober%config%sober%config.json new file mode 100644 index 0000000..e38108f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.var%app%org.vinegarhq.Sober%config%sober%config.json differ diff --git a/config/nvim-1/undo/%home%coast%.wezterm.lua b/config/nvim-1/undo/%home%coast%.wezterm.lua new file mode 100755 index 0000000..5d55e1b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.wezterm.lua differ diff --git a/config/nvim-1/undo/%home%coast%.xinitrc b/config/nvim-1/undo/%home%coast%.xinitrc new file mode 100644 index 0000000..47506d2 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.xinitrc differ diff --git a/config/nvim-1/undo/%home%coast%.zprofile b/config/nvim-1/undo/%home%coast%.zprofile new file mode 100644 index 0000000..660503b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.zprofile differ diff --git a/config/nvim-1/undo/%home%coast%.zshrc b/config/nvim-1/undo/%home%coast%.zshrc new file mode 100644 index 0000000..97b0d29 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%.zshrc differ diff --git a/config/nvim-1/undo/%home%coast%Games%Red Dead Redemption 2%launch.sh b/config/nvim-1/undo/%home%coast%Games%Red Dead Redemption 2%launch.sh new file mode 100644 index 0000000..5ef820a Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Games%Red Dead Redemption 2%launch.sh differ diff --git a/config/nvim-1/undo/%home%coast%NOTES b/config/nvim-1/undo/%home%coast%NOTES new file mode 100644 index 0000000..75ddf7a Binary files /dev/null and b/config/nvim-1/undo/%home%coast%NOTES differ diff --git a/config/nvim-1/undo/%home%coast%Projects%X%term%term b/config/nvim-1/undo/%home%coast%Projects%X%term%term new file mode 100644 index 0000000..029dfce Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%X%term%term differ diff --git a/config/nvim-1/undo/%home%coast%Projects%X%term%xterm.c b/config/nvim-1/undo/%home%coast%Projects%X%term%xterm.c new file mode 100644 index 0000000..ea2d63a Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%X%term%xterm.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%abcl%main.cl b/config/nvim-1/undo/%home%coast%Projects%abcl%main.cl new file mode 100644 index 0000000..11b585d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%abcl%main.cl differ diff --git a/config/nvim-1/undo/%home%coast%Projects%gtk%main.c b/config/nvim-1/undo/%home%coast%Projects%gtk%main.c new file mode 100644 index 0000000..926449f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%gtk%main.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble new file mode 100644 index 0000000..e35c00b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble differ diff --git a/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%.git%COMMIT_EDITMSG b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..a13bcc8 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%LICENSE b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%LICENSE new file mode 100644 index 0000000..07f7bc6 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%LICENSE differ diff --git a/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%ashscrobble.py b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%ashscrobble.py new file mode 100644 index 0000000..9bd5354 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%py%ashscrobble%ashscrobble.py differ diff --git a/config/nvim-1/undo/%home%coast%Projects%py%dmenu.lua b/config/nvim-1/undo/%home%coast%Projects%py%dmenu.lua new file mode 100644 index 0000000..226ff18 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%py%dmenu.lua differ diff --git a/config/nvim-1/undo/%home%coast%Projects%py%dmenu.py b/config/nvim-1/undo/%home%coast%Projects%py%dmenu.py new file mode 100644 index 0000000..d5ce864 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%py%dmenu.py differ diff --git a/config/nvim-1/undo/%home%coast%Projects%pylua%dmenu.lua b/config/nvim-1/undo/%home%coast%Projects%pylua%dmenu.lua new file mode 100644 index 0000000..745ec8d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%pylua%dmenu.lua differ diff --git a/config/nvim-1/undo/%home%coast%Projects%river%kwm%config.def.zon b/config/nvim-1/undo/%home%coast%Projects%river%kwm%config.def.zon new file mode 100644 index 0000000..5e37c03 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%river%kwm%config.def.zon differ diff --git a/config/nvim-1/undo/%home%coast%Projects%river%river%build.zig.zon b/config/nvim-1/undo/%home%coast%Projects%river%river%build.zig.zon new file mode 100644 index 0000000..506bb14 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%river%river%build.zig.zon differ diff --git a/config/nvim-1/undo/%home%coast%Projects%rs%guessing_game%.gitignore b/config/nvim-1/undo/%home%coast%Projects%rs%guessing_game%.gitignore new file mode 100755 index 0000000..6470d6c Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%rs%guessing_game%.gitignore differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%config.h b/config/nvim-1/undo/%home%coast%Projects%wayland%config.h new file mode 100644 index 0000000..08706f7 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%config.h differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%main.py b/config/nvim-1/undo/%home%coast%Projects%wayland%main.py new file mode 100644 index 0000000..2bb2df2 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%main.py differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%window.c b/config/nvim-1/undo/%home%coast%Projects%wayland%window.c new file mode 100644 index 0000000..bc5fc59 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%window.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlbar%main.c b/config/nvim-1/undo/%home%coast%Projects%wayland%wlbar%main.c new file mode 100644 index 0000000..33c973c Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlbar%main.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.git%COMMIT_EDITMSG b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..0dfdf76 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.gitignore b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.gitignore new file mode 100644 index 0000000..10af800 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%.gitignore differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%config.h b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%config.h new file mode 100644 index 0000000..4d208cf Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%config.h differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%main.c b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%main.c new file mode 100644 index 0000000..ec97d25 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%main.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%makefile b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%makefile new file mode 100644 index 0000000..b2b8ad9 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock%makefile differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock.c b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock.c new file mode 100644 index 0000000..ba2e77f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlclock.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wled%.git%COMMIT_EDITMSG b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..8082f55 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wled%.gitignore b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%.gitignore new file mode 100644 index 0000000..9e426c4 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%.gitignore differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wled%LICENSE b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%LICENSE new file mode 100644 index 0000000..741c79f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%LICENSE differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wled%README b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%README new file mode 100644 index 0000000..fd02d46 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%README differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wled%build.sh b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%build.sh new file mode 100644 index 0000000..8ed7a03 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%build.sh differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wled%client.c b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%client.c new file mode 100644 index 0000000..3224b29 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%client.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wled%config.h b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%config.h new file mode 100644 index 0000000..33620cb Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wled%config.h differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%wlindow%client.c b/config/nvim-1/undo/%home%coast%Projects%wayland%wlindow%client.c new file mode 100644 index 0000000..dde5658 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%wlindow%client.c differ diff --git a/config/nvim-1/undo/%home%coast%Projects%wayland%x11alt.c b/config/nvim-1/undo/%home%coast%Projects%wayland%x11alt.c new file mode 100644 index 0000000..6cd7f53 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%Projects%wayland%x11alt.c differ diff --git a/config/nvim-1/undo/%home%coast%ashos%linux%.config b/config/nvim-1/undo/%home%coast%ashos%linux%.config new file mode 100644 index 0000000..2adf754 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%ashos%linux%.config differ diff --git a/config/nvim-1/undo/%home%coast%ashos%syslinux.cfg b/config/nvim-1/undo/%home%coast%ashos%syslinux.cfg new file mode 100644 index 0000000..f64a12e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%ashos%syslinux.cfg differ diff --git a/config/nvim-1/undo/%home%coast%conduwuit b/config/nvim-1/undo/%home%coast%conduwuit new file mode 100644 index 0000000..09757fa Binary files /dev/null and b/config/nvim-1/undo/%home%coast%conduwuit differ diff --git a/config/nvim-1/undo/%home%coast%driver%driver.c b/config/nvim-1/undo/%home%coast%driver%driver.c new file mode 100644 index 0000000..37a7b4b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%driver%driver.c differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%.git%COMMIT_EDITMSG b/config/nvim-1/undo/%home%coast%git%compositor%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..4e46888 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%.gitignore b/config/nvim-1/undo/%home%coast%git%compositor%.gitignore new file mode 100644 index 0000000..93d85b0 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%.gitignore differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%Makefile b/config/nvim-1/undo/%home%coast%git%compositor%Makefile new file mode 100644 index 0000000..3a81de7 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%Makefile differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%build.sh b/config/nvim-1/undo/%home%coast%git%compositor%build.sh new file mode 100644 index 0000000..4213af1 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%build.sh differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%makefile b/config/nvim-1/undo/%home%coast%git%compositor%makefile new file mode 100644 index 0000000..863c008 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%makefile differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%compositor.c b/config/nvim-1/undo/%home%coast%git%compositor%src%compositor.c new file mode 100644 index 0000000..5b64f3e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%compositor.c differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%config.h b/config/nvim-1/undo/%home%coast%git%compositor%src%config.h new file mode 100644 index 0000000..6f37cc9 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%config.h differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%include%compositor.h b/config/nvim-1/undo/%home%coast%git%compositor%src%include%compositor.h new file mode 100644 index 0000000..510b876 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%include%compositor.h differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%include%keybinds.h b/config/nvim-1/undo/%home%coast%git%compositor%src%include%keybinds.h new file mode 100644 index 0000000..4e35078 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%include%keybinds.h differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%include%screenshot.h b/config/nvim-1/undo/%home%coast%git%compositor%src%include%screenshot.h new file mode 100644 index 0000000..b10e27e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%include%screenshot.h differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.c b/config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.c new file mode 100644 index 0000000..e36edb7 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.c differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.h b/config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.h new file mode 100644 index 0000000..5412574 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%keybinds.h differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%screenshot.c b/config/nvim-1/undo/%home%coast%git%compositor%src%screenshot.c new file mode 100644 index 0000000..d5f9bdb Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%screenshot.c differ diff --git a/config/nvim-1/undo/%home%coast%git%compositor%src%util.c b/config/nvim-1/undo/%home%coast%git%compositor%src%util.c new file mode 100644 index 0000000..f4326c1 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%compositor%src%util.c differ diff --git a/config/nvim-1/undo/%home%coast%git%hst%config.h b/config/nvim-1/undo/%home%coast%git%hst%config.h new file mode 100644 index 0000000..dd9887b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%hst%config.h differ diff --git a/config/nvim-1/undo/%home%coast%git%neuswc%config.mk b/config/nvim-1/undo/%home%coast%git%neuswc%config.mk new file mode 100644 index 0000000..ce38cda Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%neuswc%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%git%neuswc%libswc%compositor.h b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%compositor.h new file mode 100644 index 0000000..6d1077e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%compositor.h differ diff --git a/config/nvim-1/undo/%home%coast%git%neuswc%libswc%output.h b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%output.h new file mode 100644 index 0000000..39865f6 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%output.h differ diff --git a/config/nvim-1/undo/%home%coast%git%neuswc%libswc%pointer.h b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%pointer.h new file mode 100644 index 0000000..a15ad9f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%pointer.h differ diff --git a/config/nvim-1/undo/%home%coast%git%neuswc%libswc%util.h b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%util.h new file mode 100644 index 0000000..b94bcd4 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%neuswc%libswc%util.h differ diff --git a/config/nvim-1/undo/%home%coast%git%neuwld%config.mk b/config/nvim-1/undo/%home%coast%git%neuwld%config.mk new file mode 100644 index 0000000..f609412 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%neuwld%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%git%swc%config.mk b/config/nvim-1/undo/%home%coast%git%swc%config.mk new file mode 100644 index 0000000..f68e27f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%swc%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%git%swcshot%main.c b/config/nvim-1/undo/%home%coast%git%swcshot%main.c new file mode 100644 index 0000000..8619f34 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%swcshot%main.c differ diff --git a/config/nvim-1/undo/%home%coast%git%terminal%Makefile b/config/nvim-1/undo/%home%coast%git%terminal%Makefile new file mode 100644 index 0000000..c6d428e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%terminal%Makefile differ diff --git a/config/nvim-1/undo/%home%coast%git%terminal%main.c b/config/nvim-1/undo/%home%coast%git%terminal%main.c new file mode 100644 index 0000000..107db70 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%terminal%main.c differ diff --git a/config/nvim-1/undo/%home%coast%git%wld%config.mk b/config/nvim-1/undo/%home%coast%git%wld%config.mk new file mode 100644 index 0000000..bce0bba Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%wld%config.mk differ diff --git a/config/nvim-1/undo/%home%coast%git%wsxwm%Makefile b/config/nvim-1/undo/%home%coast%git%wsxwm%Makefile new file mode 100644 index 0000000..68f3f92 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%wsxwm%Makefile differ diff --git a/config/nvim-1/undo/%home%coast%git%wsxwm%source%include%wsxwm.h b/config/nvim-1/undo/%home%coast%git%wsxwm%source%include%wsxwm.h new file mode 100644 index 0000000..bc9e7e9 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%wsxwm%source%include%wsxwm.h differ diff --git a/config/nvim-1/undo/%home%coast%git%wsxwm%source%test.diff b/config/nvim-1/undo/%home%coast%git%wsxwm%source%test.diff new file mode 100644 index 0000000..7b07e18 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%wsxwm%source%test.diff differ diff --git a/config/nvim-1/undo/%home%coast%git%wsxwm%source%wsxwm.c b/config/nvim-1/undo/%home%coast%git%wsxwm%source%wsxwm.c new file mode 100644 index 0000000..86d64e4 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%git%wsxwm%source%wsxwm.c differ diff --git a/config/nvim-1/undo/%home%coast%hwfetch b/config/nvim-1/undo/%home%coast%hwfetch new file mode 100644 index 0000000..52b9439 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%hwfetch differ diff --git a/config/nvim-1/undo/%home%coast%main.bash b/config/nvim-1/undo/%home%coast%main.bash new file mode 100644 index 0000000..599b67f Binary files /dev/null and b/config/nvim-1/undo/%home%coast%main.bash differ diff --git a/config/nvim-1/undo/%home%coast%main.c b/config/nvim-1/undo/%home%coast%main.c new file mode 100644 index 0000000..c891d53 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%main.c differ diff --git a/config/nvim-1/undo/%home%coast%main.lua b/config/nvim-1/undo/%home%coast%main.lua new file mode 100644 index 0000000..3d596cd Binary files /dev/null and b/config/nvim-1/undo/%home%coast%main.lua differ diff --git a/config/nvim-1/undo/%home%coast%royal b/config/nvim-1/undo/%home%coast%royal new file mode 100644 index 0000000..a198106 Binary files /dev/null and b/config/nvim-1/undo/%home%coast%royal differ diff --git a/config/nvim-1/undo/%home%coast%shared%loader.c b/config/nvim-1/undo/%home%coast%shared%loader.c new file mode 100644 index 0000000..9c7774e Binary files /dev/null and b/config/nvim-1/undo/%home%coast%shared%loader.c differ diff --git a/config/nvim-1/undo/%home%coast%shared%shared.c b/config/nvim-1/undo/%home%coast%shared%shared.c new file mode 100644 index 0000000..d87057b Binary files /dev/null and b/config/nvim-1/undo/%home%coast%shared%shared.c differ diff --git a/config/nvim-1/undo/%home%coast%test.py b/config/nvim-1/undo/%home%coast%test.py new file mode 100644 index 0000000..43a396d Binary files /dev/null and b/config/nvim-1/undo/%home%coast%test.py differ diff --git a/config/nvim-2/graft b/config/nvim-2/graft new file mode 160000 index 0000000..93af584 --- /dev/null +++ b/config/nvim-2/graft @@ -0,0 +1 @@ +Subproject commit 93af5846dea167f2ea44991ad3448d10b1979355 diff --git a/config/nvim-2/init.vim b/config/nvim-2/init.vim new file mode 100644 index 0000000..522f4e6 --- /dev/null +++ b/config/nvim-2/init.vim @@ -0,0 +1,12 @@ +se notgc bg=dark|colo vim|se nu rnu|se ch=0|se ls=0|se fcs=eob:\ |se shm+=I + +if !isdirectory(expand("~/.config/nvim/undodir"))|call mkdir(expand("~/.config/nvim/undodir"))|endif +if !isdirectory(expand("~/.config/nvim/vscript"))|call mkdir(expand("~/.config/nvim/vscript"))|endif + +let sciond = expand("~/.config/nvim/scion") +if !isdirectory(sciond)|execute "!git clone --depth=1 https://git.sr.ht/~coasteen/vim-scion " . shellescape(sciond)|endif + +let vscript_dir = expand("~/.config/nvim/vscript") +if isdirectory(vscript_dir)|for file in split(glob(vscript_dir . "/*.vim"), '\n')|execute "source " . fnameescape(file)|endfor|endif + +se udf|se udir=~/.config/nvim/undodir diff --git a/config/nvim-2/nvim/init.vim b/config/nvim-2/nvim/init.vim new file mode 100644 index 0000000..17c29f4 --- /dev/null +++ b/config/nvim-2/nvim/init.vim @@ -0,0 +1,12 @@ +se notgc bg=dark|colo vim|se nu rnu|se ch=0|se ls=0|se fcs=eob:\ |se shm+=I + +if !isdirectory(expand("~/.config/nvim/undodir"))|call mkdir(expand("~/.config/nvim/undodir"))|endif +if !isdirectory(expand("~/.config/nvim/vscript"))|call mkdir(expand("~/.config/nvim/vscript"))|endif + +let sciond = expand("~/.config/nvim/scion") +if !isdirectory(sciond)|execute "!git clone --depth=1 https://github.com/coasteen/vim-scion.git " . shellescape(sciond)|endif + +let vscript_dir = expand("~/.config/nvim/vscript") +if isdirectory(vscript_dir)|for file in split(glob(vscript_dir . "/*.vim"), '\n')|execute "source " . fnameescape(file)|endfor|endif + +se udf|se udir=~/.config/nvim/undodir diff --git a/config/nvim-2/nvim/pack-bak/graft/start/LuaSnip b/config/nvim-2/nvim/pack-bak/graft/start/LuaSnip new file mode 160000 index 0000000..a62e108 --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/LuaSnip @@ -0,0 +1 @@ +Subproject commit a62e1083a3cfe8b6b206e7d3d33a51091df25357 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/cmp-buffer b/config/nvim-2/nvim/pack-bak/graft/start/cmp-buffer new file mode 160000 index 0000000..b74fab3 --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/cmp-buffer @@ -0,0 +1 @@ +Subproject commit b74fab3656eea9de20a9b8116afa3cfc4ec09657 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/cmp-nvim-lsp b/config/nvim-2/nvim/pack-bak/graft/start/cmp-nvim-lsp new file mode 160000 index 0000000..cbc7b02 --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/cmp-nvim-lsp @@ -0,0 +1 @@ +Subproject commit cbc7b02bb99fae35cb42f514762b89b5126651ef diff --git a/config/nvim-2/nvim/pack-bak/graft/start/nvim-autopairs b/config/nvim-2/nvim/pack-bak/graft/start/nvim-autopairs new file mode 160000 index 0000000..7b9923a --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/nvim-autopairs @@ -0,0 +1 @@ +Subproject commit 7b9923abad60b903ece7c52940e1321d39eccc79 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/nvim-cmp b/config/nvim-2/nvim/pack-bak/graft/start/nvim-cmp new file mode 160000 index 0000000..a1d5048 --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/nvim-cmp @@ -0,0 +1 @@ +Subproject commit a1d504892f2bc56c2e79b65c6faded2fd21f3eca diff --git a/config/nvim-2/nvim/pack-bak/graft/start/nvim-lspconfig b/config/nvim-2/nvim/pack-bak/graft/start/nvim-lspconfig new file mode 160000 index 0000000..451d4ef --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/nvim-lspconfig @@ -0,0 +1 @@ +Subproject commit 451d4ef9abd4f0f08e379ef0d55d1c391b6125a7 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-closetag b/config/nvim-2/nvim/pack-bak/graft/start/vim-closetag new file mode 160000 index 0000000..d0a562f --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-closetag @@ -0,0 +1 @@ +Subproject commit d0a562f8bdb107a50595aefe53b1a690460c3822 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-commentary b/config/nvim-2/nvim/pack-bak/graft/start/vim-commentary new file mode 160000 index 0000000..64a654e --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-commentary @@ -0,0 +1 @@ +Subproject commit 64a654ef4a20db1727938338310209b6a63f60c9 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-endwise b/config/nvim-2/nvim/pack-bak/graft/start/vim-endwise new file mode 160000 index 0000000..4994afb --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-endwise @@ -0,0 +1 @@ +Subproject commit 4994afb0cdf956d9a665a14b9c834869e602c396 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-fugitive b/config/nvim-2/nvim/pack-bak/graft/start/vim-fugitive new file mode 160000 index 0000000..3b753cf --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-fugitive @@ -0,0 +1 @@ +Subproject commit 3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-polyglot b/config/nvim-2/nvim/pack-bak/graft/start/vim-polyglot new file mode 160000 index 0000000..f061edd --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-polyglot @@ -0,0 +1 @@ +Subproject commit f061eddb7cdcc614c8406847b2bfb53099832a4e diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-sensible b/config/nvim-2/nvim/pack-bak/graft/start/vim-sensible new file mode 160000 index 0000000..0ce2d84 --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-sensible @@ -0,0 +1 @@ +Subproject commit 0ce2d843d6f588bb0c8c7eec6449171615dc56d9 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-surround b/config/nvim-2/nvim/pack-bak/graft/start/vim-surround new file mode 160000 index 0000000..3d188ed --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-surround @@ -0,0 +1 @@ +Subproject commit 3d188ed2113431cf8dac77be61b842acb64433d9 diff --git a/config/nvim-2/nvim/pack-bak/graft/start/vim-vinegar b/config/nvim-2/nvim/pack-bak/graft/start/vim-vinegar new file mode 160000 index 0000000..bb1bcdd --- /dev/null +++ b/config/nvim-2/nvim/pack-bak/graft/start/vim-vinegar @@ -0,0 +1 @@ +Subproject commit bb1bcddf43cfebe05eb565a84ab069b357d0b3d6 diff --git a/config/nvim-2/nvim/pack/scion/start/LuaSnip b/config/nvim-2/nvim/pack/scion/start/LuaSnip new file mode 160000 index 0000000..a62e108 --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/LuaSnip @@ -0,0 +1 @@ +Subproject commit a62e1083a3cfe8b6b206e7d3d33a51091df25357 diff --git a/config/nvim-2/nvim/pack/scion/start/cmp-buffer b/config/nvim-2/nvim/pack/scion/start/cmp-buffer new file mode 160000 index 0000000..b74fab3 --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/cmp-buffer @@ -0,0 +1 @@ +Subproject commit b74fab3656eea9de20a9b8116afa3cfc4ec09657 diff --git a/config/nvim-2/nvim/pack/scion/start/cmp-nvim-lsp b/config/nvim-2/nvim/pack/scion/start/cmp-nvim-lsp new file mode 160000 index 0000000..cbc7b02 --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/cmp-nvim-lsp @@ -0,0 +1 @@ +Subproject commit cbc7b02bb99fae35cb42f514762b89b5126651ef diff --git a/config/nvim-2/nvim/pack/scion/start/nvim-autopairs b/config/nvim-2/nvim/pack/scion/start/nvim-autopairs new file mode 160000 index 0000000..7b9923a --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/nvim-autopairs @@ -0,0 +1 @@ +Subproject commit 7b9923abad60b903ece7c52940e1321d39eccc79 diff --git a/config/nvim-2/nvim/pack/scion/start/nvim-cmp b/config/nvim-2/nvim/pack/scion/start/nvim-cmp new file mode 160000 index 0000000..a1d5048 --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/nvim-cmp @@ -0,0 +1 @@ +Subproject commit a1d504892f2bc56c2e79b65c6faded2fd21f3eca diff --git a/config/nvim-2/nvim/pack/scion/start/nvim-colorizer.lua b/config/nvim-2/nvim/pack/scion/start/nvim-colorizer.lua new file mode 160000 index 0000000..a065833 --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/nvim-colorizer.lua @@ -0,0 +1 @@ +Subproject commit a065833f35a3a7cc3ef137ac88b5381da2ba302e diff --git a/config/nvim-2/nvim/pack/scion/start/nvim-lspconfig b/config/nvim-2/nvim/pack/scion/start/nvim-lspconfig new file mode 160000 index 0000000..451d4ef --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/nvim-lspconfig @@ -0,0 +1 @@ +Subproject commit 451d4ef9abd4f0f08e379ef0d55d1c391b6125a7 diff --git a/config/nvim-2/nvim/pack/scion/start/nvim-treesitter b/config/nvim-2/nvim/pack/scion/start/nvim-treesitter new file mode 160000 index 0000000..4916d65 --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/nvim-treesitter @@ -0,0 +1 @@ +Subproject commit 4916d6592ede8c07973490d9322f187e07dfefac diff --git a/config/nvim-2/nvim/pack/scion/start/vim-closetag b/config/nvim-2/nvim/pack/scion/start/vim-closetag new file mode 160000 index 0000000..d0a562f --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-closetag @@ -0,0 +1 @@ +Subproject commit d0a562f8bdb107a50595aefe53b1a690460c3822 diff --git a/config/nvim-2/nvim/pack/scion/start/vim-commentary b/config/nvim-2/nvim/pack/scion/start/vim-commentary new file mode 160000 index 0000000..64a654e --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-commentary @@ -0,0 +1 @@ +Subproject commit 64a654ef4a20db1727938338310209b6a63f60c9 diff --git a/config/nvim-2/nvim/pack/scion/start/vim-endwise b/config/nvim-2/nvim/pack/scion/start/vim-endwise new file mode 160000 index 0000000..4994afb --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-endwise @@ -0,0 +1 @@ +Subproject commit 4994afb0cdf956d9a665a14b9c834869e602c396 diff --git a/config/nvim-2/nvim/pack/scion/start/vim-fugitive b/config/nvim-2/nvim/pack/scion/start/vim-fugitive new file mode 160000 index 0000000..3b753cf --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-fugitive @@ -0,0 +1 @@ +Subproject commit 3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0 diff --git a/config/nvim-2/nvim/pack/scion/start/vim-polyglot b/config/nvim-2/nvim/pack/scion/start/vim-polyglot new file mode 160000 index 0000000..f061edd --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-polyglot @@ -0,0 +1 @@ +Subproject commit f061eddb7cdcc614c8406847b2bfb53099832a4e diff --git a/config/nvim-2/nvim/pack/scion/start/vim-sensible b/config/nvim-2/nvim/pack/scion/start/vim-sensible new file mode 160000 index 0000000..0ce2d84 --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-sensible @@ -0,0 +1 @@ +Subproject commit 0ce2d843d6f588bb0c8c7eec6449171615dc56d9 diff --git a/config/nvim-2/nvim/pack/scion/start/vim-surround b/config/nvim-2/nvim/pack/scion/start/vim-surround new file mode 160000 index 0000000..3d188ed --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-surround @@ -0,0 +1 @@ +Subproject commit 3d188ed2113431cf8dac77be61b842acb64433d9 diff --git a/config/nvim-2/nvim/pack/scion/start/vim-vinegar b/config/nvim-2/nvim/pack/scion/start/vim-vinegar new file mode 160000 index 0000000..bb1bcdd --- /dev/null +++ b/config/nvim-2/nvim/pack/scion/start/vim-vinegar @@ -0,0 +1 @@ +Subproject commit bb1bcddf43cfebe05eb565a84ab069b357d0b3d6 diff --git a/config/nvim-2/nvim/scion b/config/nvim-2/nvim/scion new file mode 160000 index 0000000..0b4ecbd --- /dev/null +++ b/config/nvim-2/nvim/scion @@ -0,0 +1 @@ +Subproject commit 0b4ecbd27497c31a23675f93412931801d85c7e1 diff --git a/config/nvim-2/nvim/scion_state.json b/config/nvim-2/nvim/scion_state.json new file mode 100644 index 0000000..9e1f32e --- /dev/null +++ b/config/nvim-2/nvim/scion_state.json @@ -0,0 +1,21 @@ +{ + "installed": { + "vim-endwise": "64a654ef4a20db1727938338310209b6a63f60c9", + "vim-vinegar": "a1d504892f2bc56c2e79b65c6faded2fd21f3eca", + "nvim-lspconfig": "451d4ef9abd4f0f08e379ef0d55d1c391b6125a7", + "nvim-cmp": "3d188ed2113431cf8dac77be61b842acb64433d9", + "vim-commentary": "0b4ecbd27497c31a23675f93412931801d85c7e1", + "cmp-buffer": "0ce2d843d6f588bb0c8c7eec6449171615dc56d9", + "cmp-nvim-lsp": "bb1bcddf43cfebe05eb565a84ab069b357d0b3d6", + "nvim-autopairs": "cbc7b02bb99fae35cb42f514762b89b5126651ef", + "vim-surround": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0", + "LuaSnip": "4994afb0cdf956d9a665a14b9c834869e602c396", + "vim-sensible": "d0a562f8bdb107a50595aefe53b1a690460c3822", + "vim-fugitive": "b74fab3656eea9de20a9b8116afa3cfc4ec09657", + "vim-closetag": "4916d6592ede8c07973490d9322f187e07dfefac", + "vim-polyglot": "7b9923abad60b903ece7c52940e1321d39eccc79", + "nvim-treesitter": "a62e1083a3cfe8b6b206e7d3d33a51091df25357", + "nvim-colorizer.lua": "a065833f35a3a7cc3ef137ac88b5381da2ba302e" + }, + "last_update": null +} \ No newline at end of file diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%alacritty%alacritty.toml b/config/nvim-2/nvim/undodir/%home%coast%.config%alacritty%alacritty.toml new file mode 100644 index 0000000..d5a3c87 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%alacritty%alacritty.toml differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%fastfetch%config.jsonc b/config/nvim-2/nvim/undodir/%home%coast%.config%fastfetch%config.jsonc new file mode 100644 index 0000000..6fe97d1 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%fastfetch%config.jsonc differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%niri%config.kdl b/config/nvim-2/nvim/undodir/%home%coast%.config%niri%config.kdl new file mode 100644 index 0000000..27acd12 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%niri%config.kdl differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%graft%config.rb b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%graft%config.rb new file mode 100644 index 0000000..324ab66 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%graft%config.rb differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%init.vim b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%init.vim new file mode 100644 index 0000000..8e0ffc1 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%init.vim differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%key.vim b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%key.vim new file mode 100644 index 0000000..ee0be81 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%key.vim differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%config.rb b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%config.rb new file mode 100644 index 0000000..de63755 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%config.rb differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%scion.rb b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%scion.rb new file mode 100644 index 0000000..0c9be05 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%scion%scion.rb differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%test.sh b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%test.sh new file mode 100644 index 0000000..7c1c89c Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%test.sh differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lsp.vim b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lsp.vim new file mode 100644 index 0000000..d2400b6 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lsp.vim differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lua.vim b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lua.vim new file mode 100644 index 0000000..d2307e3 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%lua.vim differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%scp.vim b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%scp.vim new file mode 100644 index 0000000..d38c83b Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%scp.vim differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%theme.vim b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%theme.vim new file mode 100644 index 0000000..9253f7b Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%nvim%vscript%theme.vim differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%rofi%config.rasi b/config/nvim-2/nvim/undodir/%home%coast%.config%rofi%config.rasi new file mode 100644 index 0000000..c93d30d Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%rofi%config.rasi differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%starship.toml b/config/nvim-2/nvim/undodir/%home%coast%.config%starship.toml new file mode 100644 index 0000000..dc0fd24 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%starship.toml differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%systemd%user%.#plasma-polkit-agent.servicec252b1882abfd1a3 b/config/nvim-2/nvim/undodir/%home%coast%.config%systemd%user%.#plasma-polkit-agent.servicec252b1882abfd1a3 new file mode 100644 index 0000000..940c0fd Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%systemd%user%.#plasma-polkit-agent.servicec252b1882abfd1a3 differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%config.jsonc b/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%config.jsonc new file mode 100644 index 0000000..065e305 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%config.jsonc differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%style.css b/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%style.css new file mode 100644 index 0000000..0262f4f Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%style.css differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%window.sh b/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%window.sh new file mode 100644 index 0000000..8a353d1 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%waybar%window.sh differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf b/config/nvim-2/nvim/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf new file mode 100644 index 0000000..45ebe8d Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%prismlauncher.desktop b/config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%prismlauncher.desktop new file mode 100644 index 0000000..f0e0cde Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%prismlauncher.desktop differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%throne.desktop b/config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%throne.desktop new file mode 100644 index 0000000..0c048ca Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.local%share%applications%throne.desktop differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.zsh.d%zsh-syntaxhighlighting.zsh b/config/nvim-2/nvim/undodir/%home%coast%.zsh.d%zsh-syntaxhighlighting.zsh new file mode 100644 index 0000000..231d60e Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.zsh.d%zsh-syntaxhighlighting.zsh differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%.zshrc b/config/nvim-2/nvim/undodir/%home%coast%.zshrc new file mode 100644 index 0000000..a83dcf8 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%.zshrc differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%DEVLIST b/config/nvim-2/nvim/undodir/%home%coast%DEVLIST new file mode 100644 index 0000000..80369bc Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%DEVLIST differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%Downloads%snispoof%config.json b/config/nvim-2/nvim/undodir/%home%coast%Downloads%snispoof%config.json new file mode 100644 index 0000000..1fca528 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%Downloads%snispoof%config.json differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%PRISMLAUNCHER%instances%26.1.2%minecraft%config%DistantHorizons.toml b/config/nvim-2/nvim/undodir/%home%coast%PRISMLAUNCHER%instances%26.1.2%minecraft%config%DistantHorizons.toml new file mode 100644 index 0000000..c436481 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%PRISMLAUNCHER%instances%26.1.2%minecraft%config%DistantHorizons.toml differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%Xray%config.json b/config/nvim-2/nvim/undodir/%home%coast%Xray%config.json new file mode 100644 index 0000000..9635c25 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%Xray%config.json differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%bash.sh b/config/nvim-2/nvim/undodir/%home%coast%bash.sh new file mode 100644 index 0000000..d93b76a Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%bash.sh differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%copyparty-setup.py b/config/nvim-2/nvim/undodir/%home%coast%copyparty-setup.py new file mode 100644 index 0000000..cdf8e2a Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%copyparty-setup.py differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%dlhub%goodlinks.txt b/config/nvim-2/nvim/undodir/%home%coast%dlhub%goodlinks.txt new file mode 100644 index 0000000..24d0b10 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%dlhub%goodlinks.txt differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%dlhub%script.py b/config/nvim-2/nvim/undodir/%home%coast%dlhub%script.py new file mode 100644 index 0000000..108eec0 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%dlhub%script.py differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%main.c b/config/nvim-2/nvim/undodir/%home%coast%main.c new file mode 100644 index 0000000..7ed02b6 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%mhr-cfw%config.json b/config/nvim-2/nvim/undodir/%home%coast%mhr-cfw%config.json new file mode 100644 index 0000000..47d857f Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%mhr-cfw%config.json differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%pertree b/config/nvim-2/nvim/undodir/%home%coast%pertree new file mode 100644 index 0000000..65d3ee6 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%pertree differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%.git%COMMIT_EDITMSG b/config/nvim-2/nvim/undodir/%home%coast%piss%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..4b50e6d Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%LICENSE b/config/nvim-2/nvim/undodir/%home%coast%piss%LICENSE new file mode 100644 index 0000000..adbb88b Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%LICENSE differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%README.md b/config/nvim-2/nvim/undodir/%home%coast%piss%README.md new file mode 100644 index 0000000..9f5e7ea Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%README.md differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%makefile b/config/nvim-2/nvim/undodir/%home%coast%piss%makefile new file mode 100644 index 0000000..b5f5f38 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%makefile differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%pissrc.example.lua b/config/nvim-2/nvim/undodir/%home%coast%piss%pissrc.example.lua new file mode 100644 index 0000000..8812aac Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%pissrc.example.lua differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%src%chd.1 b/config/nvim-2/nvim/undodir/%home%coast%piss%src%chd.1 new file mode 100644 index 0000000..57269c6 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%src%chd.1 differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%src%daemon.c b/config/nvim-2/nvim/undodir/%home%coast%piss%src%daemon.c new file mode 100644 index 0000000..990c7c1 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%src%daemon.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%piss%src%piss.1 b/config/nvim-2/nvim/undodir/%home%coast%piss%src%piss.1 new file mode 100644 index 0000000..8d66e00 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%piss%src%piss.1 differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..79d5e94 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.gitignore b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.gitignore new file mode 100644 index 0000000..da38c50 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%.gitignore differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%README b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%README new file mode 100644 index 0000000..72beb72 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%README differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%main.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%main.c new file mode 100644 index 0000000..23b4ca9 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%makefile b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%makefile new file mode 100644 index 0000000..96e432c Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%makefile differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%src%main.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%src%main.c new file mode 100644 index 0000000..a5ec018 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%catter%src%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.git%COMMIT_EDITMSG b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..fb2cb6b Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.gitignore b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.gitignore new file mode 100644 index 0000000..589b4da Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%.gitignore differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%LICENSE b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%LICENSE new file mode 100644 index 0000000..08ed009 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%LICENSE differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%README b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%README new file mode 100644 index 0000000..3bd3366 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%README differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%src%main.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%src%main.c new file mode 100644 index 0000000..4e6ff1a Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%compteur%src%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%main.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%main.c new file mode 100644 index 0000000..679ff66 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%makefile b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%makefile new file mode 100644 index 0000000..17c6793 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%makefile differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%rand b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%rand new file mode 100644 index 0000000..56d03ad Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%rand differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%input.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%input.c new file mode 100644 index 0000000..45aa5c7 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%input.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%main.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%main.c new file mode 100644 index 0000000..ed928db Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%ct%src%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%cterm%cterm.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%cterm%cterm.c new file mode 100644 index 0000000..7d07740 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%cterm%cterm.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.git%COMMIT_EDITMSG b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..75627d0 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.gitignore b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.gitignore new file mode 100644 index 0000000..51d07c6 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%.gitignore differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%build.sh b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%build.sh new file mode 100644 index 0000000..bf83347 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%build.sh differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%main.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%main.c new file mode 100644 index 0000000..e373775 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%gl%Valkhaus%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile b/config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile new file mode 100644 index 0000000..4531b80 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile-opt b/config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile-opt new file mode 100644 index 0000000..c082083 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%makefile-opt differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%template-opt.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%template-opt.c new file mode 100644 index 0000000..5ddc68f Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%template-opt.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%main.c b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%main.c new file mode 100644 index 0000000..dbdcffb Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%main.c differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%makefile b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%makefile new file mode 100644 index 0000000..9f8abb3 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%makefile differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.frag b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.frag new file mode 100644 index 0000000..6f417f2 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.frag differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.vert b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.vert new file mode 100644 index 0000000..3c4b521 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%c%vk%Valk%shader.vert differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%eul-license%v1 b/config/nvim-2/nvim/undodir/%home%coast%projects%eul-license%v1 new file mode 100644 index 0000000..80dd9ed Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%eul-license%v1 differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%.git%COMMIT_EDITMSG b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..29aa774 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%README.md b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%README.md new file mode 100644 index 0000000..0fa47e7 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-asifaiusf%README.md differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..1a80d3c Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README new file mode 100644 index 0000000..17004b3 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README.md b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README.md new file mode 100644 index 0000000..db08edb Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%README.md differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%Rakefile b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%Rakefile new file mode 100644 index 0000000..35efbe9 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%Rakefile differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%config.rb b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%config.rb new file mode 100644 index 0000000..fee7f37 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%config.rb differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%scion.rb b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%scion.rb new file mode 100644 index 0000000..e994a7a Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%vim-scion%scion.rb differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%config.rb b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%config.rb new file mode 100644 index 0000000..d752ef9 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%config.rb differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%main.rb b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%main.rb new file mode 100644 index 0000000..6d3af5c Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%projects%ruby%wayland-rec%main.rb differ diff --git a/config/nvim-2/nvim/undodir/%home%coast%shit.sh b/config/nvim-2/nvim/undodir/%home%coast%shit.sh new file mode 100644 index 0000000..6e9aeb6 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%home%coast%shit.sh differ diff --git a/config/nvim-2/nvim/undodir/%mnt%Home%dotfiles%.gitignore b/config/nvim-2/nvim/undodir/%mnt%Home%dotfiles%.gitignore new file mode 100644 index 0000000..f80e3f4 Binary files /dev/null and b/config/nvim-2/nvim/undodir/%mnt%Home%dotfiles%.gitignore differ diff --git a/config/nvim-2/nvim/vscript/key.vim b/config/nvim-2/nvim/vscript/key.vim new file mode 100644 index 0000000..7a1fcf5 --- /dev/null +++ b/config/nvim-2/nvim/vscript/key.vim @@ -0,0 +1,2 @@ +let mapleader="," +nnoremap x :!chmod +x % diff --git a/config/nvim-2/nvim/vscript/lua.vim b/config/nvim-2/nvim/vscript/lua.vim new file mode 100644 index 0000000..aa14c46 --- /dev/null +++ b/config/nvim-2/nvim/vscript/lua.vim @@ -0,0 +1,87 @@ +lua << EOF + +vim.o.termguicolors = true + +local on_attach = function(client, bufnr) + local opts = { buffer = bufnr, remap = false } + + vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) + vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) + vim.keymap.set("n", "gr", vim.lsp.buf.references, opts) + vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "ca", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) +end + +vim.api.nvim_create_autocmd("FileType", { + pattern = { "lua" }, + callback = function() + vim.lsp.start({ + name = "lua_ls", + cmd = { "lua-language-server" }, + on_attach = on_attach, + }) + end, +}) + +vim.api.nvim_create_autocmd("FileType", { + pattern = { "python" }, + callback = function() + vim.lsp.start({ + name = "pyright", + cmd = { "pyright-langserver", "--stdio" }, + on_attach = on_attach, + }) + end, +}) + +vim.api.nvim_create_autocmd("FileType", { + pattern = { "c", "cpp" }, + callback = function() + vim.lsp.start({ + name = "clangd", + cmd = { "clangd" }, + on_attach = on_attach, + }) + end, +}) + +local cmp = require("cmp") + +cmp.setup({ + snippet = { + expand = function(args) + vim.snippet.expand(args.body) + end, + }, + + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.confirm({ select = true }), + }), + + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + { name = "buffer" }, + }), +}) + +vim.diagnostic.config({ + virtual_text = true, + signs = true, + underline = true, + update_in_insert = false, + severity_sort = true, + + float = { + border = "rounded", + source = true, + }, +}) + + +--autopairs? +require("nvim-autopairs").setup() + +EOF diff --git a/config/nvim-2/nvim/vscript/scp.vim b/config/nvim-2/nvim/vscript/scp.vim new file mode 100644 index 0000000..6824c18 --- /dev/null +++ b/config/nvim-2/nvim/vscript/scp.vim @@ -0,0 +1,29 @@ +function! Sc(char) + let closing = {'(': ')', '[': ']', '{': '}', '<': '>', '"': '"', "'": "'"} + + if has_key(closing, a:char) + let line = getline('.') + let col = col('.') - 1 + let before = col > 0 ? line[col-1] : '' + let after = col < len(line) ? line[col] : '' + if before =~ '\w' && after =~ '\w' + return a:char + endif + if (a:char == '"' || a:char == "'") && before == a:char + return a:char + endif + if after == closing[a:char] + return "\" + endif + return a:char . closing[a:char] . "\" + endif + + return a:char +endfunction + +inoremap ( =Sc('(') +inoremap [ =Sc('[') +inoremap { =Sc('{') +inoremap < =Sc('<') +inoremap " =Sc('"') +inoremap ' =Sc("'") diff --git a/config/nvim-2/nvim/vscript/theme.vim b/config/nvim-2/nvim/vscript/theme.vim new file mode 100644 index 0000000..02993f3 --- /dev/null +++ b/config/nvim-2/nvim/vscript/theme.vim @@ -0,0 +1,61 @@ +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:coastcolors_name = "coastcolors" + +hi Normal guifg=#E7E2DB guibg=NONE gui=NONE +hi NormalNC guifg=#E7E2DB guibg=NONE gui=NONE +hi NormalFloat guifg=#E7E2DB guibg=#141414 gui=NONE + +hi LineNr guifg=#9F6A5E guibg=NONE +hi CursorLineNr guifg=#C4A08A guibg=NONE gui=bold +hi CursorLine guibg=#141414 +hi CursorColumn guibg=#141414 +hi ColorColumn guibg=#101010 + +hi SignColumn guifg=#9F6A5E guibg=NONE +hi FoldColumn guifg=#9F6A5E guibg=NONE +hi Folded guifg=#C4A08A guibg=#141414 gui=italic + +hi VertSplit guifg=#2A2A2A +hi WinSeparator guifg=#2A2A2A + +hi StatusLine guifg=#E7E2DB guibg=#1A1A1A +hi StatusLineNC guifg=#9F6A5E guibg=#141414 + +hi TabLine guifg=#C4A08A guibg=#141414 +hi TabLineSel guifg=#E7E2DB guibg=#9F6A5E gui=bold +hi TabLineFill guibg=#141414 + +hi Visual guibg=#2A2A2A +hi VisualNOS guibg=#2A2A2A + +hi Search guifg=#2A1A0E guibg=#D4813A +hi IncSearch guifg=#E7E2DB guibg=#A0522D +hi CurSearch guifg=#E7E2DB guibg=#A0522D + +hi Pmenu guifg=#E7E2DB guibg=#141414 +hi PmenuSel guifg=#E7E2DB guibg=#9F6A5E +hi PmenuSbar guibg=#1A1A1A +hi PmenuThumb guibg=#3A2A22 + +hi NonText guifg=#2A2A2A +hi SpecialKey guifg=#2A2A2A +hi Whitespace guifg=#1A1A1A +hi EndOfBuffer guifg=#1A1A1A + +hi Comment guifg=#B8896E gui=italic +hi Constant guifg=#2E6DA4 +hi String guifg=#27794A +hi Number guifg=#2E6DA4 +hi Boolean guifg=#2E6DA4 gui=bold + +hi Function guifg=#8B3A62 gui=bold +hi Statement guifg=#A0522D gui=bold +hi Keyword guifg=#C0392B gui=bold +hi Type guifg=#2A7D7D gui=bold + +hi Error guifg=#E7E2DB guibg=#C0392B gui=bold +hi Todo guifg=#2A1A0E guibg=#D4813A gui=bold diff --git a/config/nvim-2/pack-bak/graft/start/LuaSnip b/config/nvim-2/pack-bak/graft/start/LuaSnip new file mode 160000 index 0000000..a62e108 --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/LuaSnip @@ -0,0 +1 @@ +Subproject commit a62e1083a3cfe8b6b206e7d3d33a51091df25357 diff --git a/config/nvim-2/pack-bak/graft/start/cmp-buffer b/config/nvim-2/pack-bak/graft/start/cmp-buffer new file mode 160000 index 0000000..b74fab3 --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/cmp-buffer @@ -0,0 +1 @@ +Subproject commit b74fab3656eea9de20a9b8116afa3cfc4ec09657 diff --git a/config/nvim-2/pack-bak/graft/start/cmp-nvim-lsp b/config/nvim-2/pack-bak/graft/start/cmp-nvim-lsp new file mode 160000 index 0000000..cbc7b02 --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/cmp-nvim-lsp @@ -0,0 +1 @@ +Subproject commit cbc7b02bb99fae35cb42f514762b89b5126651ef diff --git a/config/nvim-2/pack-bak/graft/start/nvim-autopairs b/config/nvim-2/pack-bak/graft/start/nvim-autopairs new file mode 160000 index 0000000..7b9923a --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/nvim-autopairs @@ -0,0 +1 @@ +Subproject commit 7b9923abad60b903ece7c52940e1321d39eccc79 diff --git a/config/nvim-2/pack-bak/graft/start/nvim-cmp b/config/nvim-2/pack-bak/graft/start/nvim-cmp new file mode 160000 index 0000000..a1d5048 --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/nvim-cmp @@ -0,0 +1 @@ +Subproject commit a1d504892f2bc56c2e79b65c6faded2fd21f3eca diff --git a/config/nvim-2/pack-bak/graft/start/nvim-lspconfig b/config/nvim-2/pack-bak/graft/start/nvim-lspconfig new file mode 160000 index 0000000..451d4ef --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/nvim-lspconfig @@ -0,0 +1 @@ +Subproject commit 451d4ef9abd4f0f08e379ef0d55d1c391b6125a7 diff --git a/config/nvim-2/pack-bak/graft/start/vim-closetag b/config/nvim-2/pack-bak/graft/start/vim-closetag new file mode 160000 index 0000000..d0a562f --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-closetag @@ -0,0 +1 @@ +Subproject commit d0a562f8bdb107a50595aefe53b1a690460c3822 diff --git a/config/nvim-2/pack-bak/graft/start/vim-commentary b/config/nvim-2/pack-bak/graft/start/vim-commentary new file mode 160000 index 0000000..64a654e --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-commentary @@ -0,0 +1 @@ +Subproject commit 64a654ef4a20db1727938338310209b6a63f60c9 diff --git a/config/nvim-2/pack-bak/graft/start/vim-endwise b/config/nvim-2/pack-bak/graft/start/vim-endwise new file mode 160000 index 0000000..4994afb --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-endwise @@ -0,0 +1 @@ +Subproject commit 4994afb0cdf956d9a665a14b9c834869e602c396 diff --git a/config/nvim-2/pack-bak/graft/start/vim-fugitive b/config/nvim-2/pack-bak/graft/start/vim-fugitive new file mode 160000 index 0000000..3b753cf --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-fugitive @@ -0,0 +1 @@ +Subproject commit 3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0 diff --git a/config/nvim-2/pack-bak/graft/start/vim-polyglot b/config/nvim-2/pack-bak/graft/start/vim-polyglot new file mode 160000 index 0000000..f061edd --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-polyglot @@ -0,0 +1 @@ +Subproject commit f061eddb7cdcc614c8406847b2bfb53099832a4e diff --git a/config/nvim-2/pack-bak/graft/start/vim-sensible b/config/nvim-2/pack-bak/graft/start/vim-sensible new file mode 160000 index 0000000..0ce2d84 --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-sensible @@ -0,0 +1 @@ +Subproject commit 0ce2d843d6f588bb0c8c7eec6449171615dc56d9 diff --git a/config/nvim-2/pack-bak/graft/start/vim-surround b/config/nvim-2/pack-bak/graft/start/vim-surround new file mode 160000 index 0000000..3d188ed --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-surround @@ -0,0 +1 @@ +Subproject commit 3d188ed2113431cf8dac77be61b842acb64433d9 diff --git a/config/nvim-2/pack-bak/graft/start/vim-vinegar b/config/nvim-2/pack-bak/graft/start/vim-vinegar new file mode 160000 index 0000000..bb1bcdd --- /dev/null +++ b/config/nvim-2/pack-bak/graft/start/vim-vinegar @@ -0,0 +1 @@ +Subproject commit bb1bcddf43cfebe05eb565a84ab069b357d0b3d6 diff --git a/config/nvim-2/scion b/config/nvim-2/scion new file mode 160000 index 0000000..0b4ecbd --- /dev/null +++ b/config/nvim-2/scion @@ -0,0 +1 @@ +Subproject commit 0b4ecbd27497c31a23675f93412931801d85c7e1 diff --git a/config/nvim-2/scion_state.json b/config/nvim-2/scion_state.json new file mode 100644 index 0000000..4ac6706 --- /dev/null +++ b/config/nvim-2/scion_state.json @@ -0,0 +1,19 @@ +{ + "installed": { + "vim-endwise": "a1d504892f2bc56c2e79b65c6faded2fd21f3eca", + "vim-vinegar": "4994afb0cdf956d9a665a14b9c834869e602c396", + "nvim-lspconfig": "64a654ef4a20db1727938338310209b6a63f60c9", + "nvim-cmp": "0ce2d843d6f588bb0c8c7eec6449171615dc56d9", + "vim-commentary": "0b4ecbd27497c31a23675f93412931801d85c7e1", + "cmp-buffer": "d0a562f8bdb107a50595aefe53b1a690460c3822", + "cmp-nvim-lsp": "cbc7b02bb99fae35cb42f514762b89b5126651ef", + "nvim-autopairs": "3d188ed2113431cf8dac77be61b842acb64433d9", + "vim-surround": "451d4ef9abd4f0f08e379ef0d55d1c391b6125a7", + "LuaSnip": "cbc7b02bb99fae35cb42f514762b89b5126651ef", + "vim-sensible": "7b9923abad60b903ece7c52940e1321d39eccc79", + "vim-fugitive": "bb1bcddf43cfebe05eb565a84ab069b357d0b3d6", + "vim-closetag": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0", + "vim-polyglot": "f061eddb7cdcc614c8406847b2bfb53099832a4e" + }, + "last_update": null +} \ No newline at end of file diff --git a/config/nvim-2/undodir/%home%coast%.config%alacritty%alacritty.toml b/config/nvim-2/undodir/%home%coast%.config%alacritty%alacritty.toml new file mode 100644 index 0000000..9601b32 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%alacritty%alacritty.toml differ diff --git a/config/nvim-2/undodir/%home%coast%.config%fastfetch%config.jsonc b/config/nvim-2/undodir/%home%coast%.config%fastfetch%config.jsonc new file mode 100644 index 0000000..3ebc7ee Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%fastfetch%config.jsonc differ diff --git a/config/nvim-2/undodir/%home%coast%.config%niri%config.kdl b/config/nvim-2/undodir/%home%coast%.config%niri%config.kdl new file mode 100644 index 0000000..3563a30 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%niri%config.kdl differ diff --git a/config/nvim-2/undodir/%home%coast%.config%nvim%graft%config.rb b/config/nvim-2/undodir/%home%coast%.config%nvim%graft%config.rb new file mode 100644 index 0000000..324ab66 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%nvim%graft%config.rb differ diff --git a/config/nvim-2/undodir/%home%coast%.config%nvim%init.vim b/config/nvim-2/undodir/%home%coast%.config%nvim%init.vim new file mode 100644 index 0000000..d4e7d89 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%nvim%init.vim differ diff --git a/config/nvim-2/undodir/%home%coast%.config%nvim%key.vim b/config/nvim-2/undodir/%home%coast%.config%nvim%key.vim new file mode 100644 index 0000000..ee0be81 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%nvim%key.vim differ diff --git a/config/nvim-2/undodir/%home%coast%.config%nvim%test.sh b/config/nvim-2/undodir/%home%coast%.config%nvim%test.sh new file mode 100644 index 0000000..7c1c89c Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%nvim%test.sh differ diff --git a/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lsp.vim b/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lsp.vim new file mode 100644 index 0000000..d2400b6 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lsp.vim differ diff --git a/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lua.vim b/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lua.vim new file mode 100644 index 0000000..5e89793 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%lua.vim differ diff --git a/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%scp.vim b/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%scp.vim new file mode 100644 index 0000000..d38c83b Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%nvim%vscript%scp.vim differ diff --git a/config/nvim-2/undodir/%home%coast%.config%waybar%config.jsonc b/config/nvim-2/undodir/%home%coast%.config%waybar%config.jsonc new file mode 100644 index 0000000..38e3164 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%waybar%config.jsonc differ diff --git a/config/nvim-2/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf b/config/nvim-2/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf new file mode 100644 index 0000000..45ebe8d Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.config%xdg-desktop-portal%portals.conf differ diff --git a/config/nvim-2/undodir/%home%coast%.zshrc b/config/nvim-2/undodir/%home%coast%.zshrc new file mode 100644 index 0000000..f6f7ae6 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%.zshrc differ diff --git a/config/nvim-2/undodir/%home%coast%DEVLIST b/config/nvim-2/undodir/%home%coast%DEVLIST new file mode 100644 index 0000000..ca37bfb Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%DEVLIST differ diff --git a/config/nvim-2/undodir/%home%coast%main.c b/config/nvim-2/undodir/%home%coast%main.c new file mode 100644 index 0000000..993c793 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%main.c differ diff --git a/config/nvim-2/undodir/%home%coast%pertree b/config/nvim-2/undodir/%home%coast%pertree new file mode 100644 index 0000000..65d3ee6 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%pertree differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG b/config/nvim-2/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..79d5e94 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%catter%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%catter%.gitignore b/config/nvim-2/undodir/%home%coast%projects%c%catter%.gitignore new file mode 100644 index 0000000..da38c50 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%catter%.gitignore differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%catter%README b/config/nvim-2/undodir/%home%coast%projects%c%catter%README new file mode 100644 index 0000000..72beb72 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%catter%README differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%catter%main.c b/config/nvim-2/undodir/%home%coast%projects%c%catter%main.c new file mode 100644 index 0000000..23b4ca9 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%catter%main.c differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%catter%makefile b/config/nvim-2/undodir/%home%coast%projects%c%catter%makefile new file mode 100644 index 0000000..96e432c Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%catter%makefile differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%catter%src%main.c b/config/nvim-2/undodir/%home%coast%projects%c%catter%src%main.c new file mode 100644 index 0000000..a5ec018 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%catter%src%main.c differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%makefile-opt b/config/nvim-2/undodir/%home%coast%projects%c%makefile-opt new file mode 100644 index 0000000..c082083 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%makefile-opt differ diff --git a/config/nvim-2/undodir/%home%coast%projects%c%template-opt.c b/config/nvim-2/undodir/%home%coast%projects%c%template-opt.c new file mode 100644 index 0000000..5ddc68f Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%c%template-opt.c differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG new file mode 100644 index 0000000..1a80d3c Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%.git%COMMIT_EDITMSG differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README new file mode 100644 index 0000000..17004b3 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README.md b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README.md new file mode 100644 index 0000000..db08edb Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%README.md differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%Rakefile b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%Rakefile new file mode 100644 index 0000000..35efbe9 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%Rakefile differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%config.rb b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%config.rb new file mode 100644 index 0000000..fee7f37 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%config.rb differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%scion.rb b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%scion.rb new file mode 100644 index 0000000..e994a7a Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%vim-scion%scion.rb differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%config.rb b/config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%config.rb new file mode 100644 index 0000000..d752ef9 Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%config.rb differ diff --git a/config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%main.rb b/config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%main.rb new file mode 100644 index 0000000..6d3af5c Binary files /dev/null and b/config/nvim-2/undodir/%home%coast%projects%ruby%wayland-rec%main.rb differ diff --git a/config/nvim-2/vscript/key.vim b/config/nvim-2/vscript/key.vim new file mode 100644 index 0000000..7a1fcf5 --- /dev/null +++ b/config/nvim-2/vscript/key.vim @@ -0,0 +1,2 @@ +let mapleader="," +nnoremap x :!chmod +x % diff --git a/config/nvim-2/vscript/lua.vim b/config/nvim-2/vscript/lua.vim new file mode 100644 index 0000000..8d6eec0 --- /dev/null +++ b/config/nvim-2/vscript/lua.vim @@ -0,0 +1,122 @@ +lua << EOF + +vim.o.termguicolors = true + +local on_attach = function(client, bufnr) + local opts = { buffer = bufnr, remap = false } + + vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) + vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) + vim.keymap.set("n", "gr", vim.lsp.buf.references, opts) + vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "ca", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) +end + +vim.api.nvim_create_autocmd("FileType", { + pattern = { "lua" }, + callback = function() + vim.lsp.start({ + name = "lua_ls", + cmd = { "lua-language-server" }, + on_attach = on_attach, + }) + end, +}) + +vim.api.nvim_create_autocmd("FileType", { + pattern = { "python" }, + callback = function() + vim.lsp.start({ + name = "pyright", + cmd = { "pyright-langserver", "--stdio" }, + on_attach = on_attach, + }) + end, +}) + +vim.api.nvim_create_autocmd("FileType", { + pattern = { "c", "cpp" }, + callback = function() + vim.lsp.start({ + name = "clangd", + cmd = { "clangd" }, + on_attach = on_attach, + }) + end, +}) + +local cmp = require("cmp") + +cmp.setup({ + snippet = { + expand = function(args) + vim.snippet.expand(args.body) + end, + }, + + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.confirm({ select = true }), + }), + + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + { name = "buffer" }, + }), +}) + +vim.diagnostic.config({ + virtual_text = true, + signs = true, + underline = true, + update_in_insert = false, + severity_sort = true, + + float = { + border = "rounded", + source = true, + }, +}) + +vim.cmd([[ +highlight clear +syntax reset +highlight Normal guibg=NONE +highlight NormalNC guibg=NONE +highlight SignColumn guibg=NONE +highlight FoldColumn guibg=NONE +highlight VertSplit guibg=NONE +highlight StatusLine guibg=NONE +highlight StatusLineNC guibg=NONE +highlight LineNr guibg=NONE +highlight CursorLine guibg=#151515 +highlight CursorLineNr guibg=NONE gui=bold +highlight Pmenu guibg=#121212 +highlight PmenuSel guibg=#2a2a2a +highlight PmenuSbar guibg=#121212 +highlight PmenuThumb guibg=#4a4a4a +highlight NormalFloat guibg=NONE +highlight FloatBorder guibg=NONE +highlight DiagnosticError guifg=#ff6b6b +highlight DiagnosticWarn guifg=#ffd08a +highlight DiagnosticInfo guifg=#9fe7ff +highlight DiagnosticHint guifg=#7dff9a +highlight DiagnosticVirtualTextError guifg=#ff6b6b guibg=NONE +highlight DiagnosticVirtualTextWarn guifg=#ffd08a guibg=NONE +highlight DiagnosticVirtualTextInfo guifg=#9fe7ff guibg=NONE +highlight DiagnosticVirtualTextHint guifg=#7dff7a guibg=NONE +highlight DiagnosticUnderlineError gui=undercurl guisp=#ff6b6b +highlight DiagnosticUnderlineWarn gui=undercurl guisp=#ffd08a +highlight DiagnosticUnderlineInfo gui=undercurl guisp=#9fe7ff +highlight DiagnosticUnderlineHint gui=undercurl guisp=#7dff7a +highlight LspReferenceText guibg=#1f1f1f +highlight LspReferenceRead guibg=#1f1f1f +highlight LspReferenceWrite guibg=#1f1f1f +]]) + +--autopairs? +require("nvim-autopairs").setup() + +EOF diff --git a/config/nvim-2/vscript/scp.vim b/config/nvim-2/vscript/scp.vim new file mode 100644 index 0000000..6824c18 --- /dev/null +++ b/config/nvim-2/vscript/scp.vim @@ -0,0 +1,29 @@ +function! Sc(char) + let closing = {'(': ')', '[': ']', '{': '}', '<': '>', '"': '"', "'": "'"} + + if has_key(closing, a:char) + let line = getline('.') + let col = col('.') - 1 + let before = col > 0 ? line[col-1] : '' + let after = col < len(line) ? line[col] : '' + if before =~ '\w' && after =~ '\w' + return a:char + endif + if (a:char == '"' || a:char == "'") && before == a:char + return a:char + endif + if after == closing[a:char] + return "\" + endif + return a:char . closing[a:char] . "\" + endif + + return a:char +endfunction + +inoremap ( =Sc('(') +inoremap [ =Sc('[') +inoremap { =Sc('{') +inoremap < =Sc('<') +inoremap " =Sc('"') +inoremap ' =Sc("'") diff --git a/config/nvim-root/init.lua b/config/nvim-root/init.lua new file mode 100755 index 0000000..1d60c81 --- /dev/null +++ b/config/nvim-root/init.lua @@ -0,0 +1,168 @@ +vim.cmd [[ + set nocompatible + filetype plugin indent on + syntax enable + call plug#begin('~/.local/share/nvim/plugged') + Plug 'tpope/vim-sensible' + Plug 'junegunn/fzf.vim' + Plug 'tpope/vim-surround' + Plug 'tpope/vim-commentary' + Plug 'jiangmiao/auto-pairs' + Plug 'tpope/vim-repeat' + Plug 'mattn/emmet-vim' + Plug 'norcalli/nvim-colorizer.lua' + call plug#end() +]] + +vim.opt.clipboard = "unnamedplus" +vim.opt.updatetime = 300 +vim.opt.timeoutlen = 500 +vim.opt.signcolumn = "yes" +vim.opt.completeopt = { "menuone", "noinsert", "noselect" } +vim.opt.encoding = "utf-8" +vim.opt.number = true +vim.opt.relativenumber = true +vim.opt.numberwidth = 4 +vim.opt.tabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.expandtab = true +vim.opt.smartindent = true +vim.opt.incsearch = true +vim.opt.hlsearch = true +vim.opt.ignorecase = true +vim.opt.smartcase = true +vim.opt.wrap = true +vim.opt.mouse = "a" +vim.opt.scrolloff = 5 +vim.opt.cursorline = true +vim.opt.showmode = false +vim.opt.shortmess:append("I") +vim.opt.autoindent = true +vim.opt.termguicolors = true +vim.opt.list = true +vim.opt.undodir = vim.fn.stdpath("cache") .. "/undo" +vim.opt.undofile = true +vim.opt.wrapscan = true +vim.opt.shortmess:append("c") +vim.opt.autoread = true +vim.opt.cmdheight = 1 +vim.opt.belloff = "all" +vim.opt.laststatus = 2 +vim.opt.scrolljump = 3 +vim.opt.hidden = true +vim.opt.splitbelow = true +vim.opt.splitright = true +vim.opt.backup = false +vim.opt.writebackup = false +vim.opt.lazyredraw = true +vim.opt.smoothscroll = true + +vim.api.nvim_set_hl(0, "Normal", { fg = "#a6536f", bg = "NONE", ctermfg = 132, ctermbg = "NONE" }) +vim.api.nvim_set_hl(0, "NormalNC", { fg = "#bb6c82", bg = "NONE", ctermfg = 168, ctermbg = "NONE" }) +vim.api.nvim_set_hl(0, "LineNr", { fg = "#743c5e", bg = "NONE", ctermfg = 132, ctermbg = "NONE" }) +vim.api.nvim_set_hl(0, "CursorLine", { bg = "#3f1f32", fg = "NONE", blend = 30 }) +vim.api.nvim_set_hl(0, "VertSplit", { fg = "#3f1f32", bg = "NONE", ctermfg = 237, ctermbg = "NONE" }) + +vim.api.nvim_set_hl(0, "StatusLine", { + fg = "#a6536f", + bg = "#2a1c2e", + ctermfg = 132, + ctermbg = 235, +}) + +vim.api.nvim_set_hl(0, "StatusLineMode", { + fg = "#f7d8e5", + bg = "#5e2f4c", + bold = true, + ctermfg = 224, + ctermbg = 131, +}) + +vim.api.nvim_set_hl(0, "Visual", { bg = "#5a2c3a", fg = "NONE", ctermbg = 52, ctermfg = "NONE" }) +vim.api.nvim_set_hl(0, "VisualNOS", { bg = "#5a2c3a", fg = "NONE", ctermbg = 52, ctermfg = "NONE" }) +vim.api.nvim_set_hl(0, "VisualSB", { bg = "#5a2c3a", fg = "NONE", ctermbg = 52, ctermfg = "NONE" }) +vim.api.nvim_set_hl(0, "Search", { fg = "#b0576f", bg = "#1c1533", ctermfg = 131, ctermbg = 234 }) +vim.api.nvim_set_hl(0, "IncSearch", { fg = "#f5a3ba", bg = "#1c1533", ctermfg = 218, ctermbg = 234 }) +vim.api.nvim_set_hl(0, "Pmenu", { fg = "#b0576f", bg = "NONE", ctermfg = 131, ctermbg = "NONE" }) +vim.api.nvim_set_hl(0, "PmenuSel", { fg = "#000000", bg = "#b0576f", ctermfg = 0, ctermbg = 131 }) +vim.api.nvim_set_hl(0, "WildMenu", { fg = "#b0576f", bg = "NONE", ctermfg = 131, ctermbg = "NONE" }) +vim.api.nvim_set_hl(0, "Folded", { fg = "#c18299", bg = "NONE", ctermfg = 174, ctermbg = "NONE" }) +vim.api.nvim_set_hl(0, "SignColumn", { fg = "#f0b6c8", bg = "NONE", ctermfg = 224, ctermbg = "NONE" }) + +local mode_names = { + n = "ROOT NRM", + i = "ROOT INS", + v = "ROOT VSL", + V = "ROOT VLI", + [""] = "ROOT VBL", + R = "ROOT RPL", + c = "ROOT CMD", +} + +function _G.ModeName() + return mode_names[vim.fn.mode()] or "UNK" +end + +vim.opt.statusline = table.concat { + "%#StatusLineMode# ", + "%{v:lua.ModeName()} ", + "%#StatusLine# ", + "%f %m %r ", + "%=", + "Ln:%l/%L ", + "Col:%c ", + "[%p%%]", +} + +vim.g.mapleader = " " +local map = vim.keymap.set +map("n", "w", ":w") +map("n", "q", ":q") +map("n", "h", ":nohlsearch", { silent = true }) +map("n", "n", ":set relativenumber!") +map("n", "", "h") +map("n", "", "j") +map("n", "", "k") +map("n", "", "l") +map("n", "v", ":Ex") +map("", "j", "gj") +map("", "k", "gk") + +vim.keymap.set({ "n", "v" }, "cd", vim.cmd.Ex) + +vim.keymap.set({ "n", "v" }, "d", '"_d', { desc = "Delete without yanking" }) +vim.keymap.set("n", "bn", ":bnext", { desc = "Next buffer" }) +vim.keymap.set("n", "bp", ":bprevious", { desc = "Previous buffer" }) + +vim.keymap.set("n", "", "h", { desc = "Move to left window" }) +vim.keymap.set("n", "", "j", { desc = "Move to bottom window" }) +vim.keymap.set("n", "", "k", { desc = "Move to top window" }) +vim.keymap.set("n", "", "l", { desc = "Move to right window" }) + +local modes_to_disable = { "n", "v", "x", "s", "c" } +local arrows = { "", "", "", "" } + +for _, mode in ipairs(modes_to_disable) do + for _, key in ipairs(arrows) do + vim.keymap.set(mode, key, "", { silent = true }) + end +end + +vim.keymap.set("n", "sv", ":vsplit", { desc = "Split window vertically" }) +vim.keymap.set("n", "sh", ":split", { desc = "Split window horizontally" }) +vim.keymap.set("n", "", ":resize +2", { desc = "Increase window height" }) +vim.keymap.set("n", "", ":resize -2", { desc = "Decrease window height" }) +vim.keymap.set("n", "", ":vertical resize -2", { desc = "Decrease window width" }) +vim.keymap.set("n", "", ":vertical resize +2", { desc = "Increase window width" }) + +vim.keymap.set("n", "", ":m .+1==", { desc = "Move line down" }) +vim.keymap.set("n", "", ":m .-2==", { desc = "Move line up" }) +vim.keymap.set("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) +vim.keymap.set("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) + +require('colorizer').setup { + '*', + css = { names = true }, + html = { names = true }, +} + diff --git a/config/picom/picom-animations.conf b/config/picom/picom-animations.conf new file mode 100755 index 0000000..b59cfcb --- /dev/null +++ b/config/picom/picom-animations.conf @@ -0,0 +1,310 @@ +{ + match = "window_type = 'normal'"; + animations = ( + { + triggers = ["close"]; + opacity = { + curve = "cubic-bezier(0,1,1,1)"; + duration = 0.3; + start = "window-raw-opacity-before"; + end = 0; + }; + blur-opacity = "opacity"; + shadow-opacity = "opacity"; + + scale-x = { + curve = "cubic-bezier(0,1.3,1,1)"; + duration = 0.3; + start = 1; + end = 0.6; + }; + scale-y = "scale-x"; + + offset-x = "(1 - scale-x) / 2 * window-width"; + offset-y = "(1 - scale-y) / 2 * window-height"; + + shadow-scale-x = "scale-x"; + shadow-scale-y = "scale-y"; + shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; + }, + + { + triggers = ["open"]; + opacity = { + curve = "cubic-bezier(0,1,1,1)"; + duration = 0.3; + start = 0; + end = "window-raw-opacity"; + }; + blur-opacity = "opacity"; + shadow-opacity = "opacity"; + + scale-x = { + curve = "cubic-bezier(0,1.3,1,1)"; + duration = 0.3; + start = 0.6; + end = 1; + }; + scale-y = "scale-x"; + + offset-x = "(1 - scale-x) / 2 * window-width"; + offset-y = "(1 - scale-y) / 2 * window-height"; + + shadow-scale-x = "scale-x"; + shadow-scale-y = "scale-y"; + shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; + }, + + { + triggers = ["geometry"]; + scale-x = { + curve = "cubic-bezier(0,0,0,1.28)"; + duration = 0.3; + start = "window-width-before / window-width"; + end = 1; + }; + + scale-x-reverse = { + curve = "cubic-bezier(0,0,0,1.28)"; + duration = 0.4; + start = "window-width / window-width-before"; + end = 1; + }; + scale-y = { + curve = "cubic-bezier(0,0,0,1.28)"; + duration = 0.3; + start = "window-height-before / window-height"; + end = 1; + }; + scale-y-reverse = { + curve = "cubic-bezier(0,0,0,1.28)"; + duration = 0.4; + start = "window-height / window-height-before"; + end = 1; + }; + offset-x = { + curve = "cubic-bezier(0,0,0,1.28)"; + duration = 0.3; + start = "window-x-before - window-x"; + end = 0; + }; + offset-y = { + curve = "cubic-bezier(0,0,0,1.28)"; + duration = 0.3; + start = "window-y-before - window-y"; + end = 0; + }; + shadow-scale-x = "scale-x"; + shadow-scale-y = "scale-y"; + shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; + } + ) +}, + +{ + match = "class_g = 'Rofi'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "disappear"; + duration = 0.05; + scale = 0.4; + }, + { + triggers = ["open", "show"]; + preset = "appear"; + duration = 0.15; + scale = 0.4; + } + ) +}, + +{ + match = "class_g = 'dunst'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "fly-out"; + direction = "up"; + duration = 0.15; + }, + { + triggers = ["open", "show"]; + preset = "fly-in"; + direction = "up"; + duration = 0.15; + } + ) +}, + +{ + match = "class_g = 'jgmenu'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "disappear"; + duration = 0.05; + scale = 0.4; + }, + { + triggers = ["open", "show"]; + preset = "appear"; + duration = 0.1; + scale = 0.4; + } + ) +}, + +{ + match = "class_g = 'bspwm-scratch'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "fly-out"; + direction = "up"; + duration = 0.15; + }, + { + triggers = ["open", "show"]; + preset = "fly-in"; + direction = "up"; + duration = 0.15; + } + ) +}, + +{ + match = "name = 'Eww - launchermenu'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "slide-out"; + direction = "right"; + duration = 0.15; + }, + { + triggers = ["open", "show"]; + preset = "slide-in"; + direction = "right"; + duration = 0.15; + } + ) +}, + +{ + match = "name = 'Eww - music'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "slide-out"; + direction = "up"; + duration = 0.15; + }, + { + triggers = ["open", "show"]; + preset = "slide-in"; + direction = "up"; + duration = 0.15; + } + ) +}, + +{ + match = "name = 'Eww - date'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "fly-out"; + direction = "up"; + duration = 0.15; + }, + { + triggers = ["open", "show"]; + preset = "fly-in"; + direction = "up"; + duration = 0.15; + } + ) +}, + +{ + match = "name = 'Eww - csheet'"; + animations = ( + { + triggers = ["close", "hide"]; + preset = "disappear"; + duration = 0.05; + scale = 0.4; + }, + { + triggers = ["open", "show"]; + preset = "appear"; + duration = 0.1; + scale = 0.4; + } + ) +}, + +{ + match = "window_type = 'dock'"; + animations = ( + { + triggers = ["focus-in", "focus-out"]; + opacity = { + curve = "cubic-bezier(0, 0, 0, 1)"; + duration = 0.1; + start = 0; + end = 1; + }; + blur-opacity = "opacity"; + shadow-opacity = "opacity"; + + scale-x = { + curve = "cubic-bezier(0, 0, 0, 1)"; + duration = 0.15; + start = 0.9; + end = 1; + }; + scale-y = "scale-x"; + + offset-x = "(1 - scale-x) / 2 * window-width"; + offset-y = "(1 - scale-y) / 2 * window-height"; + + shadow-scale-x = "scale-x"; + shadow-scale-y = "scale-y"; + shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; + }, + + { + triggers = ["focus-out"]; + opacity = { + curve = "cubic-bezier(0, 0, 0, 1)"; + duration = 0.1; + start = 1; + end = 0; + }; + blur-opacity = "opacity"; + shadow-opacity = "opacity"; + + scale-x = { + curve = "cubic-bezier(0, 0, 0, 1)"; + duration = 0.15; + start = 1; + end = 0.9; + }; + scale-y = "scale-x"; + + offset-x = "(1 - scale-x) / 2 * window-width"; + offset-y = "(1 - scale-y) / 2 * window-height"; + + shadow-scale-x = "scale-x"; + shadow-scale-y = "scale-y"; + shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; + } + ) +} diff --git a/config/picom/picom.conf b/config/picom/picom.conf new file mode 100755 index 0000000..29f35a2 --- /dev/null +++ b/config/picom/picom.conf @@ -0,0 +1,151 @@ +shadow-radius = 1; +shadow-opacity = .1; +shadow-offset-x = -7; +shadow-offset-y = -7; +shadow-color = "#000000" + +fading = true; +fade-in-step = 0.03; +fade-out-step = 0.03; +fade-delta = 5 +no-fading-openclose = false; +no-fading-destroyed-argb = false + +frame-opacity = 1.0; + +backend = "glx" +dithered-present = false; +vsync = true; + +detect-rounded-corners = true; +detect-client-opacity = true; +detect-transient = true; + +use-damage = true; + +blur: + { + method = "dual_kawase"; + size = 10; + deviation = 2.5; + } + +rules: ( + { + blur-background = true; + blur-background-fixed = true; + fade = false; + }, + { + match = "window_type = 'dock'"; + corner-radius = 0; + shadow = false; + }, + { + match = "class_g = 'dwm' || class_g = 'Polybar' || class_g = 'dmenu'"; + corner-radius = 0; + blur-background = true; + opacity = 0.80; + shadow = false; + }, + { + match = "fullscreen = true"; + corner-radius = 0; + }, + { + match = "window_type = 'normal'"; + fade = true; + shadow = true; + }, + { + match = "window_type = 'dialog'"; + shadow = true; + }, + { + match = "window_type = 'tooltip'"; + corner-radius = 0; + opacity = 0.90; + }, + { + match = "window_type = 'dock'"; + corner-radius = 0; + fade = true; + }, + { + match = "window_type = 'dropdown_menu' || window_type = 'menu' || window_type = 'popup' || window_type = 'popup_menu'"; + corner-radius = 0; + }, + { + match = "class_g = 'Alacritty' || class_g = 'kitty' || class_g = 'FloaTerm'"; + opacity = 0.8; + blur-background = true; + }, + { + match = "class_g = 'Polybar' || class_g = 'eww-bar' || class_g = 'Viewnior' || class_g = 'Rofi' || class_g = 'mpv' || class_g = 'bspwm-scratch' || class_g = 'Dunst' || class_g = 'retroarch'"; + corner-radius = 0; + }, + { + match = "name = 'Notification' || class_g ?= 'Notify-osd' || class_g = 'Dunst' || class_g = 'Polybar' || class_g = 'Eww' || class_g = 'jgmenu' || class_g = 'scratch' || class_g = 'Spotify' || class_g = 'retroarch' || class_g = 'firefox' || class_g = 'Rofi' || class_g = 'Screenkey' || class_g = 'mpv' || class_g = 'Viewnior' || _GTK_FRAME_EXTENTS@"; + shadow = false; + }, + { + match = "window_type = 'normal'"; + animations = ( + { + triggers = ["open"]; + opacity = { + curve = "cubic-bezier(0,1,1,1)"; + duration = 0.3; + start = 0; + end = "window-raw-opacity"; + }; + blur-opacity = "opacity"; + shadow-opacity = "opacity"; + + scale-x = { + curve = "cubic-bezier(0,1.3,1,1)"; + duration = 0.3; + start = 0.6; + end = 1; + }; + scale-y = "scale-x"; + + offset-x = "(1 - scale-x) / 2 * window-width"; + offset-y = "(1 - scale-y) / 2 * window-height"; + + shadow-scale-x = "scale-x"; + shadow-scale-y = "scale-y"; + shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; + }, + { + triggers = ["close"]; + opacity = { + curve = "cubic-bezier(0,1,1,1)"; + duration = 0.3; + start = "window-raw-opacity-before"; + end = 0; + }; + blur-opacity = "opacity"; + shadow-opacity = "opacity"; + + scale-x = { + curve = "cubic-bezier(0,1.3,1,1)"; + duration = 0.3; + start = 1; + end = 0.6; + }; + scale-y = "scale-x"; + + offset-x = "(1 - scale-x) / 2 * window-width"; + offset-y = "(1 - scale-y) / 2 * window-height"; + + shadow-scale-x = "scale-x"; + shadow-scale-y = "scale-y"; + shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; + } + ) + }, + @include "picom-animations.conf" +) diff --git a/config/piss/pissrc b/config/piss/pissrc new file mode 100755 index 0000000..1ec3420 --- /dev/null +++ b/config/piss/pissrc @@ -0,0 +1,4 @@ +#!/bin/sh +piss bind "Super + Shift + S" "screenie" +piss bind "Super + R" "$HOME/Projects/py/dmenu.py" +piss bind "Super + Shift + Return" "dmenu_run -l 10 -fn \"JetBrainsMono Nerd Font:size=11\" -nb \"#121212\" -nf \"#e0e0e0\" -sb \"#222222\" -sf \"#e0e0e0\" -p \"Run:\"" diff --git a/config/plugged/plug.vim b/config/plugged/plug.vim new file mode 100755 index 0000000..a225a6d --- /dev/null +++ b/config/plugged/plug.vim @@ -0,0 +1,2877 @@ +" vim-plug: Vim plugin manager +" ============================ +" +" 1. Download plug.vim and put it in 'autoload' directory +" +" # Vim +" curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ +" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim +" +" # Neovim +" sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \ +" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' +" +" 2. Add a vim-plug section to your ~/.vimrc (or ~/.config/nvim/init.vim for Neovim) +" +" call plug#begin() +" +" " List your plugins here +" Plug 'tpope/vim-sensible' +" +" call plug#end() +" +" 3. Reload the file or restart Vim, then you can, +" +" :PlugInstall to install plugins +" :PlugUpdate to update plugins +" :PlugDiff to review the changes from the last update +" :PlugClean to remove plugins no longer in the list +" +" For more information, see https://github.com/junegunn/vim-plug +" +" +" Copyright (c) 2024 Junegunn Choi +" +" MIT License +" +" 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. + +if exists('g:loaded_plug') + finish +endif +let g:loaded_plug = 1 + +let s:cpo_save = &cpo +set cpo&vim + +let s:plug_src = 'https://github.com/junegunn/vim-plug.git' +let s:plug_tab = get(s:, 'plug_tab', -1) +let s:plug_buf = get(s:, 'plug_buf', -1) +let s:mac_gui = has('gui_macvim') && has('gui_running') +let s:is_win = has('win32') +let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win) +let s:vim8 = has('patch-8.0.0039') && exists('*job_start') +if s:is_win && &shellslash + set noshellslash + let s:me = resolve(expand(':p')) + set shellslash +else + let s:me = resolve(expand(':p')) +endif +let s:base_spec = { 'branch': '', 'frozen': 0 } +let s:TYPE = { +\ 'string': type(''), +\ 'list': type([]), +\ 'dict': type({}), +\ 'funcref': type(function('call')) +\ } +let s:loaded = get(s:, 'loaded', {}) +let s:triggers = get(s:, 'triggers', {}) + +function! s:is_powershell(shell) + return a:shell =~# 'powershell\(\.exe\)\?$' || a:shell =~# 'pwsh\(\.exe\)\?$' +endfunction + +function! s:isabsolute(dir) abort + return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)') +endfunction + +function! s:git_dir(dir) abort + let gitdir = s:trim(a:dir) . '/.git' + if isdirectory(gitdir) + return gitdir + endif + if !filereadable(gitdir) + return '' + endif + let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*') + if len(gitdir) && !s:isabsolute(gitdir) + let gitdir = a:dir . '/' . gitdir + endif + return isdirectory(gitdir) ? gitdir : '' +endfunction + +function! s:git_origin_url(dir) abort + let gitdir = s:git_dir(a:dir) + let config = gitdir . '/config' + if empty(gitdir) || !filereadable(config) + return '' + endif + return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze') +endfunction + +function! s:git_revision(dir) abort + let gitdir = s:git_dir(a:dir) + let head = gitdir . '/HEAD' + if empty(gitdir) || !filereadable(head) + return '' + endif + + let line = get(readfile(head), 0, '') + let ref = matchstr(line, '^ref: \zs.*') + if empty(ref) + return line + endif + + if filereadable(gitdir . '/' . ref) + return get(readfile(gitdir . '/' . ref), 0, '') + endif + + if filereadable(gitdir . '/packed-refs') + for line in readfile(gitdir . '/packed-refs') + if line =~# ' ' . ref + return matchstr(line, '^[0-9a-f]*') + endif + endfor + endif + + return '' +endfunction + +function! s:git_local_branch(dir) abort + let gitdir = s:git_dir(a:dir) + let head = gitdir . '/HEAD' + if empty(gitdir) || !filereadable(head) + return '' + endif + let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*') + return len(branch) ? branch : 'HEAD' +endfunction + +function! s:git_origin_branch(spec) + if len(a:spec.branch) + return a:spec.branch + endif + + " The file may not be present if this is a local repository + let gitdir = s:git_dir(a:spec.dir) + let origin_head = gitdir.'/refs/remotes/origin/HEAD' + if len(gitdir) && filereadable(origin_head) + return matchstr(get(readfile(origin_head), 0, ''), + \ '^ref: refs/remotes/origin/\zs.*') + endif + + " The command may not return the name of a branch in detached HEAD state + let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir)) + return v:shell_error ? '' : result[-1] +endfunction + +if s:is_win + function! s:plug_call(fn, ...) + let shellslash = &shellslash + try + set noshellslash + return call(a:fn, a:000) + finally + let &shellslash = shellslash + endtry + endfunction +else + function! s:plug_call(fn, ...) + return call(a:fn, a:000) + endfunction +endif + +function! s:plug_getcwd() + return s:plug_call('getcwd') +endfunction + +function! s:plug_fnamemodify(fname, mods) + return s:plug_call('fnamemodify', a:fname, a:mods) +endfunction + +function! s:plug_expand(fmt) + return s:plug_call('expand', a:fmt, 1) +endfunction + +function! s:plug_tempname() + return s:plug_call('tempname') +endfunction + +function! plug#begin(...) + if a:0 > 0 + let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p')) + elseif exists('g:plug_home') + let home = s:path(g:plug_home) + elseif has('nvim') + let home = stdpath('data') . '/plugged' + elseif !empty(&rtp) + let home = s:path(split(&rtp, ',')[0]) . '/plugged' + else + return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.') + endif + if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp + return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.') + endif + + let g:plug_home = home + let g:plugs = {} + let g:plugs_order = [] + let s:triggers = {} + + call s:define_commands() + return 1 +endfunction + +function! s:define_commands() + command! -nargs=+ -bar Plug call plug#() + if !executable('git') + return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.') + endif + if has('win32') + \ && &shellslash + \ && (&shell =~# 'cmd\(\.exe\)\?$' || s:is_powershell(&shell)) + return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.') + endif + if !has('nvim') + \ && (has('win32') || has('win32unix')) + \ && !has('multi_byte') + return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.') + endif + command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(0, []) + command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(0, []) + command! -nargs=0 -bar -bang PlugClean call s:clean(0) + command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif + command! -nargs=0 -bar PlugStatus call s:status() + command! -nargs=0 -bar PlugDiff call s:diff() + command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(0, ) +endfunction + +function! s:to_a(v) + return type(a:v) == s:TYPE.list ? a:v : [a:v] +endfunction + +function! s:to_s(v) + return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n" +endfunction + +function! s:glob(from, pattern) + return s:lines(globpath(a:from, a:pattern)) +endfunction + +function! s:source(from, ...) + let found = 0 + for pattern in a:000 + for vim in s:glob(a:from, pattern) + execute 'source' s:esc(vim) + let found = 1 + endfor + endfor + return found +endfunction + +function! s:assoc(dict, key, val) + let a:dict[a:key] = add(get(a:dict, a:key, []), a:val) +endfunction + +function! s:ask(message, ...) + call inputsave() + echohl WarningMsg + let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) ')) + echohl None + call inputrestore() + echo "\r" + return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0 +endfunction + +function! s:ask_no_interrupt(...) + try + return call('s:ask', a:000) + catch + return 0 + endtry +endfunction + +function! s:lazy(plug, opt) + return has_key(a:plug, a:opt) && + \ (empty(s:to_a(a:plug[a:opt])) || + \ !isdirectory(a:plug.dir) || + \ len(s:glob(s:rtp(a:plug), 'plugin')) || + \ len(s:glob(s:rtp(a:plug), 'after/plugin'))) +endfunction + +function! plug#end() + if !exists('g:plugs') + return s:err('plug#end() called without calling plug#begin() first') + endif + + if exists('#PlugLOD') + augroup PlugLOD + autocmd! + augroup END + augroup! PlugLOD + endif + let lod = { 'ft': {}, 'map': {}, 'cmd': {} } + + if get(g:, 'did_load_filetypes', 0) + filetype off + endif + for name in g:plugs_order + if !has_key(g:plugs, name) + continue + endif + let plug = g:plugs[name] + if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for') + let s:loaded[name] = 1 + continue + endif + + if has_key(plug, 'on') + let s:triggers[name] = { 'map': [], 'cmd': [] } + for cmd in s:to_a(plug.on) + if cmd =~? '^.\+' + if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i')) + call s:assoc(lod.map, cmd, name) + endif + call add(s:triggers[name].map, cmd) + elseif cmd =~# '^[A-Z]' + let cmd = substitute(cmd, '!*$', '', '') + if exists(':'.cmd) != 2 + call s:assoc(lod.cmd, cmd, name) + endif + call add(s:triggers[name].cmd, cmd) + else + call s:err('Invalid `on` option: '.cmd. + \ '. Should start with an uppercase letter or ``.') + endif + endfor + endif + + if has_key(plug, 'for') + let types = s:to_a(plug.for) + if !empty(types) + augroup filetypedetect + call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim') + if has('nvim-0.5.0') + call s:source(s:rtp(plug), 'ftdetect/**/*.lua', 'after/ftdetect/**/*.lua') + endif + augroup END + endif + for type in types + call s:assoc(lod.ft, type, name) + endfor + endif + endfor + + for [cmd, names] in items(lod.cmd) + execute printf( + \ has('patch-7.4.1898') + \ ? 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "", , , , ,%s)' + \ : 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "", , , , %s)' + \ , cmd, string(cmd), string(names)) + endfor + + for [map, names] in items(lod.map) + for [mode, map_prefix, key_prefix] in + \ [['i', '', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']] + execute printf( + \ '%snoremap %s %s:call lod_map(%s, %s, %s, "%s")', + \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix) + endfor + endfor + + for [ft, names] in items(lod.ft) + augroup PlugLOD + execute printf('autocmd FileType %s call lod_ft(%s, %s)', + \ ft, string(ft), string(names)) + augroup END + endfor + + call s:reorg_rtp() + filetype plugin indent on + if has('vim_starting') + if has('syntax') && !exists('g:syntax_on') + syntax enable + end + else + call s:reload_plugins() + endif +endfunction + +function! s:loaded_names() + return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)') +endfunction + +function! s:load_plugin(spec) + call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim') + if has('nvim-0.5.0') + call s:source(s:rtp(a:spec), 'plugin/**/*.lua', 'after/plugin/**/*.lua') + endif +endfunction + +function! s:reload_plugins() + for name in s:loaded_names() + call s:load_plugin(g:plugs[name]) + endfor +endfunction + +function! s:trim(str) + return substitute(a:str, '[\/]\+$', '', '') +endfunction + +function! s:version_requirement(val, min) + for idx in range(0, len(a:min) - 1) + let v = get(a:val, idx, 0) + if v < a:min[idx] | return 0 + elseif v > a:min[idx] | return 1 + endif + endfor + return 1 +endfunction + +function! s:git_version_requirement(...) + if !exists('s:git_version') + let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)') + endif + return s:version_requirement(s:git_version, a:000) +endfunction + +function! s:progress_opt(base) + return a:base && !s:is_win && + \ s:git_version_requirement(1, 7, 1) ? '--progress' : '' +endfunction + +function! s:rtp(spec) + return s:path(a:spec.dir . get(a:spec, 'rtp', '')) +endfunction + +if s:is_win + function! s:path(path) + return s:trim(substitute(a:path, '/', '\', 'g')) + endfunction + + function! s:dirpath(path) + return s:path(a:path) . '\' + endfunction + + function! s:is_local_plug(repo) + return a:repo =~? '^[a-z]:\|^[%~]' + endfunction + + " Copied from fzf + function! s:wrap_cmds(cmds) + let cmds = [ + \ '@echo off', + \ 'setlocal enabledelayedexpansion'] + \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds]) + \ + ['endlocal'] + if has('iconv') + if !exists('s:codepage') + let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0) + endif + return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage)) + endif + return map(cmds, 'v:val."\r"') + endfunction + + function! s:batchfile(cmd) + let batchfile = s:plug_tempname().'.bat' + call writefile(s:wrap_cmds(a:cmd), batchfile) + let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0}) + if s:is_powershell(&shell) + let cmd = '& ' . cmd + endif + return [batchfile, cmd] + endfunction +else + function! s:path(path) + return s:trim(a:path) + endfunction + + function! s:dirpath(path) + return substitute(a:path, '[/\\]*$', '/', '') + endfunction + + function! s:is_local_plug(repo) + return a:repo[0] =~ '[/$~]' + endfunction +endif + +function! s:err(msg) + echohl ErrorMsg + echom '[vim-plug] '.a:msg + echohl None +endfunction + +function! s:warn(cmd, msg) + echohl WarningMsg + execute a:cmd 'a:msg' + echohl None +endfunction + +function! s:esc(path) + return escape(a:path, ' ') +endfunction + +function! s:escrtp(path) + return escape(a:path, ' ,') +endfunction + +function! s:remove_rtp() + for name in s:loaded_names() + let rtp = s:rtp(g:plugs[name]) + execute 'set rtp-='.s:escrtp(rtp) + let after = globpath(rtp, 'after') + if isdirectory(after) + execute 'set rtp-='.s:escrtp(after) + endif + endfor +endfunction + +function! s:reorg_rtp() + if !empty(s:first_rtp) + execute 'set rtp-='.s:first_rtp + execute 'set rtp-='.s:last_rtp + endif + + " &rtp is modified from outside + if exists('s:prtp') && s:prtp !=# &rtp + call s:remove_rtp() + unlet! s:middle + endif + + let s:middle = get(s:, 'middle', &rtp) + let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])') + let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)') + let rtp = join(map(rtps, 'escape(v:val, ",")'), ',') + \ . ','.s:middle.',' + \ . join(map(afters, 'escape(v:val, ",")'), ',') + let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g') + let s:prtp = &rtp + + if !empty(s:first_rtp) + execute 'set rtp^='.s:first_rtp + execute 'set rtp+='.s:last_rtp + endif +endfunction + +function! s:doautocmd(...) + if exists('#'.join(a:000, '#')) + execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '' : '') join(a:000) + endif +endfunction + +function! s:dobufread(names) + for name in a:names + let path = s:rtp(g:plugs[name]) + for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin'] + if len(finddir(dir, path)) + if exists('#BufRead') + doautocmd BufRead + endif + return + endif + endfor + endfor +endfunction + +function! plug#load(...) + if a:0 == 0 + return s:err('Argument missing: plugin name(s) required') + endif + if !exists('g:plugs') + return s:err('plug#begin was not called') + endif + let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000 + let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)') + if !empty(unknowns) + let s = len(unknowns) > 1 ? 's' : '' + return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', '))) + end + let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)') + if !empty(unloaded) + for name in unloaded + call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) + endfor + call s:dobufread(unloaded) + return 1 + end + return 0 +endfunction + +function! s:remove_triggers(name) + if !has_key(s:triggers, a:name) + return + endif + for cmd in s:triggers[a:name].cmd + execute 'silent! delc' cmd + endfor + for map in s:triggers[a:name].map + execute 'silent! unmap' map + execute 'silent! iunmap' map + endfor + call remove(s:triggers, a:name) +endfunction + +function! s:lod(names, types, ...) + for name in a:names + call s:remove_triggers(name) + let s:loaded[name] = 1 + endfor + call s:reorg_rtp() + + for name in a:names + let rtp = s:rtp(g:plugs[name]) + for dir in a:types + call s:source(rtp, dir.'/**/*.vim') + if has('nvim-0.5.0') " see neovim#14686 + call s:source(rtp, dir.'/**/*.lua') + endif + endfor + if a:0 + if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2)) + execute 'runtime' a:1 + endif + call s:source(rtp, a:2) + endif + call s:doautocmd('User', name) + endfor +endfunction + +function! s:lod_ft(pat, names) + let syn = 'syntax/'.a:pat.'.vim' + call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn) + execute 'autocmd! PlugLOD FileType' a:pat + call s:doautocmd('filetypeplugin', 'FileType') + call s:doautocmd('filetypeindent', 'FileType') +endfunction + +if has('patch-7.4.1898') + function! s:lod_cmd(cmd, bang, l1, l2, args, mods, names) + call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) + call s:dobufread(a:names) + execute printf('%s %s%s%s %s', a:mods, (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) + endfunction +else + function! s:lod_cmd(cmd, bang, l1, l2, args, names) + call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) + call s:dobufread(a:names) + execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) + endfunction +endif + +function! s:lod_map(map, names, with_prefix, prefix) + call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) + call s:dobufread(a:names) + let extra = '' + while 1 + let c = getchar(0) + if c == 0 + break + endif + let extra .= nr2char(c) + endwhile + + if a:with_prefix + let prefix = v:count ? v:count : '' + let prefix .= '"'.v:register.a:prefix + if mode(1) == 'no' + if v:operator == 'c' + let prefix = "\" . prefix + endif + let prefix .= v:operator + endif + call feedkeys(prefix, 'n') + endif + call feedkeys(substitute(a:map, '^', "\", '') . extra) +endfunction + +function! plug#(repo, ...) + if a:0 > 1 + return s:err('Invalid number of arguments (1..2)') + endif + + try + let repo = s:trim(a:repo) + let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec + let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??')) + let spec = extend(s:infer_properties(name, repo), opts) + if !has_key(g:plugs, name) + call add(g:plugs_order, name) + endif + let g:plugs[name] = spec + let s:loaded[name] = get(s:loaded, name, 0) + catch + return s:err(repo . ' ' . v:exception) + endtry +endfunction + +function! s:parse_options(arg) + let opts = copy(s:base_spec) + let type = type(a:arg) + let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)' + if type == s:TYPE.string + if empty(a:arg) + throw printf(opt_errfmt, 'tag', 'string') + endif + let opts.tag = a:arg + elseif type == s:TYPE.dict + for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as'] + if has_key(a:arg, opt) + \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt])) + throw printf(opt_errfmt, opt, 'string') + endif + endfor + for opt in ['on', 'for'] + if has_key(a:arg, opt) + \ && type(a:arg[opt]) != s:TYPE.list + \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt])) + throw printf(opt_errfmt, opt, 'string or list') + endif + endfor + if has_key(a:arg, 'do') + \ && type(a:arg.do) != s:TYPE.funcref + \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do)) + throw printf(opt_errfmt, 'do', 'string or funcref') + endif + call extend(opts, a:arg) + if has_key(opts, 'dir') + let opts.dir = s:dirpath(s:plug_expand(opts.dir)) + endif + else + throw 'Invalid argument type (expected: string or dictionary)' + endif + return opts +endfunction + +function! s:infer_properties(name, repo) + let repo = a:repo + if s:is_local_plug(repo) + return { 'dir': s:dirpath(s:plug_expand(repo)) } + else + if repo =~ ':' + let uri = repo + else + if repo !~ '/' + throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo) + endif + let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git') + let uri = printf(fmt, repo) + endif + return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri } + endif +endfunction + +function! s:install(force, names) + call s:update_impl(0, a:force, a:names) +endfunction + +function! s:update(force, names) + call s:update_impl(1, a:force, a:names) +endfunction + +function! plug#helptags() + if !exists('g:plugs') + return s:err('plug#begin was not called') + endif + for spec in values(g:plugs) + let docd = join([s:rtp(spec), 'doc'], '/') + if isdirectory(docd) + silent! execute 'helptags' s:esc(docd) + endif + endfor + return 1 +endfunction + +function! s:syntax() + syntax clear + syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber + syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX,plugAbort + syn match plugNumber /[0-9]\+[0-9.]*/ contained + syn match plugBracket /[[\]]/ contained + syn match plugX /x/ contained + syn match plugAbort /\~/ contained + syn match plugDash /^-\{1}\ / + syn match plugPlus /^+/ + syn match plugStar /^*/ + syn match plugMessage /\(^- \)\@<=.*/ + syn match plugName /\(^- \)\@<=[^ ]*:/ + syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/ + syn match plugTag /(tag: [^)]\+)/ + syn match plugInstall /\(^+ \)\@<=[^:]*/ + syn match plugUpdate /\(^* \)\@<=[^:]*/ + syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag + syn match plugEdge /^ \X\+$/ + syn match plugEdge /^ \X*/ contained nextgroup=plugSha + syn match plugSha /[0-9a-f]\{7,9}/ contained + syn match plugRelDate /([^)]*)$/ contained + syn match plugNotLoaded /(not loaded)$/ + syn match plugError /^x.*/ + syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/ + syn match plugH2 /^.*:\n-\+$/ + syn match plugH2 /^-\{2,}/ + syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean + hi def link plug1 Title + hi def link plug2 Repeat + hi def link plugH2 Type + hi def link plugX Exception + hi def link plugAbort Ignore + hi def link plugBracket Structure + hi def link plugNumber Number + + hi def link plugDash Special + hi def link plugPlus Constant + hi def link plugStar Boolean + + hi def link plugMessage Function + hi def link plugName Label + hi def link plugInstall Function + hi def link plugUpdate Type + + hi def link plugError Error + hi def link plugDeleted Ignore + hi def link plugRelDate Comment + hi def link plugEdge PreProc + hi def link plugSha Identifier + hi def link plugTag Constant + + hi def link plugNotLoaded Comment +endfunction + +function! s:lpad(str, len) + return a:str . repeat(' ', a:len - len(a:str)) +endfunction + +function! s:lines(msg) + return split(a:msg, "[\r\n]") +endfunction + +function! s:lastline(msg) + return get(s:lines(a:msg), -1, '') +endfunction + +function! s:new_window() + execute get(g:, 'plug_window', '-tabnew') +endfunction + +function! s:plug_window_exists() + let buflist = tabpagebuflist(s:plug_tab) + return !empty(buflist) && index(buflist, s:plug_buf) >= 0 +endfunction + +function! s:switch_in() + if !s:plug_window_exists() + return 0 + endif + + if winbufnr(0) != s:plug_buf + let s:pos = [tabpagenr(), winnr(), winsaveview()] + execute 'normal!' s:plug_tab.'gt' + let winnr = bufwinnr(s:plug_buf) + execute winnr.'wincmd w' + call add(s:pos, winsaveview()) + else + let s:pos = [winsaveview()] + endif + + setlocal modifiable + return 1 +endfunction + +function! s:switch_out(...) + call winrestview(s:pos[-1]) + setlocal nomodifiable + if a:0 > 0 + execute a:1 + endif + + if len(s:pos) > 1 + execute 'normal!' s:pos[0].'gt' + execute s:pos[1] 'wincmd w' + call winrestview(s:pos[2]) + endif +endfunction + +function! s:finish_bindings() + nnoremap R :call retry() + nnoremap D :PlugDiff + nnoremap S :PlugStatus + nnoremap U :call status_update() + xnoremap U :call status_update() + nnoremap ]] :silent! call section('') + nnoremap [[ :silent! call section('b') +endfunction + +function! s:prepare(...) + if empty(s:plug_getcwd()) + throw 'Invalid current working directory. Cannot proceed.' + endif + + for evar in ['$GIT_DIR', '$GIT_WORK_TREE'] + if exists(evar) + throw evar.' detected. Cannot proceed.' + endif + endfor + + call s:job_abort(0) + if s:switch_in() + if b:plug_preview == 1 + pc + endif + enew + else + call s:new_window() + endif + + nnoremap q :call close_pane() + if a:0 == 0 + call s:finish_bindings() + endif + let b:plug_preview = -1 + let s:plug_tab = tabpagenr() + let s:plug_buf = winbufnr(0) + call s:assign_name() + + for k in ['', 'L', 'o', 'X', 'd', 'dd'] + execute 'silent! unmap ' k + endfor + setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell + if exists('+colorcolumn') + setlocal colorcolumn= + endif + setf vim-plug + if exists('g:syntax_on') + call s:syntax() + endif +endfunction + +function! s:close_pane() + if b:plug_preview == 1 + pc + let b:plug_preview = -1 + elseif exists('s:jobs') && !empty(s:jobs) + call s:job_abort(1) + else + bd + endif +endfunction + +function! s:assign_name() + " Assign buffer name + let prefix = '[Plugins]' + let name = prefix + let idx = 2 + while bufexists(name) + let name = printf('%s (%s)', prefix, idx) + let idx = idx + 1 + endwhile + silent! execute 'f' fnameescape(name) +endfunction + +function! s:chsh(swap) + let prev = [&shell, &shellcmdflag, &shellredir] + if !s:is_win + set shell=sh + endif + if a:swap + if s:is_powershell(&shell) + let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s' + elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$' + set shellredir=>%s\ 2>&1 + endif + endif + return prev +endfunction + +function! s:bang(cmd, ...) + let batchfile = '' + try + let [sh, shellcmdflag, shrd] = s:chsh(a:0) + " FIXME: Escaping is incomplete. We could use shellescape with eval, + " but it won't work on Windows. + let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd + if s:is_win + let [batchfile, cmd] = s:batchfile(cmd) + endif + let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%') + execute "normal! :execute g:_plug_bang\\" + finally + unlet g:_plug_bang + let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] + if s:is_win && filereadable(batchfile) + call delete(batchfile) + endif + endtry + return v:shell_error ? 'Exit status: ' . v:shell_error : '' +endfunction + +function! s:regress_bar() + let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '') + call s:progress_bar(2, bar, len(bar)) +endfunction + +function! s:is_updated(dir) + return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir)) +endfunction + +function! s:do(pull, force, todo) + if has('nvim') + " Reset &rtp to invalidate Neovim cache of loaded Lua modules + " See https://github.com/junegunn/vim-plug/pull/1157#issuecomment-1809226110 + let &rtp = &rtp + endif + for [name, spec] in items(a:todo) + if !isdirectory(spec.dir) + continue + endif + let installed = has_key(s:update.new, name) + let updated = installed ? 0 : + \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir)) + if a:force || installed || updated + execute 'cd' s:esc(spec.dir) + call append(3, '- Post-update hook for '. name .' ... ') + let error = '' + let type = type(spec.do) + if type == s:TYPE.string + if spec.do[0] == ':' + if !get(s:loaded, name, 0) + let s:loaded[name] = 1 + call s:reorg_rtp() + endif + call s:load_plugin(spec) + try + execute spec.do[1:] + catch + let error = v:exception + endtry + if !s:plug_window_exists() + cd - + throw 'Warning: vim-plug was terminated by the post-update hook of '.name + endif + else + let error = s:bang(spec.do) + endif + elseif type == s:TYPE.funcref + try + call s:load_plugin(spec) + let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged') + call spec.do({ 'name': name, 'status': status, 'force': a:force }) + catch + let error = v:exception + endtry + else + let error = 'Invalid hook type' + endif + call s:switch_in() + call setline(4, empty(error) ? (getline(4) . 'OK') + \ : ('x' . getline(4)[1:] . error)) + if !empty(error) + call add(s:update.errors, name) + call s:regress_bar() + endif + cd - + endif + endfor +endfunction + +function! s:hash_match(a, b) + return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0 +endfunction + +function! s:disable_credential_helper() + return s:git_version_requirement(2) && get(g:, 'plug_disable_credential_helper', 1) +endfunction + +function! s:checkout(spec) + let sha = a:spec.commit + let output = s:git_revision(a:spec.dir) + let error = 0 + if !empty(output) && !s:hash_match(sha, s:lines(output)[0]) + let credential_helper = s:disable_credential_helper() ? '-c credential.helper= ' : '' + let output = s:system( + \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir) + let error = v:shell_error + endif + return [output, error] +endfunction + +function! s:finish(pull) + let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen')) + if new_frozen + let s = new_frozen > 1 ? 's' : '' + call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s)) + endif + call append(3, '- Finishing ... ') | 4 + redraw + call plug#helptags() + call plug#end() + call setline(4, getline(4) . 'Done!') + redraw + let msgs = [] + if !empty(s:update.errors) + call add(msgs, "Press 'R' to retry.") + endif + if a:pull && len(s:update.new) < len(filter(getline(5, '$'), + \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'")) + call add(msgs, "Press 'D' to see the updated changes.") + endif + echo join(msgs, ' ') + call s:finish_bindings() +endfunction + +function! s:retry() + if empty(s:update.errors) + return + endif + echo + call s:update_impl(s:update.pull, s:update.force, + \ extend(copy(s:update.errors), [s:update.threads])) +endfunction + +function! s:is_managed(name) + return has_key(g:plugs[a:name], 'uri') +endfunction + +function! s:names(...) + return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')) +endfunction + +function! s:check_ruby() + silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'") + if !exists('g:plug_ruby') + redraw! + return s:warn('echom', 'Warning: Ruby interface is broken') + endif + let ruby_version = split(g:plug_ruby, '\.') + unlet g:plug_ruby + return s:version_requirement(ruby_version, [1, 8, 7]) +endfunction + +function! s:update_impl(pull, force, args) abort + let sync = index(a:args, '--sync') >= 0 || has('vim_starting') + let args = filter(copy(a:args), 'v:val != "--sync"') + let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ? + \ remove(args, -1) : get(g:, 'plug_threads', 16) + + let managed = filter(deepcopy(g:plugs), 's:is_managed(v:key)') + let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') : + \ filter(managed, 'index(args, v:key) >= 0') + + if empty(todo) + return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install')) + endif + + if !s:is_win && s:git_version_requirement(2, 3) + let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : '' + let $GIT_TERMINAL_PROMPT = 0 + for plug in values(todo) + let plug.uri = substitute(plug.uri, + \ '^https://git::@github\.com', 'https://github.com', '') + endfor + endif + + if !isdirectory(g:plug_home) + try + call mkdir(g:plug_home, 'p') + catch + return s:err(printf('Invalid plug directory: %s. '. + \ 'Try to call plug#begin with a valid directory', g:plug_home)) + endtry + endif + + if has('nvim') && !exists('*jobwait') && threads > 1 + call s:warn('echom', '[vim-plug] Update Neovim for parallel installer') + endif + + let use_job = s:nvim || s:vim8 + let python = (has('python') || has('python3')) && !use_job + let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby() + + let s:update = { + \ 'start': reltime(), + \ 'all': todo, + \ 'todo': copy(todo), + \ 'errors': [], + \ 'pull': a:pull, + \ 'force': a:force, + \ 'new': {}, + \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1, + \ 'bar': '', + \ 'fin': 0 + \ } + + call s:prepare(1) + call append(0, ['', '']) + normal! 2G + silent! redraw + + " Set remote name, overriding a possible user git config's clone.defaultRemoteName + let s:clone_opt = ['--origin', 'origin'] + if get(g:, 'plug_shallow', 1) + call extend(s:clone_opt, ['--depth', '1']) + if s:git_version_requirement(1, 7, 10) + call add(s:clone_opt, '--no-single-branch') + endif + endif + + if has('win32unix') || has('wsl') + call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input']) + endif + + let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : '' + + " Python version requirement (>= 2.7) + if python && !has('python3') && !ruby && !use_job && s:update.threads > 1 + redir => pyv + silent python import platform; print platform.python_version() + redir END + let python = s:version_requirement( + \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) + endif + + if (python || ruby) && s:update.threads > 1 + try + let imd = &imd + if s:mac_gui + set noimd + endif + if ruby + call s:update_ruby() + else + call s:update_python() + endif + catch + let lines = getline(4, '$') + let printed = {} + silent! 4,$d _ + for line in lines + let name = s:extract_name(line, '.', '') + if empty(name) || !has_key(printed, name) + call append('$', line) + if !empty(name) + let printed[name] = 1 + if line[0] == 'x' && index(s:update.errors, name) < 0 + call add(s:update.errors, name) + end + endif + endif + endfor + finally + let &imd = imd + call s:update_finish() + endtry + else + call s:update_vim() + while use_job && sync + sleep 100m + if s:update.fin + break + endif + endwhile + endif +endfunction + +function! s:log4(name, msg) + call setline(4, printf('- %s (%s)', a:msg, a:name)) + redraw +endfunction + +function! s:update_finish() + if exists('s:git_terminal_prompt') + let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt + endif + if s:switch_in() + call append(3, '- Updating ...') | 4 + for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))')) + let [pos, _] = s:logpos(name) + if !pos + continue + endif + let out = '' + let error = 0 + if has_key(spec, 'commit') + call s:log4(name, 'Checking out '.spec.commit) + let [out, error] = s:checkout(spec) + elseif has_key(spec, 'tag') + let tag = spec.tag + if tag =~ '\*' + let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir)) + if !v:shell_error && !empty(tags) + let tag = tags[0] + call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) + call append(3, '') + endif + endif + call s:log4(name, 'Checking out '.tag) + let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir) + let error = v:shell_error + endif + if !error && filereadable(spec.dir.'/.gitmodules') && + \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir)) + call s:log4(name, 'Updating submodules. This may take a while.') + let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir) + let error = v:shell_error + endif + let msg = s:format_message(v:shell_error ? 'x': '-', name, out) + if error + call add(s:update.errors, name) + call s:regress_bar() + silent execute pos 'd _' + call append(4, msg) | 4 + elseif !empty(out) + call setline(pos, msg[0]) + endif + redraw + endfor + silent 4 d _ + try + call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")')) + catch + call s:warn('echom', v:exception) + call s:warn('echo', '') + return + endtry + call s:finish(s:update.pull) + call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.') + call s:switch_out('normal! gg') + endif +endfunction + +function! s:mark_aborted(name, message) + let attrs = { 'running': 0, 'error': 1, 'abort': 1, 'lines': [a:message] } + let s:jobs[a:name] = extend(get(s:jobs, a:name, {}), attrs) +endfunction + +function! s:job_abort(cancel) + if (!s:nvim && !s:vim8) || !exists('s:jobs') + return + endif + + for [name, j] in items(s:jobs) + if s:nvim + silent! call jobstop(j.jobid) + elseif s:vim8 + silent! call job_stop(j.jobid) + endif + if j.new + call s:rm_rf(g:plugs[name].dir) + endif + if a:cancel + call s:mark_aborted(name, 'Aborted') + endif + endfor + + if a:cancel + for todo in values(s:update.todo) + let todo.abort = 1 + endfor + else + let s:jobs = {} + endif +endfunction + +function! s:last_non_empty_line(lines) + let len = len(a:lines) + for idx in range(len) + let line = a:lines[len-idx-1] + if !empty(line) + return line + endif + endfor + return '' +endfunction + +function! s:bullet_for(job, ...) + if a:job.running + return a:job.new ? '+' : '*' + endif + if get(a:job, 'abort', 0) + return '~' + endif + return a:job.error ? 'x' : get(a:000, 0, '-') +endfunction + +function! s:job_out_cb(self, data) abort + let self = a:self + let data = remove(self.lines, -1) . a:data + let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]') + call extend(self.lines, lines) + " To reduce the number of buffer updates + let self.tick = get(self, 'tick', -1) + 1 + if !self.running || self.tick % len(s:jobs) == 0 + let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines) + if len(result) + call s:log(s:bullet_for(self), self.name, result) + endif + endif +endfunction + +function! s:job_exit_cb(self, data) abort + let a:self.running = 0 + let a:self.error = a:data != 0 + call s:reap(a:self.name) + call s:tick() +endfunction + +function! s:job_cb(fn, job, ch, data) + if !s:plug_window_exists() " plug window closed + return s:job_abort(0) + endif + call call(a:fn, [a:job, a:data]) +endfunction + +function! s:nvim_cb(job_id, data, event) dict abort + return (a:event == 'stdout' || a:event == 'stderr') ? + \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) : + \ s:job_cb('s:job_exit_cb', self, 0, a:data) +endfunction + +function! s:spawn(name, spec, queue, opts) + let job = { 'name': a:name, 'spec': a:spec, 'running': 1, 'error': 0, 'lines': [''], + \ 'new': get(a:opts, 'new', 0), 'queue': copy(a:queue) } + let Item = remove(job.queue, 0) + let argv = type(Item) == s:TYPE.funcref ? call(Item, [a:spec]) : Item + let s:jobs[a:name] = job + + if s:nvim + if has_key(a:opts, 'dir') + let job.cwd = a:opts.dir + endif + call extend(job, { + \ 'on_stdout': function('s:nvim_cb'), + \ 'on_stderr': function('s:nvim_cb'), + \ 'on_exit': function('s:nvim_cb'), + \ }) + let jid = s:plug_call('jobstart', argv, job) + if jid > 0 + let job.jobid = jid + else + let job.running = 0 + let job.error = 1 + let job.lines = [jid < 0 ? argv[0].' is not executable' : + \ 'Invalid arguments (or job table is full)'] + endif + elseif s:vim8 + let cmd = join(map(copy(argv), 'plug#shellescape(v:val, {"script": 0})')) + if has_key(a:opts, 'dir') + let cmd = s:with_cd(cmd, a:opts.dir, 0) + endif + let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd] + let jid = job_start(s:is_win ? join(argv, ' ') : argv, { + \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]), + \ 'err_cb': function('s:job_cb', ['s:job_out_cb', job]), + \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]), + \ 'err_mode': 'raw', + \ 'out_mode': 'raw' + \}) + if job_status(jid) == 'run' + let job.jobid = jid + else + let job.running = 0 + let job.error = 1 + let job.lines = ['Failed to start job'] + endif + else + let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [argv, a:opts.dir] : [argv])) + let job.error = v:shell_error != 0 + let job.running = 0 + endif +endfunction + +function! s:reap(name) + let job = remove(s:jobs, a:name) + if job.error + call add(s:update.errors, a:name) + elseif get(job, 'new', 0) + let s:update.new[a:name] = 1 + endif + + let more = len(get(job, 'queue', [])) + let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) + if len(result) + call s:log(s:bullet_for(job), a:name, result) + endif + + if !job.error && more + let job.spec.queue = job.queue + let s:update.todo[a:name] = job.spec + else + let s:update.bar .= s:bullet_for(job, '=') + call s:bar() + endif +endfunction + +function! s:bar() + if s:switch_in() + let total = len(s:update.all) + call setline(1, (s:update.pull ? 'Updating' : 'Installing'). + \ ' plugins ('.len(s:update.bar).'/'.total.')') + call s:progress_bar(2, s:update.bar, total) + call s:switch_out() + endif +endfunction + +function! s:logpos(name) + let max = line('$') + for i in range(4, max > 4 ? max : 4) + if getline(i) =~# '^[-+x*] '.a:name.':' + for j in range(i + 1, max > 5 ? max : 5) + if getline(j) !~ '^ ' + return [i, j - 1] + endif + endfor + return [i, i] + endif + endfor + return [0, 0] +endfunction + +function! s:log(bullet, name, lines) + if s:switch_in() + let [b, e] = s:logpos(a:name) + if b > 0 + silent execute printf('%d,%d d _', b, e) + if b > winheight('.') + let b = 4 + endif + else + let b = 4 + endif + " FIXME For some reason, nomodifiable is set after :d in vim8 + setlocal modifiable + call append(b - 1, s:format_message(a:bullet, a:name, a:lines)) + call s:switch_out() + endif +endfunction + +function! s:update_vim() + let s:jobs = {} + + call s:bar() + call s:tick() +endfunction + +function! s:checkout_command(spec) + let a:spec.branch = s:git_origin_branch(a:spec) + return ['git', 'checkout', '-q', a:spec.branch, '--'] +endfunction + +function! s:merge_command(spec) + let a:spec.branch = s:git_origin_branch(a:spec) + return ['git', 'merge', '--ff-only', 'origin/'.a:spec.branch] +endfunction + +function! s:tick() + let pull = s:update.pull + let prog = s:progress_opt(s:nvim || s:vim8) +while 1 " Without TCO, Vim stack is bound to explode + if empty(s:update.todo) + if empty(s:jobs) && !s:update.fin + call s:update_finish() + let s:update.fin = 1 + endif + return + endif + + let name = keys(s:update.todo)[0] + let spec = remove(s:update.todo, name) + if get(spec, 'abort', 0) + call s:mark_aborted(name, 'Skipped') + call s:reap(name) + continue + endif + + let queue = get(spec, 'queue', []) + let new = empty(globpath(spec.dir, '.git', 1)) + + if empty(queue) + call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...') + redraw + endif + + let has_tag = has_key(spec, 'tag') + if len(queue) + call s:spawn(name, spec, queue, { 'dir': spec.dir }) + elseif !new + let [error, _] = s:git_validate(spec, 0) + if empty(error) + if pull + let cmd = s:disable_credential_helper() ? ['git', '-c', 'credential.helper=', 'fetch'] : ['git', 'fetch'] + if has_tag && !empty(globpath(spec.dir, '.git/shallow')) + call extend(cmd, ['--depth', '99999999']) + endif + if !empty(prog) + call add(cmd, prog) + endif + let queue = [cmd, split('git remote set-head origin -a')] + if !has_tag && !has_key(spec, 'commit') + call extend(queue, [function('s:checkout_command'), function('s:merge_command')]) + endif + call s:spawn(name, spec, queue, { 'dir': spec.dir }) + else + let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 } + endif + else + let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 } + endif + else + let cmd = ['git', 'clone'] + if !has_tag + call extend(cmd, s:clone_opt) + endif + if !empty(prog) + call add(cmd, prog) + endif + call s:spawn(name, spec, [extend(cmd, [spec.uri, s:trim(spec.dir)]), function('s:checkout_command'), function('s:merge_command')], { 'new': 1 }) + endif + + if !s:jobs[name].running + call s:reap(name) + endif + if len(s:jobs) >= s:update.threads + break + endif +endwhile +endfunction + +function! s:update_python() +let py_exe = has('python') ? 'python' : 'python3' +execute py_exe "<< EOF" +import datetime +import functools +import os +try: + import queue +except ImportError: + import Queue as queue +import random +import re +import shutil +import signal +import subprocess +import tempfile +import threading as thr +import time +import traceback +import vim + +G_NVIM = vim.eval("has('nvim')") == '1' +G_PULL = vim.eval('s:update.pull') == '1' +G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1 +G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)')) +G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt')) +G_PROGRESS = vim.eval('s:progress_opt(1)') +G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads')) +G_STOP = thr.Event() +G_IS_WIN = vim.eval('s:is_win') == '1' + +class PlugError(Exception): + def __init__(self, msg): + self.msg = msg +class CmdTimedOut(PlugError): + pass +class CmdFailed(PlugError): + pass +class InvalidURI(PlugError): + pass +class Action(object): + INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-'] + +class Buffer(object): + def __init__(self, lock, num_plugs, is_pull): + self.bar = '' + self.event = 'Updating' if is_pull else 'Installing' + self.lock = lock + self.maxy = int(vim.eval('winheight(".")')) + self.num_plugs = num_plugs + + def __where(self, name): + """ Find first line with name in current buffer. Return line num. """ + found, lnum = False, 0 + matcher = re.compile('^[-+x*] {0}:'.format(name)) + for line in vim.current.buffer: + if matcher.search(line) is not None: + found = True + break + lnum += 1 + + if not found: + lnum = -1 + return lnum + + def header(self): + curbuf = vim.current.buffer + curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs) + + num_spaces = self.num_plugs - len(self.bar) + curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ') + + with self.lock: + vim.command('normal! 2G') + vim.command('redraw') + + def write(self, action, name, lines): + first, rest = lines[0], lines[1:] + msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)] + msg.extend([' ' + line for line in rest]) + + try: + if action == Action.ERROR: + self.bar += 'x' + vim.command("call add(s:update.errors, '{0}')".format(name)) + elif action == Action.DONE: + self.bar += '=' + + curbuf = vim.current.buffer + lnum = self.__where(name) + if lnum != -1: # Found matching line num + del curbuf[lnum] + if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]): + lnum = 3 + else: + lnum = 3 + curbuf.append(msg, lnum) + + self.header() + except vim.error: + pass + +class Command(object): + CD = 'cd /d' if G_IS_WIN else 'cd' + + def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None): + self.cmd = cmd + if cmd_dir: + self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd) + self.timeout = timeout + self.callback = cb if cb else (lambda msg: None) + self.clean = clean if clean else (lambda: None) + self.proc = None + + @property + def alive(self): + """ Returns true only if command still running. """ + return self.proc and self.proc.poll() is None + + def execute(self, ntries=3): + """ Execute the command with ntries if CmdTimedOut. + Returns the output of the command if no Exception. + """ + attempt, finished, limit = 0, False, self.timeout + + while not finished: + try: + attempt += 1 + result = self.try_command() + finished = True + return result + except CmdTimedOut: + if attempt != ntries: + self.notify_retry() + self.timeout += limit + else: + raise + + def notify_retry(self): + """ Retry required for command, notify user. """ + for count in range(3, 0, -1): + if G_STOP.is_set(): + raise KeyboardInterrupt + msg = 'Timeout. Will retry in {0} second{1} ...'.format( + count, 's' if count != 1 else '') + self.callback([msg]) + time.sleep(1) + self.callback(['Retrying ...']) + + def try_command(self): + """ Execute a cmd & poll for callback. Returns list of output. + Raises CmdFailed -> return code for Popen isn't 0 + Raises CmdTimedOut -> command exceeded timeout without new output + """ + first_line = True + + try: + tfile = tempfile.NamedTemporaryFile(mode='w+b') + preexec_fn = not G_IS_WIN and os.setsid or None + self.proc = subprocess.Popen(self.cmd, stdout=tfile, + stderr=subprocess.STDOUT, + stdin=subprocess.PIPE, shell=True, + preexec_fn=preexec_fn) + thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,)) + thrd.start() + + thread_not_started = True + while thread_not_started: + try: + thrd.join(0.1) + thread_not_started = False + except RuntimeError: + pass + + while self.alive: + if G_STOP.is_set(): + raise KeyboardInterrupt + + if first_line or random.random() < G_LOG_PROB: + first_line = False + line = '' if G_IS_WIN else nonblock_read(tfile.name) + if line: + self.callback([line]) + + time_diff = time.time() - os.path.getmtime(tfile.name) + if time_diff > self.timeout: + raise CmdTimedOut(['Timeout!']) + + thrd.join(0.5) + + tfile.seek(0) + result = [line.decode('utf-8', 'replace').rstrip() for line in tfile] + + if self.proc.returncode != 0: + raise CmdFailed([''] + result) + + return result + except: + self.terminate() + raise + + def terminate(self): + """ Terminate process and cleanup. """ + if self.alive: + if G_IS_WIN: + os.kill(self.proc.pid, signal.SIGINT) + else: + os.killpg(self.proc.pid, signal.SIGTERM) + self.clean() + +class Plugin(object): + def __init__(self, name, args, buf_q, lock): + self.name = name + self.args = args + self.buf_q = buf_q + self.lock = lock + self.tag = args.get('tag', 0) + + def manage(self): + try: + if os.path.exists(self.args['dir']): + self.update() + else: + self.install() + with self.lock: + thread_vim_command("let s:update.new['{0}'] = 1".format(self.name)) + except PlugError as exc: + self.write(Action.ERROR, self.name, exc.msg) + except KeyboardInterrupt: + G_STOP.set() + self.write(Action.ERROR, self.name, ['Interrupted!']) + except: + # Any exception except those above print stack trace + msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip()) + self.write(Action.ERROR, self.name, msg.split('\n')) + raise + + def install(self): + target = self.args['dir'] + if target[-1] == '\\': + target = target[0:-1] + + def clean(target): + def _clean(): + try: + shutil.rmtree(target) + except OSError: + pass + return _clean + + self.write(Action.INSTALL, self.name, ['Installing ...']) + callback = functools.partial(self.write, Action.INSTALL, self.name) + cmd = 'git clone {0} {1} {2} {3} 2>&1'.format( + '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'], + esc(target)) + com = Command(cmd, None, G_TIMEOUT, callback, clean(target)) + result = com.execute(G_RETRIES) + self.write(Action.DONE, self.name, result[-1:]) + + def repo_uri(self): + cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url' + command = Command(cmd, self.args['dir'], G_TIMEOUT,) + result = command.execute(G_RETRIES) + return result[-1] + + def update(self): + actual_uri = self.repo_uri() + expect_uri = self.args['uri'] + regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$') + ma = regex.match(actual_uri) + mb = regex.match(expect_uri) + if ma is None or mb is None or ma.groups() != mb.groups(): + msg = ['', + 'Invalid URI: {0}'.format(actual_uri), + 'Expected {0}'.format(expect_uri), + 'PlugClean required.'] + raise InvalidURI(msg) + + if G_PULL: + self.write(Action.UPDATE, self.name, ['Updating ...']) + callback = functools.partial(self.write, Action.UPDATE, self.name) + fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else '' + cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS) + com = Command(cmd, self.args['dir'], G_TIMEOUT, callback) + result = com.execute(G_RETRIES) + self.write(Action.DONE, self.name, result[-1:]) + else: + self.write(Action.DONE, self.name, ['Already installed']) + + def write(self, action, name, msg): + self.buf_q.put((action, name, msg)) + +class PlugThread(thr.Thread): + def __init__(self, tname, args): + super(PlugThread, self).__init__() + self.tname = tname + self.args = args + + def run(self): + thr.current_thread().name = self.tname + buf_q, work_q, lock = self.args + + try: + while not G_STOP.is_set(): + name, args = work_q.get_nowait() + plug = Plugin(name, args, buf_q, lock) + plug.manage() + work_q.task_done() + except queue.Empty: + pass + +class RefreshThread(thr.Thread): + def __init__(self, lock): + super(RefreshThread, self).__init__() + self.lock = lock + self.running = True + + def run(self): + while self.running: + with self.lock: + thread_vim_command('noautocmd normal! a') + time.sleep(0.33) + + def stop(self): + self.running = False + +if G_NVIM: + def thread_vim_command(cmd): + vim.session.threadsafe_call(lambda: vim.command(cmd)) +else: + def thread_vim_command(cmd): + vim.command(cmd) + +def esc(name): + return '"' + name.replace('"', '\"') + '"' + +def nonblock_read(fname): + """ Read a file with nonblock flag. Return the last line. """ + fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK) + buf = os.read(fread, 100000).decode('utf-8', 'replace') + os.close(fread) + + line = buf.rstrip('\r\n') + left = max(line.rfind('\r'), line.rfind('\n')) + if left != -1: + left += 1 + line = line[left:] + + return line + +def main(): + thr.current_thread().name = 'main' + nthreads = int(vim.eval('s:update.threads')) + plugs = vim.eval('s:update.todo') + mac_gui = vim.eval('s:mac_gui') == '1' + + lock = thr.Lock() + buf = Buffer(lock, len(plugs), G_PULL) + buf_q, work_q = queue.Queue(), queue.Queue() + for work in plugs.items(): + work_q.put(work) + + start_cnt = thr.active_count() + for num in range(nthreads): + tname = 'PlugT-{0:02}'.format(num) + thread = PlugThread(tname, (buf_q, work_q, lock)) + thread.start() + if mac_gui: + rthread = RefreshThread(lock) + rthread.start() + + while not buf_q.empty() or thr.active_count() != start_cnt: + try: + action, name, msg = buf_q.get(True, 0.25) + buf.write(action, name, ['OK'] if not msg else msg) + buf_q.task_done() + except queue.Empty: + pass + except KeyboardInterrupt: + G_STOP.set() + + if mac_gui: + rthread.stop() + rthread.join() + +main() +EOF +endfunction + +function! s:update_ruby() + ruby << EOF + module PlugStream + SEP = ["\r", "\n", nil] + def get_line + buffer = '' + loop do + char = readchar rescue return + if SEP.include? char.chr + buffer << $/ + break + else + buffer << char + end + end + buffer + end + end unless defined?(PlugStream) + + def esc arg + %["#{arg.gsub('"', '\"')}"] + end + + def killall pid + pids = [pid] + if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM + pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil } + else + unless `which pgrep 2> /dev/null`.empty? + children = pids + until children.empty? + children = children.map { |pid| + `pgrep -P #{pid}`.lines.map { |l| l.chomp } + }.flatten + pids += children + end + end + pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil } + end + end + + def compare_git_uri a, b + regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$} + regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1) + end + + require 'thread' + require 'fileutils' + require 'timeout' + running = true + iswin = VIM::evaluate('s:is_win').to_i == 1 + pull = VIM::evaluate('s:update.pull').to_i == 1 + base = VIM::evaluate('g:plug_home') + all = VIM::evaluate('s:update.todo') + limit = VIM::evaluate('get(g:, "plug_timeout", 60)') + tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1 + nthr = VIM::evaluate('s:update.threads').to_i + maxy = VIM::evaluate('winheight(".")').to_i + vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/ + cd = iswin ? 'cd /d' : 'cd' + tot = VIM::evaluate('len(s:update.todo)') || 0 + bar = '' + skip = 'Already installed' + mtx = Mutex.new + take1 = proc { mtx.synchronize { running && all.shift } } + logh = proc { + cnt = bar.length + $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})" + $curbuf[2] = '[' + bar.ljust(tot) + ']' + VIM::command('normal! 2G') + VIM::command('redraw') + } + where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } } + log = proc { |name, result, type| + mtx.synchronize do + ing = ![true, false].include?(type) + bar += type ? '=' : 'x' unless ing + b = case type + when :install then '+' when :update then '*' + when true, nil then '-' else + VIM::command("call add(s:update.errors, '#{name}')") + 'x' + end + result = + if type || type.nil? + ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"] + elsif result =~ /^Interrupted|^Timeout/ + ["#{b} #{name}: #{result}"] + else + ["#{b} #{name}"] + result.lines.map { |l| " " << l } + end + if lnum = where.call(name) + $curbuf.delete lnum + lnum = 4 if ing && lnum > maxy + end + result.each_with_index do |line, offset| + $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp) + end + logh.call + end + } + bt = proc { |cmd, name, type, cleanup| + tried = timeout = 0 + begin + tried += 1 + timeout += limit + fd = nil + data = '' + if iswin + Timeout::timeout(timeout) do + tmp = VIM::evaluate('tempname()') + system("(#{cmd}) > #{tmp}") + data = File.read(tmp).chomp + File.unlink tmp rescue nil + end + else + fd = IO.popen(cmd).extend(PlugStream) + first_line = true + log_prob = 1.0 / nthr + while line = Timeout::timeout(timeout) { fd.get_line } + data << line + log.call name, line.chomp, type if name && (first_line || rand < log_prob) + first_line = false + end + fd.close + end + [$? == 0, data.chomp] + rescue Timeout::Error, Interrupt => e + if fd && !fd.closed? + killall fd.pid + fd.close + end + cleanup.call if cleanup + if e.is_a?(Timeout::Error) && tried < tries + 3.downto(1) do |countdown| + s = countdown > 1 ? 's' : '' + log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type + sleep 1 + end + log.call name, 'Retrying ...', type + retry + end + [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"] + end + } + main = Thread.current + threads = [] + watcher = Thread.new { + if vim7 + while VIM::evaluate('getchar(1)') + sleep 0.1 + end + else + require 'io/console' # >= Ruby 1.9 + nil until IO.console.getch == 3.chr + end + mtx.synchronize do + running = false + threads.each { |t| t.raise Interrupt } unless vim7 + end + threads.each { |t| t.join rescue nil } + main.kill + } + refresh = Thread.new { + while true + mtx.synchronize do + break unless running + VIM::command('noautocmd normal! a') + end + sleep 0.2 + end + } if VIM::evaluate('s:mac_gui') == 1 + + clone_opt = VIM::evaluate('s:clone_opt').join(' ') + progress = VIM::evaluate('s:progress_opt(1)') + nthr.times do + mtx.synchronize do + threads << Thread.new { + while pair = take1.call + name = pair.first + dir, uri, tag = pair.last.values_at *%w[dir uri tag] + exists = File.directory? dir + ok, result = + if exists + chdir = "#{cd} #{iswin ? dir : esc(dir)}" + ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil + current_uri = data.lines.to_a.last + if !ret + if data =~ /^Interrupted|^Timeout/ + [false, data] + else + [false, [data.chomp, "PlugClean required."].join($/)] + end + elsif !compare_git_uri(current_uri, uri) + [false, ["Invalid URI: #{current_uri}", + "Expected: #{uri}", + "PlugClean required."].join($/)] + else + if pull + log.call name, 'Updating ...', :update + fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : '' + bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil + else + [true, skip] + end + end + else + d = esc dir.sub(%r{[\\/]+$}, '') + log.call name, 'Installing ...', :install + bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc { + FileUtils.rm_rf dir + } + end + mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok + log.call name, result, ok + end + } if running + end + end + threads.each { |t| t.join rescue nil } + logh.call + refresh.kill if refresh + watcher.kill +EOF +endfunction + +function! s:shellesc_cmd(arg, script) + let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g') + return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g') +endfunction + +function! s:shellesc_ps1(arg) + return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'" +endfunction + +function! s:shellesc_sh(arg) + return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'" +endfunction + +" Escape the shell argument based on the shell. +" Vim and Neovim's shellescape() are insufficient. +" 1. shellslash determines whether to use single/double quotes. +" Double-quote escaping is fragile for cmd.exe. +" 2. It does not work for powershell. +" 3. It does not work for *sh shells if the command is executed +" via cmd.exe (ie. cmd.exe /c sh -c command command_args) +" 4. It does not support batchfile syntax. +" +" Accepts an optional dictionary with the following keys: +" - shell: same as Vim/Neovim 'shell' option. +" If unset, fallback to 'cmd.exe' on Windows or 'sh'. +" - script: If truthy and shell is cmd.exe, escape for batchfile syntax. +function! plug#shellescape(arg, ...) + if a:arg =~# '^[A-Za-z0-9_/:.-]\+$' + return a:arg + endif + let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {} + let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh') + let script = get(opts, 'script', 1) + if shell =~# 'cmd\(\.exe\)\?$' + return s:shellesc_cmd(a:arg, script) + elseif s:is_powershell(shell) + return s:shellesc_ps1(a:arg) + endif + return s:shellesc_sh(a:arg) +endfunction + +function! s:glob_dir(path) + return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)') +endfunction + +function! s:progress_bar(line, bar, total) + call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']') +endfunction + +function! s:compare_git_uri(a, b) + " See `git help clone' + " https:// [user@] github.com[:port] / junegunn/vim-plug [.git] + " [git@] github.com[:port] : junegunn/vim-plug [.git] + " file:// / junegunn/vim-plug [/] + " / junegunn/vim-plug [/] + let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$' + let ma = matchlist(a:a, pat) + let mb = matchlist(a:b, pat) + return ma[1:2] ==# mb[1:2] +endfunction + +function! s:format_message(bullet, name, message) + if a:bullet != 'x' + return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))] + else + let lines = map(s:lines(a:message), '" ".v:val') + return extend([printf('x %s:', a:name)], lines) + endif +endfunction + +function! s:with_cd(cmd, dir, ...) + let script = a:0 > 0 ? a:1 : 1 + let pwsh = s:is_powershell(&shell) + let cd = s:is_win && !pwsh ? 'cd /d' : 'cd' + let sep = pwsh ? ';' : '&&' + return printf('%s %s %s %s', cd, plug#shellescape(a:dir, {'script': script, 'shell': &shell}), sep, a:cmd) +endfunction + +function! s:system(cmd, ...) + let batchfile = '' + try + let [sh, shellcmdflag, shrd] = s:chsh(1) + if type(a:cmd) == s:TYPE.list + " Neovim's system() supports list argument to bypass the shell + " but it cannot set the working directory for the command. + " Assume that the command does not rely on the shell. + if has('nvim') && a:0 == 0 + return system(a:cmd) + endif + let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})')) + if s:is_powershell(&shell) + let cmd = '& ' . cmd + endif + else + let cmd = a:cmd + endif + if a:0 > 0 + let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list) + endif + if s:is_win && type(a:cmd) != s:TYPE.list + let [batchfile, cmd] = s:batchfile(cmd) + endif + return system(cmd) + finally + let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] + if s:is_win && filereadable(batchfile) + call delete(batchfile) + endif + endtry +endfunction + +function! s:system_chomp(...) + let ret = call('s:system', a:000) + return v:shell_error ? '' : substitute(ret, '\n$', '', '') +endfunction + +function! s:git_validate(spec, check_branch) + let err = '' + if isdirectory(a:spec.dir) + let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)] + let remote = result[-1] + if empty(remote) + let err = join([remote, 'PlugClean required.'], "\n") + elseif !s:compare_git_uri(remote, a:spec.uri) + let err = join(['Invalid URI: '.remote, + \ 'Expected: '.a:spec.uri, + \ 'PlugClean required.'], "\n") + elseif a:check_branch && has_key(a:spec, 'commit') + let sha = s:git_revision(a:spec.dir) + if empty(sha) + let err = join(add(result, 'PlugClean required.'), "\n") + elseif !s:hash_match(sha, a:spec.commit) + let err = join([printf('Invalid HEAD (expected: %s, actual: %s)', + \ a:spec.commit[:6], sha[:6]), + \ 'PlugUpdate required.'], "\n") + endif + elseif a:check_branch + let current_branch = result[0] + " Check tag + let origin_branch = s:git_origin_branch(a:spec) + if has_key(a:spec, 'tag') + let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) + if a:spec.tag !=# tag && a:spec.tag !~ '\*' + let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.', + \ (empty(tag) ? 'N/A' : tag), a:spec.tag) + endif + " Check branch + elseif origin_branch !=# current_branch + let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.', + \ current_branch, origin_branch) + endif + if empty(err) + let ahead_behind = split(s:lastline(s:system([ + \ 'git', 'rev-list', '--count', '--left-right', + \ printf('HEAD...origin/%s', origin_branch) + \ ], a:spec.dir)), '\t') + if v:shell_error || len(ahead_behind) != 2 + let err = "Failed to compare with the origin. The default branch might have changed.\nPlugClean required." + else + let [ahead, behind] = ahead_behind + if ahead && behind + " Only mention PlugClean if diverged, otherwise it's likely to be + " pushable (and probably not that messed up). + let err = printf( + \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n" + \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind) + elseif ahead + let err = printf("Ahead of origin/%s by %d commit(s).\n" + \ .'Cannot update until local changes are pushed.', + \ origin_branch, ahead) + endif + endif + endif + endif + else + let err = 'Not found' + endif + return [err, err =~# 'PlugClean'] +endfunction + +function! s:rm_rf(dir) + if isdirectory(a:dir) + return s:system(s:is_win + \ ? 'rmdir /S /Q '.plug#shellescape(a:dir) + \ : ['rm', '-rf', a:dir]) + endif +endfunction + +function! s:clean(force) + call s:prepare() + call append(0, 'Searching for invalid plugins in '.g:plug_home) + call append(1, '') + + " List of valid directories + let dirs = [] + let errs = {} + let [cnt, total] = [0, len(g:plugs)] + for [name, spec] in items(g:plugs) + if !s:is_managed(name) || get(spec, 'frozen', 0) + call add(dirs, spec.dir) + else + let [err, clean] = s:git_validate(spec, 1) + if clean + let errs[spec.dir] = s:lines(err)[0] + else + call add(dirs, spec.dir) + endif + endif + let cnt += 1 + call s:progress_bar(2, repeat('=', cnt), total) + normal! 2G + redraw + endfor + + let allowed = {} + for dir in dirs + let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1 + let allowed[dir] = 1 + for child in s:glob_dir(dir) + let allowed[child] = 1 + endfor + endfor + + let todo = [] + let found = sort(s:glob_dir(g:plug_home)) + while !empty(found) + let f = remove(found, 0) + if !has_key(allowed, f) && isdirectory(f) + call add(todo, f) + call append(line('$'), '- ' . f) + if has_key(errs, f) + call append(line('$'), ' ' . errs[f]) + endif + let found = filter(found, 'stridx(v:val, f) != 0') + end + endwhile + + 4 + redraw + if empty(todo) + call append(line('$'), 'Already clean.') + else + let s:clean_count = 0 + call append(3, ['Directories to delete:', '']) + redraw! + if a:force || s:ask_no_interrupt('Delete all directories?') + call s:delete([6, line('$')], 1) + else + call setline(4, 'Cancelled.') + nnoremap d :set opfunc=delete_opg@ + nmap dd d_ + xnoremap d :call delete_op(visualmode(), 1) + echo 'Delete the lines (d{motion}) to delete the corresponding directories' + endif + endif + 4 + setlocal nomodifiable +endfunction + +function! s:delete_op(type, ...) + call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0) +endfunction + +function! s:delete(range, force) + let [l1, l2] = a:range + let force = a:force + let err_count = 0 + while l1 <= l2 + let line = getline(l1) + if line =~ '^- ' && isdirectory(line[2:]) + execute l1 + redraw! + let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1) + let force = force || answer > 1 + if answer + let err = s:rm_rf(line[2:]) + setlocal modifiable + if empty(err) + call setline(l1, '~'.line[1:]) + let s:clean_count += 1 + else + delete _ + call append(l1 - 1, s:format_message('x', line[1:], err)) + let l2 += len(s:lines(err)) + let err_count += 1 + endif + let msg = printf('Removed %d directories.', s:clean_count) + if err_count > 0 + let msg .= printf(' Failed to remove %d directories.', err_count) + endif + call setline(4, msg) + setlocal nomodifiable + endif + endif + let l1 += 1 + endwhile +endfunction + +function! s:upgrade() + echo 'Downloading the latest version of vim-plug' + redraw + let tmp = s:plug_tempname() + let new = tmp . '/plug.vim' + + try + let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp]) + if v:shell_error + return s:err('Error upgrading vim-plug: '. out) + endif + + if readfile(s:me) ==# readfile(new) + echo 'vim-plug is already up-to-date' + return 0 + else + call rename(s:me, s:me . '.old') + call rename(new, s:me) + unlet g:loaded_plug + echo 'vim-plug has been upgraded' + return 1 + endif + finally + silent! call s:rm_rf(tmp) + endtry +endfunction + +function! s:upgrade_specs() + for spec in values(g:plugs) + let spec.frozen = get(spec, 'frozen', 0) + endfor +endfunction + +function! s:status() + call s:prepare() + call append(0, 'Checking plugins') + call append(1, '') + + let ecnt = 0 + let unloaded = 0 + let [cnt, total] = [0, len(g:plugs)] + for [name, spec] in items(g:plugs) + let is_dir = isdirectory(spec.dir) + if has_key(spec, 'uri') + if is_dir + let [err, _] = s:git_validate(spec, 1) + let [valid, msg] = [empty(err), empty(err) ? 'OK' : err] + else + let [valid, msg] = [0, 'Not found. Try PlugInstall.'] + endif + else + if is_dir + let [valid, msg] = [1, 'OK'] + else + let [valid, msg] = [0, 'Not found.'] + endif + endif + let cnt += 1 + let ecnt += !valid + " `s:loaded` entry can be missing if PlugUpgraded + if is_dir && get(s:loaded, name, -1) == 0 + let unloaded = 1 + let msg .= ' (not loaded)' + endif + call s:progress_bar(2, repeat('=', cnt), total) + call append(3, s:format_message(valid ? '-' : 'x', name, msg)) + normal! 2G + redraw + endfor + call setline(1, 'Finished. '.ecnt.' error(s).') + normal! gg + setlocal nomodifiable + if unloaded + echo "Press 'L' on each line to load plugin, or 'U' to update" + nnoremap L :call status_load(line('.')) + xnoremap L :call status_load(line('.')) + end +endfunction + +function! s:extract_name(str, prefix, suffix) + return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$') +endfunction + +function! s:status_load(lnum) + let line = getline(a:lnum) + let name = s:extract_name(line, '-', '(not loaded)') + if !empty(name) + call plug#load(name) + setlocal modifiable + call setline(a:lnum, substitute(line, ' (not loaded)$', '', '')) + setlocal nomodifiable + endif +endfunction + +function! s:status_update() range + let lines = getline(a:firstline, a:lastline) + let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)') + if !empty(names) + echo + execute 'PlugUpdate' join(names) + endif +endfunction + +function! s:is_preview_window_open() + silent! wincmd P + if &previewwindow + wincmd p + return 1 + endif +endfunction + +function! s:find_name(lnum) + for lnum in reverse(range(1, a:lnum)) + let line = getline(lnum) + if empty(line) + return '' + endif + let name = s:extract_name(line, '-', '') + if !empty(name) + return name + endif + endfor + return '' +endfunction + +function! s:preview_commit() + if b:plug_preview < 0 + let b:plug_preview = !s:is_preview_window_open() + endif + + let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}') + if empty(sha) + let name = matchstr(getline('.'), '^- \zs[^:]*\ze:$') + if empty(name) + return + endif + let title = 'HEAD@{1}..' + let command = 'git diff --no-color HEAD@{1}' + else + let title = sha + let command = 'git show --no-color --pretty=medium '.sha + let name = s:find_name(line('.')) + endif + + if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir) + return + endif + + if !s:is_preview_window_open() + execute get(g:, 'plug_pwindow', 'vertical rightbelow new') + execute 'e' title + else + execute 'pedit' title + wincmd P + endif + setlocal previewwindow filetype=git buftype=nofile bufhidden=wipe nobuflisted modifiable + let batchfile = '' + try + let [sh, shellcmdflag, shrd] = s:chsh(1) + let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && '.command + if s:is_win + let [batchfile, cmd] = s:batchfile(cmd) + endif + execute 'silent %!' cmd + finally + let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] + if s:is_win && filereadable(batchfile) + call delete(batchfile) + endif + endtry + setlocal nomodifiable + nnoremap q :q + wincmd p +endfunction + +function! s:section(flags) + call search('\(^[x-] \)\@<=[^:]\+:', a:flags) +endfunction + +function! s:format_git_log(line) + let indent = ' ' + let tokens = split(a:line, nr2char(1)) + if len(tokens) != 5 + return indent.substitute(a:line, '\s*$', '', '') + endif + let [graph, sha, refs, subject, date] = tokens + let tag = matchstr(refs, 'tag: [^,)]\+') + let tag = empty(tag) ? ' ' : ' ('.tag.') ' + return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date) +endfunction + +function! s:append_ul(lnum, text) + call append(a:lnum, ['', a:text, repeat('-', len(a:text))]) +endfunction + +function! s:diff() + call s:prepare() + call append(0, ['Collecting changes ...', '']) + let cnts = [0, 0] + let bar = '' + let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)') + call s:progress_bar(2, bar, len(total)) + for origin in [1, 0] + let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))')))) + if empty(plugs) + continue + endif + call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') + for [k, v] in plugs + let branch = s:git_origin_branch(v) + if len(branch) + let range = origin ? '..origin/'.branch : 'HEAD@{1}..' + let cmd = ['git', 'log', '--graph', '--color=never'] + if s:git_version_requirement(2, 10, 0) + call add(cmd, '--no-show-signature') + endif + call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range]) + if has_key(v, 'rtp') + call extend(cmd, ['--', v.rtp]) + endif + let diff = s:system_chomp(cmd, v.dir) + if !empty(diff) + let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' + call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) + let cnts[origin] += 1 + endif + endif + let bar .= '=' + call s:progress_bar(2, bar, len(total)) + normal! 2G + redraw + endfor + if !cnts[origin] + call append(5, ['', 'N/A']) + endif + endfor + call setline(1, printf('%d plugin(s) updated.', cnts[0]) + \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : '')) + + if cnts[0] || cnts[1] + nnoremap (plug-preview) :silent! call preview_commit() + if empty(maparg("\", 'n')) + nmap (plug-preview) + endif + if empty(maparg('o', 'n')) + nmap o (plug-preview) + endif + endif + if cnts[0] + nnoremap X :call revert() + echo "Press 'X' on each block to revert the update" + endif + normal! gg + setlocal nomodifiable +endfunction + +function! s:revert() + if search('^Pending updates', 'bnW') + return + endif + + let name = s:find_name(line('.')) + if empty(name) || !has_key(g:plugs, name) || + \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y' + return + endif + + call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir) + setlocal modifiable + normal! "_dap + setlocal nomodifiable + echo 'Reverted' +endfunction + +function! s:snapshot(force, ...) abort + call s:prepare() + setf vim + call append(0, ['" Generated by vim-plug', + \ '" '.strftime("%c"), + \ '" :source this file in vim to restore the snapshot', + \ '" or execute: vim -S snapshot.vim', + \ '', '', 'PlugUpdate!']) + 1 + let anchor = line('$') - 3 + let names = sort(keys(filter(copy(g:plugs), + \'has_key(v:val, "uri") && isdirectory(v:val.dir)'))) + for name in reverse(names) + let sha = has_key(g:plugs[name], 'commit') ? g:plugs[name].commit : s:git_revision(g:plugs[name].dir) + if !empty(sha) + call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha)) + redraw + endif + endfor + + if a:0 > 0 + let fn = s:plug_expand(a:1) + if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?')) + return + endif + call writefile(getline(1, '$'), fn) + echo 'Saved as '.a:1 + silent execute 'e' s:esc(fn) + setf vim + endif +endfunction + +function! s:split_rtp() + return split(&rtp, '\\\@ +# For yt ads: place the greasemonkey script yt-ads.js in your greasemonkey folder (~/.config/qutebrowser/greasemonkey). +# The script skips through the entire ad, so all you have to do is click the skip button. +# Yeah it's not ublock origin, but if you want a minimal browser, this is a solution for the tradeoff. +# You can also watch yt vids directly in mpv, see qutebrowser FAQ for how to do that. +# If you want additional blocklists, you can get the python-adblock package, or you can uncomment the ublock lists here. +c.content.blocking.enabled = True +# c.content.blocking.method = 'adblock' # uncomment this if you install python-adblock +# c.content.blocking.adblock.lists = [ +# "https://github.com/ewpratten/youtube_ad_blocklist/blob/master/blocklist.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/legacy.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/filters.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/filters-2020.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/filters-2021.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/filters-2022.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/filters-2023.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/filters-2024.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/badware.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/privacy.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/badlists.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/annoyances.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/annoyances-cookies.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/annoyances-others.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/badlists.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/quick-fixes.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/resource-abuse.txt", +# "https://github.com/uBlockOrigin/uAssets/raw/master/filters/unbreak.txt"] + diff --git a/config/qutebrowser/greasemonkey/yt-ads.js b/config/qutebrowser/greasemonkey/yt-ads.js new file mode 100755 index 0000000..932fd29 --- /dev/null +++ b/config/qutebrowser/greasemonkey/yt-ads.js @@ -0,0 +1,19 @@ +// ==UserScript== +// @name Auto Skip YouTube Ads +// @version 1.1.0 +// @description Speed up and skip YouTube ads automatically +// @author jso8910 and others +// @match *://*.youtube.com/* +// ==/UserScript== + + +document.addEventListener('load', () => { + const btn = document.querySelector('.videoAdUiSkipButton,.ytp-ad-skip-button-modern') + if (btn) { + btn.click() + } + const ad = [...document.querySelectorAll('.ad-showing')][0]; + if (ad) { + document.querySelector('video').currentTime = 9999999999; + } +}, true); diff --git a/config/qutebrowser/quickmarks b/config/qutebrowser/quickmarks new file mode 100755 index 0000000..e69de29 diff --git a/config/rofi/config.rasi b/config/rofi/config.rasi new file mode 100755 index 0000000..88e4ad0 --- /dev/null +++ b/config/rofi/config.rasi @@ -0,0 +1,64 @@ +* { + highlight: bold italic; + scrollbar: true; + + base-bg: #1e1e2e; + base-bg-soft: #181825; + base-bg-alt: #11111b; + + base-fg: #cdd6f4; + base-fg-dim: #6c7086; + + accent: #f5c2e7; + accent-light: #cba6f7; + accent-dark: #f38ba8; + + border-gray: #313244; + + background: @base-bg; + background-color: @background; + foreground: @base-fg; + border-color: @border-gray; + separatorcolor: @border-color; + scrollbar-handle: @border-color; + + normal-background: @background; + normal-foreground: @foreground; + alternate-normal-background: @base-bg-soft; + alternate-normal-foreground: @foreground; + + selected-normal-background: @accent; + selected-normal-foreground: @base-bg-alt; + + active-background: @accent; + active-foreground: @base-bg-alt; + alternate-active-background: @accent; + alternate-active-foreground: @active-foreground; + + selected-active-background: @accent-light; + selected-active-foreground: @active-foreground; + + urgent-background: @accent-dark; + urgent-foreground: @base-bg-alt; + alternate-urgent-background: @accent-dark; + alternate-urgent-foreground: @urgent-foreground; + + selected-urgent-background: @accent-light; + selected-urgent-foreground: @urgent-foreground; + + padding: 6px 6px; +} + +configuration { + font: "JetBrainsMono Nerd Font 14"; + show-icons: true; + terminal: "foot"; +} + +element-icon { + size: 20px; +} + +window { + border-radius: 0px; +} diff --git a/config/rofi/gruvbox.rasi b/config/rofi/gruvbox.rasi new file mode 100755 index 0000000..4941db9 --- /dev/null +++ b/config/rofi/gruvbox.rasi @@ -0,0 +1,61 @@ +* { + highlight: bold italic; + scrollbar: true; + + base-bg: #0f0f0f; + base-bg-soft: #1a1a1a; + base-bg-alt: #2a2a2a; + base-fg: #e0def4; + base-fg-dim: #6e6a86; + + accent: #ebbcba; + accent-light: #ea9a97; + accent-dark: #d7827e; + + border-gray: #454545; + + background: @base-bg; + background-color: @background; + foreground: @base-fg; + border-color: @border-gray; + separatorcolor: @border-color; + scrollbar-handle: @border-color; + + normal-background: @background; + normal-foreground: @foreground; + alternate-normal-background: @base-bg-soft; + alternate-normal-foreground: @foreground; + selected-normal-background: @accent; + selected-normal-foreground: @base-bg; + + active-background: @accent; + active-foreground: @base-bg; + alternate-active-background: @accent; + alternate-active-foreground: @active-foreground; + selected-active-background: @accent-light; + selected-active-foreground: @active-foreground; + + urgent-background: @accent-dark; + urgent-foreground: @base-bg; + alternate-urgent-background: @accent-dark; + alternate-urgent-foreground: @urgent-foreground; + selected-urgent-background: @accent-light; + selected-urgent-foreground: @urgent-foreground; + + padding: 6px 6px; +} + +configuration { + font: "JetBrainsMono Nerd Font 14"; + show-icons: true; + terminal: "footclient"; +} + +element-icon { + size: 20px; +} + +window { + border-radius: 10px; +} + diff --git a/config/rofi/rofi/config.rasi b/config/rofi/rofi/config.rasi new file mode 100755 index 0000000..d99eab8 --- /dev/null +++ b/config/rofi/rofi/config.rasi @@ -0,0 +1,61 @@ +* { + highlight: bold italic; + scrollbar: true; + + base-bg: #000000; + base-bg-soft: #1a1a1a; + base-bg-alt: #0d0d0d; + base-fg: #f5f5f5; + base-fg-dim: #808080; + accent: #ffffff; + accent-light: #e0e0e0; + accent-dark: #4d4d4d; + border-gray: #333333; + + background: @base-bg; + background-color: @background; + foreground: @base-fg; + border-color: @border-gray; + separatorcolor: @border-color; + scrollbar-handle: @border-color; + + normal-background: @background; + normal-foreground: @foreground; + alternate-normal-background: @base-bg-soft; + alternate-normal-foreground: @foreground; + + selected-normal-background: @accent; + selected-normal-foreground: @base-bg-alt; + + active-background: @accent; + active-foreground: @base-bg-alt; + alternate-active-background: @accent; + alternate-active-foreground: @active-foreground; + + selected-active-background: @accent-light; + selected-active-foreground: @active-foreground; + + urgent-background: @accent-dark; + urgent-foreground: @base-bg-alt; + alternate-urgent-background: @accent-dark; + alternate-urgent-foreground: @urgent-foreground; + + selected-urgent-background: @accent-light; + selected-urgent-foreground: @urgent-foreground; + + padding: 6px 6px; +} + +configuration { + font: "JetBrainsMono Nerd Font 14"; + show-icons: true; + terminal: "foot"; +} + +element-icon { + size: 20px; +} + +window { + border-radius: 10px; +} diff --git a/config/shell/aliases b/config/shell/aliases new file mode 100755 index 0000000..a882dec --- /dev/null +++ b/config/shell/aliases @@ -0,0 +1,45 @@ +#!/bin/sh +#general aliases +alias forge="su forgejo" +alias cst="emacs ~/.suckless/st/config.h" +alias resmacs="systemctl --user restart emacsd" +alias smi="nvidia-smi" +alias src="source ~/.zshrc" +alias bat="sb-battery" +alias battery="sb-battery" +alias vimrc="vim .vimrc" +alias ri="ranger" +alias rim="ranger" +alias quit="exit" +alias :q="exit" +alias :q!="exit" +alias :Q="exit" +alias :Q!="exit" +alias :quit="exit" +alias :quit!="exit" +alias :QUIT="exit" +alias :QUIT!="exit" +alias q="exit" +alias fnl="fennel" +alias "git push -u origin main"="push" +alias irc="irssi" +alias hsw="home-manager switch --flake ~/.config/home-manager" +alias hsc="emacs ~/.config/home-manager/home.nix" +alias yell="echo" +alias chm="ecop cat ~/.config/home-manager/home.nix" +if [ -n "$ZSH_VERSION" ]; then + alias ed="ed -p '%: '" +else + alias ed="ed -p '$: '" +fi +alias weather="curl wttr.in/masjedsoleyman" +#typo/shortcut +alias c="clear" +alias cear="clear" +alias "cd.."="cd .." +alias claer="clear" +alias claer="clear" +alias clare="clear" +alias cleae="clear" +alias clera="clear" +alias hotp="htop" diff --git a/config/shell/exports b/config/shell/exports new file mode 100755 index 0000000..9ca27a9 --- /dev/null +++ b/config/shell/exports @@ -0,0 +1,7 @@ +export PATH=$HOME/.local/bin:$PATH +export PATH=$HOME/.luarocks/bin:$PATH +if [ -n "$ZSH_VERSION" ]; then + export ZSH="/home/avery/.oh-my-zsh" +fi +export NIXPKGS_ALLOW_UNFREE=1 +export EDITOR="emacs" diff --git a/config/shell/shell/aliases b/config/shell/shell/aliases new file mode 100755 index 0000000..d53e7b2 --- /dev/null +++ b/config/shell/shell/aliases @@ -0,0 +1,53 @@ + #!/bin/sh + #general aliases + alias xi="doas xbps-install -S $1" + alias nf="clear && fastfetch" + alias ascdis="fastfetch --logo $1" + alias forge="su forgejo" + alias emoji="cat ~/.local/share/emoji | grep $1" + alias cst="emacs ~/.suckless/st/config.h" + alias las="ls" + alias lasa="ls -a" + alias lasal="ls -al" + alias anal="ls -ahl" + alias resmacs="systemctl --user restart emacsd" + alias smi="nvidia-smi" + alias src="source ~/.zshrc" + alias bat="sb-battery" + alias battery="sb-battery" + alias vimrc="vim .vimrc" + alias ri="ranger" + alias rim="ranger" + alias quit="exit" + alias :q="exit" + alias :q!="exit" + alias :Q="exit" + alias :Q!="exit" + alias :quit="exit" + alias :quit!="exit" + alias :QUIT="exit" + alias :QUIT!="exit" + alias q="exit" + alias fnl="fennel" + alias "push"="git push -u origin main" + alias irc="irssi" + alias hsw="home-manager switch --flake ~/.config/home-manager" + alias hsc="emacs ~/.config/home-manager/home.nix" + alias yell="echo" + alias chm="ecop cat ~/.config/home-manager/home.nix" + if [ -n "$ZSH_VERSION" ]; then + alias ed="ed -p '%: '" + else + alias ed="ed -p '$: '" + fi + alias weather="curl wttr.in/masjedsoleyman" + #typo/shortcut + alias c="clear" + alias cear="clear" + alias "cd.."="cd .." + alias claer="clear" + alias claer="clear" + alias clare="clear" + alias cleae="clear" + alias clera="clear" + alias hotp="htop" diff --git a/config/shell/shell/aliases.backup b/config/shell/shell/aliases.backup new file mode 100755 index 0000000..c8f86ac --- /dev/null +++ b/config/shell/shell/aliases.backup @@ -0,0 +1,27 @@ +#!/bin/zsh +#general aliases +alias emacs="emacsclient -c" +alias vimrc="edsc .vimrc" +alias ri="ranger" +alias rim="ranger" +alias :q="exit" +alias :q!="exit" +alias :Q="exit" +alias :Q!="exit" +alias :quit="exit" +alias :quit!="exit" +alias :QUIT="exit" +alias :QUIT!="exit" +alias fnl="fennel" +alias irc="irssi" +alias hsw="home-manager switch" +#typo/shortcut +alias c="clear" +alias cear="clear" +alias "cd.."="cd .." +alias claer="clear" +alias claer="clear" +alias clare="clear" +alias cleae="clear" +alias clera="clear" +alias hotp="htop" diff --git a/config/shell/shell/exports b/config/shell/shell/exports new file mode 100755 index 0000000..9ed30bc --- /dev/null +++ b/config/shell/shell/exports @@ -0,0 +1,8 @@ +export PATH=$HOME/.local/bin:$PATH +export PATH=$HOME/.luarocks/bin:$PATH +if [ -n "$ZSH_VERSION" ]; then + export ZSH="/home/avery/.oh-my-zsh" +fi +export NIXPKGS_ALLOW_UNFREE=1 +export EDITOR="emacs" +export BROWSER="brave" diff --git a/config/shell/shell/exports.backup b/config/shell/shell/exports.backup new file mode 100755 index 0000000..c1d9f0e --- /dev/null +++ b/config/shell/shell/exports.backup @@ -0,0 +1,4 @@ +export PATH=$HOME/.local/bin:$PATH +export PATH=$HOME/.luarocks/bin:$PATH +export ZSH="/home/avery/.oh-my-zsh" +export NIXPKGS_ALLOW_UNFREE=1 diff --git a/config/starship.toml b/config/starship.toml new file mode 100755 index 0000000..119021d --- /dev/null +++ b/config/starship.toml @@ -0,0 +1,36 @@ +format = """ +[](#0f0f0f)\ +$username\ +[](bg:#1a1a1a fg:#0f0f0f)\ +$directory\ +[](bg:#2a2a2a fg:#1a1a1a)\ +$all_langs\ +[](bg:#1a1a1a fg:#2a2a2a)\ +$time\ +[](fg:#1a1a1a) +""" + +add_newline = false + +[username] +show_always = true +style_user = "bg:#0f0f0f fg:#ebbcba" +style_root = "bg:#0f0f0f fg:#eb6f92" +format = '[$user]($style)' +disabled = false + +[os] +style = "bg:#1a1a1a fg:#ebbcba" +disabled = true + +[directory] +style = "fg:#ebbcba bg:#1a1a1a" +format = "[ $path ]($style)" +truncation_length = 3 +truncation_symbol = "…/" + +[directory.substitutions] +"Documents" = "󰈙 " +"Downloads" = " " +"Music" = " " +"Pictures" = " " diff --git a/config/sway/config b/config/sway/config new file mode 100755 index 0000000..d7c5c04 --- /dev/null +++ b/config/sway/config @@ -0,0 +1,131 @@ +exec "foot --server" +exec "wbg /home/coast/Pictures/walls/wallhaven-yq5dmg_1920x1080.png" +exec "dbus-update-activation-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=Sway" +exec "gnome-keyring-daemon --start --components=secrets" +exec "waybar" +exec "mpd ~/.mpdconf" +exec "mpc add /" +exec "flatpak override --env=GTK_THEME=Catppuccin-B-MB-Dark --user" +exec "mako" + +set $mod Mod4 +set $left h +set $down j +set $up k +set $right l + +set $term footclient +set $menu rofi -show drun -config /home/coast/.config/rofi/config.rasi +set $webBrowser firefox-bin +set $discordApp vesktop-bin --proxy-server="socks5://127.0.0.1:65000" +set $restartWaybar "pkill waybar; waybar &" +set $fileManager pcmanfm + + +output HDMI-A-1 resolution 1920x1080@100Hz position 0,0 + +workspace 2 output HDMI-A-1 + +output * bg /home/coast/Pictures/walls/wallhaven-yq5dmg_1920x1080.png fill + + exec swayidle -w \ + timeout 300 'hyprlock' \ + timeout 600 'swaymsg "output * power off"' \ + resume 'swaymsg "output * power on"' \ + before-sleep 'hyprlock' + +input type:keyboard { + xkb_layout us +} + +gaps inner 5 +gaps outer 9 + +default_border pixel 1 + +client.focused #6c6c9d #6c6c9d #ffffff #6c6c9d #6c6c9d +client.unfocused #1e1e2e #1e1e2e #5c5c5c #1e1e2e #1e1e2e +client.focused_inactive #1e1e2e #1e1e2e #5c5c5c #1e1e2e #1e1e2e + +bindsym $mod+Return exec $term +bindsym $mod+s kill +bindsym $mod+r exec $menu +bindsym $mod+Shift+q exec swaymsg exit +bindsym $mod+ctrl+r reload + +floating_modifier $mod normal + +bindsym $mod+space exec swaymsg floating toggle && swaymsg resize set 1000 800 && swaymsg move position center + +bindsym $mod+backslash move position center + +bindsym $mod+$left focus left +bindsym $mod+$down focus down +bindsym $mod+$up focus up +bindsym $mod+$right focus right + +bindsym $mod+Shift+$left move left +bindsym $mod+Shift+$down move down +bindsym $mod+Shift+$up move up +bindsym $mod+Shift+$right move right + +bindsym $mod+Mod1+$left resize shrink width 30px +bindsym $mod+Mod1+$right resize grow width 30px +bindsym $mod+Mod1+$up resize shrink height 30px +bindsym $mod+Mod1+$down resize grow height 30px + +bindsym $mod+Left move left 40px +bindsym $mod+Right move right 40px +bindsym $mod+Up move up 40px +bindsym $mod+Down move down 40px + +bindsym $mod+Shift+Left resize shrink width 40px +bindsym $mod+Shift+Right resize grow width 40px +bindsym $mod+Shift+Up resize shrink height 40px +bindsym $mod+Shift+Down resize grow height 40px + +bindsym $mod+1 workspace number 1 +bindsym $mod+2 workspace number 2 +bindsym $mod+3 workspace number 3 +bindsym $mod+4 workspace number 4 +bindsym $mod+5 workspace number 5 +bindsym $mod+6 workspace number 6 +bindsym $mod+7 workspace number 7 +bindsym $mod+8 workspace number 8 +bindsym $mod+9 workspace number 9 + +bindsym $mod+Shift+1 move container to workspace number 1 +bindsym $mod+Shift+2 move container to workspace number 2 +bindsym $mod+Shift+3 move container to workspace number 3 +bindsym $mod+Shift+4 move container to workspace number 4 +bindsym $mod+Shift+5 move container to workspace number 5 +bindsym $mod+Shift+6 move container to workspace number 6 +bindsym $mod+Shift+7 move container to workspace number 7 +bindsym $mod+Shift+8 move container to workspace number 8 +bindsym $mod+Shift+9 move container to workspace number 9 + +bindsym $mod+c scratchpad show +bindsym $mod+Shift+c move scratchpad + +bindsym $mod+Shift+b exec $webBrowser +bindsym $mod+Shift+v exec $discordApp +bindsym $mod+f exec $fileManager +bindsym $mod+Shift+p exec $restartWaybar +bindsym $mod+ctrl+l exec hyprlock + +bindsym $mod+Shift+s exec screenie-wlr + +bindsym $mod+Mod1+Up exec /home/coast/.local/bin/mpc-shuf.sh shuf +bindsym $mod+Mod1+Down exec /home/coast/.local/bin/mpc-shuf.sh shufno +bindsym $mod+Mod1+Right exec /home/coast/.local/bin/mpc-shuf.sh next +bindsym $mod+Mod1+Left exec /home/coast/.local/bin/mpc-shuf.sh prev +bindsym $mod+Shift+r exec /home/coast/.local/bin/mpc-shuf.sh search +bindsym $mod+ctrl+a exec /home/coast/.local/bin/mpc-shuf.sh album +bindsym $mod+Mod1+r exec /home/coast/.local/bin/mpc-shuf.sh artist +bindsym $mod+slash exec /home/coast/.local/bin/mpc-shuf.sh info +bindsym $mod+comma exec mpc volume -5 +bindsym $mod+period exec mpc volume +5 +bindsym $mod+bracketright exec /home/coast/.local/bin/mpc-shuf.sh toggle +bindsym $mod+ctrl+Up exec /home/coast/.local/bin/mpc-shuf.sh reload + +xwayland enable diff --git a/config/sxhkd/sxhkdrc b/config/sxhkd/sxhkdrc new file mode 100755 index 0000000..a44e11d --- /dev/null +++ b/config/sxhkd/sxhkdrc @@ -0,0 +1,18 @@ +super + shift + r + brwmenu +super + shift + b + mullvad-browser-bin +super + f + pcmanfm +super + shift + f + st -e ranger +super + shift + t + torbrowser-launcher +super + shift + i + mullvad-browser-bin --private-window +super + shift + n + nekoray +super + shift + v + vesktop-bin +super + shift + g + st -e htop diff --git a/config/systemd/emacsd.service b/config/systemd/emacsd.service new file mode 100755 index 0000000..950f2c6 --- /dev/null +++ b/config/systemd/emacsd.service @@ -0,0 +1,11 @@ +[Unit] +Description=Emacs daemon + +[Service] +Type=forking +ExecStart=/usr/bin/emacs --daemon +ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)" +Restart=on-failure + +[Install] +WantedBy=default.target diff --git a/config/tmux/tmux.conf b/config/tmux/tmux.conf new file mode 100755 index 0000000..7bd46dc --- /dev/null +++ b/config/tmux/tmux.conf @@ -0,0 +1,67 @@ +set -g default-terminal "tmux-256color" +set -ga terminal-overrides ",*:RGB" +set -g mouse on +set -g set-clipboard on + +unbind C-b +set -g prefix C-a +bind-key C-a send-prefix + +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R + +unbind % +bind | split-window -h -c "#{pane_current_path}" + +unbind '"' +bind - split-window -v -c "#{pane_current_path}" + +unbind r +bind r source-file $HOME/.config/tmux/tmux.conf + +set -g base-index 1 +set -g pane-base-index 1 +set -g renumber-windows on + +set -g mode-keys vi +bind-key -T copy-mode-vi v send-keys -X begin-selection +bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle +bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel +unbind -T copy-mode-vi MouseDragEnd1Pane + +bind -n M-h select-pane -L +bind -n M-j select-pane -D +bind -n M-k select-pane -U +bind -n M-l select-pane -R + +bind -n M-1 select-window -t 1 +bind -n M-2 select-window -t 2 +bind -n M-3 select-window -t 3 +bind -n M-4 select-window -t 4 +bind -n M-5 select-window -t 5 +bind -n M-6 select-window -t 6 +bind -n M-7 select-window -t 7 +bind -n M-8 select-window -t 8 +bind -n M-9 select-window -t 9 + +set -g status on +set -g status-justify centre +set -g status-bg "#1a1a1a" +set -g status-fg "#ebbcba" +set -g status-style "bg=#1a1a1a,fg=#ebbcba" + +set -g status-left "#[bg=#ebbcba,fg=#1a1a1a,bold] #S " +set -g status-right " #[bg=#ebbcba,fg=#1a1a1a,bold] %H:%M " +set -g window-status-current-format "#[fg=#ebbcba]#[bg=#ebbcba,fg=#1a1a1a,bold] #I: #W #[fg=#ebbcba,bg=#1a1a1a]" +set -g window-status-format "#[fg=#ebbcba]#[bg=#ebbcba,fg=#111111] #I #[fg=#ebbcba,bg=#1a1a1a]" + +set -g pane-border-style "fg=#ebbcba" +set -g pane-active-border-style "fg=#ebbcba" + +set -g mode-style "bg=#ebbcba,fg=#ebbcba" + +set -g message-style "fg=#ebbcba,bg=#1a1a1a,bold" +set -g message-command-style "fg=#ebbcba,bg=#1a1a1a,bold" + diff --git a/config/waybar-2/config.jsonc b/config/waybar-2/config.jsonc new file mode 100644 index 0000000..a2ed085 --- /dev/null +++ b/config/waybar-2/config.jsonc @@ -0,0 +1,27 @@ +{ + "layer": "top", + "position": "bottom", + "height": 35, + "spacing": 4, + "modules-left": ["hyprland/workspaces"], + "modules-center": ["hyprland/window"], + "modules-right": ["clock"], + + "hyprland/workspaces": { + "disable-scroll": true, + "all-outputs": true, + "format": "{id}", + "on-click": "activate" + }, + + "hyprland/window": { + "format": "{}", + "max-length": 40, + "separate-outputs": true + }, + + "clock": { + "format": "{:%I:%M %p}", + "tooltip": false + } +} diff --git a/config/waybar-2/style.css b/config/waybar-2/style.css new file mode 100644 index 0000000..10b2071 --- /dev/null +++ b/config/waybar-2/style.css @@ -0,0 +1,42 @@ +* { + border: none; + border-radius: 0; + font-family: "JetBrainsMono Nerd Font"; + font-size: 15px; + min-height: 0; +} + +window#waybar { + background-color: rgba(30, 30, 46, 0.8); + color: #cdd6f4; +} + +#workspaces { + margin: 0 4px; +} + +#workspaces button { + padding: 0 8px; + margin: 0 4px; + color: #6c7086; +} + +#workspaces button.active { + color: #89b4fa; + border-bottom: 2px solid #89b4fa; +} + +#workspaces button:hover { + background: rgba(137, 180, 250, 0.1); + box-shadow: inherit; + text-shadow: inherit; +} + +#window { + color: #cdd6f4; +} + +#clock { + font-weight: bold; + padding-right: 15px; +} diff --git a/config/waybar-2/waybar/config.jsonc b/config/waybar-2/waybar/config.jsonc new file mode 100755 index 0000000..8d04fac --- /dev/null +++ b/config/waybar-2/waybar/config.jsonc @@ -0,0 +1,154 @@ +{ + "reload-style-on-change": true, + "layer": "top", + "position": "top", + "output": "HDMI-A-1", + "spacing": 0, + "height": 35, + "border-radius": 25, + + "modules-left": ["niri/workspaces"], + "modules-center": [], + "modules-right": ["group/right"], + + "group/right": { + "orientation": "inherit", + "modules": [ + "clock" + ] + }, + + "custom/active_window": { + "exec": "~/.config/waybar/window.sh", + "return-type": "json", + "markup": true + }, + + "niri/workspaces": { + "on-click": "activate", + "format": "{icon}", + "format-icons": { + "default": "", + "active": "", + "urgent": "", + "empty": "" + }, + "persistent-workspaces": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "6": [], + "7": [], + "8": [] + } + }, + + "custom/wbmenu": { + "format": "", + "on-click": "rofi -show drun -config ~/.config/rofi/gruvbox.rasi", + "on-click-right": "xdg-terminal-exec", + "tooltip-format": "Menu\n\nSuper + Return" + }, + + "cpu": { + "interval": 2, + "format": "{icon} ", + "format-icons": ["󰪞", "󰪟", "󰪠", "󰪡", "󰪢", "󰪣", "󰪤", "󰪥"] + }, + + "memory": { + "interval": 2, + "format": "{icon}", + "format-icons": ["󰪞", "󰪟", "󰪠", "󰪡", "󰪢", "󰪣", "󰪤", "󰪥"] + }, + + "clock": { + "format": " {:%I:%M %p • %a, %d/%m} ", + "format-alt": "{:%A, %d %B %Y}", + "tooltip-format": "{:%Y %B}\n{calendar}" + }, + + "network": { + "format-icons": ["󰤯", "󰤟", "󰤢", "󰤥", "󰤨"], + "format": "{icon}", + "format-wifi": "{icon}", + "format-ethernet": "󰌘", + "format-disconnected": "󰤮", + "tooltip-format-wifi": "{essid} ({frequency} GHz)\n⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}", + "tooltip-format-ethernet": "⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}", + "tooltip-format-disconnected": "Disconnected", + "interval": 3, + "spacing": 1 + }, + + "battery": { + "format": "{capacity}% {icon}", + "format-discharging": "{icon}", + "format-charging": "{icon}", + "format-plugged": "", + "format-icons": { + "charging": ["󰢜", "󰂆", "󰂇", "󰂈", "󰢝", "󰂉", "󰢞", "󰂊", "󰂋", "󰂅"], + "default": ["󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"] + }, + "format-full": "󰂅", + "tooltip-format-discharging": "{power:>1.0f}W↓ {capacity}%", + "tooltip-format-charging": "{power:>1.0f}W↑ {capacity}%", + "interval": 5, + "states": { + "warning": 20, + "critical": 10 + } + }, + + "bluetooth": { + "format": "󰂯", + "format-disabled": "󰂲", + "format-connected": "", + "format-no-controller": "", + "tooltip-format": "Devices connected: {num_connections}" + }, + + "pulseaudio": { + "format": "{icon}", + "on-click-right": "pamixer -t", + "tooltip-format": "Playing at {volume}%", + "scroll-step": 5, + "format-muted": "", + "format-icons": { + "default": [" ", " ", " "] + } + }, + + "group/tray-expander": { + "orientation": "inherit", + "drawer": { + "transition-duration": 600, + "children-class": "tray-group-item" + }, + "modules": ["custom/expand-icon", "tray"] + }, + + "custom/expand-icon": { + "format": "", + "tooltip": false + }, + + "tray": { + "icon-size": 16, + "spacing": 8 + }, + + "custom/separator#blank": { + "format": " ", + "interval": "once", + "tooltip": false + }, + + "custom/separator#dot": { + "format": " ", + "interval": "once", + "tooltip": false + } +} diff --git a/config/waybar-2/waybar/style.css b/config/waybar-2/waybar/style.css new file mode 100755 index 0000000..7f63e4b --- /dev/null +++ b/config/waybar-2/waybar/style.css @@ -0,0 +1,207 @@ +@define-color background #0E0F12; +@define-color foreground #E6DAD1; +@define-color accent #A07A6A; +@define-color muted #6E5A52; +@define-color subtle #15161A; + +* { + color: @foreground; + border: none; + border-radius: 0; + min-height: 0; + font-family: 'JetBrainsMono Nerd Font Propo'; + font-size: 12px; +} + +window#waybar { + background-color: @background; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar > box { + background-color: @background; + border-radius: 32px; + margin: 2px 10px 0px 10px; +} + +window#waybar.empty #window { + background: transparent; + background-color: transparent; + border: none; + border-radius: 0; + color: transparent; + padding: 0; + margin: 0; +} + +#waybar.empty .modules-center { + opacity: 0; +} + +.modules-left { + margin-left: 8px; +} +.modules-right { + margin-right: 8px; +} + +#workspaces { + padding: 0px 5px; + margin: 3.5px 3.5px; + border-radius: 11px; + background-color: alpha(@foreground, 0.06); + opacity: 0.95; +} + +#workspaces button { + all: initial; + color: @foreground; + padding: 0 6px; + margin: 0 1.5px; + min-width: 9px; +} + +#workspaces button.empty { + opacity: 0.45; +} + +#workspaces button.active { + border-radius: 18px; + background: alpha(@foreground, 0.14); + opacity: 1; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 5px; + padding-right: 5px; + padding-left: 5px; +} + +#workspaces button:hover { + border-radius: 18px; + background: alpha(@foreground, 0.08); + opacity: 1; +} + +#workspaces button.urgent { + border-radius: 18px; + background: alpha(#f13333, 0.4); + opacity: 1; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 5px; + padding-right: 5px; + padding-left: 5px; +} + +#clock { + font-size: 13px; + font-weight: 700; +} + +#battery, +#pulseaudio, +#custom-screenrecording-indicator, +#custom-update { + min-width: 12px; + margin: 0 7.5px; +} + +#pulseaudio { + margin-right: 5px; +} + +#bluetooth { + margin-right: 12px; +} + +#network { + margin-right: 9px; +} + +#custom-idle-indicator, +#custom-notification-silencing-indicator { + margin-right: 2px; + min-width: 15px; +} + +#custom-update { + font-size: 10px; +} + +#custom-screenrecording-indicator { + min-width: 12px; + margin-left: 8.75px; + font-size: 10px; +} + +#custom-screenrecording-indicator.active { + color: red; +} + +#tray { + background: alpha(@foreground, 0.0); + border-radius: 16px; + padding: 0px 5px; + margin: 3.5px 2px; + margin-right: 4px; +} + +#custom-omarchy { + background: alpha(@foreground, 0.08); + border-radius: 99px; + margin-top: 4px; + margin-bottom: 4px; + margin-left: -3px; + margin-right: 5px; + padding-right: 7px; + padding-left: 7px; +} + +#cpu, #memory { + font-size: 18px; + padding: 2px 1px; +} + +#custom-active_window { + padding: 3px 6px; + border-radius: 14px; + background: alpha(@foreground, 0.06); + font-size: 12px; +} + +#group-right1, +#group_right1, +#right1 { + font-weight: 800; + background: transparent; + padding: 0px 5px; + margin: 3.5px 2px; +} + +#group-left, +#group_left, +#left, +#group-right, +#group_right, +#right { + font-weight: 800; + background: alpha(@foreground, 0.06); + border-radius: 12px; + padding: 0px 5px; + margin: 3.5px 2px; +} + +tooltip { + background: @subtle; + border: 1px solid alpha(@foreground, 0.12); + border-radius: 4px 4px 11px 11px; +} + +tooltip label { + color: alpha(@foreground, 0.92); +} + +.hidden { + opacity: 0; +} diff --git a/config/waybar-2/waybar/window.sh b/config/waybar-2/waybar/window.sh new file mode 100755 index 0000000..abf1e39 --- /dev/null +++ b/config/waybar-2/waybar/window.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +MAX_TITLE_LEN=20 + +print_status() { + window=$(hyprctl activewindow -j 2>/dev/null) + address=$(jq -r '.address // empty' <<< "$window") + + # No active window → show Desktop + Workspace + if [[ -z "$address" || "$address" == "null" ]]; then + ws=$(hyprctl activeworkspace -j | jq -r '.id') + + top_line="Desktop" + bottom_line="Workspace $ws" + + esc_top=$(sed 's/&/&/g; s//>/g' <<< "$top_line") + esc_bottom=$(sed 's/&/&/g; s//>/g' <<< "$bottom_line") + + text="$esc_top +$esc_bottom" + + jq -nc \ + --arg text "$text" \ + --arg tooltip "$bottom_line" \ + '{ text: $text, class: "custom-window", tooltip: $tooltip }' + return + fi + + class=$(jq -r '.class // "Unknown"' <<< "$window") + title=$(jq -r '.title // ""' <<< "$window") + + app_class="${class,,}" + + # Discord / Vesktop cleanup + if [[ "$app_class" == *discord* || "$app_class" == *vesktop* ]]; then + title=$(sed -E 's/^\([0-9]+\)[[:space:]]*//' <<< "$title") + title=$(sed -E 's/^Discord[[:space:]]*\|[[:space:]]*//' <<< "$title") + fi + + # Truncate title + if (( ${#title} > MAX_TITLE_LEN )); then + title="${title:0:$((MAX_TITLE_LEN-3))}..." + fi + + esc_top=$(sed 's/&/&/g; s//>/g' <<< "$class") + esc_bottom=$(sed 's/&/&/g; s//>/g' <<< "$title") + + text="$esc_top +$esc_bottom" + + tooltip="$class: $title" + + jq -nc \ + --arg text "$text" \ + --arg tooltip "$tooltip" \ + '{ text: $text, class: "custom-window", tooltip: $tooltip }' +} + +# Initial output +print_status + +last="" + +# Update only when state changes +while true; do + current_window=$(hyprctl activewindow -j 2>/dev/null) + current_ws=$(hyprctl activeworkspace -j 2>/dev/null) + + current="$current_window$current_ws" + + if [[ "$current" != "$last" ]]; then + print_status + last="$current" + fi + + sleep 0.5 +done diff --git a/config/waybar/config.jsonc b/config/waybar/config.jsonc new file mode 100755 index 0000000..6907e47 --- /dev/null +++ b/config/waybar/config.jsonc @@ -0,0 +1,107 @@ +{ + "position": "top", +// "output": "HDMI-A-1", + "layer": "top", + "modules-left": [ +// "custom/distro", + "niri/workspaces", + "niri/window" + ], + "modules-center": [ + ], + "modules-right": [ + "network", + "pulseaudio", + "clock" + ], + "pulseaudio": { + "tooltip": false, + "scroll-step": 5, + "format": " {volume}%", + "format-muted": "muted", + "format-icons": { + "default": [ + "", + "", + "" + ] + } + }, + "privacy": { + "icon-spacing": 10, + "icon-size": 18, + "transition-duration": 250, + "tooltip": false, + "modules": [ + { + "type": "screenshare", + "tooltip": true, + "tooltip-icon-size": 24 + }, + { + "type": "audio-out", + "tooltip": true, + "tooltip-icon-size": 24 + }, + { + "type": "audio-in", + "tooltip": true, + "tooltip-icon-size": 24 + } + ] + }, + "custom/distro": { + "format": "󱄅", + "on-click": "sh -c 'rofi -show drun -config ~/.config/rofi/gruvbox.rasi'", + "tooltip": false + }, + "bluetooth": { + "format": " {status}", + "format-connected": " CONN", + "tooltip": true, + "on-click": "footclient -e bluetoothctl", + "tooltip-format-connected": "{device_alias}" + }, + "clock": { + "format": "󰥔 {:%I:%M %p}", + "tooltip": true, + "tooltip-format": "{:%a, %b %d, :%I:%M:%S %p}" + }, + "niri/workspaces": { + "format": "●", + "active-format": "{icon} ●", + "window-icons": true, + "icon-size": 20 + }, + "niri/window": { + "icon": false, + "icon-size": 20 + }, + "niri/mode": { + "format": "{}" + }, + "network": { + // "interface": "wlo1", + "interface": "eno1", + "format-wifi": "󰖩 {essid}", + "format-ethernet": "󰛳 {ipaddr}/{cidr}", + "format-disconnected": "󱚼 disconnected", + "tooltip": true, + "tooltip-format": "Click to copy", + "max-length": 50, + "on-click": "sh -c 'ip addr show eno1 | grep \"inet \" | awk \"{print \\$2}\" | sed \"s#/.*##\" | wl-copy'" + }, + "battery": { + "format": "BAT {capacity}%", + "interval": 10, + "states": { + "warning": 20, + "critical": 10 + }, + "format-time": "{H}:{m}", + "format-charging": "BAT {capacity}%", + "format-discharging": "BAT {capacity}%", + "tooltip-format": "{power}W, {cycles} cycles" + } +} + diff --git a/config/waybar/style.css b/config/waybar/style.css new file mode 100755 index 0000000..601dd6d --- /dev/null +++ b/config/waybar/style.css @@ -0,0 +1,82 @@ +@define-color border #211e1e; +@define-color background #111111; +@define-color surface0 #151111; +@define-color overlay0 #161515; +@define-color text #e0def4; +@define-color text_dim #6e6a86; +@define-color blue #31748f; +@define-color green #9ccfd8; +@define-color yellow #f6c177; +@define-color peach #ebbcba; +@define-color maroon #e79591; +@define-color lavender #c4a7e7; +@define-color pink #eb6f92; +@define-color teal #9ccfd8; +@define-color grey #6e6a86; + +* { + border: none; + font-family: "JetBrainsMono Nerd Font"; + font-size: 15px; + min-height: 10px; +} + +window#waybar { + background: transparent; +} + +#disk, +#pulseaudio, +#window, +#clock, +#network, +#battery, +#privacy, +#memory, +#cpu, +#workspaces, +#tray, +#bluetooth, +#tray menu { + margin-top: 0; + padding: 5px 10px; + margin: 3px 0 13px 10px; + background: @surface0; + color: @peach; + transition: 0.3s; + border: 1.5px solid @border; + border-radius: 8px; +} + +#window { transition: none; } + +window#waybar.empty #window { + background: transparent; + box-shadow: none; + border: none; +} + +#network { color: @peach; } +#clock { margin-right: 12px; color: @peach; } +#pulseaudio { color: @peach; } + +#workspaces { + margin-left: 12px; + color: @peach; +} + +#workspaces button { + margin: 0; + padding: 1px 3px; + color: @peach; + transition: none; +} + +#workspaces button.empty { color: @peach; } +#workspaces button.active { color: @maroon; } +#workspaces button.urgent { color: @peach; } + +#workspaces button:hover { + background: @overlay0; + color: @peach; +} diff --git a/config/wofi/config b/config/wofi/config new file mode 100755 index 0000000..0f7e7ba --- /dev/null +++ b/config/wofi/config @@ -0,0 +1,32 @@ +# mode & placement +show=drun +location=top +width=700 +lines=8 +columns=2 +dynamic_lines=false + +# icons +allow_images=true +image_size=36 + +# search & UX +matching=fuzzy +insensitive=true +hide_scroll=false +prompt= + +# terminal +term=foot + +# keybinds (vim-ish) +key_up=Ctrl-k +key_down=Ctrl-j +key_left=Ctrl-h +key_right=Ctrl-l +key_submit=Return +key_forward=Tab +key_backward=Shift-ISO_Left_Tab + +# stylesheet +style=/home/tony/.config/wofi/style.css diff --git a/config/wofi/style.css b/config/wofi/style.css new file mode 100755 index 0000000..4ee72bd --- /dev/null +++ b/config/wofi/style.css @@ -0,0 +1,59 @@ +* { + font-family: "UbuntuMono", monospace; + font-size: 16px; + font-weight: bold; +} + +window { + margin: 0px; + border: 2px solid #7f7f7f; /* Bright grey */ + border-radius: 5px; + background-color: #1c1c1c; /* Dark grey */ + font-family: monospace; + font-size: 12px; +} + +#input { + margin: 5px; + border: 1px solid #1c1c1c; /* Dark grey */ + color: #d3d3d3; /* Light grey */ + background-color: #1c1c1c; /* Dark grey */ +} + +#input image { + color: #d3d3d3; /* Light grey */ +} + +#inner-box { + margin: 5px; + border: none; + background-color: #1c1c1c; /* Dark grey */ +} + +#outer-box { + margin: 5px; + border: none; + background-color: #1c1c1c; /* Dark grey */ +} + +#scroll { + margin: 0px; + border: none; +} + +#text { + margin: 5px; + border: none; + color: #d3d3d3; /* Light grey */ +} + +#entry:selected { + background-color: #7f7f7f; /* Bright grey */ + font-weight: normal; +} + +#text:selected { + background-color: #7f7f7f; /* Bright grey */ + font-weight: normal; +} + diff --git a/config/xmobar/xmobarrc b/config/xmobar/xmobarrc new file mode 100755 index 0000000..8d75d19 --- /dev/null +++ b/config/xmobar/xmobarrc @@ -0,0 +1,13 @@ +Config { + font = "xft:JetBrainsMono Nerd Font-12", + bgColor = "#282828", + fgColor = "#EBDBB2", + position = TopSize L 100 30, + commands = [ + Run XMonadLog, + Run Date "TIME %I:%M %p" "date" 10, + Run Com "sh" ["-c", "ip -4 addr show | grep inet | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1 | head -n1"] "localip" 50 + ], + alignSep = "}{", + template = " %XMonadLog%}{ NET %localip% : %date% " + } diff --git a/config/xmonad/xmonad.hs b/config/xmonad/xmonad.hs new file mode 100755 index 0000000..efec589 --- /dev/null +++ b/config/xmonad/xmonad.hs @@ -0,0 +1,51 @@ +import XMonad +import XMonad.Util.EZConfig (additionalKeysP) +import XMonad.Util.Run +import XMonad.Hooks.DynamicLog +import XMonad.Hooks.StatusBar +import XMonad.Hooks.ManageDocks +import XMonad.Layout.Spacing +import System.IO + +keybinds = + [ + ("M-", spawn "alacritty"), + ("M-r", spawn "rofi -show drun -config ~/.config/rofi/gruvbox.rasi"), + ("M-S-s", spawn "flameshot gui"), + ("M-s", kill) + ] + +cLayoutHook = avoidStruts $ spacing 5 $ layoutHook def + +cXMobarPP :: PP +cXMobarPP = def + { + ppCurrent = xmobarColor "#83A598" "" , + ppHidden = xmobarColor "#EBDBB2" "", + ppHiddenNoWindows = xmobarColor "#EBDBB2" "", + ppTitle = xmobarColor "#EBDBB2" "" . shorten 60 . wrap "[" "]", + ppLayout = \layout -> "" + } + +cXStatusBar = statusBarProp "xmobar" (pure cXMobarPP) + +logHook = dynamicLogWithPP $ def + { ppOutput = \s -> return (), + ppCurrent = id, + ppVisible = id, + ppHidden = id, + ppUrgent = id, + ppTitle = id + } + +main = xmonad . withSB (statusBarProp "xmobar -f 'xft:JetBrainsMono Nerd Font-14'" (pure cXMobarPP)) $ withEasySB cXStatusBar defToggleStrutsKey $ def + { + modMask = mod4Mask, + terminal = "alacritty", + borderWidth = 2, + normalBorderColor = "#282828", + focusedBorderColor = "#383838", + workspaces = map show [1..9], + layoutHook = cLayoutHook + } + `additionalKeysP` keybinds diff --git a/dmenu b/dmenu new file mode 160000 index 0000000..7175c48 --- /dev/null +++ b/dmenu @@ -0,0 +1 @@ +Subproject commit 7175c4880bac3d2a2d4a6262b59193f0a38e2fdb diff --git a/dwl/.gitea/issue_template/bug_report.yml b/dwl/.gitea/issue_template/bug_report.yml new file mode 100755 index 0000000..77ce108 --- /dev/null +++ b/dwl/.gitea/issue_template/bug_report.yml @@ -0,0 +1,62 @@ +name: Bug Report +about: Something in dwl isn't working correctly +title: +labels: + - 'Kind/Bug' +body: + - type: markdown + attributes: + value: | + - Only report bugs that can be reproduced on the main (or wlroots-next) branch without patches. + - Proprietary graphics drivers, including nvidia, are not supported. Please use the open source equivalents, such as nouveau, if you would like to use dwl. + - Report patch issues to their respective authors. + + - type: input + id: dwl_version + attributes: + label: 'dwl version:' + placeholder: '`dwl -v`' + validations: + required: true + + - type: input + id: wlroots_version + attributes: + label: 'wlroots version:' + validations: + required: true + + - type: input + id: distro + attributes: + label: What distro (and version) are you using? + validations: + required: false + + - type: textarea + attributes: + label: Description + value: | + The steps you took to reproduce the problem. + validations: + required: false + + - type: textarea + id: debug_log + attributes: + label: Debug Log + value: | + Run `dwl -d 2> ~/dwl.log` from a TTY and attach the **full** (do not truncate it) file here, or upload it to a pastebin. + Please try to keep the reproduction as brief as possible and exit dwl. + validations: + required: false + + - type: textarea + id: backtrace + attributes: + label: Stack Trace + value: | + - Only required if dwl crashes. + - If the lines mentioning dwl or wlroots have `??`. Please compile both dwl and wlroots from source (enabling debug symbols) and try to reproduce. + validations: + required: false diff --git a/dwl/.gitea/issue_template/enhancement-idea.yml b/dwl/.gitea/issue_template/enhancement-idea.yml new file mode 100755 index 0000000..be1bbf2 --- /dev/null +++ b/dwl/.gitea/issue_template/enhancement-idea.yml @@ -0,0 +1,9 @@ +name: Enhancement idea +about: Suggest a feature or improvement +title: +labels: + - 'Kind/Feature' +body: + - type: textarea + attributes: + label: Description diff --git a/dwl/.gitignore b/dwl/.gitignore new file mode 100755 index 0000000..0dde90e --- /dev/null +++ b/dwl/.gitignore @@ -0,0 +1,6 @@ +dwl +*.o +*-protocol.c +*-protocol.h +.ccls-cache +config.h diff --git a/dwl/.mailmap b/dwl/.mailmap new file mode 100755 index 0000000..911248c --- /dev/null +++ b/dwl/.mailmap @@ -0,0 +1 @@ +Lennart Jablonka diff --git a/dwl/CHANGELOG.md b/dwl/CHANGELOG.md new file mode 100755 index 0000000..3a299c4 --- /dev/null +++ b/dwl/CHANGELOG.md @@ -0,0 +1,200 @@ +# Changelog + +* [0.7](#0.7) +* [0.6](#0.6) +* [0.5](#0.5) + + +## 0.7 + +See also [0.6](#0.6) release notes. 0.7 builds against wlroots 0.18.x. + +### Added + +* Add support for the alpha-modifier-v1 protocol ([wlroots!4616][wlroots!4616]). +* dwl now will survive GPU resets ([#601][601]). + +[wlroots!4616]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4616 +[601]: https://codeberg.org/dwl/dwl/issues/601 + + +### Fixed + +* Crash when re-mapping unmapped clients. + + +### Contributors + +Guido Cella +Lennart Jablonka + + +## 0.6 + +### Added + +* Add `rootcolor` to change the default background color ([#544][544]). +* Implement the wlr-virtual-pointer-unstable-v1 protocol ([#574][574]). +* Implement the pointer-constraints and relative-pointer protocols ([#317][317]) +* Implement the wlr-output-power-management protocol ([#599][599]) + +[544]: https://codeberg.org/dwl/dwl/pulls/544 +[574]: https://codeberg.org/dwl/dwl/pulls/574 +[317]: https://codeberg.org/dwl/dwl/issues/317 +[599]: https://codeberg.org/dwl/dwl/issues/559 + + +### Changed + +* Keyboards are now managed through keyboard groups ([#549][549]). +* Only the first matched keybinding is executed. +* Allow toggling the layout before selecting a different one ([#570][570]). +* Fullscreen clients are now rendered above wlr_layer_surfaces in the top layer + ([#609][609]). +* The default menu was changed from `bemenu-run` to `wmenu-run` ([#553][553]). +* The option `sloppyfocus` now replicates the dwm behavior ([#599][599]). +* Allow configure position of monitors with negative values. (-1, -1) is + used to auto-configure them ([#635][635]). +* dwl now kills the entire process group of `startup_cmd` +* The O_NONBLOCK flag is set for stdout. + +[549]: https://codeberg.org/dwl/dwl/pulls/549 +[570]: https://codeberg.org/dwl/dwl/pulls/570 +[609]: https://codeberg.org/dwl/dwl/pulls/609 +[553]: https://codeberg.org/dwl/dwl/issues/553 +[599]: https://codeberg.org/dwl/dwl/pulls/599 +[635]: https://codeberg.org/dwl/dwl/pulls/635 + + +### Removed + +* The SLOC limit is now removed ([#497][497]). + +[497]: https://codeberg.org/dwl/dwl/pulls/497 + + +### Fixed + +* Clients not having the correct border color when mapping. +* Compliance with the xdg-decoration-unstable-v1 ([#546][546]). +* dwl no longer sends negative values in xdg_toplevel.configure events. +* Crashes with disabled monitors ([#472][472]). + +[546]: https://codeberg.org/dwl/dwl/pulls/546 +[472]: https://codeberg.org/dwl/dwl/issues/472 + + +### Contributors + +Ben Jargowsky +Benjamin Chausse +David Donahue +Devin J. Pohly +Dima Krasner +Emil Miler +Forrest Bushstone +Guido Cella +Peter Hofmann +Rutherther +Squibid +choc +fictitiousexistence +korei999 +sewn +thanatos + + +## 0.5 + +### Added + +* Allow configure x and y position of outputs ([#301][301]) +* Implement repeatable keybindings ([#368][368]) +* Print app id in printstatus() output ([#381][381]) +* Display client count in monocle symbol ([#387][387]) +* Export XCURSOR_SIZE to fix apps using an older version of Qt ([#425][425]) +* Support for wp-fractional-scale-v1 (through wlr_scene: [wlroots!3511][wlroots!3511]) +* dwl now sends `wl_surface.preferred_buffer_scale` (through wlr_scene: [wlroots!4269][wlroots!4269]) +* Add support for xdg-shell v6 ([#465][465]) +* Add support for wp-cursor-shape-v1 ([#444][444]) +* Add desktop file ([#484][484]) +* Add macro to easily configure colors ([#466][466]) +* Color of urgent clients are now red ([#494][494]) +* New flag `-d` and option `log_level` to change the wlroots debug level +* Add CHANGELOG.md ([#501][501]) + +[301]: https://github.com/djpohly/dwl/pull/301 +[368]: https://github.com/djpohly/dwl/pull/368 +[381]: https://github.com/djpohly/dwl/pull/381 +[387]: https://github.com/djpohly/dwl/issues/387 +[425]: https://github.com/djpohly/dwl/pull/425 +[wlroots!4269]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4269 +[wlroots!3511]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3511 +[465]: https://github.com/djpohly/dwl/pull/465 +[444]: https://github.com/djpohly/dwl/pull/444 +[484]: https://github.com/djpohly/dwl/pull/484 +[466]: https://github.com/djpohly/dwl/issues/466 +[494]: https://github.com/djpohly/dwl/pull/494 +[501]: https://github.com/djpohly/dwl/pull/501 + + +### Changed + +* Replace `tags` with `TAGCOUNT` in config.def.h ([#403][403]) +* Pop ups are now destroyed when focusing another client ([#408][408]) +* dwl does not longer respect size hints, instead clip windows if they are + larger than they should be ([#455][455]) +* The version of wlr-layer-shell-unstable-v1 was lowered to 3 (from 4) +* Use the same border color as dwm ([#494][494]) + +[403]: https://github.com/djpohly/dwl/pull/403 +[408]: https://github.com/djpohly/dwl/pull/409 +[455]: https://github.com/djpohly/dwl/pull/455 +[494]: https://github.com/djpohly/dwl/pull/494 + + +### Removed + +* Remove unused `rootcolor` option ([#401][401]) +* Remove support for wlr-input-inhibitor-unstable-v1 ([#430][430]) +* Remove support for KDE idle protocol ([#431][431]) + +[401]: https://github.com/djpohly/dwl/pull/401 +[430]: https://github.com/djpohly/dwl/pull/430 +[431]: https://github.com/djpohly/dwl/pull/431 + + +### Fixed + +* Fix crash when creating a layer surface with all outputs disabled + ([#421][421]) +* Fix other clients being shown as focused if the focused client have pop ups + open ([#408][408]) +* Resize fullscreen clients when updating monitor mode +* dwl no longer crash at exit like sometimes did +* Fullscreen background appearing above clients ([#487][487]) +* Fix a segfault when user provides invalid xkb_rules ([#518][518]) + +[421]: https://github.com/djpohly/dwl/pull/421 +[408]: https://github.com/djpohly/dwl/issues/408 +[487]: https://github.com/djpohly/dwl/issues/487 +[518]: https://github.com/djpohly/dwl/pull/518 + + +### Contributors + +* A Frederick Christensen +* Angelo Antony +* Ben Collerson +* Devin J. Pohly +* Forrest Bushstone +* gan-of-culture +* godalming123 +* Job79 +* link2xt +* Micah Gorrell +* Nikita Ivanov +* Palanix +* pino-desktop +* Weiseguy +* Yves Zoundi diff --git a/dwl/LICENSE b/dwl/LICENSE new file mode 100755 index 0000000..658085a --- /dev/null +++ b/dwl/LICENSE @@ -0,0 +1,692 @@ +dwl - dwm for Wayland + +Copyright © 2020 dwl team + +See also the files LICENSE.tinywl, LICENSE.dwm and LICENSE.sway. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +---- + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/dwl/LICENSE.dwm b/dwl/LICENSE.dwm new file mode 100755 index 0000000..507e4dc --- /dev/null +++ b/dwl/LICENSE.dwm @@ -0,0 +1,39 @@ +Portions of dwl based on dwm code are used under the following license: + +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich + +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/dwl/LICENSE.sway b/dwl/LICENSE.sway new file mode 100755 index 0000000..3e0cacc --- /dev/null +++ b/dwl/LICENSE.sway @@ -0,0 +1,19 @@ +Copyright (c) 2016-2017 Drew DeVault + +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/dwl/LICENSE.tinywl b/dwl/LICENSE.tinywl new file mode 100755 index 0000000..7023690 --- /dev/null +++ b/dwl/LICENSE.tinywl @@ -0,0 +1,127 @@ +dwl is originally based on TinyWL, which is used under the following license: + +This work is licensed under CC0, which effectively puts it in the public domain. + +--- + +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/dwl/Makefile b/dwl/Makefile new file mode 100755 index 0000000..9bc67db --- /dev/null +++ b/dwl/Makefile @@ -0,0 +1,78 @@ +.POSIX: +.SUFFIXES: + +include config.mk + +# flags for compiling +DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \ + -DVERSION=\"$(VERSION)\" $(XWAYLAND) +DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \ + -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \ + -Wfloat-conversion + +# CFLAGS / LDFLAGS +PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) +DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) +LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + +all: dwl +dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ +dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h +util.o: util.c util.h + +# wayland-scanner is a tool which generates C headers and rigging for Wayland +# protocols, which are specified in XML. wlroots requires you to rig these up +# to your build system yourself and provide them in the include path. +WAYLAND_SCANNER = `$(PKG_CONFIG) --variable=wayland_scanner wayland-scanner` +WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols` + +cursor-shape-v1-protocol.h: + $(WAYLAND_SCANNER) enum-header \ + $(WAYLAND_PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@ +pointer-constraints-unstable-v1-protocol.h: + $(WAYLAND_SCANNER) enum-header \ + $(WAYLAND_PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@ +wlr-layer-shell-unstable-v1-protocol.h: + $(WAYLAND_SCANNER) enum-header \ + protocols/wlr-layer-shell-unstable-v1.xml $@ +wlr-output-power-management-unstable-v1-protocol.h: + $(WAYLAND_SCANNER) server-header \ + protocols/wlr-output-power-management-unstable-v1.xml $@ +xdg-shell-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ + +config.h: + cp config.def.h $@ +clean: + rm -f dwl *.o *-protocol.h + +dist: clean + mkdir -p dwl-$(VERSION) + cp -R LICENSE* Makefile CHANGELOG.md README.md client.h config.def.h \ + config.mk protocols dwl.1 dwl.c util.c util.h dwl.desktop \ + dwl-$(VERSION) + tar -caf dwl-$(VERSION).tar.gz dwl-$(VERSION) + rm -rf dwl-$(VERSION) + +install: dwl + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f dwl $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl + mkdir -p $(DESTDIR)$(MANDIR)/man1 + cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 + chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 + mkdir -p $(DESTDIR)$(DATADIR)/wayland-sessions + cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \ + $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + +.SUFFIXES: .c .o +.c.o: + $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -c $< diff --git a/dwl/README.md b/dwl/README.md new file mode 100755 index 0000000..aa95bab --- /dev/null +++ b/dwl/README.md @@ -0,0 +1,201 @@ +# dwl - dwm for Wayland + +Join us on our IRC channel: [#dwl on Libera Chat] +Or on our [Discord server]. + +dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is +intended to fill the same space in the Wayland world that dwm does in X11, +primarily in terms of functionality, and secondarily in terms of +philosophy. Like dwm, dwl is: + +- Easy to understand, hack on, and extend with patches +- One C source file (or a very small number) configurable via `config.h` +- Tied to as few external dependencies as possible + +## Getting Started: + +### **dwl branch 0.7 and releases based upon 0.7 build against [wlroots] 0.18** + +### Latest semi-stable [release] +This is probably where you want to start. This builds against the dependent +packages' versions currently shipping in major distributions. If your +distribution's wlroots version is older, use an earlier dwl [release] or [0.x +branch]. + +### Development branch [main] +Active development progresses on the `main` branch. The `main` branch is built +against a late (and often changing) git commit of wlroots. While the adventurous +are welcome to use `main`, it is a rocky road. Using `main` requires that the +user be willing to chase git commits of wlroots. Testing development pull +requests may involve merging unmerged pull requests in [wlroots]' git repository +and/or git commits of wayland. + +### Building dwl +dwl has the following dependencies: +- libinput +- wayland +- wlroots (compiled with the libinput backend) +- xkbcommon +- wayland-protocols (compile-time only) +- pkg-config (compile-time only) + +dwl has the following additional dependencies if XWayland support is enabled: +- libxcb +- libxcb-wm +- wlroots (compiled with X11 support) +- Xwayland (runtime only) + +Install these (and their `-devel` versions if your distro has separate +development packages) and run `make`. If you wish to build against a released +version of wlroots (*you probably do*), use a [release] or a [0.x branch]. If +you want to use the unstable development `main` branch, you need to use the git +version of [wlroots]. + +To enable XWayland, you should uncomment its flags in `config.mk`. + +## Configuration + +All configuration is done by editing `config.h` and recompiling, in the same +manner as dwm. There is no way to separately restart the window manager in +Wayland without restarting the entire display server, so any changes will take +effect the next time dwl is executed. + +As in the dwm community, we encourage users to share patches they have +created. Check out the [dwl-patches] repository! + +## Running dwl + +dwl can be run on any of the backends supported by wlroots. This means you can +run it as a separate window inside either an X11 or Wayland session, as well as +directly from a VT console. Depending on your distro's setup, you may need to +add your user to the `video` and `input` groups before you can run dwl on a +VT. If you are using `elogind` or `systemd-logind` you need to install polkit; +otherwise you need to add yourself in the `seat` group and enable/start the +seatd daemon. + +When dwl is run with no arguments, it will launch the server and begin handling +any shortcuts configured in `config.h`. There is no status bar or other +decoration initially; these are instead clients that can be run within the +Wayland session. Do note that the default background color is black. This can be +modified in `config.h`. + +If you would like to run a script or command automatically at startup, you can +specify the command using the `-s` option. This command will be executed as a +shell command using `/bin/sh -c`. It serves a similar function to `.xinitrc`, +but differs in that the display server will not shut down when this process +terminates. Instead, dwl will send this process a SIGTERM at shutdown and wait +for it to terminate (if it hasn't already). This makes it ideal for execing into +a user service manager like [s6], [anopa], [runit], [dinit], or [`systemd +--user`]. + +Note: The `-s` command is run as a *child process* of dwl, which means that it +does not have the ability to affect the environment of dwl or of any processes +that it spawns. If you need to set environment variables that affect the entire +dwl session, these must be set prior to running dwl. For example, Wayland +requires a valid `XDG_RUNTIME_DIR`, which is usually set up by a session manager +such as `elogind` or `systemd-logind`. If your system doesn't do this +automatically, you will need to configure it prior to launching `dwl`, e.g.: + + export XDG_RUNTIME_DIR=/tmp/xdg-runtime-$(id -u) + mkdir -p $XDG_RUNTIME_DIR + dwl + +### Status information + +Information about selected layouts, current window title, app-id, and +selected/occupied/urgent tags is written to the stdin of the `-s` command (see +the `printstatus()` function for details). This information can be used to +populate an external status bar with a script that parses the +information. Failing to read this information will cause dwl to block, so if you +do want to run a startup command that does not consume the status information, +you can close standard input with the `<&-` shell redirection, for example: + + dwl -s 'foot --server <&-' + +If your startup command is a shell script, you can achieve the same inside the +script with the line + + exec <&- + +To get a list of status bars that work with dwl consult our [wiki]. + +## Replacements for X applications + +You can find a [list of useful resources on our wiki]. + +## Background + +dwl is not meant to provide every feature under the sun. Instead, like dwm, it +sticks to features which are necessary, simple, and straightforward to implement +given the base on which it is built. Implemented default features are: + +- Any features provided by dwm/Xlib: simple window borders, tags, keybindings, + client rules, mouse move/resize. Providing a built-in status bar is an + exception to this goal, to avoid dependencies on font rendering and/or drawing + libraries when an external bar could work well. +- Configurable multi-monitor layout support, including position and rotation +- Configurable HiDPI/multi-DPI support +- Idle-inhibit protocol which lets applications such as mpv disable idle + monitoring +- Provide information to external status bars via stdout/stdin +- Urgency hints via xdg-activate protocol +- Support screen lockers via ext-session-lock-v1 protocol +- Various Wayland protocols +- XWayland support as provided by wlroots (can be enabled in `config.mk`) +- Zero flickering - Wayland users naturally expect that "every frame is perfect" +- Layer shell popups (used by Waybar) +- Damage tracking provided by scenegraph API + +Given the Wayland architecture, dwl has to implement features from dwm **and** +the xorg-server. Because of this, it is impossible to maintain the original +project goal of 2000 SLOC and have a reasonably complete compositor with +features comparable to dwm. However, this does not mean that the code will grow +indiscriminately. We will try to keep the code as small as possible. + +Features under consideration (possibly as patches) are: + +- Protocols made trivial by wlroots +- Implement the text-input and input-method protocols to support IME once ibus + implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and + https://codeberg.org/dwl/dwl/pulls/235) + +Feature *non-goals* for the main codebase include: + +- Client-side decoration (any more than is necessary to tell the clients not to) +- Client-initiated window management, such as move, resize, and close, which can + be done through the compositor +- Animations and visual effects + +## Acknowledgements + +dwl began by extending the TinyWL example provided (CC0) by the sway/wlroots +developers. This was made possible in many cases by looking at how sway +accomplished something, then trying to do the same in as suckless a way as +possible. + +Many thanks to suckless.org and the dwm developers and community for the +inspiration, and to the various contributors to the project, including: + +- **Devin J. Pohly for creating and nurturing the fledgling project** +- Alexander Courtis for the XWayland implementation +- Guido Cella for the layer-shell protocol implementation, patch maintenance, + and for helping to keep the project running +- Stivvo for output management and fullscreen support, and patch maintenance + + +[`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User +[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl +[0.7-rc1]: https://codeberg.org/dwl/dwl/releases/tag/v0.7-rc1 +[0.x branch]: https://codeberg.org/dwl/dwl/branches +[anopa]: https://jjacky.com/anopa/ +[dinit]: https://davmac.org/projects/dinit/ +[dwl-patches]: https://codeberg.org/dwl/dwl-patches +[list of useful resources on our wiki]: https://codeberg.org/dwl/dwl/wiki/Home#migrating-from-x +[main]: https://codeberg.org/dwl/dwl/src/branch/main +[release]: https://codeberg.org/dwl/dwl/releases +[runit]: http://smarden.org/runit/faq.html#userservices +[s6]: https://skarnet.org/software/s6/ +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ +[wiki]: https://codeberg.org/dwl/dwl/wiki/Home#compatible-status-bars +[Discord server]: https://discord.gg/jJxZnrGPWN +[Wayland]: https://wayland.freedesktop.org/ diff --git a/dwl/client.h b/dwl/client.h new file mode 100755 index 0000000..42f225f --- /dev/null +++ b/dwl/client.h @@ -0,0 +1,408 @@ +/* + * Attempt to consolidate unavoidable suck into one file, away from dwl.c. This + * file is not meant to be pretty. We use a .h file with static inline + * functions instead of a separate .c module, or function pointers like sway, so + * that they will simply compile out if the chosen #defines leave them unused. + */ + +/* Leave these functions first; they're used in the others */ +static inline int +client_is_x11(Client *c) +{ +#ifdef XWAYLAND + return c->type == X11; +#endif + return 0; +} + +static inline struct wlr_surface * +client_surface(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->surface; +#endif + return c->surface.xdg->surface; +} + +static inline int +toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) +{ + struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface; + struct wlr_surface *root_surface; + struct wlr_layer_surface_v1 *layer_surface; + Client *c = NULL; + LayerSurface *l = NULL; + int type = -1; +#ifdef XWAYLAND + struct wlr_xwayland_surface *xsurface; +#endif + + if (!s) + return -1; + root_surface = wlr_surface_get_root_surface(s); + +#ifdef XWAYLAND + if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) { + c = xsurface->data; + type = c->type; + goto end; + } +#endif + + if ((layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) { + l = layer_surface->data; + type = LayerShell; + goto end; + } + + xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface); + while (xdg_surface) { + tmp_xdg_surface = NULL; + switch (xdg_surface->role) { + case WLR_XDG_SURFACE_ROLE_POPUP: + if (!xdg_surface->popup || !xdg_surface->popup->parent) + return -1; + + tmp_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); + + if (!tmp_xdg_surface) + return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); + + xdg_surface = tmp_xdg_surface; + break; + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + c = xdg_surface->data; + type = c->type; + goto end; + case WLR_XDG_SURFACE_ROLE_NONE: + return -1; + } + } + +end: + if (pl) + *pl = l; + if (pc) + *pc = c; + return type; +} + +/* The others */ +static inline void +client_activate_surface(struct wlr_surface *s, int activated) +{ + struct wlr_xdg_toplevel *toplevel; +#ifdef XWAYLAND + struct wlr_xwayland_surface *xsurface; + if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { + wlr_xwayland_surface_activate(xsurface, activated); + return; + } +#endif + if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s))) + wlr_xdg_toplevel_set_activated(toplevel, activated); +} + +static inline uint32_t +client_set_bounds(Client *c, int32_t width, int32_t height) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return 0; +#endif + if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= + XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0 + && (c->bounds.width != width || c->bounds.height != height)) { + c->bounds.width = width; + c->bounds.height = height; + return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); + } + return 0; +} + +static inline const char * +client_get_appid(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->class; +#endif + return c->surface.xdg->toplevel->app_id; +} + +static inline void +client_get_clip(Client *c, struct wlr_box *clip) +{ + struct wlr_box xdg_geom = {0}; + *clip = (struct wlr_box){ + .x = 0, + .y = 0, + .width = c->geom.width - c->bw, + .height = c->geom.height - c->bw, + }; + +#ifdef XWAYLAND + if (client_is_x11(c)) + return; +#endif + + wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom); + clip->x = xdg_geom.x; + clip->y = xdg_geom.y; +} + +static inline void +client_get_geometry(Client *c, struct wlr_box *geom) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) { + geom->x = c->surface.xwayland->x; + geom->y = c->surface.xwayland->y; + geom->width = c->surface.xwayland->width; + geom->height = c->surface.xwayland->height; + return; + } +#endif + wlr_xdg_surface_get_geometry(c->surface.xdg, geom); +} + +static inline Client * +client_get_parent(Client *c) +{ + Client *p = NULL; +#ifdef XWAYLAND + if (client_is_x11(c)) { + if (c->surface.xwayland->parent) + toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); + return p; + } +#endif + if (c->surface.xdg->toplevel->parent) + toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL); + return p; +} + +static inline int +client_has_children(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return !wl_list_empty(&c->surface.xwayland->children); +#endif + /* surface.xdg->link is never empty because it always contains at least the + * surface itself. */ + return wl_list_length(&c->surface.xdg->link) > 1; +} + +static inline const char * +client_get_title(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->title; +#endif + return c->surface.xdg->toplevel->title; +} + +static inline int +client_is_float_type(Client *c) +{ + struct wlr_xdg_toplevel *toplevel; + struct wlr_xdg_toplevel_state state; + +#ifdef XWAYLAND + if (client_is_x11(c)) { + struct wlr_xwayland_surface *surface = c->surface.xwayland; + xcb_size_hints_t *size_hints = surface->size_hints; + size_t i; + if (surface->modal) + return 1; + + for (i = 0; i < surface->window_type_len; i++) + if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] + || surface->window_type[i] == netatom[NetWMWindowTypeSplash] + || surface->window_type[i] == netatom[NetWMWindowTypeToolbar] + || surface->window_type[i] == netatom[NetWMWindowTypeUtility]) + return 1; + + return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 + && (size_hints->max_width == size_hints->min_width + || size_hints->max_height == size_hints->min_height); + } +#endif + + toplevel = c->surface.xdg->toplevel; + state = toplevel->current; + return toplevel->parent || (state.min_width != 0 && state.min_height != 0 + && (state.min_width == state.max_width + || state.min_height == state.max_height)); +} + +static inline int +client_is_rendered_on_mon(Client *c, Monitor *m) +{ + /* This is needed for when you don't want to check formal assignment, + * but rather actual displaying of the pixels. + * Usually VISIBLEON suffices and is also faster. */ + struct wlr_surface_output *s; + int unused_lx, unused_ly; + if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly)) + return 0; + wl_list_for_each(s, &client_surface(c)->current_outputs, link) + if (s->output == m->wlr_output) + return 1; + return 0; +} + +static inline int +client_is_stopped(Client *c) +{ + int pid; + siginfo_t in = {0}; +#ifdef XWAYLAND + if (client_is_x11(c)) + return 0; +#endif + + wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); + if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) { + /* This process is not our child process, while is very unluckely that + * it is stopped, in order to do not skip frames assume that it is. */ + if (errno == ECHILD) + return 1; + } else if (in.si_pid) { + if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED) + return 1; + if (in.si_code == CLD_CONTINUED) + return 0; + } + + return 0; +} + +static inline int +client_is_unmanaged(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->override_redirect; +#endif + return 0; +} + +static inline void +client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb) +{ + if (kb) + wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes, + kb->num_keycodes, &kb->modifiers); + else + wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); +} + +static inline void +client_restack_surface(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + wlr_xwayland_surface_restack(c->surface.xwayland, NULL, + XCB_STACK_MODE_ABOVE); +#endif + return; +} + +static inline void +client_send_close(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) { + wlr_xwayland_surface_close(c->surface.xwayland); + return; + } +#endif + wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel); +} + +static inline void +client_set_border_color(Client *c, const float color[static 4]) +{ + int i; + for (i = 0; i < 4; i++) + wlr_scene_rect_set_color(c->border[i], color); +} + +static inline void +client_set_fullscreen(Client *c, int fullscreen) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) { + wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen); + return; + } +#endif + wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); +} + +static inline uint32_t +client_set_size(Client *c, uint32_t width, uint32_t height) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) { + wlr_xwayland_surface_configure(c->surface.xwayland, + c->geom.x + c->bw, c->geom.y + c->bw, width, height); + return 0; + } +#endif + if ((int32_t)width == c->surface.xdg->toplevel->current.width + && (int32_t)height == c->surface.xdg->toplevel->current.height) + return 0; + return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height); +} + +static inline void +client_set_tiled(Client *c, uint32_t edges) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return; +#endif + if (wl_resource_get_version(c->surface.xdg->toplevel->resource) + >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { + wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); + } else { + wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, edges != WLR_EDGE_NONE); + } +} + +static inline void +client_set_suspended(Client *c, int suspended) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return; +#endif + + wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); +} + +static inline int +client_wants_focus(Client *c) +{ +#ifdef XWAYLAND + return client_is_unmanaged(c) + && wlr_xwayland_or_surface_wants_focus(c->surface.xwayland) + && wlr_xwayland_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE; +#endif + return 0; +} + +static inline int +client_wants_fullscreen(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->fullscreen; +#endif + return c->surface.xdg->toplevel->requested.fullscreen; +} diff --git a/dwl/config.def.h b/dwl/config.def.h new file mode 100755 index 0000000..5008b91 --- /dev/null +++ b/dwl/config.def.h @@ -0,0 +1,212 @@ +/* Taken from https://github.com/djpohly/dwl/issues/466 */ +#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \ + ((hex >> 16) & 0xFF) / 255.0f, \ + ((hex >> 8) & 0xFF) / 255.0f, \ + (hex & 0xFF) / 255.0f } +/* appearance */ +static const int sloppyfocus = 1; /* focus follows mouse */ +static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ +static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ +static int gaps = 1; /* 1 means gaps between windows are added */ +static const unsigned int gappx = 10; /* gap pixel between windows */ +static const unsigned int borderpx = 1; /* border pixel of windows */ +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 float rootcolor[] = COLOR(0x000000ff); +/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +static uint32_t colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, + [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, + [SchemeUrg] = { 0, 0, 0x770000ff }, +}; + +/* tagging - TAGCOUNT must be no greater than 31 */ +static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +/* logging */ +static int log_level = WLR_ERROR; + +/* Autostart */ +static const char *const autostart[] = { + "wbg", "/path/to/your/image", NULL, + NULL /* terminate */ +}; + + +/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ +static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ + /* examples: */ + { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ +}; + +/* layout(s) */ +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +}; + +/* monitors */ +/* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator + * WARNING: negative values other than (-1, -1) cause problems with Xwayland clients + * https://gitlab.freedesktop.org/xorg/xserver/-/issues/899 +*/ +/* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ +static const MonitorRule monrules[] = { + /* name mfact nmaster scale layout rotate/reflect x y */ + /* example of a HiDPI laptop monitor: + { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + */ + /* defaults */ + { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, +}; + +/* keyboard */ +static const struct xkb_rule_names xkb_rules = { + /* can specify fields: rules, model, layout, variant, options */ + /* example: + .options = "ctrl:nocaps", + */ + .options = NULL, +}; + +static const int repeat_rate = 25; +static const int repeat_delay = 600; + +/* Trackpad */ +static const int tap_to_click = 1; +static const int tap_and_drag = 1; +static const int drag_lock = 1; +static const int natural_scrolling = 0; +static const int disable_while_typing = 1; +static const int left_handed = 0; +static const int middle_button_emulation = 0; +/* You can choose between: +LIBINPUT_CONFIG_SCROLL_NO_SCROLL +LIBINPUT_CONFIG_SCROLL_2FG +LIBINPUT_CONFIG_SCROLL_EDGE +LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN +*/ +static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; + +/* You can choose between: +LIBINPUT_CONFIG_CLICK_METHOD_NONE +LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS +LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER +*/ +static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + +/* You can choose between: +LIBINPUT_CONFIG_SEND_EVENTS_ENABLED +LIBINPUT_CONFIG_SEND_EVENTS_DISABLED +LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE +*/ +static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + +/* You can choose between: +LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT +LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE +*/ +static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; +static const double accel_speed = 0.0; + +/* You can choose between: +LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle +LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right +*/ +static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; + +/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ +#define MODKEY WLR_MODIFIER_ALT + +#define TAGKEYS(KEY,SKEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,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 const char *termcmd[] = { "foot", NULL }; +static const char *menucmd[] = { "wmenu-run", NULL }; + +static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_b, togglebar, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, movestack, {.i = +1} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, movestack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY, XKB_KEY_g, togglegaps, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 40, 0, 0 }}}, + { MODKEY, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, -40, 0, 0 }}}, + { MODKEY, XKB_KEY_Right, moveresizekb, {.v = (int []){ 40, 0, 0, 0 }}}, + { MODKEY, XKB_KEY_Left, moveresizekb, {.v = (int []){ -40, 0, 0, 0 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 0, 0, 40 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, 0, 0, -40 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, moveresizekb, {.v = (int []){ 0, 0, 40, 0 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, moveresizekb, {.v = (int []){ 0, 0, -40, 0 }}}, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), + TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), + TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), + TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), + TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), + TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), + TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ + { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, + /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is + * do not remove them. + */ +#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } + CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), + CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), +}; + +static const Button buttons[] = { + { ClkLtSymbol, 0, BTN_LEFT, setlayout, {.v = &layouts[0]} }, + { ClkLtSymbol, 0, BTN_RIGHT, setlayout, {.v = &layouts[2]} }, + { ClkTitle, 0, BTN_MIDDLE, zoom, {0} }, + { ClkStatus, 0, BTN_MIDDLE, spawn, {.v = termcmd} }, + { ClkClient, MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, + { ClkClient, MODKEY, BTN_MIDDLE, togglefloating, {0} }, + { ClkClient, MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + { ClkTagBar, 0, BTN_LEFT, view, {0} }, + { ClkTagBar, 0, BTN_RIGHT, toggleview, {0} }, + { ClkTagBar, MODKEY, BTN_LEFT, tag, {0} }, + { ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} }, +}; diff --git a/dwl/config.def.h.orig b/dwl/config.def.h.orig new file mode 100755 index 0000000..87594bc --- /dev/null +++ b/dwl/config.def.h.orig @@ -0,0 +1,210 @@ +/* Taken from https://github.com/djpohly/dwl/issues/466 */ +#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \ + ((hex >> 16) & 0xFF) / 255.0f, \ + ((hex >> 8) & 0xFF) / 255.0f, \ + (hex & 0xFF) / 255.0f } +/* appearance */ +static const int sloppyfocus = 1; /* focus follows mouse */ +static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ +static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ +static int gaps = 1; /* 1 means gaps between windows are added */ +static const unsigned int gappx = 10; /* gap pixel between windows */ +static const unsigned int borderpx = 1; /* border pixel of windows */ +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 float rootcolor[] = COLOR(0x000000ff); +/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +static uint32_t colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, + [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, + [SchemeUrg] = { 0, 0, 0x770000ff }, +}; + +/* tagging - TAGCOUNT must be no greater than 31 */ +static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +/* logging */ +static int log_level = WLR_ERROR; + +/* Autostart */ +static const char *const autostart[] = { + "wbg", "/path/to/your/image", NULL, + NULL /* terminate */ +}; + + +/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ +static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ + /* examples: */ + { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ +}; + +/* layout(s) */ +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +}; + +/* monitors */ +/* (x=-1, y=-1) is reserved as an "autoconfigure" monitor position indicator + * WARNING: negative values other than (-1, -1) cause problems with Xwayland clients + * https://gitlab.freedesktop.org/xorg/xserver/-/issues/899 +*/ +/* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ +static const MonitorRule monrules[] = { + /* name mfact nmaster scale layout rotate/reflect x y */ + /* example of a HiDPI laptop monitor: + { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + */ + /* defaults */ + { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, +}; + +/* keyboard */ +static const struct xkb_rule_names xkb_rules = { + /* can specify fields: rules, model, layout, variant, options */ + /* example: + .options = "ctrl:nocaps", + */ + .options = NULL, +}; + +static const int repeat_rate = 25; +static const int repeat_delay = 600; + +/* Trackpad */ +static const int tap_to_click = 1; +static const int tap_and_drag = 1; +static const int drag_lock = 1; +static const int natural_scrolling = 0; +static const int disable_while_typing = 1; +static const int left_handed = 0; +static const int middle_button_emulation = 0; +/* You can choose between: +LIBINPUT_CONFIG_SCROLL_NO_SCROLL +LIBINPUT_CONFIG_SCROLL_2FG +LIBINPUT_CONFIG_SCROLL_EDGE +LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN +*/ +static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; + +/* You can choose between: +LIBINPUT_CONFIG_CLICK_METHOD_NONE +LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS +LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER +*/ +static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + +/* You can choose between: +LIBINPUT_CONFIG_SEND_EVENTS_ENABLED +LIBINPUT_CONFIG_SEND_EVENTS_DISABLED +LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE +*/ +static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + +/* You can choose between: +LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT +LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE +*/ +static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; +static const double accel_speed = 0.0; + +/* You can choose between: +LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle +LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right +*/ +static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; + +/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ +#define MODKEY WLR_MODIFIER_ALT + +#define TAGKEYS(KEY,SKEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,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 const char *termcmd[] = { "foot", NULL }; +static const char *menucmd[] = { "wmenu-run", NULL }; + +static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_b, togglebar, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY, XKB_KEY_g, togglegaps, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 40, 0, 0 }}}, + { MODKEY, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, -40, 0, 0 }}}, + { MODKEY, XKB_KEY_Right, moveresizekb, {.v = (int []){ 40, 0, 0, 0 }}}, + { MODKEY, XKB_KEY_Left, moveresizekb, {.v = (int []){ -40, 0, 0, 0 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 0, 0, 40 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, 0, 0, -40 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, moveresizekb, {.v = (int []){ 0, 0, 40, 0 }}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, moveresizekb, {.v = (int []){ 0, 0, -40, 0 }}}, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), + TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), + TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), + TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), + TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), + TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), + TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ + { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, + /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is + * do not remove them. + */ +#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } + CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), + CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), +}; + +static const Button buttons[] = { + { ClkLtSymbol, 0, BTN_LEFT, setlayout, {.v = &layouts[0]} }, + { ClkLtSymbol, 0, BTN_RIGHT, setlayout, {.v = &layouts[2]} }, + { ClkTitle, 0, BTN_MIDDLE, zoom, {0} }, + { ClkStatus, 0, BTN_MIDDLE, spawn, {.v = termcmd} }, + { ClkClient, MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, + { ClkClient, MODKEY, BTN_MIDDLE, togglefloating, {0} }, + { ClkClient, MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + { ClkTagBar, 0, BTN_LEFT, view, {0} }, + { ClkTagBar, 0, BTN_RIGHT, toggleview, {0} }, + { ClkTagBar, MODKEY, BTN_LEFT, tag, {0} }, + { ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} }, +}; diff --git a/dwl/config.mk b/dwl/config.mk new file mode 100755 index 0000000..153e80d --- /dev/null +++ b/dwl/config.mk @@ -0,0 +1,17 @@ +_VERSION = 0.7 +VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)` + +PKG_CONFIG = pkg-config + +# paths +PREFIX = /usr/local +MANDIR = $(PREFIX)/share/man +DATADIR = $(PREFIX)/share + +#XWAYLAND = +#XLIBS = +# Uncomment to build XWayland support +XWAYLAND = -DXWAYLAND +XLIBS = xcb xcb-icccm + +CC = gcc diff --git a/dwl/drwl.h b/dwl/drwl.h new file mode 100755 index 0000000..b06a736 --- /dev/null +++ b/dwl/drwl.h @@ -0,0 +1,311 @@ +/* + * drwl - https://codeberg.org/sewn/drwl + * + * Copyright (c) 2023-2024 sewn + * Copyright (c) 2024 notchoc + * + * 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. + * + * The UTF-8 Decoder included is from Bjoern Hoehrmann: + * Copyright (c) 2008-2010 Bjoern Hoehrmann + * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + */ +#pragma once + +#include +#include +#include + +enum { ColFg, ColBg, ColBorder }; /* colorscheme index */ + +typedef struct fcft_font Fnt; +typedef pixman_image_t Img; + +typedef struct { + Img *image; + Fnt *font; + uint32_t *scheme; +} Drwl; + +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 12 +#define UTF8_INVALID 0xFFFD + +static const uint8_t utf8d[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, +}; + +static inline uint32_t +utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) +{ + uint32_t type = utf8d[byte]; + + *codep = (*state != UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + +static int +drwl_init(void) +{ + fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); + return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR); +} + +static Drwl * +drwl_create(void) +{ + Drwl *drwl; + + if (!(drwl = calloc(1, sizeof(Drwl)))) + return NULL; + + return drwl; +} + +static void +drwl_setfont(Drwl *drwl, Fnt *font) +{ + if (drwl) + drwl->font = font; +} + +static void +drwl_setimage(Drwl *drwl, Img *image) +{ + if (drwl) + drwl->image = image; +} + +static Fnt * +drwl_font_create(Drwl *drwl, size_t count, + const char *names[static count], const char *attributes) +{ + Fnt *font = fcft_from_name(count, names, attributes); + if (drwl) + drwl_setfont(drwl, font); + return font; +} + +static void +drwl_font_destroy(Fnt *font) +{ + fcft_destroy(font); +} + +static inline pixman_color_t +convert_color(uint32_t clr) +{ + return (pixman_color_t){ + ((clr >> 24) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, + ((clr >> 16) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, + ((clr >> 8) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, + (clr & 0xFF) * 0x101 + }; +} + +static void +drwl_setscheme(Drwl *drwl, uint32_t *scm) +{ + if (drwl) + drwl->scheme = scm; +} + +static Img * +drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits) +{ + Img *image; + pixman_region32_t clip; + + image = pixman_image_create_bits_no_clear( + PIXMAN_a8r8g8b8, w, h, bits, w * 4); + if (!image) + return NULL; + pixman_region32_init_rect(&clip, 0, 0, w, h); + pixman_image_set_clip_region32(image, &clip); + pixman_region32_fini(&clip); + + if (drwl) + drwl_setimage(drwl, image); + return image; +} + +static void +drwl_rect(Drwl *drwl, + int x, int y, unsigned int w, unsigned int h, + int filled, int invert) +{ + pixman_color_t clr; + if (!drwl || !drwl->scheme || !drwl->image) + return; + + clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); + if (filled) + pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1, + &(pixman_rectangle16_t){x, y, w, h}); + else + pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4, + (pixman_rectangle16_t[4]){ + { x, y, w, 1 }, + { x, y + h - 1, w, 1 }, + { x, y, 1, h }, + { x + w - 1, y, 1, h }}); +} + +static int +drwl_text(Drwl *drwl, + int x, int y, unsigned int w, unsigned int h, + unsigned int lpad, const char *text, int invert) +{ + int ty; + int render = x || y || w || h; + long x_kern; + uint32_t cp = 0, last_cp = 0, state; + pixman_color_t clr; + pixman_image_t *fg_pix = NULL; + int noellipsis = 0; + const struct fcft_glyph *glyph, *eg = NULL; + int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; + + if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font) + return 0; + + if (!render) { + w = invert ? invert : ~invert; + } else { + clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); + fg_pix = pixman_image_create_solid_fill(&clr); + + drwl_rect(drwl, x, y, w, h, 1, !invert); + + x += lpad; + w -= lpad; + } + + if (render && (drwl->scheme[ColBg] & 0xFF) != 0xFF) + fcft_subpixel_mode = FCFT_SUBPIXEL_NONE; + + if (render) + eg = fcft_rasterize_char_utf32(drwl->font, 0x2026 /* … */, fcft_subpixel_mode); + + for (const char *p = text, *pp; pp = p, *p; p++) { + for (state = UTF8_ACCEPT; *p && + utf8decode(&state, &cp, *p) > UTF8_REJECT; p++) + ; + if (!*p || state == UTF8_REJECT) { + cp = UTF8_INVALID; + if (p > pp) + p--; + } + + glyph = fcft_rasterize_char_utf32(drwl->font, cp, fcft_subpixel_mode); + if (!glyph) + continue; + + x_kern = 0; + if (last_cp) + fcft_kerning(drwl->font, last_cp, cp, &x_kern, NULL); + last_cp = cp; + + ty = y + (h - drwl->font->height) / 2 + drwl->font->ascent; + + if (render && !noellipsis && x_kern + glyph->advance.x + eg->advance.x > w && + *(p + 1) != '\0') { + /* cannot fit ellipsis after current codepoint */ + if (drwl_text(drwl, 0, 0, 0, 0, 0, pp, 0) + x_kern <= w) { + noellipsis = 1; + } else { + w -= eg->advance.x; + pixman_image_composite32( + PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0, + x + eg->x, ty - eg->y, eg->width, eg->height); + } + } + + if ((x_kern + glyph->advance.x) > w) + break; + + x += x_kern; + + if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) + /* pre-rendered glyphs (eg. emoji) */ + pixman_image_composite32( + PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0, + x + glyph->x, ty - glyph->y, glyph->width, glyph->height); + else if (render) + pixman_image_composite32( + PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0, + x + glyph->x, ty - glyph->y, glyph->width, glyph->height); + + x += glyph->advance.x; + w -= glyph->advance.x; + } + + if (render) + pixman_image_unref(fg_pix); + + return x + (render ? w : 0); +} + +static unsigned int +drwl_font_getwidth(Drwl *drwl, const char *text) +{ + if (!drwl || !drwl->font || !text) + return 0; + return drwl_text(drwl, 0, 0, 0, 0, 0, text, 0); +} + +static void +drwl_image_destroy(Img *image) +{ + pixman_image_unref(image); +} + +static void +drwl_destroy(Drwl *drwl) +{ + if (drwl->font) + drwl_font_destroy(drwl->font); + if (drwl->image) + drwl_image_destroy(drwl->image); + free(drwl); +} + +static void +drwl_fini(void) +{ + fcft_fini(); +} diff --git a/dwl/dwl-patches/LICENSE b/dwl/dwl-patches/LICENSE new file mode 100755 index 0000000..658085a --- /dev/null +++ b/dwl/dwl-patches/LICENSE @@ -0,0 +1,692 @@ +dwl - dwm for Wayland + +Copyright © 2020 dwl team + +See also the files LICENSE.tinywl, LICENSE.dwm and LICENSE.sway. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +---- + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/dwl/dwl-patches/LICENSE.dwm b/dwl/dwl-patches/LICENSE.dwm new file mode 100755 index 0000000..507e4dc --- /dev/null +++ b/dwl/dwl-patches/LICENSE.dwm @@ -0,0 +1,39 @@ +Portions of dwl based on dwm code are used under the following license: + +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich + +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/dwl/dwl-patches/LICENSE.sway b/dwl/dwl-patches/LICENSE.sway new file mode 100755 index 0000000..3e0cacc --- /dev/null +++ b/dwl/dwl-patches/LICENSE.sway @@ -0,0 +1,19 @@ +Copyright (c) 2016-2017 Drew DeVault + +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/dwl/dwl-patches/LICENSE.tinywl b/dwl/dwl-patches/LICENSE.tinywl new file mode 100755 index 0000000..7023690 --- /dev/null +++ b/dwl/dwl-patches/LICENSE.tinywl @@ -0,0 +1,127 @@ +dwl is originally based on TinyWL, which is used under the following license: + +This work is licensed under CC0, which effectively puts it in the public domain. + +--- + +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/dwl/dwl-patches/README.md b/dwl/dwl-patches/README.md new file mode 100755 index 0000000..bdfa62a --- /dev/null +++ b/dwl/dwl-patches/README.md @@ -0,0 +1,87 @@ +# dwl-patches +* A general [dwl wiki](https://codeberg.org/dwl/dwl/wiki) is available at the main [dwl] repository. +* This repository is exclusively for dwl PATCHES. + +*Note: All patches are user-submitted content. The authors of dwl do not continually monitor them. You are responsible for downloading and reviewing a patch before using it!* + +## Reporting Issues +- Issues with existing patches can be generated here in the dwl-patches [issues]. Please be sure to "@" reference the patch author in your issue. + +## Contributing Patches to `dwl-patches` +Since dwl follows [suckless](https://suckless.org/) philosophy, it doesn't provide every feature under the sun. To broaden dwl's functionality, one needs to get familiar with the concept of patching. To get your feet wet, consult [the hacking page](https://suckless.org/hacking/) of the suckless website. + +Patches should normally target the latest dwl [release]. +If you target an older release, specify that in the `Download` link on your `README.md` page. +If you target the unstable `main` branch, specify that in the `Download` link on your `README.md` page. + +0. Starting from a local clone of [dwl] (not dwl-patches) +1. If you do not have it already, add the remote for the main dwl repository in your local copy and fetch it: + `git remote add --fetch upstream https://codeberg.org/dwl/dwl` +2. Use git to create a branch for your new patch and hack away creating your patched version of [dwl]. +3. In your local clone of dwl, create a .patch file + `git format-patch upstream/main... --stdout > PATCHNAME.patch` +4. Now fork [dwl-patches] (not dwl) in Codeberg and clone it locally +5. Configure your `dwl-patches` local clone + `git config --local pull.rebase true` +6. In your local `dwl-patches` clone, add a directory called `patches/PATCHNAME`. Place the `PATCHNAME.patch` you created in step (2) into the `patches/PATCHNAME` directory. +7. Add a `README.md` page to the `PATCHNAME` directory using this template (add/remove sections as you like): + ```markdown + ### Description + Insert a short summary of changes that your patch implements. + + ### Download + - [git branch](/USERNAME/dwl/src/branch/PATCHNAME) + ^^^^^^^^^^ OPTIONAL: Patchers are no longer obligated to maintain public `dwl` branches devoted to their patches + - [0.7](/dwl/dwl-patches/raw/branch/main/patches/PATCHNAME/PATCHNAME.patch) + Use the ^RAW^ patch link here + ^^^ "0.7" is an example. Use the release that your patch targets + - [main YYYY-MM-DD](/dwl/dwl-patches/raw/branch/main/patches/PATCHNAME/PATCHNAME.patch) + ^^^^^^^^^^ Patches targeting the unstable "main" branch include a YYYY-MM-DD indicator + ### Authors - latest at top [Codeberg nick is mandatory; other contact methods optional] + - [YOUR_NICK](https://codeberg.org/USERNAME) + your_email@if_you_wish_to.share.it + your_irc_nick at [Libera IRC dwl channel](https://web.libera.chat/?channels=#dwl) + your_discord_handle at [dwl Discord](https://discord.gg/jJxZnrGPWN) + ``` + You may choose to include screenshots (hosted in your patch's subdirectory) in your `README.md`. The process is described [here](https://docs.codeberg.org/markdown/using-images/). + +8. Use the Codeberg web interface to send a pull request to [dwl-patches] (NOT to [dwl]) +9. WHEN YOUR PULL REQUEST IS APPROVED, your Codeberg account will also be granted commit access to [dwl-patches]. Once you have write access, you can make direct modifications/upates to your patches and you are free to create new patches rather than creating pull requests. + +Individuals who have made known that they no longer intend to maintain their patches will have commit access to the [dwl-pathces] repository removed. + +A returning user who formerly had commit access is welcome to open an issue on [dwl-patches] requesting commit access be reinstated. When doing so, please link to the original issue opened that granted commit access. + +## Updating/Modifying/Adopting Existing Patches +- If the existing patch is already being maintained by another author, do not make modifications to it. +- Create an issue at [issues] @mentioning the current maintainer. +- If you receive no reply for seven days, you may assume the patch abandoned and you may adopt the patch. +- Modify the `README.md` with new links for your raw patch and for your git branch. + - **LEAVE PREVIOUS AUTHOR(S)' NICKS/LINKS INTACT UNDER THE "Authors" HEADING!** + - Add your own nick/link to the top of the "Authors" list. + +## Deprecating Existing Patches +- Patches will not be removed from this archive but may instead be deprecated if the author(s)/maintainer(s) of a patch so desire. +- Please do not open issues or contact maintainers to request deprecation of a patch. +- Deprecation of a patch will only occur if *all* authors or current maintainers of the patch agree to the decision to deprecate. +- In such a circumstance the author(s)/maintainer(s): + - Will create a commit moving the patch to the `stale-patches` directory + - May explain in the associated `README.md` any relevant details of the decision to deprecate the patch. +- This process allows current or future users of the patch the option to adopt, modify, or integrate stale/historical code or portions thereof. + +## stale-patches +Deprecated or unmaintained patches are held in the [stale-patches] directory. +Currently, this directory also contains `.md` description files from ancient patches predating the move to Codeberg. + +If you have the inclination to revive one of these, please follow the same procedures outlined below for contributing new patches. + +In your initial pull request (or in the commit that revives the stale patch if you already have write access), remove the corresponding `.md` file or the patch directory from [stale-patches]. + +[stale-patches]: https://codeberg.org/dwl/dwl-patches/src/branch/main/stale-patches +[dwl]: https://codeberg.org/dwl/dwl +[dwl-patches]: https://codeberg.org/dwl/dwl-patches +[issues]: https://codeberg.org/dwl/dwl-patches/issues +[release]: https://codeberg.org/dwl/dwl/releases +[Codeberg]: https://codeberg.org + +## diff --git a/dwl/dwl-patches/patches/accessnthmon/README.md b/dwl/dwl-patches/patches/accessnthmon/README.md new file mode 100755 index 0000000..b7cd6a9 --- /dev/null +++ b/dwl/dwl-patches/patches/accessnthmon/README.md @@ -0,0 +1,9 @@ +### Description +Port of dwm's accessnthmon. Adds functions to tag and focus monitor by index. + +### Download +- [git branch](https://codeberg.org/Rutherther/dwl/src/branch/patch/accessnthmonitor) +- [2024-05-10](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/accessnthmon/accessnthmon.patch) +### Authors +- [Rutherther](https://codeberg.org/Rutherther) +- [Palanix](https://codeberg.org/Palanix) diff --git a/dwl/dwl-patches/patches/accessnthmon/accessnthmon.patch b/dwl/dwl-patches/patches/accessnthmon/accessnthmon.patch new file mode 100755 index 0000000..f69f57d --- /dev/null +++ b/dwl/dwl-patches/patches/accessnthmon/accessnthmon.patch @@ -0,0 +1,122 @@ +From 5f531bfb1387ded7b8817faf7df760d3b998742b Mon Sep 17 00:00:00 2001 +From: Rutherther +Date: Sat, 27 Apr 2024 21:25:16 +0200 +Subject: [PATCH] feat: access nth monitor + +--- + config.def.h | 4 +++- + dwl.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 8847e58..4709c5d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -108,7 +108,9 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } ++ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }, \ ++ { WLR_MODIFIER_ALT, KEY, focusnthmon, {.ui = TAG} }, \ ++ { WLR_MODIFIER_ALT|WLR_MODIFIER_SHIFT, SKEY, tagnthmon, {.ui = TAG} } + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +diff --git a/dwl.c b/dwl.c +index bf763df..1d42caf 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -278,8 +279,10 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data); + static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static Monitor *numtomon(int num); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); ++static void focusnthmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); +@@ -329,6 +332,7 @@ static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static void tagnthmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); +@@ -1233,6 +1237,25 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++Monitor * ++numtomon(int num) ++{ ++ Monitor *m = NULL; ++ int found = 0; ++ int i = 0; ++ ++ wl_list_for_each(m, &mons, link) { ++ if (!m->wlr_output->enabled) ++ i--; ++ else if (i == num) { ++ found = true; ++ break; ++ } ++ i++; ++ } ++ return found ? m : NULL; ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1320,6 +1343,16 @@ focusmon(const Arg *arg) + focusclient(focustop(selmon), 1); + } + ++void ++focusnthmon(const Arg *arg) ++{ ++ Monitor *m = numtomon(arg->i); ++ if (!m || m == selmon) ++ return; ++ selmon = m; ++ focusclient(focustop(selmon), 1); ++} ++ + void + focusstack(const Arg *arg) + { +@@ -2569,6 +2602,19 @@ tagmon(const Arg *arg) + setmon(sel, dirtomon(arg->i), 0); + } + ++void ++tagnthmon(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ Monitor *m = numtomon(arg->i); ++ if (!m || !sel) ++ return; ++ setmon(sel, m, 0); ++ ++ arrange(selmon); ++ arrange(m); ++} ++ + void + tile(Monitor *m) + { +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/alwayscenter/README.md b/dwl/dwl-patches/patches/alwayscenter/README.md new file mode 100755 index 0000000..63d6f86 --- /dev/null +++ b/dwl/dwl-patches/patches/alwayscenter/README.md @@ -0,0 +1,9 @@ +### Description +Automatically center floating windows. + +### Download +- [git branch](https://codeberg.org/guidocella/dwl/src/branch/alwayscenter) +- [2024-06-05](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/alwayscenter/alwayscenter.patch) + +### Authors +- [Guido Cella](https://codeberg.org/guidocella) diff --git a/dwl/dwl-patches/patches/alwayscenter/alwayscenter.patch b/dwl/dwl-patches/patches/alwayscenter/alwayscenter.patch new file mode 100755 index 0000000..59a83dc --- /dev/null +++ b/dwl/dwl-patches/patches/alwayscenter/alwayscenter.patch @@ -0,0 +1,39 @@ +From f43a49324c2ddd21100d6308d1adde9d894746e2 Mon Sep 17 00:00:00 2001 +From: Guido Cella +Date: Wed, 5 Jun 2024 12:05:16 +0200 +Subject: [PATCH] center floating windows + +--- + dwl.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/dwl.c b/dwl.c +index 12f441e..c377c67 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -499,6 +499,11 @@ applyrules(Client *c) + } + } + ++ if (mon) { ++ c->geom.x = (mon->w.width - c->geom.width) / 2 + mon->m.x; ++ c->geom.y = (mon->w.height - c->geom.height) / 2 + mon->m.y; ++ } ++ + c->isfloating |= client_is_float_type(c); + setmon(c, mon, newtags); + } +@@ -1787,6 +1792,10 @@ mapnotify(struct wl_listener *listener, void *data) + * If there is no parent, apply rules */ + if ((p = client_get_parent(c))) { + c->isfloating = 1; ++ if (p->mon) { ++ c->geom.x = (p->mon->w.width - c->geom.width) / 2 + p->mon->m.x; ++ c->geom.y = (p->mon->w.height - c->geom.height) / 2 + p->mon->m.y; ++ } + setmon(c, p->mon, p->tags); + } else { + applyrules(c); +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/attachbottom/README.md b/dwl/dwl-patches/patches/attachbottom/README.md new file mode 100755 index 0000000..80e12a0 --- /dev/null +++ b/dwl/dwl-patches/patches/attachbottom/README.md @@ -0,0 +1,10 @@ +### Description +Newly created windows are placed at the bottom of the client tile stack. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/attachbottom) +- [2024-05-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/attachbottom/attachbottom.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) +- [Aurel Weinhold](https://github.com/AurelWeinhold) diff --git a/dwl/dwl-patches/patches/attachbottom/attachbottom.patch b/dwl/dwl-patches/patches/attachbottom/attachbottom.patch new file mode 100755 index 0000000..470a79b --- /dev/null +++ b/dwl/dwl-patches/patches/attachbottom/attachbottom.patch @@ -0,0 +1,29 @@ +From 0dda3ed8634154fd3887b71133b451d66a11b61d Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Thu, 4 Jan 2024 23:31:41 +1000 +Subject: [PATCH] attachbottom + +--- + dwl.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index bf763dfc..12e08e2b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1605,7 +1605,11 @@ mapnotify(struct wl_listener *listener, void *data) + c->geom.height += 2 * c->bw; + + /* Insert this client into client lists. */ +- wl_list_insert(&clients, &c->link); ++ if (clients.prev) ++ // tile at the bottom ++ wl_list_insert(clients.prev, &c->link); ++ else ++ wl_list_insert(&clients, &c->link); + wl_list_insert(&fstack, &c->flink); + + /* Set initial monitor, tags, floating status, and focus: +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/attachfocused/README.md b/dwl/dwl-patches/patches/attachfocused/README.md new file mode 100755 index 0000000..a4f6049 --- /dev/null +++ b/dwl/dwl-patches/patches/attachfocused/README.md @@ -0,0 +1,11 @@ +### Description +Makes windows attach below the currently active window. + +KNOWN ISSUES: Upon closing the last client when using multiple monitors, the last client will briefly flash on all +monitors before closing. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/attachfocused/attachfocused.patch) + +### Authors +- [MayOrMayNotBeACat](https://codeberg.org/MayOrMayNotBeACat) diff --git a/dwl/dwl-patches/patches/attachfocused/attachfocused.patch b/dwl/dwl-patches/patches/attachfocused/attachfocused.patch new file mode 100755 index 0000000..2b8cd38 --- /dev/null +++ b/dwl/dwl-patches/patches/attachfocused/attachfocused.patch @@ -0,0 +1,29 @@ +From d03851c14073874f5b3d19a095e184dc24d219cd Mon Sep 17 00:00:00 2001 +From: MayOrMayNotBeACat +Date: Sun, 11 May 2025 20:24:51 -0400 +Subject: [PATCH] Make new windows attach to active client + +--- + dwl.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index cf3ef70..1907c5f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1726,7 +1726,11 @@ mapnotify(struct wl_listener *listener, void *data) + c->geom.height += 2 * c->bw; + + /* Insert this client into client lists. */ +- wl_list_insert(&clients, &c->link); ++ Client* focused = focustop(selmon); ++ if (focused) ++ wl_list_insert(&focused->link, &c->link); ++ else ++ wl_list_insert(&clients, &c->link); + wl_list_insert(&fstack, &c->flink); + + /* Set initial monitor, tags, floating status, and focus: +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/attachtop/README.md b/dwl/dwl-patches/patches/attachtop/README.md new file mode 100755 index 0000000..0241b7d --- /dev/null +++ b/dwl/dwl-patches/patches/attachtop/README.md @@ -0,0 +1,13 @@ +### Description +This is a port of attachtop patch for dwm: https://dwm.suckless.org/patches/attachtop + +New client attaches below the last master/on top of the stack. + +Behavior feels very intuitive as it doesn't disrupt existing masters no matter the amount of them, it only pushes the clients in stack down. + +### Download +- [git branch](https://codeberg.org/nikitaivanov/dwl/src/branch/attachtop) +- [2025-06-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/attachtop/attachtop.patch) + +### Authors +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) diff --git a/dwl/dwl-patches/patches/attachtop/attachtop.patch b/dwl/dwl-patches/patches/attachtop/attachtop.patch new file mode 100755 index 0000000..d447246 --- /dev/null +++ b/dwl/dwl-patches/patches/attachtop/attachtop.patch @@ -0,0 +1,36 @@ +From 29e6a4bef02c473cc5bd04804fe508bda265077d Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Sun, 7 Apr 2024 21:10:17 +0200 +Subject: [PATCH] New client are attached on top of the stack + +--- + dwl.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index bf763df..02e3d07 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1605,7 +1605,18 @@ mapnotify(struct wl_listener *listener, void *data) + c->geom.height += 2 * c->bw; + + /* Insert this client into client lists. */ +- wl_list_insert(&clients, &c->link); ++ i = 0; ++ wl_list_for_each(w, &clients, link) { ++ if (!VISIBLEON(w, selmon) || w->isfloating) ++ continue; ++ p = w; ++ if (++i >= selmon->nmaster) ++ break; ++ } ++ if (i > 0) ++ wl_list_insert(&p->link, &c->link); ++ else ++ wl_list_insert(&clients, &c->link); + wl_list_insert(&fstack, &c->flink); + + /* Set initial monitor, tags, floating status, and focus: +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/autostart/README.md b/dwl/dwl-patches/patches/autostart/README.md new file mode 100755 index 0000000..1fd26d3 --- /dev/null +++ b/dwl/dwl-patches/patches/autostart/README.md @@ -0,0 +1,14 @@ +### Description +Allow dwl to execute commands from autostart array in your config.h file. And when you exit dwl all processes from autostart array will be killed. + +Note: Commands from array are executed using execvp(). So if you need to execute shell command you need to prefix it with "sh", "-c" (change sh to any shell you like). + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/autostart) +- [2025-01-20](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/autostart/autostart.patch) +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/autostart/autostart-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) +- [Rayan Nakib](https://nakibrayan2.pages.dev/) +- [NFVblog](https://github.com/nf02) diff --git a/dwl/dwl-patches/patches/autostart/autostart-0.7.patch b/dwl/dwl-patches/patches/autostart/autostart-0.7.patch new file mode 100755 index 0000000..12e6d7e --- /dev/null +++ b/dwl/dwl-patches/patches/autostart/autostart-0.7.patch @@ -0,0 +1,154 @@ +From 787f7252d63945996f009828aff3c44afd0f7781 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sat, 8 Jul 2023 17:11:36 -0600 +Subject: [PATCH] port autostart patch from dwm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://dwm.suckless.org/patches/cool_autostart/ +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 7 +++++++ + dwl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 61 insertions(+), 5 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..8dc6502 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,13 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + /* logging */ + static int log_level = WLR_ERROR; + ++/* Autostart */ ++static const char *const autostart[] = { ++ "wbg", "/path/to/your/image", NULL, ++ NULL /* terminate */ ++}; ++ ++ + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ +diff --git a/dwl.c b/dwl.c +index 5bf995e..e8b8727 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -249,6 +249,7 @@ static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); ++static void autostartexec(void); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); +@@ -432,6 +433,9 @@ static xcb_atom_t netatom[NetLast]; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++static pid_t *autostart_pids; ++static size_t autostart_len; ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -580,6 +584,27 @@ arrangelayers(Monitor *m) + } + } + ++void ++autostartexec(void) { ++ const char *const *p; ++ size_t i = 0; ++ ++ /* count entries */ ++ for (p = autostart; *p; autostart_len++, p++) ++ while (*++p); ++ ++ autostart_pids = calloc(autostart_len, sizeof(pid_t)); ++ for (p = autostart; *p; i++, p++) { ++ if ((autostart_pids[i] = fork()) == 0) { ++ setsid(); ++ execvp(*p, (char *const *)p); ++ die("dwl: execvp %s:", *p); ++ } ++ /* skip arguments */ ++ while (*++p); ++ } ++} ++ + void + axisnotify(struct wl_listener *listener, void *data) + { +@@ -676,11 +701,21 @@ checkidleinhibitor(struct wlr_surface *exclude) + void + cleanup(void) + { ++ size_t i; + #ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; + #endif + wl_display_destroy_clients(dpy); ++ ++ /* kill child processes */ ++ for (i = 0; i < autostart_len; i++) { ++ if (0 < autostart_pids[i]) { ++ kill(autostart_pids[i], SIGTERM); ++ waitpid(autostart_pids[i], NULL, 0); ++ } ++ } ++ + if (child_pid > 0) { + kill(-child_pid, SIGTERM); + waitpid(child_pid, NULL, 0); +@@ -1497,18 +1532,31 @@ void + handlesig(int signo) + { + if (signo == SIGCHLD) { +-#ifdef XWAYLAND + siginfo_t in; + /* wlroots expects to reap the XWayland process itself, so we + * use WNOWAIT to keep the child waitable until we know it's not + * XWayland. + */ + while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid +- && (!xwayland || in.si_pid != xwayland->server->pid)) +- waitpid(in.si_pid, NULL, 0); +-#else +- while (waitpid(-1, NULL, WNOHANG) > 0); ++#ifdef XWAYLAND ++ && (!xwayland || in.si_pid != xwayland->server->pid) + #endif ++ ) { ++ pid_t *p, *lim; ++ waitpid(in.si_pid, NULL, 0); ++ if (in.si_pid == child_pid) ++ child_pid = -1; ++ if (!(p = autostart_pids)) ++ continue; ++ lim = &p[autostart_len]; ++ ++ for (; p < lim; p++) { ++ if (*p == in.si_pid) { ++ *p = -1; ++ break; ++ } ++ } ++ } + } else if (signo == SIGINT || signo == SIGTERM) { + quit(NULL); + } +@@ -2224,6 +2272,7 @@ run(char *startup_cmd) + die("startup: backend_start"); + + /* Now that the socket exists and the backend is started, run the startup command */ ++ autostartexec(); + if (startup_cmd) { + int piperw[2]; + if (pipe(piperw) < 0) +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/autostart/autostart.patch b/dwl/dwl-patches/patches/autostart/autostart.patch new file mode 100755 index 0000000..71d8718 --- /dev/null +++ b/dwl/dwl-patches/patches/autostart/autostart.patch @@ -0,0 +1,148 @@ +From 3b0b0249d900121a90528616f4d11f733c7a5ca2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sat, 8 Jul 2023 17:11:36 -0600 +Subject: [PATCH] port autostart patch from dwm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://dwm.suckless.org/patches/cool_autostart/ +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 7 +++++++ + dwl.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 62 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..8dc6502c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,13 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + /* logging */ + static int log_level = WLR_ERROR; + ++/* Autostart */ ++static const char *const autostart[] = { ++ "wbg", "/path/to/your/image", NULL, ++ NULL /* terminate */ ++}; ++ ++ + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ +diff --git a/dwl.c b/dwl.c +index ad21e1ba..3118e07f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -246,6 +246,7 @@ static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); ++static void autostartexec(void); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); +@@ -455,6 +456,9 @@ static struct wlr_xwayland *xwayland; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++static pid_t *autostart_pids; ++static size_t autostart_len; ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -599,6 +603,27 @@ arrangelayers(Monitor *m) + } + } + ++void ++autostartexec(void) { ++ const char *const *p; ++ size_t i = 0; ++ ++ /* count entries */ ++ for (p = autostart; *p; autostart_len++, p++) ++ while (*++p); ++ ++ autostart_pids = calloc(autostart_len, sizeof(pid_t)); ++ for (p = autostart; *p; i++, p++) { ++ if ((autostart_pids[i] = fork()) == 0) { ++ setsid(); ++ execvp(*p, (char *const *)p); ++ die("dwl: execvp %s:", *p); ++ } ++ /* skip arguments */ ++ while (*++p); ++ } ++} ++ + void + axisnotify(struct wl_listener *listener, void *data) + { +@@ -695,12 +720,23 @@ checkidleinhibitor(struct wlr_surface *exclude) + void + cleanup(void) + { ++ size_t i; ++ + cleanuplisteners(); + #ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; + #endif + wl_display_destroy_clients(dpy); ++ ++ /* kill child processes */ ++ for (i = 0; i < autostart_len; i++) { ++ if (0 < autostart_pids[i]) { ++ kill(autostart_pids[i], SIGTERM); ++ waitpid(autostart_pids[i], NULL, 0); ++ } ++ } ++ + if (child_pid > 0) { + kill(-child_pid, SIGTERM); + waitpid(child_pid, NULL, 0); +@@ -1551,10 +1587,25 @@ gpureset(struct wl_listener *listener, void *data) + void + handlesig(int signo) + { +- if (signo == SIGCHLD) +- while (waitpid(-1, NULL, WNOHANG) > 0); +- else if (signo == SIGINT || signo == SIGTERM) ++ if (signo == SIGCHLD) { ++ pid_t pid, *p, *lim; ++ while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { ++ if (pid == child_pid) ++ child_pid = -1; ++ if (!(p = autostart_pids)) ++ continue; ++ lim = &p[autostart_len]; ++ ++ for (; p < lim; p++) { ++ if (*p == pid) { ++ *p = -1; ++ break; ++ } ++ } ++ } ++ } else if (signo == SIGINT || signo == SIGTERM) { + quit(NULL); ++ } + } + + void +@@ -2241,6 +2292,7 @@ run(char *startup_cmd) + die("startup: backend_start"); + + /* Now that the socket exists and the backend is started, run the startup command */ ++ autostartexec(); + if (startup_cmd) { + int piperw[2]; + if (pipe(piperw) < 0) +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/bar-systray/README.md b/dwl/dwl-patches/patches/bar-systray/README.md new file mode 100755 index 0000000..b504173 --- /dev/null +++ b/dwl/dwl-patches/patches/bar-systray/README.md @@ -0,0 +1,19 @@ +### Description +Add a system tray to the [bar](/dwl/dwl-patches/src/branch/main/patches/bar). + +To keep dependencies to minimum, icon(svg) loading from the filesystem is not +supported. Applications that expect this will show the initial letter of the +program name, instead of a real icon. + +Menus for the icons are handled by a dmenu-like program of the user's choice. + +### Dependencies +- [bar.patch](/dwl/dwl-patches/src/branch/main/patches/bar) +- [libdbus](https://gitlab.freedesktop.org/dbus/dbus) + +### Download +- [git branch](/janetski/dwl/src/branch/0.7-bar-systray) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/bar-systray/bar-systray-0.7.patch) + +### Authors +- [janetski](https://codeberg.org/janetski) ([.vetu](https://discordapp.com/users/355488216469471242) on discord) diff --git a/dwl/dwl-patches/patches/bar-systray/bar-systray-0.7.patch b/dwl/dwl-patches/patches/bar-systray/bar-systray-0.7.patch new file mode 100755 index 0000000..1dda4c6 --- /dev/null +++ b/dwl/dwl-patches/patches/bar-systray/bar-systray-0.7.patch @@ -0,0 +1,3023 @@ +From cf228147250f4616d150fbe5276088c5f9969bba Mon Sep 17 00:00:00 2001 +From: vetu104 +Date: Sat, 29 Mar 2025 19:22:37 +0200 +Subject: [PATCH] Add a system tray next to sewn's bar + +--- + Makefile | 23 +- + config.def.h | 5 + + dbus.c | 242 +++++++++++++++ + dbus.h | 10 + + dwl.c | 107 ++++++- + systray/helpers.c | 43 +++ + systray/helpers.h | 12 + + systray/icon.c | 149 +++++++++ + systray/icon.h | 26 ++ + systray/item.c | 403 ++++++++++++++++++++++++ + systray/item.h | 46 +++ + systray/menu.c | 757 ++++++++++++++++++++++++++++++++++++++++++++++ + systray/menu.h | 11 + + systray/tray.c | 237 +++++++++++++++ + systray/tray.h | 37 +++ + systray/watcher.c | 551 +++++++++++++++++++++++++++++++++ + systray/watcher.h | 35 +++ + 17 files changed, 2681 insertions(+), 13 deletions(-) + create mode 100644 dbus.c + create mode 100644 dbus.h + create mode 100644 systray/helpers.c + create mode 100644 systray/helpers.h + create mode 100644 systray/icon.c + create mode 100644 systray/icon.h + create mode 100644 systray/item.c + create mode 100644 systray/item.h + create mode 100644 systray/menu.c + create mode 100644 systray/menu.h + create mode 100644 systray/tray.c + create mode 100644 systray/tray.h + create mode 100644 systray/watcher.c + create mode 100644 systray/watcher.h + +diff --git a/Makefile b/Makefile +index 9bc67db..9d50189 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,17 +12,28 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) ++PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) dbus-1 + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + ++TRAYOBJS = systray/watcher.o systray/tray.o systray/item.o systray/icon.o systray/menu.o systray/helpers.o ++TRAYDEPS = systray/watcher.h systray/tray.h systray/item.h systray/icon.h systray/menu.h systray/helpers.h ++ + all: dwl +-dwl: dwl.o util.o +- $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ +-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ ++dwl: dwl.o util.o dbus.o $(TRAYOBJS) $(TRAYDEPS) ++ $(CC) dwl.o util.o dbus.o $(TRAYOBJS) $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ ++dwl.o: dwl.c client.h dbus.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ +- wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ ++ $(TRAYDEPS) + util.o: util.c util.h ++dbus.o: dbus.c dbus.h ++systray/watcher.o: systray/watcher.c $(TRAYDEPS) ++systray/tray.o: systray/tray.c $(TRAYDEPS) ++systray/item.o: systray/item.c $(TRAYDEPS) ++systray/icon.o: systray/icon.c $(TRAYDEPS) ++systray/menu.o: systray/menu.c $(TRAYDEPS) ++systray/helpers.o: systray/helpers.c $(TRAYDEPS) + + # wayland-scanner is a tool which generates C headers and rigging for Wayland + # protocols, which are specified in XML. wlroots requires you to rig these up +@@ -49,7 +60,7 @@ xdg-shell-protocol.h: + config.h: + cp config.def.h $@ + clean: +- rm -f dwl *.o *-protocol.h ++ rm -f dwl *.o *-protocol.h systray/*.o + + dist: clean + mkdir -p dwl-$(VERSION) +diff --git a/config.def.h b/config.def.h +index 5d1dc2b..451643e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,8 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int systrayspacing = 2; /* systray spacing */ ++static const int showsystray = 1; /* 0 means no systray */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = {"monospace:size=10"}; +@@ -127,6 +129,7 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + /* commands */ + static const char *termcmd[] = { "foot", NULL }; + static const char *menucmd[] = { "wmenu-run", NULL }; ++static const char *dmenucmd[] = { "wmenu", NULL }; + + static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ +@@ -188,4 +191,6 @@ static const Button buttons[] = { + { ClkTagBar, 0, BTN_RIGHT, toggleview, {0} }, + { ClkTagBar, MODKEY, BTN_LEFT, tag, {0} }, + { ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} }, ++ { ClkTray, 0, BTN_LEFT, trayactivate, {0} }, ++ { ClkTray, 0, BTN_RIGHT, traymenu, {0} }, + }; +diff --git a/dbus.c b/dbus.c +new file mode 100644 +index 0000000..125312c +--- /dev/null ++++ b/dbus.c +@@ -0,0 +1,242 @@ ++#include "dbus.h" ++ ++#include "util.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++close_pipe(void *data) ++{ ++ int *pipefd = data; ++ ++ close(pipefd[0]); ++ close(pipefd[1]); ++ free(pipefd); ++} ++ ++static int ++dwl_dbus_dispatch(int fd, unsigned int mask, void *data) ++{ ++ DBusConnection *conn = data; ++ ++ int pending; ++ DBusDispatchStatus oldstatus, newstatus; ++ ++ oldstatus = dbus_connection_get_dispatch_status(conn); ++ newstatus = dbus_connection_dispatch(conn); ++ ++ /* Don't clear pending flag if status didn't change */ ++ if (oldstatus == newstatus) ++ return 0; ++ ++ if (read(fd, &pending, sizeof(int)) < 0) { ++ perror("read"); ++ die("Error in dbus dispatch"); ++ } ++ ++ return 0; ++} ++ ++static int ++dwl_dbus_watch_handle(int fd, uint32_t mask, void *data) ++{ ++ DBusWatch *watch = data; ++ ++ uint32_t flags = 0; ++ ++ if (!dbus_watch_get_enabled(watch)) ++ return 0; ++ ++ if (mask & WL_EVENT_READABLE) ++ flags |= DBUS_WATCH_READABLE; ++ if (mask & WL_EVENT_WRITABLE) ++ flags |= DBUS_WATCH_WRITABLE; ++ if (mask & WL_EVENT_HANGUP) ++ flags |= DBUS_WATCH_HANGUP; ++ if (mask & WL_EVENT_ERROR) ++ flags |= DBUS_WATCH_ERROR; ++ ++ dbus_watch_handle(watch, flags); ++ ++ return 0; ++} ++ ++static dbus_bool_t ++dwl_dbus_add_watch(DBusWatch *watch, void *data) ++{ ++ struct wl_event_loop *loop = data; ++ ++ int fd; ++ struct wl_event_source *watch_source; ++ uint32_t mask = 0, flags; ++ ++ if (!dbus_watch_get_enabled(watch)) ++ return TRUE; ++ ++ flags = dbus_watch_get_flags(watch); ++ if (flags & DBUS_WATCH_READABLE) ++ mask |= WL_EVENT_READABLE; ++ if (flags & DBUS_WATCH_WRITABLE) ++ mask |= WL_EVENT_WRITABLE; ++ ++ fd = dbus_watch_get_unix_fd(watch); ++ watch_source = wl_event_loop_add_fd(loop, fd, mask, ++ dwl_dbus_watch_handle, watch); ++ ++ dbus_watch_set_data(watch, watch_source, NULL); ++ ++ return TRUE; ++} ++ ++static void ++dwl_dbus_remove_watch(DBusWatch *watch, void *data) ++{ ++ struct wl_event_source *watch_source = dbus_watch_get_data(watch); ++ ++ if (watch_source) ++ wl_event_source_remove(watch_source); ++} ++ ++static int ++dwl_dbus_timeout_handle(void *data) ++{ ++ DBusTimeout *timeout = data; ++ ++ if (dbus_timeout_get_enabled(timeout)) ++ dbus_timeout_handle(timeout); ++ ++ return 0; ++} ++ ++static dbus_bool_t ++dwl_dbus_add_timeout(DBusTimeout *timeout, void *data) ++{ ++ struct wl_event_loop *loop = data; ++ ++ int r, interval; ++ struct wl_event_source *timeout_source; ++ ++ if (!dbus_timeout_get_enabled(timeout)) ++ return TRUE; ++ ++ interval = dbus_timeout_get_interval(timeout); ++ ++ timeout_source = ++ wl_event_loop_add_timer(loop, dwl_dbus_timeout_handle, timeout); ++ ++ r = wl_event_source_timer_update(timeout_source, interval); ++ if (r < 0) { ++ wl_event_source_remove(timeout_source); ++ return FALSE; ++ } ++ ++ dbus_timeout_set_data(timeout, timeout_source, NULL); ++ ++ return TRUE; ++} ++ ++static void ++dwl_dbus_remove_timeout(DBusTimeout *timeout, void *data) ++{ ++ struct wl_event_source *timeout_source; ++ ++ timeout_source = dbus_timeout_get_data(timeout); ++ ++ if (timeout_source) { ++ wl_event_source_timer_update(timeout_source, 0); ++ wl_event_source_remove(timeout_source); ++ } ++} ++ ++static void ++dwl_dbus_dispatch_status(DBusConnection *conn, DBusDispatchStatus status, ++ void *data) ++{ ++ int *pipefd = data; ++ ++ if (status != DBUS_DISPATCH_COMPLETE) { ++ int pending = 1; ++ if (write(pipefd[1], &pending, sizeof(int)) < 0) { ++ perror("write"); ++ die("Error in dispatch status"); ++ } ++ } ++} ++ ++struct wl_event_source * ++startbus(DBusConnection *conn, struct wl_event_loop *loop) ++{ ++ int *pipefd; ++ int pending = 1, flags; ++ struct wl_event_source *bus_source = NULL; ++ ++ pipefd = ecalloc(2, sizeof(int)); ++ ++ /* ++ * Libdbus forbids calling dbus_connection_dipatch from the ++ * DBusDispatchStatusFunction directly. Notify the event loop of ++ * updates via a self-pipe. ++ */ ++ if (pipe(pipefd) < 0) ++ goto fail; ++ if (((flags = fcntl(pipefd[0], F_GETFD)) < 0) || ++ fcntl(pipefd[0], F_SETFD, flags | FD_CLOEXEC) < 0 || ++ ((flags = fcntl(pipefd[1], F_GETFD)) < 0) || ++ fcntl(pipefd[1], F_SETFD, flags | FD_CLOEXEC) < 0) { ++ goto fail; ++ } ++ ++ dbus_connection_set_exit_on_disconnect(conn, FALSE); ++ ++ bus_source = wl_event_loop_add_fd(loop, pipefd[0], WL_EVENT_READABLE, ++ dwl_dbus_dispatch, conn); ++ if (!bus_source) ++ goto fail; ++ ++ dbus_connection_set_dispatch_status_function(conn, ++ dwl_dbus_dispatch_status, ++ pipefd, close_pipe); ++ if (!dbus_connection_set_watch_functions(conn, dwl_dbus_add_watch, ++ dwl_dbus_remove_watch, NULL, ++ loop, NULL)) { ++ goto fail; ++ } ++ if (!dbus_connection_set_timeout_functions(conn, dwl_dbus_add_timeout, ++ dwl_dbus_remove_timeout, ++ NULL, loop, NULL)) { ++ goto fail; ++ } ++ if (dbus_connection_get_dispatch_status(conn) != DBUS_DISPATCH_COMPLETE) ++ if (write(pipefd[1], &pending, sizeof(int)) < 0) ++ goto fail; ++ ++ return bus_source; ++ ++fail: ++ if (bus_source) ++ wl_event_source_remove(bus_source); ++ dbus_connection_set_timeout_functions(conn, NULL, NULL, NULL, NULL, ++ NULL); ++ dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); ++ dbus_connection_set_dispatch_status_function(conn, NULL, NULL, NULL); ++ ++ return NULL; ++} ++ ++void ++stopbus(DBusConnection *conn, struct wl_event_source *bus_source) ++{ ++ wl_event_source_remove(bus_source); ++ dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); ++ dbus_connection_set_timeout_functions(conn, NULL, NULL, NULL, NULL, ++ NULL); ++ dbus_connection_set_dispatch_status_function(conn, NULL, NULL, NULL); ++} +diff --git a/dbus.h b/dbus.h +new file mode 100644 +index 0000000..b374b98 +--- /dev/null ++++ b/dbus.h +@@ -0,0 +1,10 @@ ++#ifndef DWLDBUS_H ++#define DWLDBUS_H ++ ++#include ++#include ++ ++struct wl_event_source* startbus (DBusConnection *conn, struct wl_event_loop *loop); ++void stopbus (DBusConnection *conn, struct wl_event_source *bus_source); ++ ++#endif /* DWLDBUS_H */ +diff --git a/dwl.c b/dwl.c +index ece537a..7753ef6 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1,6 +1,7 @@ + /* + * See LICENSE file for copyright and license details. + */ ++#include + #include + #include + #include +@@ -71,6 +72,9 @@ + + #include "util.h" + #include "drwl.h" ++#include "dbus.h" ++#include "systray/tray.h" ++#include "systray/watcher.h" + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +@@ -89,7 +93,7 @@ enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ +-enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ ++enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot, ClkTray }; /* clicks */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -218,6 +222,7 @@ struct Monitor { + int real_width, real_height; /* non-scaled */ + float scale; + } b; /* bar area */ ++ Tray *tray; + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; +@@ -376,6 +381,9 @@ static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); ++static void trayactivate(const Arg *arg); ++static void traymenu(const Arg *arg); ++static void traynotify(void *data); + static void unlocksession(struct wl_listener *listener, void *data); + static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); + static void unmapnotify(struct wl_listener *listener, void *data); +@@ -451,6 +459,10 @@ static Monitor *selmon; + static char stext[256]; + static struct wl_event_source *status_event_source; + ++static DBusConnection *bus_conn; ++static struct wl_event_source *bus_source; ++static Watcher watcher = {.running = 0}; ++ + static const struct wlr_buffer_impl buffer_impl = { + .destroy = bufdestroy, + .begin_data_ptr_access = bufdatabegin, +@@ -721,8 +733,8 @@ bufrelease(struct wl_listener *listener, void *data) + void + buttonpress(struct wl_listener *listener, void *data) + { +- unsigned int i = 0, x = 0; +- double cx; ++ unsigned int i = 0, x = 0, ti = 0; ++ double cx, tx = 0; + unsigned int click; + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; +@@ -732,6 +744,7 @@ buttonpress(struct wl_listener *listener, void *data) + Arg arg = {0}; + Client *c; + const Button *b; ++ int traywidth; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + +@@ -751,6 +764,8 @@ buttonpress(struct wl_listener *listener, void *data) + (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && + (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { + cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; ++ traywidth = tray_get_width(selmon->tray); ++ + do + x += TEXTW(selmon, tags[i]); + while (cx >= x && ++i < LENGTH(tags)); +@@ -759,8 +774,16 @@ buttonpress(struct wl_listener *listener, void *data) + arg.ui = 1 << i; + } else if (cx < x + TEXTW(selmon, selmon->ltsymbol)) + click = ClkLtSymbol; +- else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) { ++ else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2) && cx < selmon->b.width - traywidth) { + click = ClkStatus; ++ } else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) { ++ unsigned int tray_n_items = watcher_get_n_items(&watcher); ++ tx = selmon->b.width - traywidth; ++ do ++ tx += tray_n_items ? (int)(traywidth / tray_n_items) : 0; ++ while (cx >= tx && ++ti < tray_n_items); ++ click = ClkTray; ++ arg.ui = ti; + } else + click = ClkTitle; + } +@@ -774,7 +797,12 @@ buttonpress(struct wl_listener *listener, void *data) + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { + if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) { +- b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg); ++ if (click == ClkTagBar && b->arg.i == 0) ++ b->func(&arg); ++ else if (click == ClkTray && b->arg.i == 0) ++ b->func(&arg); ++ else ++ b->func(&b->arg); + return; + } + } +@@ -840,6 +868,14 @@ cleanup(void) + + destroykeyboardgroup(&kb_group->destroy, NULL); + ++ if (watcher.running) ++ watcher_stop(&watcher); ++ ++ if (showbar && showsystray) { ++ stopbus(bus_conn, bus_source); ++ dbus_connection_unref(bus_conn); ++ } ++ + /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. + * Destroy it until it's fixed in the wlroots side */ + wlr_backend_destroy(backend); +@@ -868,6 +904,9 @@ cleanupmon(struct wl_listener *listener, void *data) + for (i = 0; i < LENGTH(m->pool); i++) + wlr_buffer_drop(&m->pool[i]->base); + ++ if (showsystray) ++ destroytray(m->tray); ++ + drwl_setimage(m->drw, NULL); + drwl_destroy(m->drw); + +@@ -1506,6 +1545,7 @@ dirtomon(enum wlr_direction dir) + void + drawbar(Monitor *m) + { ++ int traywidth = 0; + int x, w, tw = 0; + int boxs = m->drw->font->height / 9; + int boxw = m->drw->font->height / 6 + 2; +@@ -1518,11 +1558,13 @@ drawbar(Monitor *m) + if (!(buf = bufmon(m))) + return; + ++ traywidth = tray_get_width(m->tray); ++ + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drwl_setscheme(m->drw, colors[SchemeNorm]); + tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ +- drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); ++ drwl_text(m->drw, m->b.width - (tw + traywidth), 0, tw, m->b.height, 0, stext, 0); + } + + wl_list_for_each(c, &clients, link) { +@@ -1548,7 +1590,7 @@ drawbar(Monitor *m) + drwl_setscheme(m->drw, colors[SchemeNorm]); + x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0); + +- if ((w = m->b.width - tw - x) > m->b.height) { ++ if ((w = m->b.width - (tw + x + traywidth)) > m->b.height) { + if (c) { + drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); + drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); +@@ -1560,6 +1602,15 @@ drawbar(Monitor *m) + } + } + ++ if (traywidth > 0) { ++ pixman_image_composite32(PIXMAN_OP_SRC, ++ m->tray->image, NULL, m->drw->image, ++ 0, 0, ++ 0, 0, ++ m->b.width - traywidth, 0, ++ traywidth, m->b.height); ++ } ++ + wlr_scene_buffer_set_dest_size(m->scene_buffer, + m->b.real_width, m->b.real_height); + wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, +@@ -1568,6 +1619,26 @@ drawbar(Monitor *m) + wlr_buffer_unlock(&buf->base); + } + ++void ++traynotify(void *data) ++{ ++ Monitor *m = data; ++ ++ drawbar(m); ++} ++ ++void ++trayactivate(const Arg *arg) ++{ ++ tray_leftclicked(selmon->tray, arg->ui); ++} ++ ++void ++traymenu(const Arg *arg) ++{ ++ tray_rightclicked(selmon->tray, arg->ui, dmenucmd); ++} ++ + void + drawbars(void) + { +@@ -2818,6 +2889,15 @@ setup(void) + status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy), + STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL); + ++ bus_conn = dbus_bus_get(DBUS_BUS_SESSION, NULL); ++ if (!bus_conn) ++ die("Failed to connect to bus"); ++ bus_source = startbus(bus_conn, event_loop); ++ if (!bus_source) ++ die("Failed to start listening to bus events"); ++ if (showbar && showsystray) ++ watcher_start(&watcher, bus_conn, event_loop); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -3160,6 +3240,7 @@ updatebar(Monitor *m) + size_t i; + int rw, rh; + char fontattrs[12]; ++ Tray *tray; + + wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); + m->b.width = rw; +@@ -3185,6 +3266,18 @@ updatebar(Monitor *m) + m->lrpad = m->drw->font->height; + m->b.height = m->drw->font->height + 2; + m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale); ++ ++ if (showsystray) { ++ if (m->tray) ++ destroytray(m->tray); ++ tray = createtray(m, ++ m->b.height, systrayspacing, colors[SchemeNorm], fonts, fontattrs, ++ &traynotify, &watcher); ++ if (!tray) ++ die("Couldn't create tray for monitor"); ++ m->tray = tray; ++ wl_list_insert(&watcher.trays, &tray->link); ++ } + } + + void +diff --git a/systray/helpers.c b/systray/helpers.c +new file mode 100644 +index 0000000..d1af9f8 +--- /dev/null ++++ b/systray/helpers.c +@@ -0,0 +1,43 @@ ++#include "helpers.h" ++ ++#include ++ ++#include ++#include ++ ++// IWYU pragma: no_include "dbus/dbus-protocol.h" ++// IWYU pragma: no_include "dbus/dbus-shared.h" ++ ++int ++request_property(DBusConnection *conn, const char *busname, const char *busobj, ++ const char *prop, const char *iface, PropHandler handler, ++ void *data) ++{ ++ DBusMessage *msg = NULL; ++ DBusPendingCall *pending = NULL; ++ int r; ++ ++ if (!(msg = dbus_message_new_method_call(busname, busobj, ++ DBUS_INTERFACE_PROPERTIES, ++ "Get")) || ++ !dbus_message_append_args(msg, DBUS_TYPE_STRING, &iface, ++ DBUS_TYPE_STRING, &prop, ++ DBUS_TYPE_INVALID) || ++ !dbus_connection_send_with_reply(conn, msg, &pending, -1) || ++ !dbus_pending_call_set_notify(pending, handler, data, NULL)) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ dbus_message_unref(msg); ++ return 0; ++ ++fail: ++ if (pending) { ++ dbus_pending_call_cancel(pending); ++ dbus_pending_call_unref(pending); ++ } ++ if (msg) ++ dbus_message_unref(msg); ++ return r; ++} +diff --git a/systray/helpers.h b/systray/helpers.h +new file mode 100644 +index 0000000..2c592e0 +--- /dev/null ++++ b/systray/helpers.h +@@ -0,0 +1,12 @@ ++#ifndef HELPERS_H ++#define HELPERS_H ++ ++#include ++ ++typedef void (*PropHandler)(DBusPendingCall *pcall, void *data); ++ ++int request_property (DBusConnection *conn, const char *busname, ++ const char *busobj, const char *prop, const char *iface, ++ PropHandler handler, void *data); ++ ++#endif /* HELPERS_H */ +diff --git a/systray/icon.c b/systray/icon.c +new file mode 100644 +index 0000000..1b97866 +--- /dev/null ++++ b/systray/icon.c +@@ -0,0 +1,149 @@ ++#include "icon.h" ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define PREMUL_ALPHA(chan, alpha) (chan * alpha + 127) / 255 ++ ++/* ++ * Converts pixels from uint8_t[4] to uint32_t and ++ * straight alpha to premultiplied alpha. ++ */ ++static uint32_t * ++to_pixman(const uint8_t *src, int n_pixels, size_t *pix_size) ++{ ++ uint32_t *dest = NULL; ++ ++ *pix_size = n_pixels * sizeof(uint32_t); ++ dest = malloc(*pix_size); ++ if (!dest) ++ return NULL; ++ ++ for (int i = 0; i < n_pixels; i++) { ++ uint8_t a = src[i * 4 + 0]; ++ uint8_t r = src[i * 4 + 1]; ++ uint8_t g = src[i * 4 + 2]; ++ uint8_t b = src[i * 4 + 3]; ++ ++ /* ++ * Skip premultiplying fully opaque and fully transparent ++ * pixels. ++ */ ++ if (a == 0) { ++ dest[i] = 0; ++ ++ } else if (a == 255) { ++ dest[i] = ((uint32_t)a << 24) | ((uint32_t)r << 16) | ++ ((uint32_t)g << 8) | ((uint32_t)b); ++ ++ } else { ++ dest[i] = ((uint32_t)a << 24) | ++ ((uint32_t)PREMUL_ALPHA(r, a) << 16) | ++ ((uint32_t)PREMUL_ALPHA(g, a) << 8) | ++ ((uint32_t)PREMUL_ALPHA(b, a)); ++ } ++ } ++ ++ return dest; ++} ++ ++Icon * ++createicon(const uint8_t *buf, int width, int height, int size) ++{ ++ Icon *icon = NULL; ++ ++ int n_pixels; ++ pixman_image_t *img = NULL; ++ size_t pixbuf_size; ++ uint32_t *buf_pixman = NULL; ++ uint8_t *buf_orig = NULL; ++ ++ n_pixels = size / 4; ++ ++ icon = calloc(1, sizeof(Icon)); ++ buf_orig = malloc(size); ++ buf_pixman = to_pixman(buf, n_pixels, &pixbuf_size); ++ if (!icon || !buf_orig || !buf_pixman) ++ goto fail; ++ ++ img = pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height, ++ buf_pixman, width * 4); ++ if (!img) ++ goto fail; ++ ++ memcpy(buf_orig, buf, size); ++ ++ icon->buf_orig = buf_orig; ++ icon->buf_pixman = buf_pixman; ++ icon->img = img; ++ icon->size_orig = size; ++ icon->size_pixman = pixbuf_size; ++ ++ return icon; ++ ++fail: ++ free(buf_orig); ++ if (img) ++ pixman_image_unref(img); ++ free(buf_pixman); ++ free(icon); ++ return NULL; ++} ++ ++void ++destroyicon(Icon *icon) ++{ ++ if (icon->img) ++ pixman_image_unref(icon->img); ++ free(icon->buf_orig); ++ free(icon->buf_pixman); ++ free(icon); ++} ++ ++FallbackIcon * ++createfallbackicon(const char *appname, int fgcolor, struct fcft_font *font) ++{ ++ const struct fcft_glyph *glyph; ++ char initial; ++ ++ if ((unsigned char)appname[0] > 127) { ++ /* first character is not ascii */ ++ initial = '?'; ++ } else { ++ initial = toupper(*appname); ++ } ++ ++ glyph = fcft_rasterize_char_utf32(font, initial, FCFT_SUBPIXEL_DEFAULT); ++ if (!glyph) ++ return NULL; ++ ++ return glyph; ++} ++ ++int ++resize_image(pixman_image_t *image, int new_width, int new_height) ++{ ++ int src_width = pixman_image_get_width(image); ++ int src_height = pixman_image_get_height(image); ++ pixman_transform_t transform; ++ pixman_fixed_t scale_x, scale_y; ++ ++ if (src_width == new_width && src_height == new_height) ++ return 0; ++ ++ scale_x = pixman_double_to_fixed((double)src_width / new_width); ++ scale_y = pixman_double_to_fixed((double)src_height / new_height); ++ ++ pixman_transform_init_scale(&transform, scale_x, scale_y); ++ if (!pixman_image_set_filter(image, PIXMAN_FILTER_BEST, NULL, 0) || ++ !pixman_image_set_transform(image, &transform)) { ++ return -1; ++ } ++ ++ return 0; ++} +diff --git a/systray/icon.h b/systray/icon.h +new file mode 100644 +index 0000000..20f281b +--- /dev/null ++++ b/systray/icon.h +@@ -0,0 +1,26 @@ ++#ifndef ICON_H ++#define ICON_H ++ ++#include ++#include ++ ++#include ++#include ++ ++typedef const struct fcft_glyph FallbackIcon; ++ ++typedef struct { ++ pixman_image_t *img; ++ uint32_t *buf_pixman; ++ uint8_t *buf_orig; ++ size_t size_orig; ++ size_t size_pixman; ++} Icon; ++ ++Icon *createicon (const uint8_t *buf, int width, int height, int size); ++FallbackIcon *createfallbackicon (const char *appname, int fgcolor, ++ struct fcft_font *font); ++void destroyicon (Icon *icon); ++int resize_image (pixman_image_t *orig, int new_width, int new_height); ++ ++#endif /* ICON_H */ +diff --git a/systray/item.c b/systray/item.c +new file mode 100644 +index 0000000..4359a28 +--- /dev/null ++++ b/systray/item.c +@@ -0,0 +1,403 @@ ++#include "item.h" ++ ++#include "helpers.h" ++#include "icon.h" ++#include "watcher.h" ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++// IWYU pragma: no_include "dbus/dbus-protocol.h" ++// IWYU pragma: no_include "dbus/dbus-shared.h" ++ ++#define RULEBSIZE 256 ++#define MIN(A, B) ((A) < (B) ? (A) : (B)) ++ ++static const char *match_string = ++ "type='signal'," ++ "sender='%s'," ++ "interface='" SNI_NAME ++ "'," ++ "member='NewIcon'"; ++ ++static Watcher * ++item_get_watcher(const Item *item) ++{ ++ if (!item) ++ return NULL; ++ ++ return item->watcher; ++} ++ ++static DBusConnection * ++item_get_connection(const Item *item) ++{ ++ if (!item || !item->watcher) ++ return NULL; ++ ++ return item->watcher->conn; ++} ++ ++static const uint8_t * ++extract_image(DBusMessageIter *iter, dbus_int32_t *width, dbus_int32_t *height, ++ int *size) ++{ ++ DBusMessageIter vals, bytes; ++ const uint8_t *buf; ++ ++ dbus_message_iter_recurse(iter, &vals); ++ if (dbus_message_iter_get_arg_type(&vals) != DBUS_TYPE_INT32) ++ goto fail; ++ dbus_message_iter_get_basic(&vals, width); ++ ++ dbus_message_iter_next(&vals); ++ if (dbus_message_iter_get_arg_type(&vals) != DBUS_TYPE_INT32) ++ goto fail; ++ dbus_message_iter_get_basic(&vals, height); ++ ++ dbus_message_iter_next(&vals); ++ if (dbus_message_iter_get_arg_type(&vals) != DBUS_TYPE_ARRAY) ++ goto fail; ++ dbus_message_iter_recurse(&vals, &bytes); ++ if (dbus_message_iter_get_arg_type(&bytes) != DBUS_TYPE_BYTE) ++ goto fail; ++ dbus_message_iter_get_fixed_array(&bytes, &buf, size); ++ if (size == 0) ++ goto fail; ++ ++ return buf; ++ ++fail: ++ return NULL; ++} ++ ++static int ++select_image(DBusMessageIter *iter, int target_width) ++{ ++ DBusMessageIter vals; ++ dbus_int32_t cur_width; ++ int i = 0; ++ ++ do { ++ dbus_message_iter_recurse(iter, &vals); ++ if (dbus_message_iter_get_arg_type(&vals) != DBUS_TYPE_INT32) ++ return -1; ++ dbus_message_iter_get_basic(&vals, &cur_width); ++ if (cur_width >= target_width) ++ return i; ++ ++ i++; ++ } while (dbus_message_iter_next(iter)); ++ ++ /* return last index if desired not found */ ++ return --i; ++} ++ ++static void ++menupath_ready_handler(DBusPendingCall *pending, void *data) ++{ ++ Item *item = data; ++ ++ DBusError err = DBUS_ERROR_INIT; ++ DBusMessage *reply = NULL; ++ DBusMessageIter iter, opath; ++ char *path_dup = NULL; ++ const char *path; ++ ++ reply = dbus_pending_call_steal_reply(pending); ++ if (!reply) ++ goto fail; ++ ++ if (dbus_set_error_from_message(&err, reply)) { ++ fprintf(stderr, "DBus Error: %s - %s: Couldn't get menupath\n", ++ err.name, err.message); ++ goto fail; ++ } ++ ++ dbus_message_iter_init(reply, &iter); ++ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) ++ goto fail; ++ dbus_message_iter_recurse(&iter, &opath); ++ if (dbus_message_iter_get_arg_type(&opath) != DBUS_TYPE_OBJECT_PATH) ++ goto fail; ++ dbus_message_iter_get_basic(&opath, &path); ++ ++ path_dup = strdup(path); ++ if (!path_dup) ++ goto fail; ++ ++ item->menu_busobj = path_dup; ++ ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(pending); ++ return; ++ ++fail: ++ free(path_dup); ++ dbus_error_free(&err); ++ if (reply) ++ dbus_message_unref(reply); ++ if (pending) ++ dbus_pending_call_unref(pending); ++} ++ ++/* ++ * Gets the Id dbus property, which is the name of the application, ++ * most of the time... ++ * The initial letter will be used as a fallback icon ++ */ ++static void ++id_ready_handler(DBusPendingCall *pending, void *data) ++{ ++ Item *item = data; ++ ++ DBusError err = DBUS_ERROR_INIT; ++ DBusMessage *reply = NULL; ++ DBusMessageIter iter, string; ++ Watcher *watcher; ++ char *id_dup = NULL; ++ const char *id; ++ ++ watcher = item_get_watcher(item); ++ ++ reply = dbus_pending_call_steal_reply(pending); ++ if (!reply) ++ goto fail; ++ ++ if (dbus_set_error_from_message(&err, reply)) { ++ fprintf(stderr, "DBus Error: %s - %s: Couldn't get appid\n", ++ err.name, err.message); ++ goto fail; ++ } ++ ++ dbus_message_iter_init(reply, &iter); ++ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) ++ goto fail; ++ dbus_message_iter_recurse(&iter, &string); ++ if (dbus_message_iter_get_arg_type(&string) != DBUS_TYPE_STRING) ++ goto fail; ++ dbus_message_iter_get_basic(&string, &id); ++ ++ id_dup = strdup(id); ++ if (!id_dup) ++ goto fail; ++ item->appid = id_dup; ++ ++ /* Don't trigger update if this item already has a real icon */ ++ if (!item->icon) ++ watcher_update_trays(watcher); ++ ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(pending); ++ return; ++ ++fail: ++ dbus_error_free(&err); ++ if (id_dup) ++ free(id_dup); ++ if (reply) ++ dbus_message_unref(reply); ++ if (pending) ++ dbus_pending_call_unref(pending); ++} ++ ++static void ++pixmap_ready_handler(DBusPendingCall *pending, void *data) ++{ ++ Item *item = data; ++ ++ DBusMessage *reply = NULL; ++ DBusMessageIter iter, array, select, strct; ++ Icon *icon = NULL; ++ Watcher *watcher; ++ dbus_int32_t width, height; ++ int selected_index, size; ++ const uint8_t *buf; ++ ++ watcher = item_get_watcher(item); ++ ++ reply = dbus_pending_call_steal_reply(pending); ++ if (!reply || dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) ++ goto fail; ++ dbus_message_iter_init(reply, &iter); ++ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) ++ goto fail; ++ dbus_message_iter_recurse(&iter, &array); ++ if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) ++ goto fail; ++ dbus_message_iter_recurse(&array, &select); ++ if (dbus_message_iter_get_arg_type(&select) != DBUS_TYPE_STRUCT) ++ goto fail; ++ selected_index = select_image(&select, 22); // Get the 22*22 image ++ if (selected_index < 0) ++ goto fail; ++ ++ dbus_message_iter_recurse(&array, &strct); ++ if (dbus_message_iter_get_arg_type(&strct) != DBUS_TYPE_STRUCT) ++ goto fail; ++ for (int i = 0; i < selected_index; i++) ++ dbus_message_iter_next(&strct); ++ buf = extract_image(&strct, &width, &height, &size); ++ if (!buf) ++ goto fail; ++ ++ if (!item->icon) { ++ /* First icon */ ++ icon = createicon(buf, width, height, size); ++ if (!icon) ++ goto fail; ++ item->icon = icon; ++ watcher_update_trays(watcher); ++ ++ } else if (memcmp(item->icon->buf_orig, buf, ++ MIN(item->icon->size_orig, (size_t)size)) != 0) { ++ /* New icon */ ++ destroyicon(item->icon); ++ item->icon = NULL; ++ icon = createicon(buf, width, height, size); ++ if (!icon) ++ goto fail; ++ item->icon = icon; ++ watcher_update_trays(watcher); ++ ++ } else { ++ /* Icon didn't change */ ++ } ++ ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(pending); ++ return; ++ ++fail: ++ if (icon) ++ destroyicon(icon); ++ if (reply) ++ dbus_message_unref(reply); ++ if (pending) ++ dbus_pending_call_unref(pending); ++} ++ ++static DBusHandlerResult ++handle_newicon(Item *item, DBusConnection *conn, DBusMessage *msg) ++{ ++ const char *sender = dbus_message_get_sender(msg); ++ ++ if (sender && strcmp(sender, item->busname) == 0) { ++ request_property(conn, item->busname, item->busobj, ++ "IconPixmap", SNI_IFACE, pixmap_ready_handler, ++ item); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++ ++ } else { ++ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; ++ } ++} ++ ++static DBusHandlerResult ++filter_bus(DBusConnection *conn, DBusMessage *msg, void *data) ++{ ++ Item *item = data; ++ ++ if (dbus_message_is_signal(msg, SNI_IFACE, "NewIcon")) ++ return handle_newicon(item, conn, msg); ++ else ++ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; ++} ++ ++Item * ++createitem(const char *busname, const char *busobj, Watcher *watcher) ++{ ++ DBusConnection *conn; ++ Item *item; ++ char *busname_dup = NULL; ++ char *busobj_dup = NULL; ++ char match_rule[RULEBSIZE]; ++ ++ item = calloc(1, sizeof(Item)); ++ busname_dup = strdup(busname); ++ busobj_dup = strdup(busobj); ++ if (!item || !busname_dup || !busobj_dup) ++ goto fail; ++ ++ conn = watcher->conn; ++ item->busname = busname_dup; ++ item->busobj = busobj_dup; ++ item->watcher = watcher; ++ ++ request_property(conn, busname, busobj, "IconPixmap", SNI_IFACE, ++ pixmap_ready_handler, item); ++ ++ request_property(conn, busname, busobj, "Id", SNI_IFACE, ++ id_ready_handler, item); ++ ++ request_property(conn, busname, busobj, "Menu", SNI_IFACE, ++ menupath_ready_handler, item); ++ ++ if (snprintf(match_rule, sizeof(match_rule), match_string, busname) >= ++ RULEBSIZE) { ++ goto fail; ++ } ++ ++ if (!dbus_connection_add_filter(conn, filter_bus, item, NULL)) ++ goto fail; ++ dbus_bus_add_match(conn, match_rule, NULL); ++ ++ return item; ++ ++fail: ++ free(busname_dup); ++ free(busobj_dup); ++ return NULL; ++} ++ ++void ++destroyitem(Item *item) ++{ ++ DBusConnection *conn; ++ char match_rule[RULEBSIZE]; ++ ++ conn = item_get_connection(item); ++ ++ if (snprintf(match_rule, sizeof(match_rule), match_string, ++ item->busname) < RULEBSIZE) { ++ dbus_bus_remove_match(conn, match_rule, NULL); ++ dbus_connection_remove_filter(conn, filter_bus, item); ++ } ++ if (item->icon) ++ destroyicon(item->icon); ++ free(item->menu_busobj); ++ free(item->busname); ++ free(item->busobj); ++ free(item->appid); ++ free(item); ++} ++ ++void ++item_activate(Item *item) ++{ ++ DBusConnection *conn; ++ DBusMessage *msg = NULL; ++ dbus_int32_t x = 0, y = 0; ++ ++ conn = item_get_connection(item); ++ ++ if (!(msg = dbus_message_new_method_call(item->busname, item->busobj, ++ SNI_IFACE, "Activate")) || ++ !dbus_message_append_args(msg, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, ++ &y, DBUS_TYPE_INVALID) || ++ !dbus_connection_send_with_reply(conn, msg, NULL, -1)) { ++ goto fail; ++ } ++ ++ dbus_message_unref(msg); ++ return; ++ ++fail: ++ if (msg) ++ dbus_message_unref(msg); ++} +diff --git a/systray/item.h b/systray/item.h +new file mode 100644 +index 0000000..dc22e25 +--- /dev/null ++++ b/systray/item.h +@@ -0,0 +1,46 @@ ++#ifndef ITEM_H ++#define ITEM_H ++ ++#include "icon.h" ++#include "watcher.h" ++ ++#include ++ ++/* ++ * The FDO spec says "org.freedesktop.StatusNotifierItem"[1], ++ * but both the client libraries[2,3] actually use "org.kde.StatusNotifierItem" ++ * ++ * [1] https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/ ++ * [2] https://github.com/AyatanaIndicators/libayatana-appindicator-glib ++ * [3] https://invent.kde.org/frameworks/kstatusnotifieritem ++ * ++ */ ++#define SNI_NAME "org.kde.StatusNotifierItem" ++#define SNI_OPATH "/StatusNotifierItem" ++#define SNI_IFACE "org.kde.StatusNotifierItem" ++ ++typedef struct Item { ++ struct wl_list icons; ++ char *busname; ++ char *busobj; ++ char *menu_busobj; ++ char *appid; ++ Icon *icon; ++ FallbackIcon *fallback_icon; ++ ++ Watcher *watcher; ++ ++ int fgcolor; ++ ++ int ready; ++ ++ struct wl_list link; ++} Item; ++ ++Item *createitem (const char *busname, const char *busobj, Watcher *watcher); ++void destroyitem (Item *item); ++ ++void item_activate (Item *item); ++void item_show_menu (Item *item); ++ ++#endif /* ITEM_H */ +diff --git a/systray/menu.c b/systray/menu.c +new file mode 100644 +index 0000000..ff3bfb5 +--- /dev/null ++++ b/systray/menu.c +@@ -0,0 +1,757 @@ ++#include "menu.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++// IWYU pragma: no_include "dbus/dbus-protocol.h" ++// IWYU pragma: no_include "dbus/dbus-shared.h" ++ ++#define DBUSMENU_IFACE "com.canonical.dbusmenu" ++#define BUFSIZE 512 ++#define LABEL_MAX 64 ++ ++typedef struct { ++ struct wl_array layout; ++ DBusConnection *conn; ++ struct wl_event_loop *loop; ++ char *busname; ++ char *busobj; ++ const char **menucmd; ++} Menu; ++ ++typedef struct { ++ char label[LABEL_MAX]; ++ dbus_int32_t id; ++ struct wl_array submenu; ++ int has_submenu; ++} MenuItem; ++ ++typedef struct { ++ struct wl_event_loop *loop; ++ struct wl_event_source *fd_source; ++ struct wl_array *layout_node; ++ Menu *menu; ++ pid_t menu_pid; ++ int fd; ++} MenuShowContext; ++ ++static int extract_menu (DBusMessageIter *av, struct wl_array *menu); ++static int real_show_menu (Menu *menu, struct wl_array *m); ++static void submenus_destroy_recursive (struct wl_array *m); ++ ++static void ++menuitem_init(MenuItem *mi) ++{ ++ wl_array_init(&mi->submenu); ++ mi->id = -1; ++ *mi->label = '\0'; ++ mi->has_submenu = 0; ++} ++ ++static void ++submenus_destroy_recursive(struct wl_array *layout_node) ++{ ++ MenuItem *mi; ++ ++ wl_array_for_each(mi, layout_node) { ++ if (mi->has_submenu) { ++ submenus_destroy_recursive(&mi->submenu); ++ wl_array_release(&mi->submenu); ++ } ++ } ++} ++ ++static void ++menu_destroy(Menu *menu) ++{ ++ submenus_destroy_recursive(&menu->layout); ++ wl_array_release(&menu->layout); ++ free(menu->busname); ++ free(menu->busobj); ++ free(menu); ++} ++ ++static void ++menu_show_ctx_finalize(MenuShowContext *ctx, int error) ++{ ++ if (ctx->fd_source) ++ wl_event_source_remove(ctx->fd_source); ++ ++ if (ctx->fd >= 0) ++ close(ctx->fd); ++ ++ if (ctx->menu_pid >= 0) { ++ if (waitpid(ctx->menu_pid, NULL, WNOHANG) == 0) ++ kill(ctx->menu_pid, SIGTERM); ++ } ++ ++ if (error) ++ menu_destroy(ctx->menu); ++ ++ free(ctx); ++} ++ ++static void ++remove_newline(char *buf) ++{ ++ size_t len; ++ ++ len = strlen(buf); ++ if (len > 0 && buf[len - 1] == '\n') ++ buf[len - 1] = '\0'; ++} ++ ++static void ++send_clicked(const char *busname, const char *busobj, int itemid, ++ DBusConnection *conn) ++{ ++ DBusMessage *msg = NULL; ++ DBusMessageIter iter = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ DBusMessageIter sub = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ const char *data = ""; ++ const char *eventid = "clicked"; ++ time_t timestamp; ++ ++ timestamp = time(NULL); ++ ++ msg = dbus_message_new_method_call(busname, busobj, DBUSMENU_IFACE, ++ "Event"); ++ if (!msg) ++ goto fail; ++ ++ dbus_message_iter_init_append(msg, &iter); ++ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &itemid) || ++ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, ++ &eventid) || ++ !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, ++ DBUS_TYPE_STRING_AS_STRING, ++ &sub) || ++ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &data) || ++ !dbus_message_iter_close_container(&iter, &sub) || ++ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, ++ ×tamp)) { ++ goto fail; ++ } ++ ++ if (!dbus_connection_send_with_reply(conn, msg, NULL, -1)) ++ goto fail; ++ ++ dbus_message_unref(msg); ++ return; ++ ++fail: ++ dbus_message_iter_abandon_container_if_open(&iter, &sub); ++ if (msg) ++ dbus_message_unref(msg); ++} ++ ++static void ++menuitem_selected(const char *label, struct wl_array *m, Menu *menu) ++{ ++ MenuItem *mi; ++ ++ wl_array_for_each(mi, m) { ++ if (strcmp(mi->label, label) == 0) { ++ if (mi->has_submenu) { ++ real_show_menu(menu, &mi->submenu); ++ ++ } else { ++ send_clicked(menu->busname, menu->busobj, ++ mi->id, menu->conn); ++ menu_destroy(menu); ++ } ++ ++ return; ++ } ++ } ++} ++ ++static int ++read_pipe(int fd, uint32_t mask, void *data) ++{ ++ MenuShowContext *ctx = data; ++ ++ char buf[BUFSIZE]; ++ ssize_t bytes_read; ++ ++ bytes_read = read(fd, buf, BUFSIZE); ++ /* 0 == Got EOF, menu program closed without writing to stdout */ ++ if (bytes_read <= 0) ++ goto fail; ++ ++ buf[bytes_read] = '\0'; ++ remove_newline(buf); ++ ++ menuitem_selected(buf, ctx->layout_node, ctx->menu); ++ menu_show_ctx_finalize(ctx, 0); ++ return 0; ++ ++fail: ++ menu_show_ctx_finalize(ctx, 1); ++ return 0; ++} ++ ++static MenuShowContext * ++prepare_show_ctx(struct wl_event_loop *loop, int monitor_fd, int dmenu_pid, ++ struct wl_array *layout_node, Menu *menu) ++{ ++ MenuShowContext *ctx = NULL; ++ struct wl_event_source *fd_src = NULL; ++ ++ ctx = calloc(1, sizeof(MenuShowContext)); ++ if (!ctx) ++ goto fail; ++ ++ fd_src = wl_event_loop_add_fd(menu->loop, monitor_fd, WL_EVENT_READABLE, ++ read_pipe, ctx); ++ if (!fd_src) ++ goto fail; ++ ++ ctx->fd_source = fd_src; ++ ctx->fd = monitor_fd; ++ ctx->menu_pid = dmenu_pid; ++ ctx->layout_node = layout_node; ++ ctx->menu = menu; ++ ++ return ctx; ++ ++fail: ++ if (fd_src) ++ wl_event_source_remove(fd_src); ++ free(ctx); ++ return NULL; ++} ++ ++static int ++write_dmenu_buf(char *buf, struct wl_array *layout_node) ++{ ++ MenuItem *mi; ++ int r; ++ size_t curlen = 0; ++ ++ *buf = '\0'; ++ ++ wl_array_for_each(mi, layout_node) { ++ curlen += strlen(mi->label) + ++ 2; /* +2 is newline + nul terminator */ ++ if (curlen + 1 > BUFSIZE) { ++ r = -1; ++ goto fail; ++ } ++ ++ strcat(buf, mi->label); ++ strcat(buf, "\n"); ++ } ++ remove_newline(buf); ++ ++ return 0; ++ ++fail: ++ fprintf(stderr, "Failed to construct dmenu input\n"); ++ return r; ++} ++ ++static int ++real_show_menu(Menu *menu, struct wl_array *layout_node) ++{ ++ MenuShowContext *ctx = NULL; ++ char buf[BUFSIZE]; ++ int to_pipe[2], from_pipe[2]; ++ pid_t pid; ++ ++ if (pipe(to_pipe) < 0 || pipe(from_pipe) < 0) ++ goto fail; ++ ++ pid = fork(); ++ if (pid < 0) { ++ goto fail; ++ } else if (pid == 0) { ++ dup2(to_pipe[0], STDIN_FILENO); ++ dup2(from_pipe[1], STDOUT_FILENO); ++ ++ close(to_pipe[0]); ++ close(to_pipe[1]); ++ close(from_pipe[1]); ++ close(from_pipe[0]); ++ ++ if (execvp(menu->menucmd[0], (char *const *)menu->menucmd)) { ++ perror("Error spawning menu program"); ++ exit(EXIT_FAILURE); ++ } ++ } ++ ++ ctx = prepare_show_ctx(menu->loop, from_pipe[0], pid, layout_node, ++ menu); ++ if (!ctx) ++ goto fail; ++ ++ if (write_dmenu_buf(buf, layout_node) < 0 || ++ write(to_pipe[1], buf, strlen(buf)) < 0) { ++ goto fail; ++ } ++ ++ close(to_pipe[0]); ++ close(to_pipe[1]); ++ close(from_pipe[1]); ++ return 0; ++ ++fail: ++ close(to_pipe[0]); ++ close(to_pipe[1]); ++ close(from_pipe[1]); ++ menu_show_ctx_finalize(ctx, 1); ++ return -1; ++} ++ ++static void ++createmenuitem(MenuItem *mi, dbus_int32_t id, const char *label, ++ int toggle_state, int has_submenu) ++{ ++ char *tok; ++ char temp[LABEL_MAX]; ++ ++ if (toggle_state == 0) ++ strcpy(mi->label, "☐ "); ++ else if (toggle_state == 1) ++ strcpy(mi->label, "✓ "); ++ else ++ strcpy(mi->label, " "); ++ ++ /* Remove "mnemonics" (underscores which mark keyboard shortcuts) */ ++ strcpy(temp, label); ++ tok = strtok(temp, "_"); ++ do { ++ strcat(mi->label, tok); ++ } while ((tok = strtok(NULL, "_"))); ++ ++ if (has_submenu) { ++ mi->has_submenu = 1; ++ strcat(mi->label, " →"); ++ } ++ ++ mi->id = id; ++} ++ ++/** ++ * Populates the passed in menuitem based on the dictionary contents. ++ * ++ * @param[in] dict ++ * @param[in] itemid ++ * @param[in] mi ++ * @param[out] has_submenu ++ * @param[out] status <0 on error, 0 on success, >0 if menuitem was skipped ++ */ ++static int ++read_dict(DBusMessageIter *dict, dbus_int32_t itemid, MenuItem *mi, ++ int *has_submenu) ++{ ++ DBusMessageIter member, val; ++ const char *children_display = NULL, *label = NULL, *toggle_type = NULL; ++ const char *key; ++ dbus_bool_t visible = TRUE, enabled = TRUE; ++ dbus_int32_t toggle_state = 1; ++ int r; ++ ++ do { ++ dbus_message_iter_recurse(dict, &member); ++ if (dbus_message_iter_get_arg_type(&member) != ++ DBUS_TYPE_STRING) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&member, &key); ++ ++ dbus_message_iter_next(&member); ++ if (dbus_message_iter_get_arg_type(&member) != ++ DBUS_TYPE_VARIANT) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_recurse(&member, &val); ++ ++ if (strcmp(key, "visible") == 0) { ++ if (dbus_message_iter_get_arg_type(&val) != ++ DBUS_TYPE_BOOLEAN) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&val, &visible); ++ ++ } else if (strcmp(key, "enabled") == 0) { ++ if (dbus_message_iter_get_arg_type(&val) != ++ DBUS_TYPE_BOOLEAN) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&val, &enabled); ++ ++ } else if (strcmp(key, "toggle-type") == 0) { ++ if (dbus_message_iter_get_arg_type(&val) != ++ DBUS_TYPE_STRING) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&val, &toggle_type); ++ ++ } else if (strcmp(key, "toggle-state") == 0) { ++ if (dbus_message_iter_get_arg_type(&val) != ++ DBUS_TYPE_INT32) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&val, &toggle_state); ++ ++ } else if (strcmp(key, "children-display") == 0) { ++ if (dbus_message_iter_get_arg_type(&val) != ++ DBUS_TYPE_STRING) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&val, &children_display); ++ ++ if (strcmp(children_display, "submenu") == 0) ++ *has_submenu = 1; ++ ++ } else if (strcmp(key, "label") == 0) { ++ if (dbus_message_iter_get_arg_type(&val) != ++ DBUS_TYPE_STRING) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&val, &label); ++ } ++ } while (dbus_message_iter_next(dict)); ++ ++ /* Skip hidden etc items */ ++ if (!label || !visible || !enabled) ++ return 1; ++ ++ /* ++ * 4 characters for checkmark and submenu indicator, ++ * 1 for nul terminator ++ */ ++ if (strlen(label) + 5 > LABEL_MAX) { ++ fprintf(stderr, "Too long menu entry label: %s! Skipping...\n", ++ label); ++ return 1; ++ } ++ ++ if (toggle_type && strcmp(toggle_type, "checkmark") == 0) ++ createmenuitem(mi, itemid, label, toggle_state, *has_submenu); ++ else ++ createmenuitem(mi, itemid, label, -1, *has_submenu); ++ ++ return 0; ++ ++fail: ++ fprintf(stderr, "Error parsing menu data\n"); ++ return r; ++} ++ ++/** ++ * Extracts a menuitem from a DBusMessage ++ * ++ * @param[in] strct ++ * @param[in] mi ++ * @param[out] status <0 on error, 0 on success, >0 if menuitem was skipped ++ */ ++static int ++extract_menuitem(DBusMessageIter *strct, MenuItem *mi) ++{ ++ DBusMessageIter val, dict; ++ dbus_int32_t itemid; ++ int has_submenu = 0; ++ int r; ++ ++ dbus_message_iter_recurse(strct, &val); ++ if (dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_INT32) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&val, &itemid); ++ ++ if (!dbus_message_iter_next(&val) || ++ dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_ARRAY) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_recurse(&val, &dict); ++ if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) { ++ r = -1; ++ goto fail; ++ } ++ ++ r = read_dict(&dict, itemid, mi, &has_submenu); ++ if (r < 0) { ++ goto fail; ++ ++ } else if (r == 0 && has_submenu) { ++ dbus_message_iter_next(&val); ++ if (dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_ARRAY) ++ goto fail; ++ r = extract_menu(&val, &mi->submenu); ++ if (r < 0) ++ goto fail; ++ } ++ ++ return r; ++ ++fail: ++ return r; ++} ++ ++static int ++extract_menu(DBusMessageIter *av, struct wl_array *layout_node) ++{ ++ DBusMessageIter variant, menuitem; ++ MenuItem *mi; ++ int r; ++ ++ dbus_message_iter_recurse(av, &variant); ++ if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_VARIANT) { ++ r = -1; ++ goto fail; ++ } ++ ++ mi = wl_array_add(layout_node, sizeof(MenuItem)); ++ if (!mi) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ menuitem_init(mi); ++ ++ do { ++ dbus_message_iter_recurse(&variant, &menuitem); ++ if (dbus_message_iter_get_arg_type(&menuitem) != ++ DBUS_TYPE_STRUCT) { ++ r = -1; ++ goto fail; ++ } ++ ++ r = extract_menuitem(&menuitem, mi); ++ if (r < 0) ++ goto fail; ++ else if (r == 0) { ++ mi = wl_array_add(layout_node, sizeof(MenuItem)); ++ if (!mi) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ menuitem_init(mi); ++ } ++ /* r > 0: no action was performed on mi */ ++ } while (dbus_message_iter_next(&variant)); ++ ++ return 0; ++ ++fail: ++ return r; ++} ++ ++static void ++layout_ready(DBusPendingCall *pending, void *data) ++{ ++ Menu *menu = data; ++ ++ DBusMessage *reply = NULL; ++ DBusMessageIter iter, strct; ++ dbus_uint32_t revision; ++ int r; ++ ++ reply = dbus_pending_call_steal_reply(pending); ++ if (!reply || dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { ++ r = -1; ++ goto fail; ++ } ++ ++ dbus_message_iter_init(reply, &iter); ++ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_get_basic(&iter, &revision); ++ ++ if (!dbus_message_iter_next(&iter) || ++ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRUCT) { ++ r = -1; ++ goto fail; ++ } ++ dbus_message_iter_recurse(&iter, &strct); ++ ++ /* ++ * id 0 is the root, which contains nothing of interest. ++ * Traverse past it. ++ */ ++ if (dbus_message_iter_get_arg_type(&strct) != DBUS_TYPE_INT32 || ++ !dbus_message_iter_next(&strct) || ++ dbus_message_iter_get_arg_type(&strct) != DBUS_TYPE_ARRAY || ++ !dbus_message_iter_next(&strct) || ++ dbus_message_iter_get_arg_type(&strct) != DBUS_TYPE_ARRAY) { ++ r = -1; ++ goto fail; ++ } ++ ++ /* Root traversed over, extract the menu */ ++ wl_array_init(&menu->layout); ++ r = extract_menu(&strct, &menu->layout); ++ if (r < 0) ++ goto fail; ++ ++ r = real_show_menu(menu, &menu->layout); ++ if (r < 0) ++ goto fail; ++ ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(pending); ++ return; ++ ++fail: ++ menu_destroy(menu); ++ if (reply) ++ dbus_message_unref(reply); ++ if (pending) ++ dbus_pending_call_unref(pending); ++} ++ ++static int ++request_layout(Menu *menu) ++{ ++ DBusMessage *msg = NULL; ++ DBusMessageIter iter = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ DBusMessageIter strings = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ DBusPendingCall *pending = NULL; ++ dbus_int32_t parentid, depth; ++ int r; ++ ++ parentid = 0; ++ depth = -1; ++ ++ /* menu busobj request answer didn't arrive yet. */ ++ if (!menu->busobj) { ++ r = -1; ++ goto fail; ++ } ++ ++ msg = dbus_message_new_method_call(menu->busname, menu->busobj, ++ DBUSMENU_IFACE, "GetLayout"); ++ if (!msg) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ dbus_message_iter_init_append(msg, &iter); ++ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, ++ &parentid) || ++ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &depth) || ++ !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, ++ DBUS_TYPE_STRING_AS_STRING, ++ &strings) || ++ !dbus_message_iter_close_container(&iter, &strings)) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ if (!dbus_connection_send_with_reply(menu->conn, msg, &pending, -1) || ++ !dbus_pending_call_set_notify(pending, layout_ready, menu, NULL)) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ dbus_message_unref(msg); ++ return 0; ++ ++fail: ++ if (pending) { ++ dbus_pending_call_cancel(pending); ++ dbus_pending_call_unref(pending); ++ } ++ dbus_message_iter_abandon_container_if_open(&iter, &strings); ++ if (msg) ++ dbus_message_unref(msg); ++ menu_destroy(menu); ++ return r; ++} ++ ++static void ++about_to_show_handle(DBusPendingCall *pending, void *data) ++{ ++ Menu *menu = data; ++ ++ DBusMessage *reply = NULL; ++ ++ reply = dbus_pending_call_steal_reply(pending); ++ if (!reply) ++ goto fail; ++ ++ if (request_layout(menu) < 0) ++ goto fail; ++ ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(pending); ++ return; ++ ++fail: ++ if (reply) ++ dbus_message_unref(reply); ++ if (pending) ++ dbus_pending_call_unref(pending); ++ menu_destroy(menu); ++} ++ ++void ++menu_show(DBusConnection *conn, struct wl_event_loop *loop, const char *busname, ++ const char *busobj, const char **menucmd) ++{ ++ DBusMessage *msg = NULL; ++ DBusPendingCall *pending = NULL; ++ Menu *menu = NULL; ++ char *busname_dup = NULL, *busobj_dup = NULL; ++ dbus_int32_t parentid = 0; ++ ++ menu = calloc(1, sizeof(Menu)); ++ busname_dup = strdup(busname); ++ busobj_dup = strdup(busobj); ++ if (!menu || !busname_dup || !busobj_dup) ++ goto fail; ++ ++ menu->conn = conn; ++ menu->loop = loop; ++ menu->busname = busname_dup; ++ menu->busobj = busobj_dup; ++ menu->menucmd = menucmd; ++ ++ msg = dbus_message_new_method_call(menu->busname, menu->busobj, ++ DBUSMENU_IFACE, "AboutToShow"); ++ if (!msg) ++ goto fail; ++ ++ if (!dbus_message_append_args(msg, DBUS_TYPE_INT32, &parentid, ++ DBUS_TYPE_INVALID) || ++ !dbus_connection_send_with_reply(menu->conn, msg, &pending, -1) || ++ !dbus_pending_call_set_notify(pending, about_to_show_handle, menu, ++ NULL)) { ++ goto fail; ++ } ++ ++ dbus_message_unref(msg); ++ return; ++ ++fail: ++ if (pending) ++ dbus_pending_call_unref(pending); ++ if (msg) ++ dbus_message_unref(msg); ++ free(menu); ++} +diff --git a/systray/menu.h b/systray/menu.h +new file mode 100644 +index 0000000..7f48ada +--- /dev/null ++++ b/systray/menu.h +@@ -0,0 +1,11 @@ ++#ifndef MENU_H ++#define MENU_H ++ ++#include ++#include ++ ++/* The menu is built on demand and not kept around */ ++void menu_show (DBusConnection *conn, struct wl_event_loop *loop, ++ const char *busname, const char *busobj, const char **menucmd); ++ ++#endif /* MENU_H */ +diff --git a/systray/tray.c b/systray/tray.c +new file mode 100644 +index 0000000..7f9b1b0 +--- /dev/null ++++ b/systray/tray.c +@@ -0,0 +1,237 @@ ++#include "tray.h" ++ ++#include "icon.h" ++#include "item.h" ++#include "menu.h" ++#include "watcher.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define PIXMAN_COLOR(hex) \ ++ { .red = ((hex >> 24) & 0xff) * 0x101, \ ++ .green = ((hex >> 16) & 0xff) * 0x101, \ ++ .blue = ((hex >> 8) & 0xff) * 0x101, \ ++ .alpha = (hex & 0xff) * 0x101 } ++ ++static Watcher * ++tray_get_watcher(const Tray *tray) ++{ ++ if (!tray) ++ return NULL; ++ ++ return tray->watcher; ++} ++ ++static pixman_image_t * ++createcanvas(int width, int height, int bgcolor) ++{ ++ pixman_image_t *src, *dest; ++ pixman_color_t bgcolor_pix = PIXMAN_COLOR(bgcolor); ++ ++ dest = pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height, NULL, ++ 0); ++ src = pixman_image_create_solid_fill(&bgcolor_pix); ++ ++ pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dest, 0, 0, 0, 0, 0, ++ 0, width, height); ++ ++ pixman_image_unref(src); ++ return dest; ++} ++ ++void ++tray_update(Tray *tray) ++{ ++ Item *item; ++ Watcher *watcher; ++ int icon_size, i = 0, canvas_width, canvas_height, n_items, spacing; ++ pixman_image_t *canvas = NULL, *img; ++ ++ watcher = tray_get_watcher(tray); ++ n_items = watcher_get_n_items(watcher); ++ ++ if (!n_items) { ++ if (tray->image) { ++ pixman_image_unref(tray->image); ++ tray->image = NULL; ++ } ++ tray->cb(tray->monitor); ++ return; ++ } ++ ++ icon_size = tray->height; ++ spacing = tray->spacing; ++ canvas_width = n_items * (icon_size + spacing) + spacing; ++ canvas_height = tray->height; ++ ++ canvas = createcanvas(canvas_width, canvas_height, tray->scheme[1]); ++ if (!canvas) ++ goto fail; ++ ++ wl_list_for_each(item, &watcher->items, link) { ++ int slot_x_start = spacing + i * (icon_size + spacing); ++ int slot_x_end = slot_x_start + icon_size + spacing; ++ int slot_x_width = slot_x_end - slot_x_start; ++ ++ int slot_y_start = 0; ++ int slot_y_end = canvas_height; ++ int slot_y_width = slot_y_end - slot_y_start; ++ ++ if (item->icon) { ++ /* Real icon */ ++ img = item->icon->img; ++ if (resize_image(img, icon_size, icon_size) < 0) ++ goto fail; ++ pixman_image_composite32(PIXMAN_OP_OVER, img, NULL, ++ canvas, 0, 0, 0, 0, ++ slot_x_start, 0, canvas_width, ++ canvas_height); ++ ++ } else if (item->appid) { ++ /* Font glyph alpha mask */ ++ const struct fcft_glyph *g; ++ int pen_y, pen_x; ++ pixman_color_t fg_color = PIXMAN_COLOR(tray->scheme[0]); ++ pixman_image_t *fg; ++ ++ if (item->fallback_icon) { ++ g = item->fallback_icon; ++ } else { ++ g = createfallbackicon(item->appid, ++ item->fgcolor, ++ tray->font); ++ if (!g) ++ goto fail; ++ item->fallback_icon = g; ++ } ++ ++ pen_x = slot_x_start + (slot_x_width - g->width) / 2; ++ pen_y = slot_y_start + (slot_y_width - g->height) / 2; ++ ++ fg = pixman_image_create_solid_fill(&fg_color); ++ pixman_image_composite32(PIXMAN_OP_OVER, fg, g->pix, ++ canvas, 0, 0, 0, 0, pen_x, ++ pen_y, canvas_width, ++ canvas_height); ++ pixman_image_unref(fg); ++ } ++ i++; ++ } ++ ++ if (tray->image) ++ pixman_image_unref(tray->image); ++ tray->image = canvas; ++ tray->cb(tray->monitor); ++ ++ return; ++ ++fail: ++ if (canvas) ++ pixman_image_unref(canvas); ++ return; ++} ++ ++void ++destroytray(Tray *tray) ++{ ++ if (tray->image) ++ pixman_image_unref(tray->image); ++ if (tray->font) ++ fcft_destroy(tray->font); ++ free(tray); ++} ++ ++Tray * ++createtray(void *monitor, int height, int spacing, uint32_t *colorscheme, ++ const char **fonts, const char *fontattrs, TrayNotifyCb cb, ++ Watcher *watcher) ++{ ++ Tray *tray = NULL; ++ char fontattrs_my[128]; ++ struct fcft_font *font = NULL; ++ ++ sprintf(fontattrs_my, "%s:%s", fontattrs, "weight:bold"); ++ ++ tray = calloc(1, sizeof(Tray)); ++ font = fcft_from_name(1, fonts, fontattrs_my); ++ if (!tray || !font) ++ goto fail; ++ ++ tray->monitor = monitor; ++ tray->height = height; ++ tray->spacing = spacing; ++ tray->scheme = colorscheme; ++ tray->cb = cb; ++ tray->watcher = watcher; ++ tray->font = font; ++ ++ return tray; ++ ++fail: ++ if (font) ++ fcft_destroy(font); ++ free(tray); ++ return NULL; ++} ++ ++int ++tray_get_width(const Tray *tray) ++{ ++ if (tray && tray->image) ++ return pixman_image_get_width(tray->image); ++ else ++ return 0; ++} ++ ++int ++tray_get_icon_width(const Tray *tray) ++{ ++ if (!tray) ++ return 0; ++ ++ return tray->height; ++} ++ ++void ++tray_rightclicked(Tray *tray, unsigned int index, const char **menucmd) ++{ ++ Item *item; ++ Watcher *watcher; ++ unsigned int count = 0; ++ ++ watcher = tray_get_watcher(tray); ++ ++ wl_list_for_each(item, &watcher->items, link) { ++ if (count == index) { ++ menu_show(watcher->conn, watcher->loop, item->busname, ++ item->menu_busobj, menucmd); ++ return; ++ } ++ count++; ++ } ++} ++ ++void ++tray_leftclicked(Tray *tray, unsigned int index) ++{ ++ Item *item; ++ Watcher *watcher; ++ unsigned int count = 0; ++ ++ watcher = tray_get_watcher(tray); ++ ++ wl_list_for_each(item, &watcher->items, link) { ++ if (count == index) { ++ item_activate(item); ++ return; ++ } ++ count++; ++ } ++} +diff --git a/systray/tray.h b/systray/tray.h +new file mode 100644 +index 0000000..af4e5e3 +--- /dev/null ++++ b/systray/tray.h +@@ -0,0 +1,37 @@ ++#ifndef TRAY_H ++#define TRAY_H ++ ++#include "watcher.h" ++ ++#include ++#include ++ ++#include ++ ++typedef void (*TrayNotifyCb)(void *data); ++ ++typedef struct { ++ pixman_image_t *image; ++ struct fcft_font *font; ++ uint32_t *scheme; ++ TrayNotifyCb cb; ++ Watcher *watcher; ++ void *monitor; ++ int height; ++ int spacing; ++ ++ struct wl_list link; ++} Tray; ++ ++Tray *createtray (void *monitor, int height, int spacing, uint32_t *colorscheme, ++ const char **fonts, const char *fontattrs, TrayNotifyCb cb, ++ Watcher *watcher); ++void destroytray (Tray *tray); ++ ++int tray_get_width (const Tray *tray); ++int tray_get_icon_width (const Tray *tray); ++void tray_update (Tray *tray); ++void tray_leftclicked (Tray *tray, unsigned int index); ++void tray_rightclicked (Tray *tray, unsigned int index, const char **menucmd); ++ ++#endif /* TRAY_H */ +diff --git a/systray/watcher.c b/systray/watcher.c +new file mode 100644 +index 0000000..8dd84b9 +--- /dev/null ++++ b/systray/watcher.c +@@ -0,0 +1,551 @@ ++#include "watcher.h" ++ ++#include "item.h" ++#include "tray.h" ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++// IWYU pragma: no_include "dbus/dbus-protocol.h" ++// IWYU pragma: no_include "dbus/dbus-shared.h" ++ ++static const char *const match_rule = ++ "type='signal'," ++ "interface='" DBUS_INTERFACE_DBUS ++ "'," ++ "member='NameOwnerChanged'"; ++ ++static const char *const snw_xml = ++ "\n" ++ "\n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ "\n"; ++ ++static void ++unregister_item(Watcher *watcher, Item *item) ++{ ++ wl_list_remove(&item->link); ++ destroyitem(item); ++ ++ watcher_update_trays(watcher); ++} ++ ++static Item * ++item_name_to_ptr(const Watcher *watcher, const char *busname) ++{ ++ Item *item; ++ ++ wl_list_for_each(item, &watcher->items, link) { ++ if (!item || !item->busname) ++ return NULL; ++ if (strcmp(item->busname, busname) == 0) ++ return item; ++ } ++ ++ return NULL; ++} ++ ++static DBusHandlerResult ++handle_nameowner_changed(Watcher *watcher, DBusConnection *conn, ++ DBusMessage *msg) ++{ ++ char *name, *old_owner, *new_owner; ++ Item *item; ++ ++ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, ++ DBUS_TYPE_STRING, &old_owner, ++ DBUS_TYPE_STRING, &new_owner, ++ DBUS_TYPE_INVALID)) { ++ return DBUS_HANDLER_RESULT_HANDLED; ++ } ++ ++ if (*new_owner != '\0' || *name == '\0') ++ return DBUS_HANDLER_RESULT_HANDLED; ++ ++ item = item_name_to_ptr(watcher, name); ++ if (!item) ++ return DBUS_HANDLER_RESULT_HANDLED; ++ ++ unregister_item(watcher, item); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult ++filter_bus(DBusConnection *conn, DBusMessage *msg, void *data) ++{ ++ Watcher *watcher = data; ++ ++ if (dbus_message_is_signal(msg, DBUS_INTERFACE_DBUS, ++ "NameOwnerChanged")) ++ return handle_nameowner_changed(watcher, conn, msg); ++ ++ else ++ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; ++} ++ ++static DBusHandlerResult ++respond_register_item(Watcher *watcher, DBusConnection *conn, DBusMessage *msg) ++{ ++ DBusHandlerResult res = DBUS_HANDLER_RESULT_HANDLED; ++ ++ DBusMessage *reply = NULL; ++ Item *item; ++ const char *sender, *param, *busobj, *registree_name; ++ ++ if (!(sender = dbus_message_get_sender(msg)) || ++ !dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, ¶m, ++ DBUS_TYPE_INVALID)) { ++ reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, ++ "Malformed message"); ++ goto send; ++ } ++ ++ switch (*param) { ++ case '/': ++ registree_name = sender; ++ busobj = param; ++ break; ++ case ':': ++ registree_name = param; ++ busobj = SNI_OPATH; ++ break; ++ default: ++ reply = dbus_message_new_error_printf(msg, ++ DBUS_ERROR_INVALID_ARGS, ++ "Bad argument: \"%s\"", ++ param); ++ goto send; ++ } ++ ++ if (*registree_name != ':' || ++ !dbus_validate_bus_name(registree_name, NULL)) { ++ reply = dbus_message_new_error_printf(msg, ++ DBUS_ERROR_INVALID_ARGS, ++ "Invalid busname %s", ++ registree_name); ++ goto send; ++ } ++ ++ if (item_name_to_ptr(watcher, registree_name)) { ++ reply = dbus_message_new_error_printf(msg, ++ DBUS_ERROR_INVALID_ARGS, ++ "%s already tracked", ++ registree_name); ++ goto send; ++ } ++ ++ item = createitem(registree_name, busobj, watcher); ++ wl_list_insert(&watcher->items, &item->link); ++ watcher_update_trays(watcher); ++ ++ reply = dbus_message_new_method_return(msg); ++ ++send: ++ if (!reply || !dbus_connection_send(conn, reply, NULL)) ++ res = DBUS_HANDLER_RESULT_NEED_MEMORY; ++ ++ if (reply) ++ dbus_message_unref(reply); ++ return res; ++} ++ ++static int ++get_registered_items(const Watcher *watcher, DBusMessageIter *iter) ++{ ++ DBusMessageIter names = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ Item *item; ++ int r; ++ ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, ++ DBUS_TYPE_STRING_AS_STRING, ++ &names)) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ wl_list_for_each(item, &watcher->items, link) { ++ if (!dbus_message_iter_append_basic(&names, DBUS_TYPE_STRING, ++ &item->busname)) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ } ++ ++ dbus_message_iter_close_container(iter, &names); ++ return 0; ++ ++fail: ++ dbus_message_iter_abandon_container_if_open(iter, &names); ++ return r; ++} ++ ++static int ++get_registered_items_variant(const Watcher *watcher, DBusMessageIter *iter) ++{ ++ DBusMessageIter variant = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ int r; ++ ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "as", ++ &variant) || ++ get_registered_items(watcher, &variant) < 0) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ dbus_message_iter_close_container(iter, &variant); ++ return 0; ++ ++fail: ++ dbus_message_iter_abandon_container_if_open(iter, &variant); ++ return r; ++} ++ ++static int ++get_isregistered(DBusMessageIter *iter) ++{ ++ DBusMessageIter variant = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ dbus_bool_t is_registered = TRUE; ++ int r; ++ ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, ++ DBUS_TYPE_BOOLEAN_AS_STRING, ++ &variant) || ++ !dbus_message_iter_append_basic(&variant, DBUS_TYPE_BOOLEAN, ++ &is_registered)) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ dbus_message_iter_close_container(iter, &variant); ++ return 0; ++ ++fail: ++ dbus_message_iter_abandon_container_if_open(iter, &variant); ++ return r; ++} ++ ++static int ++get_version(DBusMessageIter *iter) ++{ ++ DBusMessageIter variant = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ dbus_int32_t protovers = 0; ++ int r; ++ ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, ++ DBUS_TYPE_INT32_AS_STRING, ++ &variant) || ++ !dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, ++ &protovers)) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ dbus_message_iter_close_container(iter, &variant); ++ return 0; ++ ++fail: ++ dbus_message_iter_abandon_container_if_open(iter, &variant); ++ return r; ++} ++ ++static DBusHandlerResult ++respond_get_prop(Watcher *watcher, DBusConnection *conn, DBusMessage *msg) ++{ ++ DBusError err = DBUS_ERROR_INIT; ++ DBusMessage *reply = NULL; ++ DBusMessageIter iter = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ const char *iface, *prop; ++ ++ if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &iface, ++ DBUS_TYPE_STRING, &prop, ++ DBUS_TYPE_INVALID)) { ++ reply = dbus_message_new_error(msg, err.name, err.message); ++ dbus_error_free(&err); ++ goto send; ++ } ++ ++ if (strcmp(iface, SNW_IFACE) != 0) { ++ reply = dbus_message_new_error_printf( ++ msg, DBUS_ERROR_UNKNOWN_INTERFACE, ++ "Unknown interface \"%s\"", iface); ++ goto send; ++ } ++ ++ reply = dbus_message_new_method_return(msg); ++ if (!reply) ++ goto fail; ++ ++ if (strcmp(prop, "ProtocolVersion") == 0) { ++ dbus_message_iter_init_append(reply, &iter); ++ if (get_version(&iter) < 0) ++ goto fail; ++ ++ } else if (strcmp(prop, "IsStatusNotifierHostRegistered") == 0) { ++ dbus_message_iter_init_append(reply, &iter); ++ if (get_isregistered(&iter) < 0) ++ goto fail; ++ ++ } else if (strcmp(prop, "RegisteredStatusNotifierItems") == 0) { ++ dbus_message_iter_init_append(reply, &iter); ++ if (get_registered_items_variant(watcher, &iter) < 0) ++ goto fail; ++ ++ } else { ++ dbus_message_unref(reply); ++ reply = dbus_message_new_error_printf( ++ reply, DBUS_ERROR_UNKNOWN_PROPERTY, ++ "Property \"%s\" does not exist", prop); ++ } ++ ++send: ++ if (!reply || !dbus_connection_send(conn, reply, NULL)) ++ goto fail; ++ ++ if (reply) ++ dbus_message_unref(reply); ++ return DBUS_HANDLER_RESULT_HANDLED; ++ ++fail: ++ if (reply) ++ dbus_message_unref(reply); ++ return DBUS_HANDLER_RESULT_NEED_MEMORY; ++} ++ ++static DBusHandlerResult ++respond_all_props(Watcher *watcher, DBusConnection *conn, DBusMessage *msg) ++{ ++ DBusMessage *reply = NULL; ++ DBusMessageIter array = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ DBusMessageIter dict = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ DBusMessageIter iter = DBUS_MESSAGE_ITER_INIT_CLOSED; ++ const char *prop; ++ ++ reply = dbus_message_new_method_return(msg); ++ if (!reply) ++ goto fail; ++ dbus_message_iter_init_append(reply, &iter); ++ ++ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", ++ &array)) ++ goto fail; ++ ++ prop = "ProtocolVersion"; ++ if (!dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, ++ NULL, &dict) || ++ !dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &prop) || ++ get_version(&dict) < 0 || ++ !dbus_message_iter_close_container(&array, &dict)) { ++ goto fail; ++ } ++ ++ prop = "IsStatusNotifierHostRegistered"; ++ if (!dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, ++ NULL, &dict) || ++ !dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &prop) || ++ get_isregistered(&dict) < 0 || ++ !dbus_message_iter_close_container(&array, &dict)) { ++ goto fail; ++ } ++ ++ prop = "RegisteredStatusNotifierItems"; ++ if (!dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, ++ NULL, &dict) || ++ !dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &prop) || ++ get_registered_items_variant(watcher, &dict) < 0 || ++ !dbus_message_iter_close_container(&array, &dict)) { ++ goto fail; ++ } ++ ++ if (!dbus_message_iter_close_container(&iter, &array) || ++ !dbus_connection_send(conn, reply, NULL)) { ++ goto fail; ++ } ++ ++ dbus_message_unref(reply); ++ return DBUS_HANDLER_RESULT_HANDLED; ++ ++fail: ++ dbus_message_iter_abandon_container_if_open(&array, &dict); ++ dbus_message_iter_abandon_container_if_open(&iter, &array); ++ if (reply) ++ dbus_message_unref(reply); ++ return DBUS_HANDLER_RESULT_NEED_MEMORY; ++} ++ ++static DBusHandlerResult ++respond_introspect(DBusConnection *conn, DBusMessage *msg) ++{ ++ DBusMessage *reply = NULL; ++ ++ reply = dbus_message_new_method_return(msg); ++ if (!reply) ++ goto fail; ++ ++ if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &snw_xml, ++ DBUS_TYPE_INVALID) || ++ !dbus_connection_send(conn, reply, NULL)) { ++ goto fail; ++ } ++ ++ dbus_message_unref(reply); ++ return DBUS_HANDLER_RESULT_HANDLED; ++ ++fail: ++ if (reply) ++ dbus_message_unref(reply); ++ return DBUS_HANDLER_RESULT_NEED_MEMORY; ++} ++ ++static DBusHandlerResult ++snw_message_handler(DBusConnection *conn, DBusMessage *msg, void *data) ++{ ++ Watcher *watcher = data; ++ ++ if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE, ++ "Introspect")) ++ return respond_introspect(conn, msg); ++ ++ else if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, ++ "GetAll")) ++ return respond_all_props(watcher, conn, msg); ++ ++ else if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, ++ "Get")) ++ return respond_get_prop(watcher, conn, msg); ++ ++ else if (dbus_message_is_method_call(msg, SNW_IFACE, ++ "RegisterStatusNotifierItem")) ++ return respond_register_item(watcher, conn, msg); ++ ++ else ++ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; ++} ++ ++static const DBusObjectPathVTable snw_vtable = { .message_function = ++ snw_message_handler }; ++ ++void ++watcher_start(Watcher *watcher, DBusConnection *conn, ++ struct wl_event_loop *loop) ++{ ++ DBusError err = DBUS_ERROR_INIT; ++ int r, flags; ++ ++ wl_list_init(&watcher->items); ++ wl_list_init(&watcher->trays); ++ watcher->conn = conn; ++ watcher->loop = loop; ++ ++ flags = DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE; ++ r = dbus_bus_request_name(conn, SNW_NAME, ++ flags, NULL); ++ if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) ++ goto fail; ++ ++ if (!dbus_connection_add_filter(conn, filter_bus, watcher, NULL)) { ++ dbus_bus_release_name(conn, SNW_NAME, NULL); ++ goto fail; ++ } ++ ++ dbus_bus_add_match(conn, match_rule, &err); ++ if (dbus_error_is_set(&err)) { ++ dbus_connection_remove_filter(conn, filter_bus, watcher); ++ dbus_bus_release_name(conn, SNW_NAME, NULL); ++ goto fail; ++ } ++ ++ if (!dbus_connection_register_object_path(conn, SNW_OPATH, &snw_vtable, ++ watcher)) { ++ dbus_bus_remove_match(conn, match_rule, NULL); ++ dbus_connection_remove_filter(conn, filter_bus, watcher); ++ dbus_bus_release_name(conn, SNW_NAME, NULL); ++ goto fail; ++ } ++ ++ watcher->running = 1; ++ return; ++ ++fail: ++ fprintf(stderr, "Couldn't start watcher, systray not available\n"); ++ dbus_error_free(&err); ++ return; ++} ++ ++void ++watcher_stop(Watcher *watcher) ++{ ++ dbus_connection_unregister_object_path(watcher->conn, SNW_OPATH); ++ dbus_bus_remove_match(watcher->conn, match_rule, NULL); ++ dbus_connection_remove_filter(watcher->conn, filter_bus, watcher); ++ dbus_bus_release_name(watcher->conn, SNW_NAME, NULL); ++ watcher->running = 0; ++} ++ ++int ++watcher_get_n_items(const Watcher *watcher) ++{ ++ return wl_list_length(&watcher->items); ++} ++ ++void ++watcher_update_trays(Watcher *watcher) ++{ ++ Tray *tray; ++ ++ wl_list_for_each(tray, &watcher->trays, link) ++ tray_update(tray); ++} +diff --git a/systray/watcher.h b/systray/watcher.h +new file mode 100644 +index 0000000..127eb64 +--- /dev/null ++++ b/systray/watcher.h +@@ -0,0 +1,35 @@ ++#ifndef WATCHER_H ++#define WATCHER_H ++ ++#include ++#include ++#include ++ ++/* ++ * The FDO spec says "org.freedesktop.StatusNotifierWatcher"[1], ++ * but both the client libraries[2,3] actually use "org.kde.StatusNotifierWatcher" ++ * ++ * [1] https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/ ++ * [2] https://github.com/AyatanaIndicators/libayatana-appindicator-glib ++ * [3] https://invent.kde.org/frameworks/kstatusnotifieritem ++ */ ++#define SNW_NAME "org.kde.StatusNotifierWatcher" ++#define SNW_OPATH "/StatusNotifierWatcher" ++#define SNW_IFACE "org.kde.StatusNotifierWatcher" ++ ++typedef struct { ++ struct wl_list items; ++ struct wl_list trays; ++ struct wl_event_loop *loop; ++ DBusConnection *conn; ++ int running; ++} Watcher; ++ ++void watcher_start (Watcher *watcher, DBusConnection *conn, ++ struct wl_event_loop *loop); ++void watcher_stop (Watcher *watcher); ++ ++int watcher_get_n_items (const Watcher *watcher); ++void watcher_update_trays (Watcher *watcher); ++ ++#endif /* WATCHER_H */ +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/bar/README.md b/dwl/dwl-patches/patches/bar/README.md new file mode 100755 index 0000000..4955753 --- /dev/null +++ b/dwl/dwl-patches/patches/bar/README.md @@ -0,0 +1,34 @@ +### Description + +Add a bar identical to dwm's bar. + +To use a status-bar, you can pass in status text via stdin: +``` +slstatus -s | dwl +``` + +### Dependencies +* tllist (build dependency, required & pulled automatically by fcft) +* fcft +* pixman + +### Download +- [main 2025-07-29](/dwl/dwl-patches/raw/branch/main/patches/bar/bar.patch) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/bar/bar-0.7.patch) +- [0.6](/dwl/dwl-patches/raw/branch/main/patches/bar/bar-0.6.patch) + +It is required to remove, regenerate or update `config.h` after applying the patch, +since it makes changes to the configuration structure. +For example, in the `pertag` patch, `TAGCOUNT` must be replaced with `LENGTH(tags)`. + +Below is a preview of the patch. + +![bar patch preview](bar.png) + +### Authors +- [sewn](https://codeberg.org/sewn) + +### Credits +- [MadcowOG](https://github.com/MadcowOG) +- [kolumni](https://github.com/kolunmi/dwlb) + diff --git a/dwl/dwl-patches/patches/bar/bar-0.6.patch b/dwl/dwl-patches/patches/bar/bar-0.6.patch new file mode 100755 index 0000000..70c9f12 --- /dev/null +++ b/dwl/dwl-patches/patches/bar/bar-0.6.patch @@ -0,0 +1,1245 @@ +From 85e40afc2ad8acba453ce8c57233542e340c1c2b Mon Sep 17 00:00:00 2001 +From: sewn +Date: Fri, 23 Aug 2024 09:42:04 +0300 +Subject: [PATCH] Implement dwm bar clone + +--- + Makefile | 2 +- + config.def.h | 31 +++- + drwl.h | 311 ++++++++++++++++++++++++++++++++++++ + dwl.c | 442 +++++++++++++++++++++++++++++++++++++++++---------- + 4 files changed, 691 insertions(+), 95 deletions(-) + create mode 100644 drwl.h + +diff --git a/Makefile b/Makefile +index 0d651e7..2a11396 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots wayland-server xkbcommon libinput $(XLIBS) ++PKGS = wlroots wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 22d2171..5d1dc2b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,15 +7,21 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); +-static const float bordercolor[] = COLOR(0x444444ff); +-static const float focuscolor[] = COLOR(0x005577ff); +-static const float urgentcolor[] = COLOR(0xff0000ff); ++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 float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static uint32_t colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, ++ [SchemeUrg] = { 0, 0, 0x770000ff }, ++}; + + /* tagging - TAGCOUNT must be no greater than 31 */ +-#define TAGCOUNT (9) ++static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + /* logging */ + static int log_level = WLR_ERROR; +@@ -127,6 +133,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY, XKB_KEY_b, togglebar, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +@@ -170,7 +177,15 @@ static const Key keys[] = { + }; + + static const Button buttons[] = { +- { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, +- { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkLtSymbol, 0, BTN_LEFT, setlayout, {.v = &layouts[0]} }, ++ { ClkLtSymbol, 0, BTN_RIGHT, setlayout, {.v = &layouts[2]} }, ++ { ClkTitle, 0, BTN_MIDDLE, zoom, {0} }, ++ { ClkStatus, 0, BTN_MIDDLE, spawn, {.v = termcmd} }, ++ { ClkClient, MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, ++ { ClkClient, MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { ClkClient, MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkTagBar, 0, BTN_LEFT, view, {0} }, ++ { ClkTagBar, 0, BTN_RIGHT, toggleview, {0} }, ++ { ClkTagBar, MODKEY, BTN_LEFT, tag, {0} }, ++ { ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} }, + }; +diff --git a/drwl.h b/drwl.h +new file mode 100644 +index 0000000..b06a736 +--- /dev/null ++++ b/drwl.h +@@ -0,0 +1,311 @@ ++/* ++ * drwl - https://codeberg.org/sewn/drwl ++ * ++ * Copyright (c) 2023-2024 sewn ++ * Copyright (c) 2024 notchoc ++ * ++ * 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. ++ * ++ * The UTF-8 Decoder included is from Bjoern Hoehrmann: ++ * Copyright (c) 2008-2010 Bjoern Hoehrmann ++ * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. ++ */ ++#pragma once ++ ++#include ++#include ++#include ++ ++enum { ColFg, ColBg, ColBorder }; /* colorscheme index */ ++ ++typedef struct fcft_font Fnt; ++typedef pixman_image_t Img; ++ ++typedef struct { ++ Img *image; ++ Fnt *font; ++ uint32_t *scheme; ++} Drwl; ++ ++#define UTF8_ACCEPT 0 ++#define UTF8_REJECT 12 ++#define UTF8_INVALID 0xFFFD ++ ++static const uint8_t utf8d[] = { ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, ++ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, ++ ++ 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, ++ 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, ++ 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, ++ 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, ++ 12,36,12,12,12,12,12,12,12,12,12,12, ++}; ++ ++static inline uint32_t ++utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) ++{ ++ uint32_t type = utf8d[byte]; ++ ++ *codep = (*state != UTF8_ACCEPT) ? ++ (byte & 0x3fu) | (*codep << 6) : ++ (0xff >> type) & (byte); ++ ++ *state = utf8d[256 + *state + type]; ++ return *state; ++} ++ ++static int ++drwl_init(void) ++{ ++ fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); ++ return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR); ++} ++ ++static Drwl * ++drwl_create(void) ++{ ++ Drwl *drwl; ++ ++ if (!(drwl = calloc(1, sizeof(Drwl)))) ++ return NULL; ++ ++ return drwl; ++} ++ ++static void ++drwl_setfont(Drwl *drwl, Fnt *font) ++{ ++ if (drwl) ++ drwl->font = font; ++} ++ ++static void ++drwl_setimage(Drwl *drwl, Img *image) ++{ ++ if (drwl) ++ drwl->image = image; ++} ++ ++static Fnt * ++drwl_font_create(Drwl *drwl, size_t count, ++ const char *names[static count], const char *attributes) ++{ ++ Fnt *font = fcft_from_name(count, names, attributes); ++ if (drwl) ++ drwl_setfont(drwl, font); ++ return font; ++} ++ ++static void ++drwl_font_destroy(Fnt *font) ++{ ++ fcft_destroy(font); ++} ++ ++static inline pixman_color_t ++convert_color(uint32_t clr) ++{ ++ return (pixman_color_t){ ++ ((clr >> 24) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 16) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 8) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ (clr & 0xFF) * 0x101 ++ }; ++} ++ ++static void ++drwl_setscheme(Drwl *drwl, uint32_t *scm) ++{ ++ if (drwl) ++ drwl->scheme = scm; ++} ++ ++static Img * ++drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits) ++{ ++ Img *image; ++ pixman_region32_t clip; ++ ++ image = pixman_image_create_bits_no_clear( ++ PIXMAN_a8r8g8b8, w, h, bits, w * 4); ++ if (!image) ++ return NULL; ++ pixman_region32_init_rect(&clip, 0, 0, w, h); ++ pixman_image_set_clip_region32(image, &clip); ++ pixman_region32_fini(&clip); ++ ++ if (drwl) ++ drwl_setimage(drwl, image); ++ return image; ++} ++ ++static void ++drwl_rect(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ int filled, int invert) ++{ ++ pixman_color_t clr; ++ if (!drwl || !drwl->scheme || !drwl->image) ++ return; ++ ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ if (filled) ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1, ++ &(pixman_rectangle16_t){x, y, w, h}); ++ else ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4, ++ (pixman_rectangle16_t[4]){ ++ { x, y, w, 1 }, ++ { x, y + h - 1, w, 1 }, ++ { x, y, 1, h }, ++ { x + w - 1, y, 1, h }}); ++} ++ ++static int ++drwl_text(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ unsigned int lpad, const char *text, int invert) ++{ ++ int ty; ++ int render = x || y || w || h; ++ long x_kern; ++ uint32_t cp = 0, last_cp = 0, state; ++ pixman_color_t clr; ++ pixman_image_t *fg_pix = NULL; ++ int noellipsis = 0; ++ const struct fcft_glyph *glyph, *eg = NULL; ++ int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; ++ ++ if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font) ++ return 0; ++ ++ if (!render) { ++ w = invert ? invert : ~invert; ++ } else { ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ fg_pix = pixman_image_create_solid_fill(&clr); ++ ++ drwl_rect(drwl, x, y, w, h, 1, !invert); ++ ++ x += lpad; ++ w -= lpad; ++ } ++ ++ if (render && (drwl->scheme[ColBg] & 0xFF) != 0xFF) ++ fcft_subpixel_mode = FCFT_SUBPIXEL_NONE; ++ ++ if (render) ++ eg = fcft_rasterize_char_utf32(drwl->font, 0x2026 /* … */, fcft_subpixel_mode); ++ ++ for (const char *p = text, *pp; pp = p, *p; p++) { ++ for (state = UTF8_ACCEPT; *p && ++ utf8decode(&state, &cp, *p) > UTF8_REJECT; p++) ++ ; ++ if (!*p || state == UTF8_REJECT) { ++ cp = UTF8_INVALID; ++ if (p > pp) ++ p--; ++ } ++ ++ glyph = fcft_rasterize_char_utf32(drwl->font, cp, fcft_subpixel_mode); ++ if (!glyph) ++ continue; ++ ++ x_kern = 0; ++ if (last_cp) ++ fcft_kerning(drwl->font, last_cp, cp, &x_kern, NULL); ++ last_cp = cp; ++ ++ ty = y + (h - drwl->font->height) / 2 + drwl->font->ascent; ++ ++ if (render && !noellipsis && x_kern + glyph->advance.x + eg->advance.x > w && ++ *(p + 1) != '\0') { ++ /* cannot fit ellipsis after current codepoint */ ++ if (drwl_text(drwl, 0, 0, 0, 0, 0, pp, 0) + x_kern <= w) { ++ noellipsis = 1; ++ } else { ++ w -= eg->advance.x; ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0, ++ x + eg->x, ty - eg->y, eg->width, eg->height); ++ } ++ } ++ ++ if ((x_kern + glyph->advance.x) > w) ++ break; ++ ++ x += x_kern; ++ ++ if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) ++ /* pre-rendered glyphs (eg. emoji) */ ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ else if (render) ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ ++ x += glyph->advance.x; ++ w -= glyph->advance.x; ++ } ++ ++ if (render) ++ pixman_image_unref(fg_pix); ++ ++ return x + (render ? w : 0); ++} ++ ++static unsigned int ++drwl_font_getwidth(Drwl *drwl, const char *text) ++{ ++ if (!drwl || !drwl->font || !text) ++ return 0; ++ return drwl_text(drwl, 0, 0, 0, 0, 0, text, 0); ++} ++ ++static void ++drwl_image_destroy(Img *image) ++{ ++ pixman_image_unref(image); ++} ++ ++static void ++drwl_destroy(Drwl *drwl) ++{ ++ if (drwl->font) ++ drwl_font_destroy(drwl->font); ++ if (drwl->image) ++ drwl_image_destroy(drwl->image); ++ free(drwl); ++} ++ ++static void ++drwl_fini(void) ++{ ++ fcft_fini(); ++} +diff --git a/dwl.c b/dwl.c +index 145fd01..ab1bc31 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -57,6 +58,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -67,6 +69,7 @@ + #endif + + #include "util.h" ++#include "drwl.h" + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +@@ -75,14 +78,17 @@ + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) +-#define TAGMASK ((1u << TAGCOUNT) - 1) ++#define TAGMASK ((1u << LENGTH(tags)) - 1) + #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) ++#define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) + + /* enums */ ++enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -96,6 +102,7 @@ typedef union { + } Arg; + + typedef struct { ++ unsigned int click; + unsigned int mod; + unsigned int button; + void (*func)(const Arg *); +@@ -185,10 +192,19 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++typedef struct { ++ struct wlr_buffer base; ++ struct wl_listener release; ++ bool busy; ++ Img *image; ++ uint32_t data[]; ++} Buffer; ++ + struct Monitor { + struct wl_list link; + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; ++ struct wlr_scene_buffer *scene_buffer; /* bar buffer */ + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ + struct wl_listener frame; + struct wl_listener destroy; +@@ -196,6 +212,11 @@ struct Monitor { + struct wl_listener destroy_lock_surface; + struct wlr_session_lock_surface_v1 *lock_surface; + struct wlr_box m; /* monitor area, layout-relative */ ++ struct { ++ int width, height; ++ int real_width, real_height; /* non-scaled */ ++ float scale; ++ } b; /* bar area */ + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; +@@ -207,6 +228,9 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ Drwl *drw; ++ Buffer *pool[2]; ++ int lrpad; + }; + + typedef struct { +@@ -249,6 +273,13 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy); ++static void bufdestroy(struct wlr_buffer *buffer); ++static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride); ++static void bufdataend(struct wlr_buffer *buffer); ++static Buffer *bufmon(Monitor *m); ++static void bufrelease(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -282,6 +313,8 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawbar(Monitor *m); ++static void drawbars(void); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -309,7 +342,6 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int + static void outputmgrtest(struct wl_listener *listener, void *data); + static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); +-static void printstatus(void); + static void powermgrsetmode(struct wl_listener *listener, void *data); + static void quit(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); +@@ -331,9 +363,11 @@ static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); ++static int statusin(int fd, unsigned int mask, void *data); + 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 togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -342,6 +376,7 @@ static void unlocksession(struct wl_listener *listener, void *data); + static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); + static void unmapnotify(struct wl_listener *listener, void *data); + static void updatemons(struct wl_listener *listener, void *data); ++static void updatebar(Monitor *m); + static void updatetitle(struct wl_listener *listener, void *data); + static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); +@@ -408,6 +443,15 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static char stext[256]; ++static struct wl_event_source *status_event_source; ++ ++static const struct wlr_buffer_impl buffer_impl = { ++ .destroy = bufdestroy, ++ .begin_data_ptr_access = bufdatabegin, ++ .end_data_ptr_access = bufdataend, ++}; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -548,6 +592,11 @@ arrangelayers(Monitor *m) + if (!m->wlr_output->enabled) + return; + ++ if (m->scene_buffer->node.enabled) { ++ usable_area.height -= m->b.real_height; ++ usable_area.y += topbar ? m->b.real_height : 0; ++ } ++ + /* Arrange exclusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 1); +@@ -590,17 +639,102 @@ axisnotify(struct wl_listener *listener, void *data) + event->delta_discrete, event->source); + } + ++bool ++baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy) ++{ ++ return true; ++} ++ ++void ++bufdestroy(struct wlr_buffer *wlr_buffer) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ if (buf->busy) ++ wl_list_remove(&buf->release.link); ++ drwl_image_destroy(buf->image); ++ free(buf); ++} ++ ++bool ++bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ ++ if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; ++ ++ *data = buf->data; ++ *stride = wlr_buffer->width * 4; ++ *format = DRM_FORMAT_ARGB8888; ++ ++ return true; ++} ++ ++void ++bufdataend(struct wlr_buffer *wlr_buffer) ++{ ++} ++ ++Buffer * ++bufmon(Monitor *m) ++{ ++ size_t i; ++ Buffer *buf = NULL; ++ ++ for (i = 0; i < LENGTH(m->pool); i++) { ++ if (m->pool[i]) { ++ if (m->pool[i]->busy) ++ continue; ++ buf = m->pool[i]; ++ break; ++ } ++ ++ buf = ecalloc(1, sizeof(Buffer) + (m->b.width * 4 * m->b.height)); ++ buf->image = drwl_image_create(NULL, m->b.width, m->b.height, buf->data); ++ wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height); ++ m->pool[i] = buf; ++ break; ++ } ++ if (!buf) ++ return NULL; ++ ++ buf->busy = true; ++ LISTEN(&buf->base.events.release, &buf->release, bufrelease); ++ wlr_buffer_lock(&buf->base); ++ drwl_setimage(m->drw, buf->image); ++ return buf; ++} ++ ++void ++bufrelease(struct wl_listener *listener, void *data) ++{ ++ Buffer *buf = wl_container_of(listener, buf, release); ++ buf->busy = false; ++ wl_list_remove(&buf->release.link); ++} ++ + void + buttonpress(struct wl_listener *listener, void *data) + { ++ unsigned int i = 0, x = 0; ++ double cx; ++ unsigned int click; + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; ++ struct wlr_scene_node *node; ++ struct wlr_scene_buffer *buffer; + uint32_t mods; ++ Arg arg = {0}; + Client *c; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + ++ click = ClkRoot; ++ xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); ++ if (c) ++ click = ClkClient; ++ + switch (event->state) { + case WLR_BUTTON_PRESSED: + cursor_mode = CurPressed; +@@ -608,17 +742,34 @@ buttonpress(struct wl_listener *listener, void *data) + if (locked) + break; + ++ if (!c && !exclusive_focus && ++ (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && ++ (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { ++ cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; ++ do ++ x += TEXTW(selmon, tags[i]); ++ while (cx >= x && ++i < LENGTH(tags)); ++ if (i < LENGTH(tags)) { ++ click = ClkTagBar; ++ arg.ui = 1 << i; ++ } else if (cx < x + TEXTW(selmon, selmon->ltsymbol)) ++ click = ClkLtSymbol; ++ else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) { ++ click = ClkStatus; ++ } else ++ click = ClkTitle; ++ } ++ + /* Change focus if the button was _pressed_ over a client */ + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); +- if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) ++ if (click == ClkClient && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { +- if (CLEANMASK(mods) == CLEANMASK(b->mod) && +- event->button == b->button && b->func) { +- b->func(&b->arg); ++ if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) { ++ b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg); + return; + } + } +@@ -689,6 +840,8 @@ cleanup(void) + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); ++ ++ drwl_fini(); + } + + void +@@ -704,6 +857,12 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + ++ for (i = 0; i < LENGTH(m->pool); i++) ++ wlr_buffer_drop(&m->pool[i]->base); ++ ++ drwl_setimage(m->drw, NULL); ++ drwl_destroy(m->drw); ++ + wl_list_remove(&m->destroy.link); + wl_list_remove(&m->frame.link); + wl_list_remove(&m->link); +@@ -714,6 +873,7 @@ cleanupmon(struct wl_listener *listener, void *data) + + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); ++ wlr_scene_node_destroy(&m->scene_buffer->node); + free(m); + } + +@@ -743,7 +903,7 @@ closemon(Monitor *m) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); +- printstatus(); ++ drawbars(); + } + + void +@@ -980,8 +1140,15 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + ++ if (!(m->drw = drwl_create())) ++ die("failed to create drwl context"); ++ ++ m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL); ++ m->scene_buffer->point_accepts_input = baracceptsinput; ++ updatebar(m); ++ + wl_list_insert(&mons, &m->link); +- printstatus(); ++ drawbars(); + + /* The xdg-protocol specifies: + * +@@ -1312,6 +1479,80 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++void ++drawbar(Monitor *m) ++{ ++ int x, w, tw = 0; ++ int boxs = m->drw->font->height / 9; ++ int boxw = m->drw->font->height / 6 + 2; ++ uint32_t i, occ = 0, urg = 0; ++ Client *c; ++ Buffer *buf; ++ ++ if (!m->scene_buffer->node.enabled) ++ return; ++ if (!(buf = bufmon(m))) ++ return; ++ ++ /* draw status first so it can be overdrawn by tags later */ ++ if (m == selmon) { /* status is only drawn on selected monitor */ ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ ++ drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != m) ++ continue; ++ occ |= c->tags; ++ if (c->isurgent) ++ urg |= c->tags; ++ } ++ x = 0; ++ c = focustop(m); ++ for (i = 0; i < LENGTH(tags); i++) { ++ w = TEXTW(m, tags[i]); ++ drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); ++ drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i); ++ if (occ & 1 << i) ++ drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, ++ m == selmon && c && c->tags & 1 << i, ++ urg & 1 << i); ++ x += w; ++ } ++ w = TEXTW(m, m->ltsymbol); ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0); ++ ++ if ((w = m->b.width - tw - x) > m->b.height) { ++ if (c) { ++ drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); ++ drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); ++ if (c && c->isfloating) ++ drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0); ++ } else { ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1); ++ } ++ } ++ ++ wlr_scene_buffer_set_dest_size(m->scene_buffer, ++ m->b.real_width, m->b.real_height); ++ wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, ++ m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); ++ wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); ++ wlr_buffer_unlock(&buf->base); ++} ++ ++void ++drawbars(void) ++{ ++ Monitor *m = NULL; ++ ++ wl_list_for_each(m, &mons, link) ++ drawbar(m); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1347,13 +1588,13 @@ focusclient(Client *c, int lift) + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) +- client_set_border_color(c, focuscolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder])); + } + + /* Deactivate old client if focus is changing */ + if (old && (!c || client_surface(c) != old)) { + /* If an overlay is focused, don't focus or activate the client, +- * but only update its position in fstack to render its border with focuscolor ++ * but only update its position in fstack to render its border with its color + * and focus it after the overlay is closed. */ + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) +@@ -1364,12 +1605,11 @@ focusclient(Client *c, int lift) + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { +- client_set_border_color(old_c, bordercolor); +- ++ client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder])); + client_activate_surface(old, 0); + } + } +- printstatus(); ++ drawbars(); + + if (!c) { + /* With no client, all we have left is to clear focus */ +@@ -1666,7 +1906,7 @@ mapnotify(struct wl_listener *listener, void *data) + + for (i = 0; i < 4; i++) { + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, +- c->isurgent ? urgentcolor : bordercolor); ++ (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder])); + c->border[i]->node.data = c; + } + +@@ -1689,7 +1929,7 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } +- printstatus(); ++ drawbars(); + + unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); +@@ -1982,46 +2222,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + } + +-void +-printstatus(void) +-{ +- Monitor *m = NULL; +- Client *c; +- uint32_t occ, urg, sel; +- const char *appid, *title; +- +- wl_list_for_each(m, &mons, link) { +- occ = urg = 0; +- wl_list_for_each(c, &clients, link) { +- if (c->mon != m) +- continue; +- occ |= c->tags; +- if (c->isurgent) +- urg |= c->tags; +- } +- if ((c = focustop(m))) { +- title = client_get_title(c); +- appid = client_get_appid(c); +- printf("%s title %s\n", m->wlr_output->name, title ? title : broken); +- printf("%s appid %s\n", m->wlr_output->name, appid ? appid : broken); +- printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); +- printf("%s floating %d\n", m->wlr_output->name, c->isfloating); +- sel = c->tags; +- } else { +- printf("%s title \n", m->wlr_output->name); +- printf("%s appid \n", m->wlr_output->name); +- printf("%s fullscreen \n", m->wlr_output->name); +- printf("%s floating \n", m->wlr_output->name); +- sel = 0; +- } +- +- printf("%s selmon %u\n", m->wlr_output->name, m == selmon); +- printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", +- m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); +- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); +- } +- fflush(stdout); +-} + + void + powermgrsetmode(struct wl_listener *listener, void *data) +@@ -2175,30 +2375,17 @@ run(char *startup_cmd) + + /* Now that the socket exists and the backend is started, run the startup command */ + if (startup_cmd) { +- int piperw[2]; +- if (pipe(piperw) < 0) +- die("startup: pipe:"); + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { ++ close(STDIN_FILENO); + setsid(); +- dup2(piperw[0], STDIN_FILENO); +- close(piperw[0]); +- close(piperw[1]); + execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); + die("startup: execl:"); + } +- dup2(piperw[1], STDOUT_FILENO); +- close(piperw[1]); +- close(piperw[0]); + } + +- /* Mark stdout as non-blocking to avoid people who does not close stdin +- * nor consumes it in their startup script getting dwl frozen */ +- if (fd_set_nonblock(STDOUT_FILENO) < 0) +- close(STDOUT_FILENO); +- +- printstatus(); ++ drawbars(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ +@@ -2262,7 +2449,7 @@ setfloating(Client *c, int floating) + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen + ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2285,7 +2472,7 @@ setfullscreen(Client *c, int fullscreen) + resize(c, c->prev, 0); + } + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2310,7 +2497,7 @@ setlayout(const Arg *arg) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); +- printstatus(); ++ drawbar(selmon); + } + + /* arg > 1.0 will set mfact absolutely */ +@@ -2383,6 +2570,7 @@ setup(void) + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + ++ + wlr_log_init(log_level, NULL); + + /* The Wayland display is managed by libwayland. It handles accepting +@@ -2569,6 +2757,11 @@ setup(void) + + wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); + ++ drwl_init(); ++ ++ status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy), ++ STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2593,6 +2786,7 @@ void + spawn(const Arg *arg) + { + if (fork() == 0) { ++ close(STDIN_FILENO); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); +@@ -2611,6 +2805,30 @@ startdrag(struct wl_listener *listener, void *data) + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); + } + ++int ++statusin(int fd, unsigned int mask, void *data) ++{ ++ char status[1024]; ++ ssize_t n; ++ ++ if (mask & WL_EVENT_ERROR) ++ die("status in event error"); ++ if (mask & WL_EVENT_HANGUP) ++ wl_event_source_remove(status_event_source); ++ ++ n = read(fd, status, sizeof(status) - 1); ++ if (n < 0 && errno != EWOULDBLOCK) ++ die("read:"); ++ ++ status[n] = '\0'; ++ status[strcspn(status, "\n")] = '\0'; ++ ++ strncpy(stext, status, sizeof(stext)); ++ drawbars(); ++ ++ return 0; ++} ++ + void + tag(const Arg *arg) + { +@@ -2621,7 +2839,7 @@ tag(const Arg *arg) + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2666,6 +2884,14 @@ tile(Monitor *m) + } + } + ++void ++togglebar(const Arg *arg) ++{ ++ wlr_scene_node_set_enabled(&selmon->scene_buffer->node, ++ !selmon->scene_buffer->node.enabled); ++ arrangelayers(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { +@@ -2694,7 +2920,7 @@ toggletag(const Arg *arg) + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2707,7 +2933,7 @@ toggleview(const Arg *arg) + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2755,7 +2981,7 @@ unmapnotify(struct wl_listener *listener, void *data) + } + + wlr_scene_node_destroy(&c->scene->node); +- printstatus(); ++ drawbars(); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -2855,6 +3081,13 @@ updatemons(struct wl_listener *listener, void *data) + } + } + ++ if (stext[0] == '\0') ++ strncpy(stext, "dwl-"VERSION, sizeof(stext)); ++ wl_list_for_each(m, &mons, link) { ++ updatebar(m); ++ drawbar(m); ++ } ++ + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a +@@ -2865,12 +3098,45 @@ updatemons(struct wl_listener *listener, void *data) + wlr_output_manager_v1_set_configuration(output_mgr, config); + } + ++void ++updatebar(Monitor *m) ++{ ++ size_t i; ++ int rw, rh; ++ char fontattrs[12]; ++ ++ wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); ++ m->b.width = rw; ++ m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); ++ ++ wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0); ++ ++ for (i = 0; i < LENGTH(m->pool); i++) ++ if (m->pool[i]) { ++ wlr_buffer_drop(&m->pool[i]->base); ++ m->pool[i] = NULL; ++ } ++ ++ if (m->b.scale == m->wlr_output->scale && m->drw) ++ return; ++ ++ drwl_font_destroy(m->drw->font); ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * m->wlr_output->scale); ++ if (!(drwl_font_create(m->drw, LENGTH(fonts), fonts, fontattrs))) ++ die("Could not load font"); ++ ++ m->b.scale = m->wlr_output->scale; ++ m->lrpad = m->drw->font->height; ++ m->b.height = m->drw->font->height + 2; ++ m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale); ++} ++ + void + updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) +- printstatus(); ++ drawbars(); + } + + void +@@ -2883,10 +3149,10 @@ urgent(struct wl_listener *listener, void *data) + return; + + c->isurgent = 1; +- printstatus(); ++ drawbars(); + + if (client_surface(c)->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +@@ -2899,7 +3165,7 @@ view(const Arg *arg) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2940,6 +3206,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + { + struct wlr_scene_node *node, *pnode; + struct wlr_surface *surface = NULL; ++ struct wlr_scene_surface *scene_surface = NULL; + Client *c = NULL; + LayerSurface *l = NULL; + int layer; +@@ -2948,9 +3215,12 @@ xytonode(double x, double y, struct wlr_surface **psurface, + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + +- if (node->type == WLR_SCENE_NODE_BUFFER) +- surface = wlr_scene_surface_try_from_buffer( +- wlr_scene_buffer_from_node(node))->surface; ++ if (node->type == WLR_SCENE_NODE_BUFFER) { ++ scene_surface = wlr_scene_surface_try_from_buffer( ++ wlr_scene_buffer_from_node(node)); ++ if (!scene_surface) continue; ++ surface = scene_surface->surface; ++ } + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; +@@ -3089,10 +3359,10 @@ sethints(struct wl_listener *listener, void *data) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); +- printstatus(); ++ drawbars(); + + if (c->isurgent && surface && surface->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/bar/bar-0.7.patch b/dwl/dwl-patches/patches/bar/bar-0.7.patch new file mode 100755 index 0000000..523ca36 --- /dev/null +++ b/dwl/dwl-patches/patches/bar/bar-0.7.patch @@ -0,0 +1,1245 @@ +From 1431cf1e9e03c8e59050af3b37514a6a2293d71d Mon Sep 17 00:00:00 2001 +From: sewn +Date: Fri, 23 Aug 2024 09:42:04 +0300 +Subject: [PATCH] Implement dwm bar clone + +--- + Makefile | 2 +- + config.def.h | 31 +++- + drwl.h | 311 ++++++++++++++++++++++++++++++++++++ + dwl.c | 442 +++++++++++++++++++++++++++++++++++++++++---------- + 4 files changed, 691 insertions(+), 95 deletions(-) + create mode 100644 drwl.h + +diff --git a/Makefile b/Makefile +index 3358bae..9bc67db 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) ++PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 22d2171..5d1dc2b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,15 +7,21 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); +-static const float bordercolor[] = COLOR(0x444444ff); +-static const float focuscolor[] = COLOR(0x005577ff); +-static const float urgentcolor[] = COLOR(0xff0000ff); ++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 float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static uint32_t colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, ++ [SchemeUrg] = { 0, 0, 0x770000ff }, ++}; + + /* tagging - TAGCOUNT must be no greater than 31 */ +-#define TAGCOUNT (9) ++static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + /* logging */ + static int log_level = WLR_ERROR; +@@ -127,6 +133,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY, XKB_KEY_b, togglebar, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +@@ -170,7 +177,15 @@ static const Key keys[] = { + }; + + static const Button buttons[] = { +- { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, +- { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkLtSymbol, 0, BTN_LEFT, setlayout, {.v = &layouts[0]} }, ++ { ClkLtSymbol, 0, BTN_RIGHT, setlayout, {.v = &layouts[2]} }, ++ { ClkTitle, 0, BTN_MIDDLE, zoom, {0} }, ++ { ClkStatus, 0, BTN_MIDDLE, spawn, {.v = termcmd} }, ++ { ClkClient, MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, ++ { ClkClient, MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { ClkClient, MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkTagBar, 0, BTN_LEFT, view, {0} }, ++ { ClkTagBar, 0, BTN_RIGHT, toggleview, {0} }, ++ { ClkTagBar, MODKEY, BTN_LEFT, tag, {0} }, ++ { ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} }, + }; +diff --git a/drwl.h b/drwl.h +new file mode 100644 +index 0000000..b06a736 +--- /dev/null ++++ b/drwl.h +@@ -0,0 +1,311 @@ ++/* ++ * drwl - https://codeberg.org/sewn/drwl ++ * ++ * Copyright (c) 2023-2024 sewn ++ * Copyright (c) 2024 notchoc ++ * ++ * 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. ++ * ++ * The UTF-8 Decoder included is from Bjoern Hoehrmann: ++ * Copyright (c) 2008-2010 Bjoern Hoehrmann ++ * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. ++ */ ++#pragma once ++ ++#include ++#include ++#include ++ ++enum { ColFg, ColBg, ColBorder }; /* colorscheme index */ ++ ++typedef struct fcft_font Fnt; ++typedef pixman_image_t Img; ++ ++typedef struct { ++ Img *image; ++ Fnt *font; ++ uint32_t *scheme; ++} Drwl; ++ ++#define UTF8_ACCEPT 0 ++#define UTF8_REJECT 12 ++#define UTF8_INVALID 0xFFFD ++ ++static const uint8_t utf8d[] = { ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, ++ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, ++ ++ 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, ++ 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, ++ 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, ++ 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, ++ 12,36,12,12,12,12,12,12,12,12,12,12, ++}; ++ ++static inline uint32_t ++utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) ++{ ++ uint32_t type = utf8d[byte]; ++ ++ *codep = (*state != UTF8_ACCEPT) ? ++ (byte & 0x3fu) | (*codep << 6) : ++ (0xff >> type) & (byte); ++ ++ *state = utf8d[256 + *state + type]; ++ return *state; ++} ++ ++static int ++drwl_init(void) ++{ ++ fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); ++ return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR); ++} ++ ++static Drwl * ++drwl_create(void) ++{ ++ Drwl *drwl; ++ ++ if (!(drwl = calloc(1, sizeof(Drwl)))) ++ return NULL; ++ ++ return drwl; ++} ++ ++static void ++drwl_setfont(Drwl *drwl, Fnt *font) ++{ ++ if (drwl) ++ drwl->font = font; ++} ++ ++static void ++drwl_setimage(Drwl *drwl, Img *image) ++{ ++ if (drwl) ++ drwl->image = image; ++} ++ ++static Fnt * ++drwl_font_create(Drwl *drwl, size_t count, ++ const char *names[static count], const char *attributes) ++{ ++ Fnt *font = fcft_from_name(count, names, attributes); ++ if (drwl) ++ drwl_setfont(drwl, font); ++ return font; ++} ++ ++static void ++drwl_font_destroy(Fnt *font) ++{ ++ fcft_destroy(font); ++} ++ ++static inline pixman_color_t ++convert_color(uint32_t clr) ++{ ++ return (pixman_color_t){ ++ ((clr >> 24) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 16) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 8) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ (clr & 0xFF) * 0x101 ++ }; ++} ++ ++static void ++drwl_setscheme(Drwl *drwl, uint32_t *scm) ++{ ++ if (drwl) ++ drwl->scheme = scm; ++} ++ ++static Img * ++drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits) ++{ ++ Img *image; ++ pixman_region32_t clip; ++ ++ image = pixman_image_create_bits_no_clear( ++ PIXMAN_a8r8g8b8, w, h, bits, w * 4); ++ if (!image) ++ return NULL; ++ pixman_region32_init_rect(&clip, 0, 0, w, h); ++ pixman_image_set_clip_region32(image, &clip); ++ pixman_region32_fini(&clip); ++ ++ if (drwl) ++ drwl_setimage(drwl, image); ++ return image; ++} ++ ++static void ++drwl_rect(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ int filled, int invert) ++{ ++ pixman_color_t clr; ++ if (!drwl || !drwl->scheme || !drwl->image) ++ return; ++ ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ if (filled) ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1, ++ &(pixman_rectangle16_t){x, y, w, h}); ++ else ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4, ++ (pixman_rectangle16_t[4]){ ++ { x, y, w, 1 }, ++ { x, y + h - 1, w, 1 }, ++ { x, y, 1, h }, ++ { x + w - 1, y, 1, h }}); ++} ++ ++static int ++drwl_text(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ unsigned int lpad, const char *text, int invert) ++{ ++ int ty; ++ int render = x || y || w || h; ++ long x_kern; ++ uint32_t cp = 0, last_cp = 0, state; ++ pixman_color_t clr; ++ pixman_image_t *fg_pix = NULL; ++ int noellipsis = 0; ++ const struct fcft_glyph *glyph, *eg = NULL; ++ int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; ++ ++ if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font) ++ return 0; ++ ++ if (!render) { ++ w = invert ? invert : ~invert; ++ } else { ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ fg_pix = pixman_image_create_solid_fill(&clr); ++ ++ drwl_rect(drwl, x, y, w, h, 1, !invert); ++ ++ x += lpad; ++ w -= lpad; ++ } ++ ++ if (render && (drwl->scheme[ColBg] & 0xFF) != 0xFF) ++ fcft_subpixel_mode = FCFT_SUBPIXEL_NONE; ++ ++ if (render) ++ eg = fcft_rasterize_char_utf32(drwl->font, 0x2026 /* … */, fcft_subpixel_mode); ++ ++ for (const char *p = text, *pp; pp = p, *p; p++) { ++ for (state = UTF8_ACCEPT; *p && ++ utf8decode(&state, &cp, *p) > UTF8_REJECT; p++) ++ ; ++ if (!*p || state == UTF8_REJECT) { ++ cp = UTF8_INVALID; ++ if (p > pp) ++ p--; ++ } ++ ++ glyph = fcft_rasterize_char_utf32(drwl->font, cp, fcft_subpixel_mode); ++ if (!glyph) ++ continue; ++ ++ x_kern = 0; ++ if (last_cp) ++ fcft_kerning(drwl->font, last_cp, cp, &x_kern, NULL); ++ last_cp = cp; ++ ++ ty = y + (h - drwl->font->height) / 2 + drwl->font->ascent; ++ ++ if (render && !noellipsis && x_kern + glyph->advance.x + eg->advance.x > w && ++ *(p + 1) != '\0') { ++ /* cannot fit ellipsis after current codepoint */ ++ if (drwl_text(drwl, 0, 0, 0, 0, 0, pp, 0) + x_kern <= w) { ++ noellipsis = 1; ++ } else { ++ w -= eg->advance.x; ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0, ++ x + eg->x, ty - eg->y, eg->width, eg->height); ++ } ++ } ++ ++ if ((x_kern + glyph->advance.x) > w) ++ break; ++ ++ x += x_kern; ++ ++ if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) ++ /* pre-rendered glyphs (eg. emoji) */ ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ else if (render) ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ ++ x += glyph->advance.x; ++ w -= glyph->advance.x; ++ } ++ ++ if (render) ++ pixman_image_unref(fg_pix); ++ ++ return x + (render ? w : 0); ++} ++ ++static unsigned int ++drwl_font_getwidth(Drwl *drwl, const char *text) ++{ ++ if (!drwl || !drwl->font || !text) ++ return 0; ++ return drwl_text(drwl, 0, 0, 0, 0, 0, text, 0); ++} ++ ++static void ++drwl_image_destroy(Img *image) ++{ ++ pixman_image_unref(image); ++} ++ ++static void ++drwl_destroy(Drwl *drwl) ++{ ++ if (drwl->font) ++ drwl_font_destroy(drwl->font); ++ if (drwl->image) ++ drwl_image_destroy(drwl->image); ++ free(drwl); ++} ++ ++static void ++drwl_fini(void) ++{ ++ fcft_fini(); ++} +diff --git a/dwl.c b/dwl.c +index a2711f6..ece537a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -58,6 +59,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -68,6 +70,7 @@ + #endif + + #include "util.h" ++#include "drwl.h" + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +@@ -76,14 +79,17 @@ + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) +-#define TAGMASK ((1u << TAGCOUNT) - 1) ++#define TAGMASK ((1u << LENGTH(tags)) - 1) + #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) ++#define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) + + /* enums */ ++enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -97,6 +103,7 @@ typedef union { + } Arg; + + typedef struct { ++ unsigned int click; + unsigned int mod; + unsigned int button; + void (*func)(const Arg *); +@@ -186,10 +193,19 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++typedef struct { ++ struct wlr_buffer base; ++ struct wl_listener release; ++ bool busy; ++ Img *image; ++ uint32_t data[]; ++} Buffer; ++ + struct Monitor { + struct wl_list link; + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; ++ struct wlr_scene_buffer *scene_buffer; /* bar buffer */ + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ + struct wl_listener frame; + struct wl_listener destroy; +@@ -197,6 +213,11 @@ struct Monitor { + struct wl_listener destroy_lock_surface; + struct wlr_session_lock_surface_v1 *lock_surface; + struct wlr_box m; /* monitor area, layout-relative */ ++ struct { ++ int width, height; ++ int real_width, real_height; /* non-scaled */ ++ float scale; ++ } b; /* bar area */ + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; +@@ -208,6 +229,9 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ Drwl *drw; ++ Buffer *pool[2]; ++ int lrpad; + }; + + typedef struct { +@@ -250,6 +274,13 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy); ++static void bufdestroy(struct wlr_buffer *buffer); ++static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride); ++static void bufdataend(struct wlr_buffer *buffer); ++static Buffer *bufmon(Monitor *m); ++static void bufrelease(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -285,6 +316,8 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawbar(Monitor *m); ++static void drawbars(void); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -313,7 +346,6 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int + static void outputmgrtest(struct wl_listener *listener, void *data); + static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); +-static void printstatus(void); + static void powermgrsetmode(struct wl_listener *listener, void *data); + static void quit(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); +@@ -335,9 +367,11 @@ static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); ++static int statusin(int fd, unsigned int mask, void *data); + 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 togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -346,6 +380,7 @@ static void unlocksession(struct wl_listener *listener, void *data); + static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); + static void unmapnotify(struct wl_listener *listener, void *data); + static void updatemons(struct wl_listener *listener, void *data); ++static void updatebar(Monitor *m); + static void updatetitle(struct wl_listener *listener, void *data); + static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); +@@ -413,6 +448,15 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static char stext[256]; ++static struct wl_event_source *status_event_source; ++ ++static const struct wlr_buffer_impl buffer_impl = { ++ .destroy = bufdestroy, ++ .begin_data_ptr_access = bufdatabegin, ++ .end_data_ptr_access = bufdataend, ++}; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -553,6 +597,11 @@ arrangelayers(Monitor *m) + if (!m->wlr_output->enabled) + return; + ++ if (m->scene_buffer->node.enabled) { ++ usable_area.height -= m->b.real_height; ++ usable_area.y += topbar ? m->b.real_height : 0; ++ } ++ + /* Arrange exclusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 1); +@@ -595,17 +644,102 @@ axisnotify(struct wl_listener *listener, void *data) + event->delta_discrete, event->source, event->relative_direction); + } + ++bool ++baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy) ++{ ++ return true; ++} ++ ++void ++bufdestroy(struct wlr_buffer *wlr_buffer) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ if (buf->busy) ++ wl_list_remove(&buf->release.link); ++ drwl_image_destroy(buf->image); ++ free(buf); ++} ++ ++bool ++bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ ++ if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; ++ ++ *data = buf->data; ++ *stride = wlr_buffer->width * 4; ++ *format = DRM_FORMAT_ARGB8888; ++ ++ return true; ++} ++ ++void ++bufdataend(struct wlr_buffer *wlr_buffer) ++{ ++} ++ ++Buffer * ++bufmon(Monitor *m) ++{ ++ size_t i; ++ Buffer *buf = NULL; ++ ++ for (i = 0; i < LENGTH(m->pool); i++) { ++ if (m->pool[i]) { ++ if (m->pool[i]->busy) ++ continue; ++ buf = m->pool[i]; ++ break; ++ } ++ ++ buf = ecalloc(1, sizeof(Buffer) + (m->b.width * 4 * m->b.height)); ++ buf->image = drwl_image_create(NULL, m->b.width, m->b.height, buf->data); ++ wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height); ++ m->pool[i] = buf; ++ break; ++ } ++ if (!buf) ++ return NULL; ++ ++ buf->busy = true; ++ LISTEN(&buf->base.events.release, &buf->release, bufrelease); ++ wlr_buffer_lock(&buf->base); ++ drwl_setimage(m->drw, buf->image); ++ return buf; ++} ++ ++void ++bufrelease(struct wl_listener *listener, void *data) ++{ ++ Buffer *buf = wl_container_of(listener, buf, release); ++ buf->busy = false; ++ wl_list_remove(&buf->release.link); ++} ++ + void + buttonpress(struct wl_listener *listener, void *data) + { ++ unsigned int i = 0, x = 0; ++ double cx; ++ unsigned int click; + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; ++ struct wlr_scene_node *node; ++ struct wlr_scene_buffer *buffer; + uint32_t mods; ++ Arg arg = {0}; + Client *c; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + ++ click = ClkRoot; ++ xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); ++ if (c) ++ click = ClkClient; ++ + switch (event->state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + cursor_mode = CurPressed; +@@ -613,17 +747,34 @@ buttonpress(struct wl_listener *listener, void *data) + if (locked) + break; + ++ if (!c && !exclusive_focus && ++ (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && ++ (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { ++ cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; ++ do ++ x += TEXTW(selmon, tags[i]); ++ while (cx >= x && ++i < LENGTH(tags)); ++ if (i < LENGTH(tags)) { ++ click = ClkTagBar; ++ arg.ui = 1 << i; ++ } else if (cx < x + TEXTW(selmon, selmon->ltsymbol)) ++ click = ClkLtSymbol; ++ else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) { ++ click = ClkStatus; ++ } else ++ click = ClkTitle; ++ } ++ + /* Change focus if the button was _pressed_ over a client */ + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); +- if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) ++ if (click == ClkClient && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { +- if (CLEANMASK(mods) == CLEANMASK(b->mod) && +- event->button == b->button && b->func) { +- b->func(&b->arg); ++ if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) { ++ b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg); + return; + } + } +@@ -697,6 +848,8 @@ cleanup(void) + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); ++ ++ drwl_fini(); + } + + void +@@ -712,6 +865,12 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + ++ for (i = 0; i < LENGTH(m->pool); i++) ++ wlr_buffer_drop(&m->pool[i]->base); ++ ++ drwl_setimage(m->drw, NULL); ++ drwl_destroy(m->drw); ++ + wl_list_remove(&m->destroy.link); + wl_list_remove(&m->frame.link); + wl_list_remove(&m->link); +@@ -722,6 +881,7 @@ cleanupmon(struct wl_listener *listener, void *data) + + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); ++ wlr_scene_node_destroy(&m->scene_buffer->node); + free(m); + } + +@@ -751,7 +911,7 @@ closemon(Monitor *m) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); +- printstatus(); ++ drawbars(); + } + + void +@@ -1022,8 +1182,15 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + ++ if (!(m->drw = drwl_create())) ++ die("failed to create drwl context"); ++ ++ m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL); ++ m->scene_buffer->point_accepts_input = baracceptsinput; ++ updatebar(m); ++ + wl_list_insert(&mons, &m->link); +- printstatus(); ++ drawbars(); + + /* The xdg-protocol specifies: + * +@@ -1336,6 +1503,80 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++void ++drawbar(Monitor *m) ++{ ++ int x, w, tw = 0; ++ int boxs = m->drw->font->height / 9; ++ int boxw = m->drw->font->height / 6 + 2; ++ uint32_t i, occ = 0, urg = 0; ++ Client *c; ++ Buffer *buf; ++ ++ if (!m->scene_buffer->node.enabled) ++ return; ++ if (!(buf = bufmon(m))) ++ return; ++ ++ /* draw status first so it can be overdrawn by tags later */ ++ if (m == selmon) { /* status is only drawn on selected monitor */ ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ ++ drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != m) ++ continue; ++ occ |= c->tags; ++ if (c->isurgent) ++ urg |= c->tags; ++ } ++ x = 0; ++ c = focustop(m); ++ for (i = 0; i < LENGTH(tags); i++) { ++ w = TEXTW(m, tags[i]); ++ drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); ++ drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i); ++ if (occ & 1 << i) ++ drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, ++ m == selmon && c && c->tags & 1 << i, ++ urg & 1 << i); ++ x += w; ++ } ++ w = TEXTW(m, m->ltsymbol); ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0); ++ ++ if ((w = m->b.width - tw - x) > m->b.height) { ++ if (c) { ++ drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); ++ drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); ++ if (c && c->isfloating) ++ drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0); ++ } else { ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1); ++ } ++ } ++ ++ wlr_scene_buffer_set_dest_size(m->scene_buffer, ++ m->b.real_width, m->b.real_height); ++ wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, ++ m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); ++ wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); ++ wlr_buffer_unlock(&buf->base); ++} ++ ++void ++drawbars(void) ++{ ++ Monitor *m = NULL; ++ ++ wl_list_for_each(m, &mons, link) ++ drawbar(m); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1371,13 +1612,13 @@ focusclient(Client *c, int lift) + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) +- client_set_border_color(c, focuscolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder])); + } + + /* Deactivate old client if focus is changing */ + if (old && (!c || client_surface(c) != old)) { + /* If an overlay is focused, don't focus or activate the client, +- * but only update its position in fstack to render its border with focuscolor ++ * but only update its position in fstack to render its border with its color + * and focus it after the overlay is closed. */ + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) +@@ -1388,12 +1629,11 @@ focusclient(Client *c, int lift) + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { +- client_set_border_color(old_c, bordercolor); +- ++ client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder])); + client_activate_surface(old, 0); + } + } +- printstatus(); ++ drawbars(); + + if (!c) { + /* With no client, all we have left is to clear focus */ +@@ -1715,7 +1955,7 @@ mapnotify(struct wl_listener *listener, void *data) + + for (i = 0; i < 4; i++) { + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, +- c->isurgent ? urgentcolor : bordercolor); ++ (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder])); + c->border[i]->node.data = c; + } + +@@ -1738,7 +1978,7 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } +- printstatus(); ++ drawbars(); + + unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); +@@ -2032,46 +2272,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + } + +-void +-printstatus(void) +-{ +- Monitor *m = NULL; +- Client *c; +- uint32_t occ, urg, sel; +- const char *appid, *title; +- +- wl_list_for_each(m, &mons, link) { +- occ = urg = 0; +- wl_list_for_each(c, &clients, link) { +- if (c->mon != m) +- continue; +- occ |= c->tags; +- if (c->isurgent) +- urg |= c->tags; +- } +- if ((c = focustop(m))) { +- title = client_get_title(c); +- appid = client_get_appid(c); +- printf("%s title %s\n", m->wlr_output->name, title ? title : broken); +- printf("%s appid %s\n", m->wlr_output->name, appid ? appid : broken); +- printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); +- printf("%s floating %d\n", m->wlr_output->name, c->isfloating); +- sel = c->tags; +- } else { +- printf("%s title \n", m->wlr_output->name); +- printf("%s appid \n", m->wlr_output->name); +- printf("%s fullscreen \n", m->wlr_output->name); +- printf("%s floating \n", m->wlr_output->name); +- sel = 0; +- } +- +- printf("%s selmon %u\n", m->wlr_output->name, m == selmon); +- printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", +- m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); +- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); +- } +- fflush(stdout); +-} + + void + powermgrsetmode(struct wl_listener *listener, void *data) +@@ -2226,30 +2426,17 @@ run(char *startup_cmd) + + /* Now that the socket exists and the backend is started, run the startup command */ + if (startup_cmd) { +- int piperw[2]; +- if (pipe(piperw) < 0) +- die("startup: pipe:"); + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { ++ close(STDIN_FILENO); + setsid(); +- dup2(piperw[0], STDIN_FILENO); +- close(piperw[0]); +- close(piperw[1]); + execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); + die("startup: execl:"); + } +- dup2(piperw[1], STDOUT_FILENO); +- close(piperw[1]); +- close(piperw[0]); + } + +- /* Mark stdout as non-blocking to avoid people who does not close stdin +- * nor consumes it in their startup script getting dwl frozen */ +- if (fd_set_nonblock(STDOUT_FILENO) < 0) +- close(STDOUT_FILENO); +- +- printstatus(); ++ drawbars(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ +@@ -2315,7 +2502,7 @@ setfloating(Client *c, int floating) + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2338,7 +2525,7 @@ setfullscreen(Client *c, int fullscreen) + resize(c, c->prev, 0); + } + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2363,7 +2550,7 @@ setlayout(const Arg *arg) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); +- printstatus(); ++ drawbar(selmon); + } + + /* arg > 1.0 will set mfact absolutely */ +@@ -2436,6 +2623,7 @@ setup(void) + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + ++ + wlr_log_init(log_level, NULL); + + /* The Wayland display is managed by libwayland. It handles accepting +@@ -2625,6 +2813,11 @@ setup(void) + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); + LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); + ++ drwl_init(); ++ ++ status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy), ++ STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2649,6 +2842,7 @@ void + spawn(const Arg *arg) + { + if (fork() == 0) { ++ close(STDIN_FILENO); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); +@@ -2667,6 +2861,30 @@ startdrag(struct wl_listener *listener, void *data) + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); + } + ++int ++statusin(int fd, unsigned int mask, void *data) ++{ ++ char status[1024]; ++ ssize_t n; ++ ++ if (mask & WL_EVENT_ERROR) ++ die("status in event error"); ++ if (mask & WL_EVENT_HANGUP) ++ wl_event_source_remove(status_event_source); ++ ++ n = read(fd, status, sizeof(status) - 1); ++ if (n < 0 && errno != EWOULDBLOCK) ++ die("read:"); ++ ++ status[n] = '\0'; ++ status[strcspn(status, "\n")] = '\0'; ++ ++ strncpy(stext, status, sizeof(stext)); ++ drawbars(); ++ ++ return 0; ++} ++ + void + tag(const Arg *arg) + { +@@ -2677,7 +2895,7 @@ tag(const Arg *arg) + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2722,6 +2940,14 @@ tile(Monitor *m) + } + } + ++void ++togglebar(const Arg *arg) ++{ ++ wlr_scene_node_set_enabled(&selmon->scene_buffer->node, ++ !selmon->scene_buffer->node.enabled); ++ arrangelayers(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { +@@ -2750,7 +2976,7 @@ toggletag(const Arg *arg) + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2763,7 +2989,7 @@ toggleview(const Arg *arg) + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2811,7 +3037,7 @@ unmapnotify(struct wl_listener *listener, void *data) + } + + wlr_scene_node_destroy(&c->scene->node); +- printstatus(); ++ drawbars(); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -2911,6 +3137,13 @@ updatemons(struct wl_listener *listener, void *data) + } + } + ++ if (stext[0] == '\0') ++ strncpy(stext, "dwl-"VERSION, sizeof(stext)); ++ wl_list_for_each(m, &mons, link) { ++ updatebar(m); ++ drawbar(m); ++ } ++ + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a +@@ -2921,12 +3154,45 @@ updatemons(struct wl_listener *listener, void *data) + wlr_output_manager_v1_set_configuration(output_mgr, config); + } + ++void ++updatebar(Monitor *m) ++{ ++ size_t i; ++ int rw, rh; ++ char fontattrs[12]; ++ ++ wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); ++ m->b.width = rw; ++ m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); ++ ++ wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0); ++ ++ for (i = 0; i < LENGTH(m->pool); i++) ++ if (m->pool[i]) { ++ wlr_buffer_drop(&m->pool[i]->base); ++ m->pool[i] = NULL; ++ } ++ ++ if (m->b.scale == m->wlr_output->scale && m->drw) ++ return; ++ ++ drwl_font_destroy(m->drw->font); ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * m->wlr_output->scale); ++ if (!(drwl_font_create(m->drw, LENGTH(fonts), fonts, fontattrs))) ++ die("Could not load font"); ++ ++ m->b.scale = m->wlr_output->scale; ++ m->lrpad = m->drw->font->height; ++ m->b.height = m->drw->font->height + 2; ++ m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale); ++} ++ + void + updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) +- printstatus(); ++ drawbars(); + } + + void +@@ -2939,10 +3205,10 @@ urgent(struct wl_listener *listener, void *data) + return; + + c->isurgent = 1; +- printstatus(); ++ drawbars(); + + if (client_surface(c)->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +@@ -2955,7 +3221,7 @@ view(const Arg *arg) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2996,6 +3262,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + { + struct wlr_scene_node *node, *pnode; + struct wlr_surface *surface = NULL; ++ struct wlr_scene_surface *scene_surface = NULL; + Client *c = NULL; + LayerSurface *l = NULL; + int layer; +@@ -3004,9 +3271,12 @@ xytonode(double x, double y, struct wlr_surface **psurface, + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + +- if (node->type == WLR_SCENE_NODE_BUFFER) +- surface = wlr_scene_surface_try_from_buffer( +- wlr_scene_buffer_from_node(node))->surface; ++ if (node->type == WLR_SCENE_NODE_BUFFER) { ++ scene_surface = wlr_scene_surface_try_from_buffer( ++ wlr_scene_buffer_from_node(node)); ++ if (!scene_surface) continue; ++ surface = scene_surface->surface; ++ } + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; +@@ -3145,10 +3415,10 @@ sethints(struct wl_listener *listener, void *data) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); +- printstatus(); ++ drawbars(); + + if (c->isurgent && surface && surface->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/bar/bar.patch b/dwl/dwl-patches/patches/bar/bar.patch new file mode 100755 index 0000000..c9527c1 --- /dev/null +++ b/dwl/dwl-patches/patches/bar/bar.patch @@ -0,0 +1,1266 @@ +From 8906a73dbc8996dd1bfff15f5b26aaee6d45fd61 Mon Sep 17 00:00:00 2001 +From: sewn +Date: Tue, 29 Jul 2025 15:21:19 +0300 +Subject: [PATCH] Implement dwm bar clone + +Signed-off-by: sewn +--- + Makefile | 2 +- + config.def.h | 33 ++-- + drwl.h | 311 ++++++++++++++++++++++++++++++++++++ + dwl.c | 441 +++++++++++++++++++++++++++++++++++++++++---------- + 4 files changed, 695 insertions(+), 92 deletions(-) + create mode 100644 drwl.h + +diff --git a/Makefile b/Makefile +index 578194f..279b1c0 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wayland-server xkbcommon libinput $(XLIBS) ++PKGS = wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 95c2afa..1b7472d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,15 +7,21 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); +-static const float bordercolor[] = COLOR(0x444444ff); +-static const float focuscolor[] = COLOR(0x005577ff); +-static const float urgentcolor[] = COLOR(0xff0000ff); ++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 float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */ ++static uint32_t colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, ++ [SchemeUrg] = { 0, 0, 0x770000ff }, ++}; + +-/* tagging - TAGCOUNT must be no greater than 31 */ +-#define TAGCOUNT (9) ++/* tagging */ ++static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + /* logging */ + static int log_level = WLR_ERROR; +@@ -127,6 +133,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY, XKB_KEY_b, togglebar, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +@@ -170,7 +177,15 @@ static const Key keys[] = { + }; + + static const Button buttons[] = { +- { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, +- { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkLtSymbol, 0, BTN_LEFT, setlayout, {.v = &layouts[0]} }, ++ { ClkLtSymbol, 0, BTN_RIGHT, setlayout, {.v = &layouts[2]} }, ++ { ClkTitle, 0, BTN_MIDDLE, zoom, {0} }, ++ { ClkStatus, 0, BTN_MIDDLE, spawn, {.v = termcmd} }, ++ { ClkClient, MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, ++ { ClkClient, MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { ClkClient, MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkTagBar, 0, BTN_LEFT, view, {0} }, ++ { ClkTagBar, 0, BTN_RIGHT, toggleview, {0} }, ++ { ClkTagBar, MODKEY, BTN_LEFT, tag, {0} }, ++ { ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} }, + }; +diff --git a/drwl.h b/drwl.h +new file mode 100644 +index 0000000..90cc35b +--- /dev/null ++++ b/drwl.h +@@ -0,0 +1,311 @@ ++/* ++ * drwl - https://codeberg.org/sewn/drwl ++ * ++ * Copyright (c) 2023-2025 sewn ++ * Copyright (c) 2024 notchoc ++ * ++ * 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. ++ * ++ * The UTF-8 Decoder included is from Bjoern Hoehrmann: ++ * Copyright (c) 2008-2010 Bjoern Hoehrmann ++ * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. ++ */ ++#pragma once ++ ++#include ++#include ++#include ++ ++enum { ColFg, ColBg, ColBorder }; /* colorscheme index */ ++ ++typedef struct fcft_font Fnt; ++typedef pixman_image_t Img; ++ ++typedef struct { ++ Img *image; ++ Fnt *font; ++ uint32_t *scheme; ++} Drwl; ++ ++#define UTF8_ACCEPT 0 ++#define UTF8_REJECT 12 ++#define UTF8_INVALID 0xFFFD ++ ++static const uint8_t utf8d[] = { ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, ++ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, ++ ++ 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, ++ 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, ++ 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, ++ 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, ++ 12,36,12,12,12,12,12,12,12,12,12,12, ++}; ++ ++static inline uint32_t ++utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) ++{ ++ uint32_t type = utf8d[byte]; ++ ++ *codep = (*state != UTF8_ACCEPT) ? ++ (byte & 0x3fu) | (*codep << 6) : ++ (0xff >> type) & (byte); ++ ++ *state = utf8d[256 + *state + type]; ++ return *state; ++} ++ ++static int ++drwl_init(void) ++{ ++ fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); ++ return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR); ++} ++ ++static Drwl * ++drwl_create(void) ++{ ++ Drwl *drwl; ++ ++ if (!(drwl = calloc(1, sizeof(Drwl)))) ++ return NULL; ++ ++ return drwl; ++} ++ ++static void ++drwl_setfont(Drwl *drwl, Fnt *font) ++{ ++ if (drwl) ++ drwl->font = font; ++} ++ ++static void ++drwl_setimage(Drwl *drwl, Img *image) ++{ ++ if (drwl) ++ drwl->image = image; ++} ++ ++static Fnt * ++drwl_font_create(Drwl *drwl, size_t count, ++ const char *names[static count], const char *attributes) ++{ ++ Fnt *font = fcft_from_name(count, names, attributes); ++ if (drwl) ++ drwl_setfont(drwl, font); ++ return font; ++} ++ ++static void ++drwl_font_destroy(Fnt *font) ++{ ++ fcft_destroy(font); ++} ++ ++static inline pixman_color_t ++convert_color(uint32_t clr) ++{ ++ return (pixman_color_t){ ++ ((clr >> 24) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 16) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 8) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ (clr & 0xFF) * 0x101 ++ }; ++} ++ ++static void ++drwl_setscheme(Drwl *drwl, uint32_t *scm) ++{ ++ if (drwl) ++ drwl->scheme = scm; ++} ++ ++static Img * ++drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits) ++{ ++ Img *image; ++ pixman_region32_t clip; ++ ++ image = pixman_image_create_bits_no_clear( ++ PIXMAN_a8r8g8b8, w, h, bits, w * 4); ++ if (!image) ++ return NULL; ++ pixman_region32_init_rect(&clip, 0, 0, w, h); ++ pixman_image_set_clip_region32(image, &clip); ++ pixman_region32_fini(&clip); ++ ++ if (drwl) ++ drwl_setimage(drwl, image); ++ return image; ++} ++ ++static void ++drwl_rect(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ int filled, int invert) ++{ ++ pixman_color_t clr; ++ if (!drwl || !drwl->scheme || !drwl->image) ++ return; ++ ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ if (filled) ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1, ++ &(pixman_rectangle16_t){x, y, w, h}); ++ else ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4, ++ (pixman_rectangle16_t[4]){ ++ { x, y, w, 1 }, ++ { x, y + h - 1, w, 1 }, ++ { x, y, 1, h }, ++ { x + w - 1, y, 1, h }}); ++} ++ ++static int ++drwl_text(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ unsigned int lpad, const char *text, int invert) ++{ ++ int ty; ++ int render = x || y || w || h; ++ long x_kern; ++ uint32_t cp = 0, last_cp = 0, state; ++ pixman_color_t clr; ++ pixman_image_t *fg_pix = NULL; ++ int noellipsis = 0; ++ const struct fcft_glyph *glyph, *eg = NULL; ++ int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; ++ ++ if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font) ++ return 0; ++ ++ if (!render) { ++ w = invert ? invert : ~invert; ++ } else { ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ fg_pix = pixman_image_create_solid_fill(&clr); ++ ++ drwl_rect(drwl, x, y, w, h, 1, !invert); ++ ++ x += lpad; ++ w -= lpad; ++ } ++ ++ if (render && (drwl->scheme[ColBg] & 0xFF) != 0xFF) ++ fcft_subpixel_mode = FCFT_SUBPIXEL_NONE; ++ ++ if (render) ++ eg = fcft_rasterize_char_utf32(drwl->font, 0x2026 /* … */, fcft_subpixel_mode); ++ ++ for (const char *p = text, *pp; pp = p, *p; p++) { ++ for (state = UTF8_ACCEPT; *p && ++ utf8decode(&state, &cp, *p) > UTF8_REJECT; p++) ++ ; ++ if (!*p || state == UTF8_REJECT) { ++ cp = UTF8_INVALID; ++ if (p > pp) ++ p--; ++ } ++ ++ glyph = fcft_rasterize_char_utf32(drwl->font, cp, fcft_subpixel_mode); ++ if (!glyph) ++ continue; ++ ++ x_kern = 0; ++ if (last_cp) ++ fcft_kerning(drwl->font, last_cp, cp, &x_kern, NULL); ++ last_cp = cp; ++ ++ ty = y + (h - drwl->font->height) / 2 + drwl->font->ascent; ++ ++ if (render && !noellipsis && x_kern + glyph->advance.x + eg->advance.x > w && ++ *(p + 1) != '\0') { ++ /* cannot fit ellipsis after current codepoint */ ++ if (drwl_text(drwl, 0, 0, 0, 0, 0, pp, 0) + x_kern <= w) { ++ noellipsis = 1; ++ } else { ++ w -= eg->advance.x; ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0, ++ x + eg->x, ty - eg->y, eg->width, eg->height); ++ } ++ } ++ ++ if ((x_kern + glyph->advance.x) > w) ++ break; ++ ++ x += x_kern; ++ ++ if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) ++ /* pre-rendered glyphs (eg. emoji) */ ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ else if (render) ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ ++ x += glyph->advance.x; ++ w -= glyph->advance.x; ++ } ++ ++ if (render) ++ pixman_image_unref(fg_pix); ++ ++ return x + (render ? w : 0); ++} ++ ++static unsigned int ++drwl_font_getwidth(Drwl *drwl, const char *text) ++{ ++ if (!drwl || !drwl->font || !text) ++ return 0; ++ return drwl_text(drwl, 0, 0, 0, 0, 0, text, 0); ++} ++ ++static void ++drwl_image_destroy(Img *image) ++{ ++ pixman_image_unref(image); ++} ++ ++static void ++drwl_destroy(Drwl *drwl) ++{ ++ if (drwl->font) ++ drwl_font_destroy(drwl->font); ++ if (drwl->image) ++ drwl_image_destroy(drwl->image); ++ free(drwl); ++} ++ ++static void ++drwl_fini(void) ++{ ++ fcft_fini(); ++} +diff --git a/dwl.c b/dwl.c +index 12f441e..bf340d8 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -59,6 +60,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -69,6 +71,7 @@ + #endif + + #include "util.h" ++#include "drwl.h" + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +@@ -77,14 +80,17 @@ + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) +-#define TAGMASK ((1u << TAGCOUNT) - 1) ++#define TAGMASK ((1u << LENGTH(tags)) - 1) + #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) + #define LISTEN_STATIC(E, H) do { struct wl_listener *_l = ecalloc(1, sizeof(*_l)); _l->notify = (H); wl_signal_add((E), _l); } while (0) ++#define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) + + /* enums */ ++enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ + + typedef union { + int i; +@@ -94,6 +100,7 @@ typedef union { + } Arg; + + typedef struct { ++ unsigned int click; + unsigned int mod; + unsigned int button; + void (*func)(const Arg *); +@@ -183,10 +190,19 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++typedef struct { ++ struct wlr_buffer base; ++ struct wl_listener release; ++ bool busy; ++ Img *image; ++ uint32_t data[]; ++} Buffer; ++ + struct Monitor { + struct wl_list link; + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; ++ struct wlr_scene_buffer *scene_buffer; /* bar buffer */ + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ + struct wl_listener frame; + struct wl_listener destroy; +@@ -194,6 +210,11 @@ struct Monitor { + struct wl_listener destroy_lock_surface; + struct wlr_session_lock_surface_v1 *lock_surface; + struct wlr_box m; /* monitor area, layout-relative */ ++ struct { ++ int width, height; ++ int real_width, real_height; /* non-scaled */ ++ float scale; ++ } b; /* bar area */ + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; +@@ -205,6 +226,9 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ Drwl *drw; ++ Buffer *pool[2]; ++ int lrpad; + }; + + typedef struct { +@@ -247,6 +271,13 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy); ++static void bufdestroy(struct wlr_buffer *buffer); ++static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride); ++static void bufdataend(struct wlr_buffer *buffer); ++static Buffer *bufmon(Monitor *m); ++static void bufrelease(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -282,6 +313,8 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data); + static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawbar(Monitor *m); ++static void drawbars(void); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -310,7 +343,6 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int + static void outputmgrtest(struct wl_listener *listener, void *data); + static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); +-static void printstatus(void); + static void powermgrsetmode(struct wl_listener *listener, void *data); + static void quit(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); +@@ -331,9 +363,11 @@ static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); ++static int statusin(int fd, unsigned int mask, void *data); + 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 togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -342,6 +376,7 @@ static void unlocksession(struct wl_listener *listener, void *data); + static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); + static void unmapnotify(struct wl_listener *listener, void *data); + static void updatemons(struct wl_listener *listener, void *data); ++static void updatebar(Monitor *m); + static void updatetitle(struct wl_listener *listener, void *data); + static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); +@@ -406,6 +441,15 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static char stext[256]; ++static struct wl_event_source *status_event_source; ++ ++static const struct wlr_buffer_impl buffer_impl = { ++ .destroy = bufdestroy, ++ .begin_data_ptr_access = bufdatabegin, ++ .end_data_ptr_access = bufdataend, ++}; ++ + /* global event handlers */ + static struct wl_listener cursor_axis = {.notify = axisnotify}; + static struct wl_listener cursor_button = {.notify = buttonpress}; +@@ -521,7 +565,7 @@ arrange(Monitor *m) + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, + (c = focustop(m)) && c->isfullscreen); + +- strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); ++ strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof(m->ltsymbol)); + + /* We move all clients (except fullscreen and unmanaged) to LyrTile while + * in floating layout to avoid "real" floating clients be always on top */ +@@ -576,6 +620,11 @@ arrangelayers(Monitor *m) + if (!m->wlr_output->enabled) + return; + ++ if (m->scene_buffer->node.enabled) { ++ usable_area.height -= m->b.real_height; ++ usable_area.y += topbar ? m->b.real_height : 0; ++ } ++ + /* Arrange exclusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 1); +@@ -618,17 +667,102 @@ axisnotify(struct wl_listener *listener, void *data) + event->delta_discrete, event->source, event->relative_direction); + } + ++bool ++baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy) ++{ ++ return true; ++} ++ ++void ++bufdestroy(struct wlr_buffer *wlr_buffer) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ if (buf->busy) ++ wl_list_remove(&buf->release.link); ++ drwl_image_destroy(buf->image); ++ free(buf); ++} ++ ++bool ++bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ ++ if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; ++ ++ *data = buf->data; ++ *stride = wlr_buffer->width * 4; ++ *format = DRM_FORMAT_ARGB8888; ++ ++ return true; ++} ++ ++void ++bufdataend(struct wlr_buffer *wlr_buffer) ++{ ++} ++ ++Buffer * ++bufmon(Monitor *m) ++{ ++ size_t i; ++ Buffer *buf = NULL; ++ ++ for (i = 0; i < LENGTH(m->pool); i++) { ++ if (m->pool[i]) { ++ if (m->pool[i]->busy) ++ continue; ++ buf = m->pool[i]; ++ break; ++ } ++ ++ buf = ecalloc(1, sizeof(Buffer) + (m->b.width * 4 * m->b.height)); ++ buf->image = drwl_image_create(NULL, m->b.width, m->b.height, buf->data); ++ wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height); ++ m->pool[i] = buf; ++ break; ++ } ++ if (!buf) ++ return NULL; ++ ++ buf->busy = true; ++ LISTEN(&buf->base.events.release, &buf->release, bufrelease); ++ wlr_buffer_lock(&buf->base); ++ drwl_setimage(m->drw, buf->image); ++ return buf; ++} ++ ++void ++bufrelease(struct wl_listener *listener, void *data) ++{ ++ Buffer *buf = wl_container_of(listener, buf, release); ++ buf->busy = false; ++ wl_list_remove(&buf->release.link); ++} ++ + void + buttonpress(struct wl_listener *listener, void *data) + { ++ unsigned int i = 0, x = 0; ++ double cx; ++ unsigned int click; + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; ++ struct wlr_scene_node *node; ++ struct wlr_scene_buffer *buffer; + uint32_t mods; ++ Arg arg = {0}; + Client *c; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + ++ click = ClkRoot; ++ xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); ++ if (c) ++ click = ClkClient; ++ + switch (event->state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + cursor_mode = CurPressed; +@@ -636,17 +770,34 @@ buttonpress(struct wl_listener *listener, void *data) + if (locked) + break; + ++ if (!c && !exclusive_focus && ++ (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && ++ (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { ++ cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; ++ do ++ x += TEXTW(selmon, tags[i]); ++ while (cx >= x && ++i < LENGTH(tags)); ++ if (i < LENGTH(tags)) { ++ click = ClkTagBar; ++ arg.ui = 1 << i; ++ } else if (cx < x + TEXTW(selmon, selmon->ltsymbol)) ++ click = ClkLtSymbol; ++ else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) { ++ click = ClkStatus; ++ } else ++ click = ClkTitle; ++ } ++ + /* Change focus if the button was _pressed_ over a client */ + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); +- if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) ++ if (click == ClkClient && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { +- if (CLEANMASK(mods) == CLEANMASK(b->mod) && +- event->button == b->button && b->func) { +- b->func(&b->arg); ++ if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) { ++ b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg); + return; + } + } +@@ -721,6 +872,8 @@ cleanup(void) + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); ++ ++ drwl_fini(); + } + + void +@@ -736,6 +889,12 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + ++ for (i = 0; i < LENGTH(m->pool); i++) ++ wlr_buffer_drop(&m->pool[i]->base); ++ ++ drwl_setimage(m->drw, NULL); ++ drwl_destroy(m->drw); ++ + wl_list_remove(&m->destroy.link); + wl_list_remove(&m->frame.link); + wl_list_remove(&m->link); +@@ -748,6 +907,7 @@ cleanupmon(struct wl_listener *listener, void *data) + + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); ++ wlr_scene_node_destroy(&m->scene_buffer->node); + free(m); + } + +@@ -814,7 +974,7 @@ closemon(Monitor *m) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); +- printstatus(); ++ drawbars(); + } + + void +@@ -1066,7 +1226,7 @@ createmon(struct wl_listener *listener, void *data) + m->nmaster = r->nmaster; + m->lt[0] = r->lt; + m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; +- strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); ++ strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof(m->ltsymbol)); + wlr_output_state_set_scale(&state, r->scale); + wlr_output_state_set_transform(&state, r->rr); + break; +@@ -1088,8 +1248,15 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + ++ if (!(m->drw = drwl_create())) ++ die("failed to create drwl context"); ++ ++ m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL); ++ m->scene_buffer->point_accepts_input = baracceptsinput; ++ updatebar(m); ++ + wl_list_insert(&mons, &m->link); +- printstatus(); ++ drawbars(); + + /* The xdg-protocol specifies: + * +@@ -1399,6 +1566,80 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++void ++drawbar(Monitor *m) ++{ ++ int x, w, tw = 0; ++ int boxs = m->drw->font->height / 9; ++ int boxw = m->drw->font->height / 6 + 2; ++ uint32_t i, occ = 0, urg = 0; ++ Client *c; ++ Buffer *buf; ++ ++ if (!m->scene_buffer->node.enabled) ++ return; ++ if (!(buf = bufmon(m))) ++ return; ++ ++ /* draw status first so it can be overdrawn by tags later */ ++ if (m == selmon) { /* status is only drawn on selected monitor */ ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ ++ drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != m) ++ continue; ++ occ |= c->tags; ++ if (c->isurgent) ++ urg |= c->tags; ++ } ++ x = 0; ++ c = focustop(m); ++ for (i = 0; i < LENGTH(tags); i++) { ++ w = TEXTW(m, tags[i]); ++ drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); ++ drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i); ++ if (occ & 1 << i) ++ drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, ++ m == selmon && c && c->tags & 1 << i, ++ urg & 1 << i); ++ x += w; ++ } ++ w = TEXTW(m, m->ltsymbol); ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0); ++ ++ if ((w = m->b.width - tw - x) > m->b.height) { ++ if (c) { ++ drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); ++ drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); ++ if (c && c->isfloating) ++ drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0); ++ } else { ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1); ++ } ++ } ++ ++ wlr_scene_buffer_set_dest_size(m->scene_buffer, ++ m->b.real_width, m->b.real_height); ++ wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, ++ m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); ++ wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); ++ wlr_buffer_unlock(&buf->base); ++} ++ ++void ++drawbars(void) ++{ ++ Monitor *m = NULL; ++ ++ wl_list_for_each(m, &mons, link) ++ drawbar(m); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1433,13 +1674,13 @@ focusclient(Client *c, int lift) + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) +- client_set_border_color(c, focuscolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder])); + } + + /* Deactivate old client if focus is changing */ + if (old && (!c || client_surface(c) != old)) { + /* If an overlay is focused, don't focus or activate the client, +- * but only update its position in fstack to render its border with focuscolor ++ * but only update its position in fstack to render its border with its color + * and focus it after the overlay is closed. */ + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) +@@ -1450,12 +1691,11 @@ focusclient(Client *c, int lift) + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { +- client_set_border_color(old_c, bordercolor); +- ++ client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder])); + client_activate_surface(old, 0); + } + } +- printstatus(); ++ drawbars(); + + if (!c) { + /* With no client, all we have left is to clear focus */ +@@ -1768,7 +2008,7 @@ mapnotify(struct wl_listener *listener, void *data) + + for (i = 0; i < 4; i++) { + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, +- c->isurgent ? urgentcolor : bordercolor); ++ (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder])); + c->border[i]->node.data = c; + } + +@@ -1791,7 +2031,7 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } +- printstatus(); ++ drawbars(); + + unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); +@@ -2084,44 +2324,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + } + +-void +-printstatus(void) +-{ +- Monitor *m = NULL; +- Client *c; +- uint32_t occ, urg, sel; +- +- wl_list_for_each(m, &mons, link) { +- occ = urg = 0; +- wl_list_for_each(c, &clients, link) { +- if (c->mon != m) +- continue; +- occ |= c->tags; +- if (c->isurgent) +- urg |= c->tags; +- } +- if ((c = focustop(m))) { +- printf("%s title %s\n", m->wlr_output->name, client_get_title(c)); +- printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c)); +- printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); +- printf("%s floating %d\n", m->wlr_output->name, c->isfloating); +- sel = c->tags; +- } else { +- printf("%s title \n", m->wlr_output->name); +- printf("%s appid \n", m->wlr_output->name); +- printf("%s fullscreen \n", m->wlr_output->name); +- printf("%s floating \n", m->wlr_output->name); +- sel = 0; +- } +- +- printf("%s selmon %u\n", m->wlr_output->name, m == selmon); +- printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", +- m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); +- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); +- } +- fflush(stdout); +-} +- + void + powermgrsetmode(struct wl_listener *listener, void *data) + { +@@ -2250,22 +2452,14 @@ run(char *startup_cmd) + + /* Now that the socket exists and the backend is started, run the startup command */ + if (startup_cmd) { +- int piperw[2]; +- if (pipe(piperw) < 0) +- die("startup: pipe:"); + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { ++ close(STDIN_FILENO); + setsid(); +- dup2(piperw[0], STDIN_FILENO); +- close(piperw[0]); +- close(piperw[1]); + execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); + die("startup: execl:"); + } +- dup2(piperw[1], STDOUT_FILENO); +- close(piperw[1]); +- close(piperw[0]); + } + + /* Mark stdout as non-blocking to avoid the startup script +@@ -2275,7 +2469,7 @@ run(char *startup_cmd) + if (fd_set_nonblock(STDOUT_FILENO) < 0) + close(STDOUT_FILENO); + +- printstatus(); ++ drawbars(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ +@@ -2341,7 +2535,7 @@ setfloating(Client *c, int floating) + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2364,7 +2558,7 @@ setfullscreen(Client *c, int fullscreen) + resize(c, c->prev, 0); + } + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2376,9 +2570,9 @@ setlayout(const Arg *arg) + selmon->sellt ^= 1; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; +- strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); ++ strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof(selmon->ltsymbol)); + arrange(selmon); +- printstatus(); ++ drawbar(selmon); + } + + /* arg > 1.0 will set mfact absolutely */ +@@ -2451,6 +2645,7 @@ setup(void) + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + ++ + wlr_log_init(log_level, NULL); + + /* The Wayland display is managed by libwayland. It handles accepting +@@ -2645,6 +2840,11 @@ setup(void) + wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); + wl_signal_add(&output_mgr->events.test, &output_mgr_test); + ++ drwl_init(); ++ ++ status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy), ++ STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2669,6 +2869,7 @@ void + spawn(const Arg *arg) + { + if (fork() == 0) { ++ close(STDIN_FILENO); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); +@@ -2687,6 +2888,30 @@ startdrag(struct wl_listener *listener, void *data) + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); + } + ++int ++statusin(int fd, unsigned int mask, void *data) ++{ ++ char status[256]; ++ ssize_t n; ++ ++ if (mask & WL_EVENT_ERROR) ++ die("status in event error"); ++ if (mask & WL_EVENT_HANGUP) ++ wl_event_source_remove(status_event_source); ++ ++ n = read(fd, status, sizeof(status) - 1); ++ if (n < 0 && errno != EWOULDBLOCK) ++ die("read:"); ++ ++ status[n] = '\0'; ++ status[strcspn(status, "\n")] = '\0'; ++ ++ strncpy(stext, status, sizeof(stext)); ++ drawbars(); ++ ++ return 0; ++} ++ + void + tag(const Arg *arg) + { +@@ -2697,7 +2922,7 @@ tag(const Arg *arg) + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2742,6 +2967,14 @@ tile(Monitor *m) + } + } + ++void ++togglebar(const Arg *arg) ++{ ++ wlr_scene_node_set_enabled(&selmon->scene_buffer->node, ++ !selmon->scene_buffer->node.enabled); ++ arrangelayers(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { +@@ -2770,7 +3003,7 @@ toggletag(const Arg *arg) + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2783,7 +3016,7 @@ toggleview(const Arg *arg) + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2831,7 +3064,7 @@ unmapnotify(struct wl_listener *listener, void *data) + } + + wlr_scene_node_destroy(&c->scene->node); +- printstatus(); ++ drawbars(); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -2931,6 +3164,13 @@ updatemons(struct wl_listener *listener, void *data) + } + } + ++ if (stext[0] == '\0') ++ strncpy(stext, "dwl-"VERSION, sizeof(stext)); ++ wl_list_for_each(m, &mons, link) { ++ updatebar(m); ++ drawbar(m); ++ } ++ + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a +@@ -2941,12 +3181,45 @@ updatemons(struct wl_listener *listener, void *data) + wlr_output_manager_v1_set_configuration(output_mgr, config); + } + ++void ++updatebar(Monitor *m) ++{ ++ size_t i; ++ int rw, rh; ++ char fontattrs[12]; ++ ++ wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); ++ m->b.width = rw; ++ m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); ++ ++ wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0); ++ ++ for (i = 0; i < LENGTH(m->pool); i++) ++ if (m->pool[i]) { ++ wlr_buffer_drop(&m->pool[i]->base); ++ m->pool[i] = NULL; ++ } ++ ++ if (m->b.scale == m->wlr_output->scale && m->drw) ++ return; ++ ++ drwl_font_destroy(m->drw->font); ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * m->wlr_output->scale); ++ if (!(drwl_font_create(m->drw, LENGTH(fonts), fonts, fontattrs))) ++ die("Could not load font"); ++ ++ m->b.scale = m->wlr_output->scale; ++ m->lrpad = m->drw->font->height; ++ m->b.height = m->drw->font->height + 2; ++ m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale); ++} ++ + void + updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) +- printstatus(); ++ drawbars(); + } + + void +@@ -2959,10 +3232,10 @@ urgent(struct wl_listener *listener, void *data) + return; + + c->isurgent = 1; +- printstatus(); ++ drawbars(); + + if (client_surface(c)->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +@@ -2975,7 +3248,7 @@ view(const Arg *arg) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -3016,6 +3289,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + { + struct wlr_scene_node *node, *pnode; + struct wlr_surface *surface = NULL; ++ struct wlr_scene_surface *scene_surface = NULL; + Client *c = NULL; + LayerSurface *l = NULL; + int layer; +@@ -3024,9 +3298,12 @@ xytonode(double x, double y, struct wlr_surface **psurface, + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + +- if (node->type == WLR_SCENE_NODE_BUFFER) +- surface = wlr_scene_surface_try_from_buffer( +- wlr_scene_buffer_from_node(node))->surface; ++ if (node->type == WLR_SCENE_NODE_BUFFER) { ++ scene_surface = wlr_scene_surface_try_from_buffer( ++ wlr_scene_buffer_from_node(node)); ++ if (!scene_surface) continue; ++ surface = scene_surface->surface; ++ } + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; +@@ -3159,10 +3436,10 @@ sethints(struct wl_listener *listener, void *data) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); +- printstatus(); ++ drawbars(); + + if (c->isurgent && surface && surface->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +-- +2.50.0 + diff --git a/dwl/dwl-patches/patches/bar/bar.png b/dwl/dwl-patches/patches/bar/bar.png new file mode 100755 index 0000000..276256b Binary files /dev/null and b/dwl/dwl-patches/patches/bar/bar.png differ diff --git a/dwl/dwl-patches/patches/barborder/README.md b/dwl/dwl-patches/patches/barborder/README.md new file mode 100755 index 0000000..6eef3ba --- /dev/null +++ b/dwl/dwl-patches/patches/barborder/README.md @@ -0,0 +1,10 @@ +### Description + +Add a border around the [bar](/dwl/dwl-patches/wiki/bar) similar to how a client is given a border. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/barborder/barborder.patch) + +### Authors +- [sewn](https://codeberg.org/sewn) + diff --git a/dwl/dwl-patches/patches/barborder/barborder.patch b/dwl/dwl-patches/patches/barborder/barborder.patch new file mode 100755 index 0000000..106a2ac --- /dev/null +++ b/dwl/dwl-patches/patches/barborder/barborder.patch @@ -0,0 +1,136 @@ +From 7d95ce0fba8f172748bbd71b4c03ce12acd54eea Mon Sep 17 00:00:00 2001 +From: sewn +Date: Fri, 23 Aug 2024 14:11:37 +0300 +Subject: [PATCH] add border to bar + +--- + config.def.h | 3 ++- + dwl.c | 32 +++++++++++++++++++------------- + 2 files changed, 21 insertions(+), 14 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 5d1dc2b..4763482 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,7 +6,7 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ +-static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int borderpx = 1; /* border pixel of windows & bar */ + 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"}; +@@ -18,6 +18,7 @@ static uint32_t colors[][3] = { + [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, + [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, + [SchemeUrg] = { 0, 0, 0x770000ff }, ++ [SchemeBar] = { 0, 0, 0x557700ff }, + }; + + /* tagging - TAGCOUNT must be no greater than 31 */ +diff --git a/dwl.c b/dwl.c +index ece537a..c637da4 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -85,7 +85,7 @@ + #define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) + + /* enums */ +-enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ ++enum { SchemeNorm, SchemeSel, SchemeUrg, SchemeBar }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ +@@ -750,7 +750,7 @@ buttonpress(struct wl_listener *listener, void *data) + if (!c && !exclusive_focus && + (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && + (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { +- cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; ++ cx = (cursor->x - selmon->m.x - borderpx) * selmon->wlr_output->scale; + do + x += TEXTW(selmon, tags[i]); + while (cx >= x && ++i < LENGTH(tags)); +@@ -1506,10 +1506,12 @@ dirtomon(enum wlr_direction dir) + void + drawbar(Monitor *m) + { +- int x, w, tw = 0; ++ int x, y = borderpx, w, tw = 0; ++ int mh = m->b.height - borderpx * 2, mw = m->b.width - borderpx * 2; + int boxs = m->drw->font->height / 9; + int boxw = m->drw->font->height / 6 + 2; + uint32_t i, occ = 0, urg = 0; ++ uint32_t borderscm[] = { colors[SchemeBar][ColBorder] }; + Client *c; + Buffer *buf; + +@@ -1518,11 +1520,15 @@ drawbar(Monitor *m) + if (!(buf = bufmon(m))) + return; + ++ drwl_setscheme(m->drw, borderscm); ++ drwl_rect(m->drw, 0, 0, m->b.width, m->b.height, 1, 0); ++ drwl_setscheme(m->drw, colors[SchemeNorm]); ++ + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drwl_setscheme(m->drw, colors[SchemeNorm]); + tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ +- drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); ++ drwl_text(m->drw, borderpx + mw - tw, y, tw, mh, 0, stext, 0); + } + + wl_list_for_each(c, &clients, link) { +@@ -1532,31 +1538,31 @@ drawbar(Monitor *m) + if (c->isurgent) + urg |= c->tags; + } +- x = 0; ++ x = borderpx; + c = focustop(m); + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(m, tags[i]); + drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); +- drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i); ++ drwl_text(m->drw, x, y, w, mh, m->lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) +- drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, ++ drwl_rect(m->drw, x + boxs, y + boxs, boxw, boxw, + m == selmon && c && c->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = TEXTW(m, m->ltsymbol); + drwl_setscheme(m->drw, colors[SchemeNorm]); +- x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0); ++ x = drwl_text(m->drw, x, y, w, mh, m->lrpad / 2, m->ltsymbol, 0); + +- if ((w = m->b.width - tw - x) > m->b.height) { ++ if ((w = mw - tw - x + borderpx) > mh) { + if (c) { + drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); +- drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); ++ drwl_text(m->drw, x, y, w, mh, m->lrpad / 2, client_get_title(c), 0); + if (c && c->isfloating) +- drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0); ++ drwl_rect(m->drw, x + boxs, y + boxs, boxw, boxw, 0, 0); + } else { + drwl_setscheme(m->drw, colors[SchemeNorm]); +- drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1); ++ drwl_rect(m->drw, x, y, w, mh, 1, 1); + } + } + +@@ -3183,7 +3189,7 @@ updatebar(Monitor *m) + + m->b.scale = m->wlr_output->scale; + m->lrpad = m->drw->font->height; +- m->b.height = m->drw->font->height + 2; ++ m->b.height = m->drw->font->height + 2 + borderpx * 2; + m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale); + } + +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/barcolors/README.md b/dwl/dwl-patches/patches/barcolors/README.md new file mode 100755 index 0000000..640961b --- /dev/null +++ b/dwl/dwl-patches/patches/barcolors/README.md @@ -0,0 +1,9 @@ +### Description +Add support for colored status text to the [bar](/dwl/dwl-patches/src/branch/main/patches/bar). Text can be colored in the same manner as with dwlb, namely by wrapping it between `^fg(color)` and `^fg()` or `^bg(color)` and `^bg()`, where `color` is a 6-digit hexadecimal value. + +### Download +- [git branch](/kerberoge/dwl/src/branch/barcolors) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/barcolors/barcolors.patch) + +### Authors +- [kerberoge](https://codeberg.org/kerberoge) diff --git a/dwl/dwl-patches/patches/barcolors/barcolors.patch b/dwl/dwl-patches/patches/barcolors/barcolors.patch new file mode 100755 index 0000000..b95f78e --- /dev/null +++ b/dwl/dwl-patches/patches/barcolors/barcolors.patch @@ -0,0 +1,144 @@ +From d2b529d9ebee6b2e625afd5c89c2ede5bb0ca91b Mon Sep 17 00:00:00 2001 +From: Kerberoge +Date: Sun, 25 Aug 2024 22:41:55 +0200 +Subject: [PATCH 1/1] updated barcolors + +--- + dwl.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 87 insertions(+), 6 deletions(-) + +diff --git a/dwl.c b/dwl.c +index ece537a..6663399 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -83,6 +83,7 @@ + #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) + #define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) ++#define PREFIX(str, prefix) !strncmp(str, prefix, strlen(prefix)) + + /* enums */ + enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ +@@ -318,6 +319,7 @@ static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); + static void drawbar(Monitor *m); + static void drawbars(void); ++static int drawstatus(Monitor *m); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -448,7 +450,7 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + +-static char stext[256]; ++static char stext[512]; + static struct wl_event_source *status_event_source; + + static const struct wlr_buffer_impl buffer_impl = { +@@ -1519,11 +1521,8 @@ drawbar(Monitor *m) + return; + + /* draw status first so it can be overdrawn by tags later */ +- if (m == selmon) { /* status is only drawn on selected monitor */ +- drwl_setscheme(m->drw, colors[SchemeNorm]); +- tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ +- drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); +- } ++ if (m == selmon) /* status is only drawn on selected monitor */ ++ tw = drawstatus(m); + + wl_list_for_each(c, &clients, link) { + if (c->mon != m) +@@ -1577,6 +1576,88 @@ drawbars(void) + drawbar(m); + } + ++int ++drawstatus(Monitor *m) ++{ ++ int x, tw, iw; ++ char rstext[512] = ""; ++ char *p, *argstart, *argend, *itext; ++ uint32_t scheme[3], *color; ++ ++ /* calculate real width of stext */ ++ for (p = stext; *p; p++) { ++ if (PREFIX(p, "^^")) { ++ strncat(rstext, p, 2); ++ p++; ++ } else if (PREFIX(p, "^fg(") || PREFIX(p, "^bg(")) { ++ argend = strchr(p, ')'); ++ if (!argend) { /* ignore this command */ ++ argstart = strchr(p, '(') + 1; ++ strncat(rstext, p, argstart - p); ++ p = argstart - 1; ++ } else { ++ p = argend; ++ } ++ } else { ++ strncat(rstext, p, 1); ++ } ++ } ++ tw = TEXTW(m, rstext) - m->lrpad; ++ ++ x = m->b.width - tw; ++ itext = stext; ++ scheme[0] = colors[SchemeNorm][0]; ++ scheme[1] = colors[SchemeNorm][1]; ++ drwl_setscheme(m->drw, scheme); ++ for (p = stext; *p; p++) { ++ if (PREFIX(p, "^^")) { ++ p++; ++ } else if (PREFIX(p, "^fg(") || PREFIX(p, "^bg(")) { ++ argstart = strchr(p, '(') + 1; ++ argend = strchr(argstart, ')'); ++ if (!argend) { /* ignore this command */ ++ p = argstart - 1; ++ continue; ++ } ++ ++ *p = '\0'; ++ iw = TEXTW(m, itext) - m->lrpad; ++ if (*itext) /* only draw text if there is something to draw */ ++ x = drwl_text(m->drw, x, 0, iw, m->b.height, 0, itext, 0); ++ *p = '^'; ++ ++ if (PREFIX(p, "^fg(")) ++ color = &scheme[0]; ++ else ++ color = &scheme[1]; ++ ++ if (argend != argstart) { ++ *argend = '\0'; ++ *color = strtoul(argstart, NULL, 16); ++ *color = *color << 8 | 0xff; /* add alpha channel */ ++ *argend = ')'; ++ } else { ++ *color = 0; /* reset */ ++ } ++ ++ /* reset color back to normal if none was provided */ ++ if (!scheme[0]) ++ scheme[0] = colors[SchemeNorm][0]; ++ if (!scheme[1]) ++ scheme[1] = colors[SchemeNorm][1]; ++ ++ itext = argend + 1; ++ drwl_setscheme(m->drw, scheme); ++ p = argend; ++ } ++ } ++ iw = TEXTW(m, itext) - m->lrpad; ++ if (*itext) ++ drwl_text(m->drw, x, 0, iw, m->b.height, 0, itext, 0); ++ ++ return tw; ++} ++ + void + focusclient(Client *c, int lift) + { +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/barpadding/README.md b/dwl/dwl-patches/patches/barpadding/README.md new file mode 100755 index 0000000..1d0f17b --- /dev/null +++ b/dwl/dwl-patches/patches/barpadding/README.md @@ -0,0 +1,10 @@ +### Description + +Add vertical and horizontal space between the [bar](/dwl/dwl-patches/wiki/bar) and the edge of the screen. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/barpadding/barpadding.patch) + +### Authors +- [sewn](https://codeberg.org/sewn) + diff --git a/dwl/dwl-patches/patches/barpadding/barpadding.patch b/dwl/dwl-patches/patches/barpadding/barpadding.patch new file mode 100755 index 0000000..e5cc185 --- /dev/null +++ b/dwl/dwl-patches/patches/barpadding/barpadding.patch @@ -0,0 +1,73 @@ +From f01cea73042155e856b2f41452724fe5c895eee4 Mon Sep 17 00:00:00 2001 +From: sewn +Date: Fri, 23 Aug 2024 09:59:03 +0300 +Subject: [PATCH] add vertical and horizontal spacing to bar + +https://dwm.suckless.org/patches/barpadding/ +--- + config.def.h | 2 ++ + dwl.c | 14 +++++++------- + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 5d1dc2b..756b1ae 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -9,6 +9,8 @@ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int vertpad = 10; /* vertical padding of bar */ ++static const int sidepad = 10; /* horizontal padding of bar */ + static const char *fonts[] = {"monospace:size=10"}; + static const float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +diff --git a/dwl.c b/dwl.c +index ece537a..380549a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -598,8 +598,8 @@ arrangelayers(Monitor *m) + return; + + if (m->scene_buffer->node.enabled) { +- usable_area.height -= m->b.real_height; +- usable_area.y += topbar ? m->b.real_height : 0; ++ usable_area.height -= m->b.real_height + vertpad; ++ usable_area.y += topbar ? m->b.real_height + vertpad : 0; + } + + /* Arrange exclusive surfaces from top->bottom */ +@@ -750,7 +750,7 @@ buttonpress(struct wl_listener *listener, void *data) + if (!c && !exclusive_focus && + (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && + (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { +- cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; ++ cx = (cursor->x - selmon->m.x - sidepad) * selmon->wlr_output->scale; + do + x += TEXTW(selmon, tags[i]); + while (cx >= x && ++i < LENGTH(tags)); +@@ -1562,8 +1562,8 @@ drawbar(Monitor *m) + + wlr_scene_buffer_set_dest_size(m->scene_buffer, + m->b.real_width, m->b.real_height); +- wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, +- m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); ++ wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x + sidepad, ++ m->m.y + (topbar ? vertpad : m->m.height - m->b.real_height - vertpad)); + wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); + wlr_buffer_unlock(&buf->base); + } +@@ -3162,8 +3162,8 @@ updatebar(Monitor *m) + char fontattrs[12]; + + wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); +- m->b.width = rw; +- m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); ++ m->b.width = rw - (2 * sidepad); ++ m->b.real_width = (int)((float)rw / m->wlr_output->scale) - (2 * sidepad); + + wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0); + +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/bartruecenteredtitle/README.md b/dwl/dwl-patches/patches/bartruecenteredtitle/README.md new file mode 100755 index 0000000..94bfcd9 --- /dev/null +++ b/dwl/dwl-patches/patches/bartruecenteredtitle/README.md @@ -0,0 +1,11 @@ +### Description +A homegrown port of dwm's _truecenteredtitle_ patch, with the addition of a config option to toggle its effects.
Requires [the bar patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar) to be applied beforehand. + +![](centeredtitle.webp) + +### Download +- [v0.7/v0.6](/dwl/dwl-patches/raw/branch/main/patches/bartruecenteredtitle/bartruecenteredtitle.patch)
Works on both v0.7 and v0.6. + +### Author +- [moonsabre](https://codeberg.org/moonsabre) +- [sewn](https://codeberg.org/sewn) diff --git a/dwl/dwl-patches/patches/bartruecenteredtitle/bartruecenteredtitle.patch b/dwl/dwl-patches/patches/bartruecenteredtitle/bartruecenteredtitle.patch new file mode 100755 index 0000000..ce02a51 --- /dev/null +++ b/dwl/dwl-patches/patches/bartruecenteredtitle/bartruecenteredtitle.patch @@ -0,0 +1,46 @@ +From 17501c9f28226b1f332d6842be0d7f50ba618a29 Mon Sep 17 00:00:00 2001 +From: moonsabre +Date: Fri, 14 Mar 2025 16:04:25 -0700 +Subject: [PATCH] Bar title centering parameter. + +--- + config.def.h | 1 + + dwl.c | 9 +++++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 5d1dc2b..8ac3a8b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -9,6 +9,7 @@ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int centeredtitle = 1; /* 1 means centered title */ + static const char *fonts[] = {"monospace:size=10"}; + static const float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +diff --git a/dwl.c b/dwl.c +index ece537a..9eb816b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1551,9 +1551,14 @@ drawbar(Monitor *m) + if ((w = m->b.width - tw - x) > m->b.height) { + if (c) { + drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); +- drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); ++ tw = TEXTW(selmon, client_get_title(c)); ++ drwl_text(m->drw, x, 0, w, m->b.height, ++ !centeredtitle || tw > w ? m->lrpad / 2 : (w - tw) / 2, ++ client_get_title(c), 0); + if (c && c->isfloating) +- drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0); ++ drwl_rect(m->drw, ++ !centeredtitle || tw > w ? x + boxs : x + ((w - tw) / 2 - boxs * 8), ++ boxs, boxw, boxw, 0, 0); + } else { + drwl_setscheme(m->drw, colors[SchemeNorm]); + drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1); +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/bartruecenteredtitle/centeredtitle.webp b/dwl/dwl-patches/patches/bartruecenteredtitle/centeredtitle.webp new file mode 100755 index 0000000..b1ad696 Binary files /dev/null and b/dwl/dwl-patches/patches/bartruecenteredtitle/centeredtitle.webp differ diff --git a/dwl/dwl-patches/patches/better-resize/README.md b/dwl/dwl-patches/patches/better-resize/README.md new file mode 100755 index 0000000..9c43862 --- /dev/null +++ b/dwl/dwl-patches/patches/better-resize/README.md @@ -0,0 +1,48 @@ +### Description +This patch allows you to configure window resizing more flexibly. +It introduces three options with the following possible values: + +- warp_cursor: +``` + 0 - the mouse cursor remains in its original position at the start of the resize. + 1 - the cursor is automatically warped to the selected corner before resizing begins. +``` + +- lock_cursor: +``` + 0 - the cursor can move freely during the resize. + 1 - the cursor position is completely frozen for the entire duration of the resize. +``` + +- resize_corner: +``` + 0: top-left + 1: top-right + 2: bottom-left + 3: bottom-right + 4: selects the corner based on the current mouse quadrant +``` + +### Demos +All demos below use resize_corner = 4: +| no warp + no lock | warp + lock | +|-|-| +| ![demo-nowarp-nolock](https://github.com/mmistika/dwl-better-resize/blob/main/demo/demo-nowarp-nolock.gif?raw=true) | ![demo-warp-lock](https://github.com/mmistika/dwl-better-resize/blob/main/demo/demo-warp-lock.gif?raw=true) | + +| no warp + lock | warp + no lock | +|-|-| +| ![demo-nowarp-lock](https://github.com/mmistika/dwl-better-resize/blob/main/demo/demo-nowarp-lock.gif?raw=true) | ![demo-warp-nolock](https://github.com/mmistika/dwl-better-resize/blob/main/demo/demo-warp-nolock.gif?raw=true) | + +### Known Issues (warp + lock) +The combination of warp_cursor and lock_cursor is not recommended without outer gaps. +If the selected resize corner aligns exactly with a screen corner, the cursor gets locked there and cannot be moved outward, so resizing only works inward. +To resize outward, you must restart the resize operation with the cursor positioned somewhere away from the screen corner. +This happens because the locked cursor cannot move past the screen edge, and therefore cannot generate a non-zero delta to resize outward. + +On multihead setups, if the resize corner is near another screen, the window may switch monitors upon completion of the resize. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/better-resize/better-resize-0.7.patch) + +### Authors +- [mmistika](https://codeberg.org/mmistika) diff --git a/dwl/dwl-patches/patches/better-resize/better-resize-0.7.patch b/dwl/dwl-patches/patches/better-resize/better-resize-0.7.patch new file mode 100755 index 0000000..1269800 --- /dev/null +++ b/dwl/dwl-patches/patches/better-resize/better-resize-0.7.patch @@ -0,0 +1,107 @@ +From f109808140cd6323b3a100663a10e048ae32e3a0 Mon Sep 17 00:00:00 2001 +From: mmistika +Date: Thu, 17 Jul 2025 11:59:18 +0200 +Subject: [PATCH] Add configurable window resize + +Signed-off-by: mmistika +--- + config.def.h | 12 ++++++++++++ + dwl.c | 45 +++++++++++++++++++++++++++++++++++++-------- + 2 files changed, 49 insertions(+), 8 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..e404549 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,18 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + /* logging */ + static int log_level = WLR_ERROR; + ++/* window resizing */ ++/* resize_corner: ++ * 0: top-left ++ * 1: top-right ++ * 2: bottom-left ++ * 3: bottom-right ++ * 4: closest to the cursor ++ */ ++static const int resize_corner = 4; ++static const int warp_cursor = 1; /* 1: warp to corner, 0: don’t warp */ ++static const int lock_cursor = 0; /* 1: lock cursor, 0: don't lock */ ++ + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ +diff --git a/dwl.c b/dwl.c +index c717c1d..aacd074 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -407,6 +407,7 @@ static KeyboardGroup *kb_group; + static unsigned int cursor_mode; + static Client *grabc; + static int grabcx, grabcy; /* client-relative */ ++static int rzcorner; + + static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; +@@ -1873,8 +1874,24 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + .width = grabc->geom.width, .height = grabc->geom.height}, 1); + return; + } else if (cursor_mode == CurResize) { +- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); ++ int cdx = (int)round(cursor->x) - grabcx; ++ int cdy = (int)round(cursor->y) - grabcy; ++ ++ const struct wlr_box box = { ++ .x = grabc->geom.x + (rzcorner & 1 ? 0 : cdx), ++ .y = grabc->geom.y + (rzcorner & 2 ? 0 : cdy), ++ .width = grabc->geom.width + (rzcorner & 1 ? cdx : -cdx), ++ .height = grabc->geom.height + (rzcorner & 2 ? cdy : -cdy) ++ }; ++ resize(grabc, box, 1); ++ ++ if (!lock_cursor) { ++ grabcx += cdx; ++ grabcy += cdy; ++ } else { ++ wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy); ++ } ++ + return; + } + +@@ -1920,12 +1937,24 @@ moveresize(const Arg *arg) + wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); + break; + case CurResize: +- /* Doesn't work for X11 output - the next absolute motion event +- * returns the cursor to where it started */ +- wlr_cursor_warp_closest(cursor, NULL, +- grabc->geom.x + grabc->geom.width, +- grabc->geom.y + grabc->geom.height); +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); ++ const char *cursors[] = { "nw-resize", "ne-resize", "sw-resize", "se-resize" }; ++ ++ rzcorner = resize_corner; ++ grabcx = (int)round(cursor->x); ++ grabcy = (int)round(cursor->y); ++ ++ if (rzcorner == 4) ++ /* identify the closest corner index */ ++ rzcorner = (grabcx - grabc->geom.x < grabc->geom.x + grabc->geom.width - grabcx ? 0 : 1) ++ + (grabcy - grabc->geom.y < grabc->geom.y + grabc->geom.height - grabcy ? 0 : 2); ++ ++ if (warp_cursor) { ++ grabcx = rzcorner & 1 ? grabc->geom.x + grabc->geom.width : grabc->geom.x; ++ grabcy = rzcorner & 2 ? grabc->geom.y + grabc->geom.height : grabc->geom.y; ++ wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy); ++ } ++ ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, cursors[rzcorner]); + break; + } + } +-- +2.50.1 + diff --git a/dwl/dwl-patches/patches/borders/README.md b/dwl/dwl-patches/patches/borders/README.md new file mode 100755 index 0000000..b046307 --- /dev/null +++ b/dwl/dwl-patches/patches/borders/README.md @@ -0,0 +1,37 @@ +### Description +Adds 2 more borders to each side (top, bottom, left, right) of every window. + + + +
+Preview +
+With the following config:
+
+```c
+static const unsigned int borderpx         = 9;  /* border pixel of windows */
+static const unsigned int borderspx        = 3;  /* width of the border that start from outside the windows */
+static const unsigned int borderepx        = 3;  /* width of the border that start from inside the windows */
+```
+
+and `border_color_type` set to `BrdOriginal`:
+
+
+and `border_color_type` set to `BrdStart`:
+
+
+and `border_color_type` set to `BrdEnd`:
+
+
+and `border_color_type` set to `BrdStartEnd`:
+
+
+
+ +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/borders) +- [2024-06-04](https://codeberg.org/dwl/dwl-patches/raw/commit/1a6825f2b8cd23044312c8040d0bf63ee7f85bc5/patches/borders/borders.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/borders/borders.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/borders/borders.patch b/dwl/dwl-patches/patches/borders/borders.patch new file mode 100755 index 0000000..c8cc847 --- /dev/null +++ b/dwl/dwl-patches/patches/borders/borders.patch @@ -0,0 +1,213 @@ +From b12cfff672f0705d8259cf26b3a574faa5ca43ae Mon Sep 17 00:00:00 2001 +From: wochap +Date: Tue, 4 Jun 2024 16:02:25 -0500 +Subject: [PATCH] implement borders patch + +tihs patch adds 2 extra borders relative to the client, they don't +change the size of the client +--- + client.h | 16 +++++++++++++--- + config.def.h | 8 ++++++++ + dwl.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++---- + 3 files changed, 70 insertions(+), 7 deletions(-) + +diff --git a/client.h b/client.h +index 800b867..33fd579 100644 +--- a/client.h ++++ b/client.h +@@ -325,11 +325,21 @@ client_send_close(Client *c) + } + + static inline void +-client_set_border_color(Client *c, const float color[static 4]) ++client_set_border_color(Client *c, const float color[static 4], const float colors[static 4], const float colore[static 4]) + { + int i; +- for (i = 0; i < 4; i++) +- wlr_scene_rect_set_color(c->border[i], color); ++ for (i = 0; i < 4; i++) { ++ if (border_color_type == BrdOriginal) { ++ wlr_scene_rect_set_color(c->border[i], color); ++ } else if (border_color_type == BrdStart) { ++ wlr_scene_rect_set_color(c->borders[i], colors); ++ } else if (border_color_type == BrdEnd) { ++ wlr_scene_rect_set_color(c->bordere[i], colore); ++ } else if (border_color_type == BrdStartEnd) { ++ wlr_scene_rect_set_color(c->borders[i], colors); ++ wlr_scene_rect_set_color(c->bordere[i], colore); ++ } ++ } + } + + static inline void +diff --git a/config.def.h b/config.def.h +index 8847e58..2d6bbe5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,8 +7,16 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int borderspx = 0; /* width of the border that start from outside the windows */ ++static const unsigned int borderepx = 0; /* width of the border that start from inside the windows */ ++static const unsigned int borderspx_offset = 0; /* offset of the border that start from outside the windows */ ++static const unsigned int borderepx_negative_offset = 0; /* offset of the border that start from inside the windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); ++static const float borderscolor[] = COLOR(0x444444ff); /* color of the border that start from outside the windows */ ++static const float borderecolor[] = COLOR(0x444444ff); /* color of the border that start from inside the windows */ ++static const int border_color_type = BrdOriginal; /* borders to be colored (focuscolor, urgentcolor) */ ++static const int borders_only_floating = 0; + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +diff --git a/dwl.c b/dwl.c +index bf763df..303832a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -86,6 +86,7 @@ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ + #endif ++enum { BrdOriginal, BrdStart, BrdEnd, BrdStartEnd }; + + typedef union { + int i; +@@ -109,6 +110,8 @@ typedef struct { + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ ++ struct wlr_scene_rect *borders[4]; /* top, bottom, left, right */ ++ struct wlr_scene_rect *bordere[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; +@@ -136,6 +139,8 @@ typedef struct { + struct wl_listener set_hints; + #endif + unsigned int bw; ++ unsigned int bws; ++ unsigned int bwe; + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ +@@ -973,6 +978,8 @@ createnotify(struct wl_listener *listener, void *data) + c = xdg_surface->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = xdg_surface; + c->bw = borderpx; ++ c->bws = borders_only_floating ? 0 : borderspx; ++ c->bwe = borders_only_floating ? 0 : borderepx; + + wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); +@@ -1268,7 +1275,7 @@ focusclient(Client *c, int lift) + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) +- client_set_border_color(c, focuscolor); ++ client_set_border_color(c, focuscolor, focuscolor, focuscolor); + } + + /* Deactivate old client if focus is changing */ +@@ -1285,7 +1292,7 @@ focusclient(Client *c, int lift) + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { +- client_set_border_color(old_c, bordercolor); ++ client_set_border_color(old_c, bordercolor, borderscolor, borderecolor); + + client_activate_surface(old, 0); + } +@@ -1597,6 +1604,12 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, + c->isurgent ? urgentcolor : bordercolor); + c->border[i]->node.data = c; ++ ++ c->borders[i] = wlr_scene_rect_create(c->scene, 0, 0, borderscolor); ++ c->borders[i]->node.data = c; ++ ++ c->bordere[i] = wlr_scene_rect_create(c->scene, 0, 0, borderecolor); ++ c->bordere[i]->node.data = c; + } + + /* Initialize client geometry with room for border */ +@@ -1618,6 +1631,12 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } ++ ++ if (borders_only_floating) { ++ c->bws = c->isfloating ? borderspx : 0; ++ c->bwe = c->isfloating ? borderepx : 0; ++ } ++ + printstatus(); + + unset_fullscreen: +@@ -2051,6 +2070,24 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); + ++ wlr_scene_rect_set_size(c->borders[0], c->geom.width - 2 * borderspx_offset, c->bws); ++ wlr_scene_rect_set_size(c->borders[1], c->geom.width - 2 * borderspx_offset, c->bws); ++ wlr_scene_rect_set_size(c->borders[2], c->bws, c->geom.height - 2 * c->bws - 2 * borderspx_offset); ++ wlr_scene_rect_set_size(c->borders[3], c->bws, c->geom.height - 2 * c->bws - 2 * borderspx_offset); ++ wlr_scene_node_set_position(&c->borders[0]->node, borderspx_offset, borderspx_offset); ++ wlr_scene_node_set_position(&c->borders[1]->node, borderspx_offset, c->geom.height - c->bws - borderspx_offset); ++ wlr_scene_node_set_position(&c->borders[2]->node, borderspx_offset, c->bws + borderspx_offset); ++ wlr_scene_node_set_position(&c->borders[3]->node, c->geom.width - c->bws - borderspx_offset, c->bws + borderspx_offset); ++ ++ wlr_scene_rect_set_size(c->bordere[0], c->geom.width - (c->bw - c->bwe) * 2 + borderepx_negative_offset * 2, c->bwe); ++ wlr_scene_rect_set_size(c->bordere[1], c->geom.width - (c->bw - c->bwe) * 2 + borderepx_negative_offset * 2, c->bwe); ++ wlr_scene_rect_set_size(c->bordere[2], c->bwe, c->geom.height - 2 * c->bw + 2 * borderepx_negative_offset); ++ wlr_scene_rect_set_size(c->bordere[3], c->bwe, c->geom.height - 2 * c->bw + 2 * borderepx_negative_offset); ++ wlr_scene_node_set_position(&c->bordere[0]->node, c->bw - c->bwe - borderepx_negative_offset, c->bw - c->bwe - borderepx_negative_offset); ++ wlr_scene_node_set_position(&c->bordere[1]->node, c->bw - c->bwe - borderepx_negative_offset, c->geom.height - c->bw + borderepx_negative_offset); ++ wlr_scene_node_set_position(&c->bordere[2]->node, c->bw - c->bwe - borderepx_negative_offset, c->bw - borderepx_negative_offset); ++ wlr_scene_node_set_position(&c->bordere[3]->node, c->geom.width - c->bw + borderepx_negative_offset, c->bw - borderepx_negative_offset); ++ + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, + c->geom.height - 2 * c->bw); +@@ -2151,6 +2188,12 @@ setfloating(Client *c, int floating) + c->isfloating = floating; + if (!c->mon) + return; ++ ++ if (borders_only_floating) { ++ c->bws = c->isfloating ? borderspx : 0; ++ c->bwe = c->isfloating ? borderepx : 0; ++ } ++ + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); +@@ -2165,6 +2208,8 @@ setfullscreen(Client *c, int fullscreen) + if (!c->mon) + return; + c->bw = fullscreen ? 0 : borderpx; ++ c->bws = fullscreen ? 0 : borderspx; ++ c->bwe = fullscreen ? 0 : borderepx; + client_set_fullscreen(c, fullscreen); + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen + ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); +@@ -2819,7 +2864,7 @@ urgent(struct wl_listener *listener, void *data) + printstatus(); + + if (client_surface(c)->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, urgentcolor, urgentcolor, urgentcolor); + } + + void +@@ -3023,7 +3068,7 @@ sethints(struct wl_listener *listener, void *data) + printstatus(); + + if (c->isurgent && surface && surface->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, urgentcolor, urgentcolor, urgentcolor); + } + + void +-- +2.44.1 diff --git a/dwl/dwl-patches/patches/bottomstack/README.md b/dwl/dwl-patches/patches/bottomstack/README.md new file mode 100755 index 0000000..fa9ede6 --- /dev/null +++ b/dwl/dwl-patches/patches/bottomstack/README.md @@ -0,0 +1,27 @@ +### Description +bstack and bstackhoriz are two stack layouts for dwl. +### Scheme +``` +bstack (TTT) bstackhoriz (===) ++-----------------+ +-----------------+ +| | | | +| | | | +| | | | ++-----+-----+-----+ +-----------------+ +| | | | +-----------------+ +| | | | +-----------------+ ++-----+-----+-----+ +-----------------+ +``` + + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.6-b/bottomstack) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/20de07dc8759200c8a4c9651475acb331d245890/patches/bottomstack/bottomstack.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/0f4e40fee49d1b8b430778e241b29496ae3b3b70/bottomstack/bottomstack.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/5368aa392c7ebf8d7d24c232b80cfae1be457d41/bottomstack/bottomstack.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [DanielMowitz](https://github.com/DanielMowitz) +- [Abanoub8](https://github.com/Abanoub8) + diff --git a/dwl/dwl-patches/patches/bottomstack/bottomstack.patch b/dwl/dwl-patches/patches/bottomstack/bottomstack.patch new file mode 100755 index 0000000..c2b9331 --- /dev/null +++ b/dwl/dwl-patches/patches/bottomstack/bottomstack.patch @@ -0,0 +1,140 @@ +From b352fb08f40b1ee2d8c4748be4922df711e3aaa9 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 5 Jul 2024 10:44:29 -0500 +Subject: [PATCH] implement bottomstack + +--- + config.def.h | 4 +++ + dwl.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..5aac3e9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,8 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "TTT", bstack }, ++ { "===", bstackhoriz }, + }; + + /* monitors */ +@@ -139,6 +141,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_u, setlayout, {.v = &layouts[3]} }, ++ { MODKEY, XKB_KEY_o, setlayout, {.v = &layouts[4]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index dc0437e..5648d5f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -57,6 +57,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -351,6 +352,8 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void bstack(Monitor *m); ++static void bstackhoriz(Monitor *m); + + /* variables */ + static const char broken[] = "broken"; +@@ -3160,3 +3163,84 @@ main(int argc, char *argv[]) + usage: + die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); + } ++ ++static void ++bstack(Monitor *m) ++{ ++ int w, h, mh, mx, tx, ty, tw; ++ int i, n = 0; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating) ++ n++; ++ if (n == 0) ++ return; ++ ++ if (n > m->nmaster) { ++ mh = (int)round(m->nmaster ? m->mfact * m->w.height : 0); ++ tw = m->w.width / (n - m->nmaster); ++ ty = m->w.y + mh; ++ } else { ++ mh = m->w.height; ++ tw = m->w.width; ++ ty = m->w.y; ++ } ++ ++ i = mx = 0; ++ tx = m-> w.x; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating) ++ continue; ++ if (i < m->nmaster) { ++ w = (m->w.width - mx) / (MIN(n, m->nmaster) - i); ++ resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w, .height = mh }, 0); ++ mx += c->geom.width; ++ } else { ++ h = m->w.height - mh; ++ resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = tw, .height = h }, 0); ++ if (tw != m->w.width) ++ tx += c->geom.width; ++ } ++ i++; ++ } ++} ++ ++static void ++bstackhoriz(Monitor *m) { ++ int w, mh, mx, tx, ty, th; ++ int i, n = 0; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating) ++ n ++; ++ if (n == 0) ++ return; ++ ++ if (n > m->nmaster) { ++ mh = (int)round(m->nmaster ? m->mfact * m->w.height : 0); ++ th = (m->w.height - mh) / (n - m->nmaster); ++ ty = m->w.y + mh; ++ } else { ++ th = mh = m->w.height; ++ ty = m->w.y; ++ } ++ ++ i = mx = 0; ++ tx = m-> w.x; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c,m) || c->isfloating) ++ continue; ++ if (i < m->nmaster) { ++ w = (m->w.width - mx) / (MIN(n, m->nmaster) - i); ++ resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w, .height = mh }, 0); ++ mx += c->geom.width; ++ } else { ++ resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = m->w.width, .height = th }, 0); ++ if (th != m->w.height) ++ ty += c->geom.height; ++ } ++ i++; ++ } ++} +-- +2.45.1 diff --git a/dwl/dwl-patches/patches/btrtile/README.md b/dwl/dwl-patches/patches/btrtile/README.md new file mode 100755 index 0000000..4766aa7 --- /dev/null +++ b/dwl/dwl-patches/patches/btrtile/README.md @@ -0,0 +1,103 @@ +### Description + +# btrtile — A Focus-Driven Tiling Layout + +It provides a focus-driven, mouse- and keyboard-friendly tiling layout that grants you granular control over how clients are placed and resized. + +![btrtile in action](https://github.com/julmajustus/dwl-patches/blob/main/demos/btrtiledemo.gif?raw=true) + +--- + +# Why btrtile + +While dwl’s patches folder is full of different layouts, I couldn't find suitable layout that would work well with my workflow and single ultrawide monitor setup. btrtile aims to solve that by introducing a layout strategy that splits clients according to user focus and pointer position. + +--- + +# Features + +- **Combined Tiling and Management** + Combines tiling layout and management of clients under one patchset. + +- **Focus-Driven Splits** + When you add a new client, btrtile checks where your pointer is relative to the focused client’s geometry. + - If the pointer is on the left half (for a horizontally large client), the new client spawns on the left side, and vice versa. + - By default, new splits are 50/50. + +- **Adaptive Splitting** + - If the area to be split is wider than its height, btrtile does a vertical split. + - Otherwise, it does a horizontal split. + +- **Keyboard and Mouse Driven** + - Supports keyboard-based commands for quick ratio adjustments and client swapping. + - Mouse-based resizing and moving are integrated for more intuitive manipulation. + +--- + +# How It Works + +btrtile organizes clients using a binary tree data structure that represents splits either vertically or horizontally. + +When a new client appears: +1. **Focused Client Detection** + btrtile checks your pointer location to find which client (if any) you’re interacting with. +2. **Split Creation** + - If there’s a focused client, btrtile creates a split node around it, placing the new client on the side where your pointer is. + +3. **Ratio Management** + Each split node has a `split_ratio` (defaulting to 0.5). This ratio defines how much space is allocated to each child node. You can adjust this ratio using keyboard or mouse actions. + +--- + +# What It Doesn’t Handle + +- **Suckless philosophy** + - Yea, it's a bloat. I tried to hide the suck inside a single file as much I could. While this approach is not ideal, it's how it's at least for now. + +--- + +# Configuring btrtile + +btrtile adds couple variables to config.h to fine tune the mouse resizing of tiled clients. + +1. **resize_factor** + - A multiplier to transfer pointer movement to client weight ratio. Depends heavily on mouse sensivity. + Defaults to 0.0002f. + +2. **resize_interval_ms** + - A time based resize call limiter. Depends on framerate and screen refresh rate. + Defaults to 16ms. (~60 resize updates per second) + +Fine tune these values to find the best values for your setup, smoother resizing can significally increase cpu overhead. +If mouse resizing feels sluggish, you can try compiling dwl with more aggressive optimization flags like -O2/-O3. + +--- + +# Patch recommendations + +1. **Patches that I use with my btrtile** + + - [focusdir](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/focusdir) + Great patch to move focus between clients. + + - [rotatetags](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/rotatetags) + Good patch to rotate the view or shift clients between tags. + + - [warpcursor](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/warpcursor) + Moves cursor location to focused client. + + - [pertag](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/pertag) + Allows each tag to have individual layout setups. + + - [gaps](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/gaps) + Add gaps between clients. + +--- + +### Download +- [git branch](https://codeberg.org/julmajustus/dwl/src/branch/btrtile-dev) +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/btrtile/btrtile-v0.7.patch) +- [0.7 WITH gaps](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/btrtile/btrtile-v0.7-gaps.patch) + +### Authors +- [julmajustus](https://codeberg.org/julmajustus) diff --git a/dwl/dwl-patches/patches/btrtile/btrtile-v0.7-gaps.patch b/dwl/dwl-patches/patches/btrtile/btrtile-v0.7-gaps.patch new file mode 100755 index 0000000..90354d1 --- /dev/null +++ b/dwl/dwl-patches/patches/btrtile/btrtile-v0.7-gaps.patch @@ -0,0 +1,922 @@ +From 858ef20d36c2d5e6a23a69b3b5909a80fab05f97 Mon Sep 17 00:00:00 2001 +From: julmajustus +Date: Thu, 13 Feb 2025 23:25:20 +0200 +Subject: [PATCH] btrtile-gaps with multi-tag support + +--- + btrtile.c | 582 +++++++++++++++++++++++++++++++++++++++++++++++++++ + config.def.h | 12 ++ + dwl.c | 152 +++++++++++--- + 3 files changed, 717 insertions(+), 29 deletions(-) + create mode 100644 btrtile.c + +diff --git a/btrtile.c b/btrtile.c +new file mode 100644 +index 0000000..650cab5 +--- /dev/null ++++ b/btrtile.c +@@ -0,0 +1,582 @@ ++/* ************************************************************************** */ ++/* */ ++/* ::: :::::::: */ ++/* btrtile.c :+: :+: :+: */ ++/* +:+ +:+ +:+ */ ++/* By: jmakkone +#+ +:+ +#+ */ ++/* +#+#+#+#+#+ +#+ */ ++/* Created: 2024/12/15 00:26:07 by jmakkone #+# #+# */ ++/* Updated: 2025/02/13 23:25:03 by jmakkone ### ########.fr */ ++/* */ ++/* ************************************************************************** */ ++ ++typedef struct LayoutNode { ++ unsigned int is_client_node; ++ unsigned int is_split_vertically; ++ float split_ratio; ++ struct LayoutNode *left; ++ struct LayoutNode *right; ++ struct LayoutNode *split_node; ++ Client *client; ++} LayoutNode; ++ ++static void apply_layout(Monitor *m, LayoutNode *node, ++ struct wlr_box area, unsigned int is_root); ++static void btrtile(Monitor *m); ++static LayoutNode *create_client_node(Client *c); ++static LayoutNode *create_split_node(unsigned int is_split_vertically, ++ LayoutNode *left, LayoutNode *right); ++static void destroy_node(LayoutNode *node); ++static void destroy_tree(Monitor *m); ++static LayoutNode *find_client_node(LayoutNode *node, Client *c); ++static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert); ++static void init_tree(Monitor *m); ++static void insert_client(Monitor *m, Client *focused_client, Client *new_client); ++static LayoutNode *remove_client_node(LayoutNode *node, Client *c); ++static void remove_client(Monitor *m, Client *c); ++static void setratio_h(const Arg *arg); ++static void setratio_v(const Arg *arg); ++static void swapclients(const Arg *arg); ++static unsigned int visible_count(LayoutNode *node, Monitor *m); ++static Client *xytoclient(double x, double y); ++ ++static int resizing_from_mouse = 0; ++static double resize_last_update_x, resize_last_update_y; ++static uint32_t last_resize_time = 0; ++ ++void ++apply_layout(Monitor *m, LayoutNode *node, ++ struct wlr_box area, unsigned int is_root) ++{ ++ Client *c; ++ float ratio; ++ unsigned int left_count, right_count, mid, e = m->gaps; ++ struct wlr_box left_area, right_area; ++ ++ if (!node) ++ return; ++ ++ if (is_root && e) { ++ area.x += gappx; ++ area.y += gappx; ++ area.width -= 2 * gappx; ++ area.height -= 2 * gappx; ++ } ++ ++ /* If this node is a client node, check if it is visible. */ ++ if (node->is_client_node) { ++ c = node->client; ++ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ return; ++ resize(c, area, 0); ++ c->old_geom = area; ++ return; ++ } ++ ++ /* For a split node, we see how many visible children are on each side: */ ++ left_count = visible_count(node->left, m); ++ right_count = visible_count(node->right, m); ++ ++ if (left_count == 0 && right_count == 0) { ++ return; ++ } else if (left_count > 0 && right_count == 0) { ++ apply_layout(m, node->left, area, 0); ++ return; ++ } else if (left_count == 0 && right_count > 0) { ++ apply_layout(m, node->right, area, 0); ++ return; ++ } ++ ++ /* If we’re here, we have visible clients in both subtrees. */ ++ ratio = node->split_ratio; ++ if (ratio < 0.05f) ++ ratio = 0.05f; ++ if (ratio > 0.95f) ++ ratio = 0.95f; ++ ++ memset(&left_area, 0, sizeof(left_area)); ++ memset(&right_area, 0, sizeof(right_area)); ++ ++ if (node->is_split_vertically) { ++ mid = (unsigned int)(area.width * ratio); ++ left_area.x = area.x; ++ left_area.y = area.y; ++ left_area.width = mid; ++ left_area.height = area.height; ++ ++ right_area.x = area.x + mid; ++ right_area.y = area.y; ++ right_area.width = area.width - mid; ++ right_area.height = area.height; ++ ++ if (e) { ++ left_area.width -= gappx / 2; ++ right_area.x += gappx / 2; ++ right_area.width -= gappx / 2; ++ } ++ } else { ++ /* horizontal split */ ++ mid = (unsigned int)(area.height * ratio); ++ left_area.x = area.x; ++ left_area.y = area.y; ++ left_area.width = area.width; ++ left_area.height = mid; ++ ++ right_area.x = area.x; ++ right_area.y = area.y + mid; ++ right_area.width = area.width; ++ right_area.height= area.height - mid; ++ ++ if (e) { ++ left_area.height -= gappx / 2; ++ right_area.y += gappx / 2; ++ right_area.height -= gappx / 2; ++ } ++ } ++ ++ apply_layout(m, node->left, left_area, 0); ++ apply_layout(m, node->right, right_area, 0); ++} ++ ++void ++btrtile(Monitor *m) ++{ ++ Client *c, *focused = NULL; ++ int n = 0; ++ LayoutNode *found; ++ struct wlr_box full_area; ++ ++ if (!m || !m->root) ++ return; ++ ++ /* Remove non tiled clients from tree. */ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon == m && !c->isfloating && !c->isfullscreen) { ++ } else { ++ remove_client(m, c); ++ } ++ } ++ ++ /* If no client is found under cursor, fallback to focustop(m) */ ++ if (!(focused = xytoclient(cursor->x, cursor->y))) ++ focused = focustop(m); ++ ++ /* Insert visible clients that are not part of the tree. */ ++ wl_list_for_each(c, &clients, link) { ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen && c->mon == m) { ++ found = find_client_node(m->root, c); ++ if (!found) { ++ insert_client(m, focused, c); ++ } ++ n++; ++ } ++ } ++ ++ if (n == 0) ++ return; ++ ++ full_area = m->w; ++ apply_layout(m, m->root, full_area, 1); ++} ++ ++LayoutNode * ++create_client_node(Client *c) ++{ ++ LayoutNode *node = calloc(1, sizeof(LayoutNode)); ++ ++ if (!node) ++ return NULL; ++ node->is_client_node = 1; ++ node->split_ratio = 0.5f; ++ node->client = c; ++ return node; ++} ++ ++LayoutNode * ++create_split_node(unsigned int is_split_vertically, ++ LayoutNode *left, LayoutNode *right) ++{ ++ LayoutNode *node = calloc(1, sizeof(LayoutNode)); ++ ++ if (!node) ++ return NULL; ++ node->is_client_node = 0; ++ node->split_ratio = 0.5f; ++ node->is_split_vertically = is_split_vertically; ++ node->left = left; ++ node->right = right; ++ if (left) ++ left->split_node = node; ++ if (right) ++ right->split_node = node; ++ return node; ++} ++ ++void ++destroy_node(LayoutNode *node) ++{ ++ if (!node) ++ return; ++ if (!node->is_client_node) { ++ destroy_node(node->left); ++ destroy_node(node->right); ++ } ++ free(node); ++} ++ ++void ++destroy_tree(Monitor *m) ++{ ++ if (!m || !m->root) ++ return; ++ destroy_node(m->root); ++ m->root = NULL; ++} ++ ++LayoutNode * ++find_client_node(LayoutNode *node, Client *c) ++{ ++ LayoutNode *res; ++ ++ if (!node || !c) ++ return NULL; ++ if (node->is_client_node) { ++ return (node->client == c) ? node : NULL; ++ } ++ res = find_client_node(node->left, c); ++ return res ? res : find_client_node(node->right, c); ++} ++ ++LayoutNode * ++find_suitable_split(LayoutNode *start_node, unsigned int need_vertical) ++{ ++ LayoutNode *n = start_node; ++ /* if we started from a client node, jump to its parent: */ ++ if (n && n->is_client_node) ++ n = n->split_node; ++ ++ while (n) { ++ if (!n->is_client_node && n->is_split_vertically == need_vertical && ++ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0) ++ return n; ++ n = n->split_node; ++ } ++ return NULL; ++} ++ ++void ++init_tree(Monitor *m) ++{ ++ if (!m) ++ return; ++ m->root = calloc(1, sizeof(LayoutNode)); ++ if (!m->root) ++ m->root = NULL; ++} ++ ++void ++insert_client(Monitor *m, Client *focused_client, Client *new_client) ++{ ++ Client *old_client; ++ LayoutNode **root = &m->root, *old_root, ++ *focused_node, *new_client_node, *old_client_node; ++ unsigned int wider, mid_x, mid_y; ++ ++ /* If no root , new client becomes the root. */ ++ if (!*root) { ++ *root = create_client_node(new_client); ++ return; ++ } ++ ++ /* Find the focused_client node, ++ * if not found split the root. */ ++ focused_node = focused_client ? ++ find_client_node(*root, focused_client) : NULL; ++ if (!focused_node) { ++ old_root = *root; ++ new_client_node = create_client_node(new_client); ++ *root = create_split_node(1, old_root, new_client_node); ++ return; ++ } ++ ++ /* Turn focused node from a client node into a split node, ++ * and attach old_client + new_client. */ ++ old_client = focused_node->client; ++ old_client_node = create_client_node(old_client); ++ new_client_node = create_client_node(new_client); ++ ++ /* Decide split direction. */ ++ wider = (focused_client->geom.width >= focused_client->geom.height); ++ focused_node->is_client_node = 0; ++ focused_node->client = NULL; ++ focused_node->is_split_vertically = (wider ? 1 : 0); ++ ++ /* Pick new_client side depending on the cursor position. */ ++ mid_x = focused_client->geom.x + focused_client->geom.width / 2; ++ mid_y = focused_client->geom.y + focused_client->geom.height / 2; ++ ++ if (wider) { ++ /* vertical split => left vs right */ ++ if (cursor->x <= mid_x) { ++ focused_node->left = new_client_node; ++ focused_node->right = old_client_node; ++ } else { ++ focused_node->left = old_client_node; ++ focused_node->right = new_client_node; ++ } ++ } else { ++ /* horizontal split => top vs bottom */ ++ if (cursor->y <= mid_y) { ++ focused_node->left = new_client_node; ++ focused_node->right = old_client_node; ++ } else { ++ focused_node->left = old_client_node; ++ focused_node->right = new_client_node; ++ } ++ } ++ old_client_node->split_node = focused_node; ++ new_client_node->split_node = focused_node; ++ focused_node->split_ratio = 0.5f; ++} ++ ++LayoutNode * ++remove_client_node(LayoutNode *node, Client *c) ++{ ++ LayoutNode *tmp; ++ if (!node) ++ return NULL; ++ if (node->is_client_node) { ++ /* If this client_node is the client we're removing, ++ * return NULL to remove it */ ++ if (node->client == c) { ++ free(node); ++ return NULL; ++ } ++ return node; ++ } ++ ++ node->left = remove_client_node(node->left, c); ++ node->right = remove_client_node(node->right, c); ++ ++ /* If one of the client node is NULL after removal and the other is not, ++ * we "lift" the other client node up to replace this split node. */ ++ if (!node->left && node->right) { ++ tmp = node->right; ++ ++ /* Save pointer to split node */ ++ if (tmp) ++ tmp->split_node = node->split_node; ++ ++ free(node); ++ return tmp; ++ } ++ ++ if (!node->right && node->left) { ++ tmp = node->left; ++ ++ /* Save pointer to split node */ ++ if (tmp) ++ tmp->split_node = node->split_node; ++ ++ free(node); ++ return tmp; ++ } ++ ++ /* If both children exist or both are NULL (empty tree), ++ * return node as is. */ ++ return node; ++} ++ ++void ++remove_client(Monitor *m, Client *c) ++{ ++ if (!m->root || !c) ++ return; ++ m->root = remove_client_node(m->root, c); ++} ++ ++void ++setratio_h(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ LayoutNode *client_node, *split_node; ++ float new_ratio; ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ ++ client_node = find_client_node(selmon->root, sel); ++ if (!client_node) ++ return; ++ ++ split_node = find_suitable_split(client_node, 1); ++ if (!split_node) ++ return; ++ ++ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f; ++ if (new_ratio < 0.05f) ++ new_ratio = 0.05f; ++ if (new_ratio > 0.95f) ++ new_ratio = 0.95f; ++ split_node->split_ratio = new_ratio; ++ ++ /* Skip the arrange if done resizing by mouse, ++ * we call arrange from motionotify */ ++ if (!resizing_from_mouse) { ++ arrange(selmon); ++ } ++} ++ ++void ++setratio_v(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ LayoutNode *client_node, *split_node; ++ float new_ratio; ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ ++ client_node = find_client_node(selmon->root, sel); ++ if (!client_node) ++ return; ++ ++ split_node = find_suitable_split(client_node, 0); ++ if (!split_node) ++ return; ++ ++ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f; ++ if (new_ratio < 0.05f) ++ new_ratio = 0.05f; ++ if (new_ratio > 0.95f) ++ new_ratio = 0.95f; ++ split_node->split_ratio = new_ratio; ++ ++ /* Skip the arrange if done resizing by mouse, ++ * we call arrange from motionotify */ ++ if (!resizing_from_mouse) { ++ arrange(selmon); ++ } ++} ++ ++void swapclients(const Arg *arg) { ++ Client *c, *tmp, *target = NULL, *sel = focustop(selmon); ++ LayoutNode *sel_node, *target_node; ++ int closest_dist = INT_MAX, dist, sel_center_x, sel_center_y, ++ cand_center_x, cand_center_y; ++ ++ if (!sel || sel->isfullscreen || ++ !selmon->root || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ ++ ++ /* Get the center coordinates of the selected client */ ++ sel_center_x = sel->geom.x + sel->geom.width / 2; ++ sel_center_y = sel->geom.y + sel->geom.height / 2; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, selmon) || c->isfloating || c->isfullscreen || c == sel) ++ continue; ++ ++ /* Get the center of candidate client */ ++ cand_center_x = c->geom.x + c->geom.width / 2; ++ cand_center_y = c->geom.y + c->geom.height / 2; ++ ++ /* Check that the candidate lies in the requested direction. */ ++ switch (arg->ui) { ++ case 0: ++ if (cand_center_x >= sel_center_x) ++ continue; ++ break; ++ case 1: ++ if (cand_center_x <= sel_center_x) ++ continue; ++ break; ++ case 2: ++ if (cand_center_y >= sel_center_y) ++ continue; ++ break; ++ case 3: ++ if (cand_center_y <= sel_center_y) ++ continue; ++ break; ++ default: ++ continue; ++ } ++ ++ /* Get distance between the centers */ ++ dist = abs(sel_center_x - cand_center_x) + abs(sel_center_y - cand_center_y); ++ if (dist < closest_dist) { ++ closest_dist = dist; ++ target = c; ++ } ++ } ++ ++ /* If target is found, swap the two clients’ positions in the layout tree */ ++ if (target) { ++ sel_node = find_client_node(selmon->root, sel); ++ target_node = find_client_node(selmon->root, target); ++ if (sel_node && target_node) { ++ tmp = sel_node->client; ++ sel_node->client = target_node->client; ++ target_node->client = tmp; ++ arrange(selmon); ++ } ++ } ++} ++ ++unsigned int ++visible_count(LayoutNode *node, Monitor *m) ++{ ++ Client *c; ++ ++ if (!node) ++ return 0; ++ /* Check if this client is visible. */ ++ if (node->is_client_node) { ++ c = node->client; ++ if (c && VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ return 1; ++ return 0; ++ } ++ /* Else it’s a split node. */ ++ return visible_count(node->left, m) + visible_count(node->right, m); ++} ++ ++Client * ++xytoclient(double x, double y) { ++ Client *c, *closest = NULL; ++ double dist, mindist = INT_MAX, dx, dy; ++ ++ wl_list_for_each_reverse(c, &clients, link) { ++ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen && ++ x >= c->geom.x && x <= (c->geom.x + c->geom.width) && ++ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){ ++ return c; ++ } ++ } ++ ++ /* If no client was found at cursor position fallback to closest. */ ++ wl_list_for_each_reverse(c, &clients, link) { ++ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) { ++ dx = 0, dy = 0; ++ ++ if (x < c->geom.x) ++ dx = c->geom.x - x; ++ else if (x > (c->geom.x + c->geom.width)) ++ dx = x - (c->geom.x + c->geom.width); ++ ++ if (y < c->geom.y) ++ dy = c->geom.y - y; ++ else if (y > (c->geom.y + c->geom.height)) ++ dy = y - (c->geom.y + c->geom.height); ++ ++ dist = sqrt(dx * dx + dy * dy); ++ if (dist < mindist) { ++ mindist = dist; ++ closest = c; ++ } ++ } ++ } ++ return closest; ++} +diff --git a/config.def.h b/config.def.h +index 22d2171..92f3ad6 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,7 +13,10 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const float resize_factor = 0.0002f; /* Resize multiplier for mouse resizing, depends on mouse sensivity. */ ++static const uint32_t resize_interval_ms = 16; /* Resize interval depends on framerate and screen refresh rate. */ + ++enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN }; + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + +@@ -31,6 +34,7 @@ static const Rule rules[] = { + /* layout(s) */ + static const Layout layouts[] = { + /* symbol arrange function */ ++ { "|w|", btrtile }, + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +@@ -148,6 +152,14 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapclients, {.i = DIR_UP} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapclients, {.i = DIR_DOWN} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapclients, {.i = DIR_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapclients, {.i = DIR_LEFT} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, setratio_h, {.f = +0.025f} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, setratio_h, {.f = -0.025f} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, setratio_v, {.f = -0.025f} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, setratio_v, {.f = +0.025f} }, + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +diff --git a/dwl.c b/dwl.c +index a2711f6..e49a061 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1,6 +1,7 @@ + /* + * See LICENSE file for copyright and license details. + */ ++#include + #include + #include + #include +@@ -103,6 +104,7 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct LayoutNode LayoutNode; + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -139,8 +141,9 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, was_tiled; + uint32_t resize; /* configure serial of a pending resize */ ++ struct wlr_box old_geom; + } Client; + + typedef struct { +@@ -208,6 +211,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ LayoutNode *root; + }; + + typedef struct { +@@ -250,6 +254,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static void btrtile(Monitor *m); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -333,6 +338,9 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); ++static void setratio_h(const Arg *arg); ++static void setratio_v(const Arg *arg); ++static void swapclients(const Arg *arg); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -431,6 +439,7 @@ static xcb_atom_t netatom[NetLast]; + + /* attempt to encapsulate suck into one file */ + #include "client.h" ++#include "btrtile.c" + + /* function implementations */ + void +@@ -601,7 +610,7 @@ buttonpress(struct wl_listener *listener, void *data) + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; + uint32_t mods; +- Client *c; ++ Client *c, *target = NULL; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); +@@ -622,7 +631,7 @@ buttonpress(struct wl_listener *listener, void *data) + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { + if (CLEANMASK(mods) == CLEANMASK(b->mod) && +- event->button == b->button && b->func) { ++ event->button == b->button && b->func) { + b->func(&b->arg); + return; + } +@@ -632,15 +641,36 @@ buttonpress(struct wl_listener *listener, void *data) + /* If you released any buttons, we exit interactive move/resize mode. */ + /* TODO should reset to the pointer focus's current setcursor */ + if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { ++ c = grabc; ++ if (c && c->was_tiled && !strcmp(selmon->ltsymbol, "|w|")) { ++ if (cursor_mode == CurMove && c->isfloating) { ++ target = xytoclient(cursor->x, cursor->y); ++ ++ if (target && !target->isfloating && !target->isfullscreen) ++ insert_client(selmon, target, c); ++ else ++ selmon->root = create_client_node(c); ++ ++ setfloating(c, 0); ++ arrange(selmon); ++ ++ } else if (cursor_mode == CurResize && !c->isfloating) { ++ resizing_from_mouse = 0; ++ } ++ } else { ++ if (cursor_mode == CurResize && resizing_from_mouse) ++ resizing_from_mouse = 0; ++ } ++ /* Default behaviour */ + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + cursor_mode = CurNormal; + /* Drop the window off on its new monitor */ + selmon = xytomon(cursor->x, cursor->y); + setmon(grabc, selmon, 0); ++ grabc = NULL; + return; +- } else { +- cursor_mode = CurNormal; + } ++ cursor_mode = CurNormal; + break; + } + /* If the event wasn't handled by the compositor, notify the client with +@@ -720,6 +750,7 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); + ++ destroy_tree(m); + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); + free(m); +@@ -1024,6 +1055,7 @@ createmon(struct wl_listener *listener, void *data) + + wl_list_insert(&mons, &m->link); + printstatus(); ++ init_tree(m); + + /* The xdg-protocol specifies: + * +@@ -1263,6 +1295,10 @@ destroynotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->destroy.link); + wl_list_remove(&c->set_title.link); + wl_list_remove(&c->fullscreen.link); ++ /* We check if the destroyed client was part of any tiled_list, to catch ++ * client removals even if they would not be currently managed by btrtile */ ++ if (selmon && selmon->root) ++ remove_client(selmon, c); + #ifdef XWAYLAND + if (c->type != XDGShell) { + wl_list_remove(&c->activate.link); +@@ -1809,7 +1845,8 @@ void + motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel) + { +- double sx = 0, sy = 0, sx_confined, sy_confined; ++ int tiled = 0; ++ double sx = 0, sy = 0, sx_confined, sy_confined, dx_total, dy_total; + Client *c = NULL, *w = NULL; + LayerSurface *l = NULL; + struct wlr_surface *surface = NULL; +@@ -1863,18 +1900,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + /* Update drag icon's position */ + wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); + +- /* If we are currently grabbing the mouse, handle and return */ ++ /* Skip if internal call or already resizing */ ++ if (time == 0 && resizing_from_mouse) ++ goto focus; ++ ++ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen; + if (cursor_mode == CurMove) { + /* Move the grabbed client to the new position. */ +- resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, +- .width = grabc->geom.width, .height = grabc->geom.height}, 1); +- return; ++ if (grabc && grabc->isfloating) { ++ resize(grabc, (struct wlr_box){ ++ .x = (int)round(cursor->x) - grabcx, ++ .y = (int)round(cursor->y) - grabcy, ++ .width = grabc->geom.width, ++ .height = grabc->geom.height ++ }, 1); ++ return; ++ } + } else if (cursor_mode == CurResize) { +- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); +- return; ++ if (tiled && resizing_from_mouse) { ++ dx_total = cursor->x - resize_last_update_x; ++ dy_total = cursor->y - resize_last_update_y; ++ ++ if (time - last_resize_time >= resize_interval_ms) { ++ Arg a = {0}; ++ if (fabs(dx_total) > fabs(dy_total)) { ++ a.f = (float)(dx_total * resize_factor); ++ setratio_h(&a); ++ } else { ++ a.f = (float)(dy_total * resize_factor); ++ setratio_v(&a); ++ } ++ arrange(selmon); ++ ++ last_resize_time = time; ++ resize_last_update_x = cursor->x; ++ resize_last_update_y = cursor->y; ++ } ++ ++ } else if (grabc && grabc->isfloating) { ++ /* Floating resize as original */ ++ resize(grabc, (struct wlr_box){ ++ .x = grabc->geom.x, ++ .y = grabc->geom.y, ++ .width = (int)round(cursor->x) - grabc->geom.x, ++ .height = (int)round(cursor->y) - grabc->geom.y ++ }, 1); ++ return; ++ } + } + ++focus: + /* If there's no client surface under the cursor, set the cursor image to a + * default. This is what makes the cursor image appear when you move it + * off of a client or over its border. */ +@@ -1908,22 +1983,41 @@ moveresize(const Arg *arg) + if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) + return; + +- /* Float the window and tell motionnotify to grab it */ +- setfloating(grabc, 1); +- switch (cursor_mode = arg->ui) { +- case CurMove: +- grabcx = (int)round(cursor->x) - grabc->geom.x; +- grabcy = (int)round(cursor->y) - grabc->geom.y; +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); +- break; +- case CurResize: +- /* Doesn't work for X11 output - the next absolute motion event +- * returns the cursor to where it started */ +- wlr_cursor_warp_closest(cursor, NULL, +- grabc->geom.x + grabc->geom.width, +- grabc->geom.y + grabc->geom.height); +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); +- break; ++ cursor_mode = arg->ui; ++ grabc->was_tiled = (!grabc->isfloating && !grabc->isfullscreen); ++ ++ if (grabc->was_tiled) { ++ switch (cursor_mode) { ++ case CurMove: ++ setfloating(grabc, 1); ++ grabcx = (int)round(cursor->x) - grabc->geom.x; ++ grabcy = (int)round(cursor->y) - grabc->geom.y; ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); ++ break; ++ case CurResize: ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); ++ resize_last_update_x = cursor->x; ++ resize_last_update_y = cursor->y; ++ resizing_from_mouse = 1; ++ break; ++ } ++ } else { ++ /* Default floating logic */ ++ /* Float the window and tell motionnotify to grab it */ ++ setfloating(grabc, 1); ++ switch (cursor_mode) { ++ case CurMove: ++ grabcx = (int)round(cursor->x) - grabc->geom.x; ++ grabcy = (int)round(cursor->y) - grabc->geom.y; ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); ++ break; ++ case CurResize: ++ wlr_cursor_warp_closest(cursor, NULL, ++ grabc->geom.x + grabc->geom.width, ++ grabc->geom.y + grabc->geom.height); ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); ++ break; ++ } + } + } + +-- +2.45.3 + diff --git a/dwl/dwl-patches/patches/btrtile/btrtile-v0.7.patch b/dwl/dwl-patches/patches/btrtile/btrtile-v0.7.patch new file mode 100755 index 0000000..b85473e --- /dev/null +++ b/dwl/dwl-patches/patches/btrtile/btrtile-v0.7.patch @@ -0,0 +1,903 @@ +From b9789420f166c20579f29ecd171a8956c681848d Mon Sep 17 00:00:00 2001 +From: julmajustus +Date: Thu, 13 Feb 2025 23:23:40 +0200 +Subject: [PATCH] btrtile with multi-tag support + +--- + btrtile.c | 563 +++++++++++++++++++++++++++++++++++++++++++++++++++ + config.def.h | 12 ++ + dwl.c | 152 +++++++++++--- + 3 files changed, 698 insertions(+), 29 deletions(-) + create mode 100644 btrtile.c + +diff --git a/btrtile.c b/btrtile.c +new file mode 100644 +index 0000000..03f4680 +--- /dev/null ++++ b/btrtile.c +@@ -0,0 +1,563 @@ ++/* ************************************************************************** */ ++/* */ ++/* ::: :::::::: */ ++/* btrtile.c :+: :+: :+: */ ++/* +:+ +:+ +:+ */ ++/* By: jmakkone +#+ +:+ +#+ */ ++/* +#+#+#+#+#+ +#+ */ ++/* Created: 2024/12/15 00:26:07 by jmakkone #+# #+# */ ++/* Updated: 2025/02/13 23:22:33 by jmakkone ### ########.fr */ ++/* */ ++/* ************************************************************************** */ ++ ++typedef struct LayoutNode { ++ unsigned int is_client_node; ++ unsigned int is_split_vertically; ++ float split_ratio; ++ struct LayoutNode *left; ++ struct LayoutNode *right; ++ struct LayoutNode *split_node; ++ Client *client; ++} LayoutNode; ++ ++static void apply_layout(Monitor *m, LayoutNode *node, ++ struct wlr_box area, unsigned int is_root); ++static void btrtile(Monitor *m); ++static LayoutNode *create_client_node(Client *c); ++static LayoutNode *create_split_node(unsigned int is_split_vertically, ++ LayoutNode *left, LayoutNode *right); ++static void destroy_node(LayoutNode *node); ++static void destroy_tree(Monitor *m); ++static LayoutNode *find_client_node(LayoutNode *node, Client *c); ++static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert); ++static void init_tree(Monitor *m); ++static void insert_client(Monitor *m, Client *focused_client, Client *new_client); ++static LayoutNode *remove_client_node(LayoutNode *node, Client *c); ++static void remove_client(Monitor *m, Client *c); ++static void setratio_h(const Arg *arg); ++static void setratio_v(const Arg *arg); ++static void swapclients(const Arg *arg); ++static unsigned int visible_count(LayoutNode *node, Monitor *m); ++static Client *xytoclient(double x, double y); ++ ++static int resizing_from_mouse = 0; ++static double resize_last_update_x, resize_last_update_y; ++static uint32_t last_resize_time = 0; ++ ++void ++apply_layout(Monitor *m, LayoutNode *node, ++ struct wlr_box area, unsigned int is_root) ++{ ++ Client *c; ++ float ratio; ++ unsigned int left_count, right_count, mid; ++ struct wlr_box left_area, right_area; ++ ++ if (!node) ++ return; ++ ++ /* If this node is a client node, check if it is visible. */ ++ if (node->is_client_node) { ++ c = node->client; ++ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ return; ++ resize(c, area, 0); ++ c->old_geom = area; ++ return; ++ } ++ ++ /* For a split node, we see how many visible children are on each side: */ ++ left_count = visible_count(node->left, m); ++ right_count = visible_count(node->right, m); ++ ++ if (left_count == 0 && right_count == 0) { ++ return; ++ } else if (left_count > 0 && right_count == 0) { ++ apply_layout(m, node->left, area, 0); ++ return; ++ } else if (left_count == 0 && right_count > 0) { ++ apply_layout(m, node->right, area, 0); ++ return; ++ } ++ ++ /* If we’re here, we have visible clients in both subtrees. */ ++ ratio = node->split_ratio; ++ if (ratio < 0.05f) ++ ratio = 0.05f; ++ if (ratio > 0.95f) ++ ratio = 0.95f; ++ ++ memset(&left_area, 0, sizeof(left_area)); ++ memset(&right_area, 0, sizeof(right_area)); ++ ++ if (node->is_split_vertically) { ++ mid = (unsigned int)(area.width * ratio); ++ left_area.x = area.x; ++ left_area.y = area.y; ++ left_area.width = mid; ++ left_area.height = area.height; ++ ++ right_area.x = area.x + mid; ++ right_area.y = area.y; ++ right_area.width = area.width - mid; ++ right_area.height = area.height; ++ } else { ++ /* horizontal split */ ++ mid = (unsigned int)(area.height * ratio); ++ left_area.x = area.x; ++ left_area.y = area.y; ++ left_area.width = area.width; ++ left_area.height = mid; ++ ++ right_area.x = area.x; ++ right_area.y = area.y + mid; ++ right_area.width = area.width; ++ right_area.height= area.height - mid; ++ } ++ ++ apply_layout(m, node->left, left_area, 0); ++ apply_layout(m, node->right, right_area, 0); ++} ++ ++void ++btrtile(Monitor *m) ++{ ++ Client *c, *focused = NULL; ++ int n = 0; ++ LayoutNode *found; ++ struct wlr_box full_area; ++ ++ if (!m || !m->root) ++ return; ++ ++ /* Remove non tiled clients from tree. */ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon == m && !c->isfloating && !c->isfullscreen) { ++ } else { ++ remove_client(m, c); ++ } ++ } ++ ++ /* If no client is found under cursor, fallback to focustop(m) */ ++ if (!(focused = xytoclient(cursor->x, cursor->y))) ++ focused = focustop(m); ++ ++ /* Insert visible clients that are not part of the tree. */ ++ wl_list_for_each(c, &clients, link) { ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen && c->mon == m) { ++ found = find_client_node(m->root, c); ++ if (!found) { ++ insert_client(m, focused, c); ++ } ++ n++; ++ } ++ } ++ ++ if (n == 0) ++ return; ++ ++ full_area = m->w; ++ apply_layout(m, m->root, full_area, 1); ++} ++ ++LayoutNode * ++create_client_node(Client *c) ++{ ++ LayoutNode *node = calloc(1, sizeof(LayoutNode)); ++ ++ if (!node) ++ return NULL; ++ node->is_client_node = 1; ++ node->split_ratio = 0.5f; ++ node->client = c; ++ return node; ++} ++ ++LayoutNode * ++create_split_node(unsigned int is_split_vertically, ++ LayoutNode *left, LayoutNode *right) ++{ ++ LayoutNode *node = calloc(1, sizeof(LayoutNode)); ++ ++ if (!node) ++ return NULL; ++ node->is_client_node = 0; ++ node->split_ratio = 0.5f; ++ node->is_split_vertically = is_split_vertically; ++ node->left = left; ++ node->right = right; ++ if (left) ++ left->split_node = node; ++ if (right) ++ right->split_node = node; ++ return node; ++} ++ ++void ++destroy_node(LayoutNode *node) ++{ ++ if (!node) ++ return; ++ if (!node->is_client_node) { ++ destroy_node(node->left); ++ destroy_node(node->right); ++ } ++ free(node); ++} ++ ++void ++destroy_tree(Monitor *m) ++{ ++ if (!m || !m->root) ++ return; ++ destroy_node(m->root); ++ m->root = NULL; ++} ++ ++LayoutNode * ++find_client_node(LayoutNode *node, Client *c) ++{ ++ LayoutNode *res; ++ ++ if (!node || !c) ++ return NULL; ++ if (node->is_client_node) { ++ return (node->client == c) ? node : NULL; ++ } ++ res = find_client_node(node->left, c); ++ return res ? res : find_client_node(node->right, c); ++} ++ ++LayoutNode * ++find_suitable_split(LayoutNode *start_node, unsigned int need_vertical) ++{ ++ LayoutNode *n = start_node; ++ /* if we started from a client node, jump to its parent: */ ++ if (n && n->is_client_node) ++ n = n->split_node; ++ ++ while (n) { ++ if (!n->is_client_node && n->is_split_vertically == need_vertical && ++ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0) ++ return n; ++ n = n->split_node; ++ } ++ return NULL; ++} ++ ++void ++init_tree(Monitor *m) ++{ ++ if (!m) ++ return; ++ m->root = calloc(1, sizeof(LayoutNode)); ++ if (!m->root) ++ m->root = NULL; ++} ++ ++void ++insert_client(Monitor *m, Client *focused_client, Client *new_client) ++{ ++ Client *old_client; ++ LayoutNode **root = &m->root, *old_root, ++ *focused_node, *new_client_node, *old_client_node; ++ unsigned int wider, mid_x, mid_y; ++ ++ /* If no root , new client becomes the root. */ ++ if (!*root) { ++ *root = create_client_node(new_client); ++ return; ++ } ++ ++ /* Find the focused_client node, ++ * if not found split the root. */ ++ focused_node = focused_client ? ++ find_client_node(*root, focused_client) : NULL; ++ if (!focused_node) { ++ old_root = *root; ++ new_client_node = create_client_node(new_client); ++ *root = create_split_node(1, old_root, new_client_node); ++ return; ++ } ++ ++ /* Turn focused node from a client node into a split node, ++ * and attach old_client + new_client. */ ++ old_client = focused_node->client; ++ old_client_node = create_client_node(old_client); ++ new_client_node = create_client_node(new_client); ++ ++ /* Decide split direction. */ ++ wider = (focused_client->geom.width >= focused_client->geom.height); ++ focused_node->is_client_node = 0; ++ focused_node->client = NULL; ++ focused_node->is_split_vertically = (wider ? 1 : 0); ++ ++ /* Pick new_client side depending on the cursor position. */ ++ mid_x = focused_client->geom.x + focused_client->geom.width / 2; ++ mid_y = focused_client->geom.y + focused_client->geom.height / 2; ++ ++ if (wider) { ++ /* vertical split => left vs right */ ++ if (cursor->x <= mid_x) { ++ focused_node->left = new_client_node; ++ focused_node->right = old_client_node; ++ } else { ++ focused_node->left = old_client_node; ++ focused_node->right = new_client_node; ++ } ++ } else { ++ /* horizontal split => top vs bottom */ ++ if (cursor->y <= mid_y) { ++ focused_node->left = new_client_node; ++ focused_node->right = old_client_node; ++ } else { ++ focused_node->left = old_client_node; ++ focused_node->right = new_client_node; ++ } ++ } ++ old_client_node->split_node = focused_node; ++ new_client_node->split_node = focused_node; ++ focused_node->split_ratio = 0.5f; ++} ++ ++LayoutNode * ++remove_client_node(LayoutNode *node, Client *c) ++{ ++ LayoutNode *tmp; ++ if (!node) ++ return NULL; ++ if (node->is_client_node) { ++ /* If this client_node is the client we're removing, ++ * return NULL to remove it */ ++ if (node->client == c) { ++ free(node); ++ return NULL; ++ } ++ return node; ++ } ++ ++ node->left = remove_client_node(node->left, c); ++ node->right = remove_client_node(node->right, c); ++ ++ /* If one of the client node is NULL after removal and the other is not, ++ * we "lift" the other client node up to replace this split node. */ ++ if (!node->left && node->right) { ++ tmp = node->right; ++ ++ /* Save pointer to split node */ ++ if (tmp) ++ tmp->split_node = node->split_node; ++ ++ free(node); ++ return tmp; ++ } ++ ++ if (!node->right && node->left) { ++ tmp = node->left; ++ ++ /* Save pointer to split node */ ++ if (tmp) ++ tmp->split_node = node->split_node; ++ ++ free(node); ++ return tmp; ++ } ++ ++ /* If both children exist or both are NULL (empty tree), ++ * return node as is. */ ++ return node; ++} ++ ++void ++remove_client(Monitor *m, Client *c) ++{ ++ if (!m->root || !c) ++ return; ++ m->root = remove_client_node(m->root, c); ++} ++ ++void ++setratio_h(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ LayoutNode *client_node, *split_node; ++ float new_ratio; ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ ++ client_node = find_client_node(selmon->root, sel); ++ if (!client_node) ++ return; ++ ++ split_node = find_suitable_split(client_node, 1); ++ if (!split_node) ++ return; ++ ++ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f; ++ if (new_ratio < 0.05f) ++ new_ratio = 0.05f; ++ if (new_ratio > 0.95f) ++ new_ratio = 0.95f; ++ split_node->split_ratio = new_ratio; ++ ++ /* Skip the arrange if done resizing by mouse, ++ * we call arrange from motionotify */ ++ if (!resizing_from_mouse) { ++ arrange(selmon); ++ } ++} ++ ++void ++setratio_v(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ LayoutNode *client_node, *split_node; ++ float new_ratio; ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ ++ client_node = find_client_node(selmon->root, sel); ++ if (!client_node) ++ return; ++ ++ split_node = find_suitable_split(client_node, 0); ++ if (!split_node) ++ return; ++ ++ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f; ++ if (new_ratio < 0.05f) ++ new_ratio = 0.05f; ++ if (new_ratio > 0.95f) ++ new_ratio = 0.95f; ++ split_node->split_ratio = new_ratio; ++ ++ /* Skip the arrange if done resizing by mouse, ++ * we call arrange from motionotify */ ++ if (!resizing_from_mouse) { ++ arrange(selmon); ++ } ++} ++ ++void swapclients(const Arg *arg) { ++ Client *c, *tmp, *target = NULL, *sel = focustop(selmon); ++ LayoutNode *sel_node, *target_node; ++ int closest_dist = INT_MAX, dist, sel_center_x, sel_center_y, ++ cand_center_x, cand_center_y; ++ ++ if (!sel || sel->isfullscreen || ++ !selmon->root || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ ++ ++ /* Get the center coordinates of the selected client */ ++ sel_center_x = sel->geom.x + sel->geom.width / 2; ++ sel_center_y = sel->geom.y + sel->geom.height / 2; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, selmon) || c->isfloating || c->isfullscreen || c == sel) ++ continue; ++ ++ /* Get the center of candidate client */ ++ cand_center_x = c->geom.x + c->geom.width / 2; ++ cand_center_y = c->geom.y + c->geom.height / 2; ++ ++ /* Check that the candidate lies in the requested direction. */ ++ switch (arg->ui) { ++ case 0: ++ if (cand_center_x >= sel_center_x) ++ continue; ++ break; ++ case 1: ++ if (cand_center_x <= sel_center_x) ++ continue; ++ break; ++ case 2: ++ if (cand_center_y >= sel_center_y) ++ continue; ++ break; ++ case 3: ++ if (cand_center_y <= sel_center_y) ++ continue; ++ break; ++ default: ++ continue; ++ } ++ ++ /* Get distance between the centers */ ++ dist = abs(sel_center_x - cand_center_x) + abs(sel_center_y - cand_center_y); ++ if (dist < closest_dist) { ++ closest_dist = dist; ++ target = c; ++ } ++ } ++ ++ /* If target is found, swap the two clients’ positions in the layout tree */ ++ if (target) { ++ sel_node = find_client_node(selmon->root, sel); ++ target_node = find_client_node(selmon->root, target); ++ if (sel_node && target_node) { ++ tmp = sel_node->client; ++ sel_node->client = target_node->client; ++ target_node->client = tmp; ++ arrange(selmon); ++ } ++ } ++} ++ ++unsigned int ++visible_count(LayoutNode *node, Monitor *m) ++{ ++ Client *c; ++ ++ if (!node) ++ return 0; ++ /* Check if this client is visible. */ ++ if (node->is_client_node) { ++ c = node->client; ++ if (c && VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ return 1; ++ return 0; ++ } ++ /* Else it’s a split node. */ ++ return visible_count(node->left, m) + visible_count(node->right, m); ++} ++ ++Client * ++xytoclient(double x, double y) { ++ Client *c, *closest = NULL; ++ double dist, mindist = INT_MAX, dx, dy; ++ ++ wl_list_for_each_reverse(c, &clients, link) { ++ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen && ++ x >= c->geom.x && x <= (c->geom.x + c->geom.width) && ++ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){ ++ return c; ++ } ++ } ++ ++ /* If no client was found at cursor position fallback to closest. */ ++ wl_list_for_each_reverse(c, &clients, link) { ++ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) { ++ dx = 0, dy = 0; ++ ++ if (x < c->geom.x) ++ dx = c->geom.x - x; ++ else if (x > (c->geom.x + c->geom.width)) ++ dx = x - (c->geom.x + c->geom.width); ++ ++ if (y < c->geom.y) ++ dy = c->geom.y - y; ++ else if (y > (c->geom.y + c->geom.height)) ++ dy = y - (c->geom.y + c->geom.height); ++ ++ dist = sqrt(dx * dx + dy * dy); ++ if (dist < mindist) { ++ mindist = dist; ++ closest = c; ++ } ++ } ++ } ++ return closest; ++} +diff --git a/config.def.h b/config.def.h +index 22d2171..92f3ad6 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,7 +13,10 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const float resize_factor = 0.0002f; /* Resize multiplier for mouse resizing, depends on mouse sensivity. */ ++static const uint32_t resize_interval_ms = 16; /* Resize interval depends on framerate and screen refresh rate. */ + ++enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN }; + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + +@@ -31,6 +34,7 @@ static const Rule rules[] = { + /* layout(s) */ + static const Layout layouts[] = { + /* symbol arrange function */ ++ { "|w|", btrtile }, + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +@@ -148,6 +152,14 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapclients, {.i = DIR_UP} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapclients, {.i = DIR_DOWN} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapclients, {.i = DIR_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapclients, {.i = DIR_LEFT} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, setratio_h, {.f = +0.025f} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, setratio_h, {.f = -0.025f} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, setratio_v, {.f = -0.025f} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, setratio_v, {.f = +0.025f} }, + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +diff --git a/dwl.c b/dwl.c +index a2711f6..e49a061 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1,6 +1,7 @@ + /* + * See LICENSE file for copyright and license details. + */ ++#include + #include + #include + #include +@@ -103,6 +104,7 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct LayoutNode LayoutNode; + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -139,8 +141,9 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, was_tiled; + uint32_t resize; /* configure serial of a pending resize */ ++ struct wlr_box old_geom; + } Client; + + typedef struct { +@@ -208,6 +211,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ LayoutNode *root; + }; + + typedef struct { +@@ -250,6 +254,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static void btrtile(Monitor *m); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -333,6 +338,9 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); ++static void setratio_h(const Arg *arg); ++static void setratio_v(const Arg *arg); ++static void swapclients(const Arg *arg); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -431,6 +439,7 @@ static xcb_atom_t netatom[NetLast]; + + /* attempt to encapsulate suck into one file */ + #include "client.h" ++#include "btrtile.c" + + /* function implementations */ + void +@@ -601,7 +610,7 @@ buttonpress(struct wl_listener *listener, void *data) + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; + uint32_t mods; +- Client *c; ++ Client *c, *target = NULL; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); +@@ -622,7 +631,7 @@ buttonpress(struct wl_listener *listener, void *data) + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { + if (CLEANMASK(mods) == CLEANMASK(b->mod) && +- event->button == b->button && b->func) { ++ event->button == b->button && b->func) { + b->func(&b->arg); + return; + } +@@ -632,15 +641,36 @@ buttonpress(struct wl_listener *listener, void *data) + /* If you released any buttons, we exit interactive move/resize mode. */ + /* TODO should reset to the pointer focus's current setcursor */ + if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { ++ c = grabc; ++ if (c && c->was_tiled && !strcmp(selmon->ltsymbol, "|w|")) { ++ if (cursor_mode == CurMove && c->isfloating) { ++ target = xytoclient(cursor->x, cursor->y); ++ ++ if (target && !target->isfloating && !target->isfullscreen) ++ insert_client(selmon, target, c); ++ else ++ selmon->root = create_client_node(c); ++ ++ setfloating(c, 0); ++ arrange(selmon); ++ ++ } else if (cursor_mode == CurResize && !c->isfloating) { ++ resizing_from_mouse = 0; ++ } ++ } else { ++ if (cursor_mode == CurResize && resizing_from_mouse) ++ resizing_from_mouse = 0; ++ } ++ /* Default behaviour */ + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + cursor_mode = CurNormal; + /* Drop the window off on its new monitor */ + selmon = xytomon(cursor->x, cursor->y); + setmon(grabc, selmon, 0); ++ grabc = NULL; + return; +- } else { +- cursor_mode = CurNormal; + } ++ cursor_mode = CurNormal; + break; + } + /* If the event wasn't handled by the compositor, notify the client with +@@ -720,6 +750,7 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); + ++ destroy_tree(m); + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); + free(m); +@@ -1024,6 +1055,7 @@ createmon(struct wl_listener *listener, void *data) + + wl_list_insert(&mons, &m->link); + printstatus(); ++ init_tree(m); + + /* The xdg-protocol specifies: + * +@@ -1263,6 +1295,10 @@ destroynotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->destroy.link); + wl_list_remove(&c->set_title.link); + wl_list_remove(&c->fullscreen.link); ++ /* We check if the destroyed client was part of any tiled_list, to catch ++ * client removals even if they would not be currently managed by btrtile */ ++ if (selmon && selmon->root) ++ remove_client(selmon, c); + #ifdef XWAYLAND + if (c->type != XDGShell) { + wl_list_remove(&c->activate.link); +@@ -1809,7 +1845,8 @@ void + motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel) + { +- double sx = 0, sy = 0, sx_confined, sy_confined; ++ int tiled = 0; ++ double sx = 0, sy = 0, sx_confined, sy_confined, dx_total, dy_total; + Client *c = NULL, *w = NULL; + LayerSurface *l = NULL; + struct wlr_surface *surface = NULL; +@@ -1863,18 +1900,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + /* Update drag icon's position */ + wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); + +- /* If we are currently grabbing the mouse, handle and return */ ++ /* Skip if internal call or already resizing */ ++ if (time == 0 && resizing_from_mouse) ++ goto focus; ++ ++ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen; + if (cursor_mode == CurMove) { + /* Move the grabbed client to the new position. */ +- resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, +- .width = grabc->geom.width, .height = grabc->geom.height}, 1); +- return; ++ if (grabc && grabc->isfloating) { ++ resize(grabc, (struct wlr_box){ ++ .x = (int)round(cursor->x) - grabcx, ++ .y = (int)round(cursor->y) - grabcy, ++ .width = grabc->geom.width, ++ .height = grabc->geom.height ++ }, 1); ++ return; ++ } + } else if (cursor_mode == CurResize) { +- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); +- return; ++ if (tiled && resizing_from_mouse) { ++ dx_total = cursor->x - resize_last_update_x; ++ dy_total = cursor->y - resize_last_update_y; ++ ++ if (time - last_resize_time >= resize_interval_ms) { ++ Arg a = {0}; ++ if (fabs(dx_total) > fabs(dy_total)) { ++ a.f = (float)(dx_total * resize_factor); ++ setratio_h(&a); ++ } else { ++ a.f = (float)(dy_total * resize_factor); ++ setratio_v(&a); ++ } ++ arrange(selmon); ++ ++ last_resize_time = time; ++ resize_last_update_x = cursor->x; ++ resize_last_update_y = cursor->y; ++ } ++ ++ } else if (grabc && grabc->isfloating) { ++ /* Floating resize as original */ ++ resize(grabc, (struct wlr_box){ ++ .x = grabc->geom.x, ++ .y = grabc->geom.y, ++ .width = (int)round(cursor->x) - grabc->geom.x, ++ .height = (int)round(cursor->y) - grabc->geom.y ++ }, 1); ++ return; ++ } + } + ++focus: + /* If there's no client surface under the cursor, set the cursor image to a + * default. This is what makes the cursor image appear when you move it + * off of a client or over its border. */ +@@ -1908,22 +1983,41 @@ moveresize(const Arg *arg) + if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) + return; + +- /* Float the window and tell motionnotify to grab it */ +- setfloating(grabc, 1); +- switch (cursor_mode = arg->ui) { +- case CurMove: +- grabcx = (int)round(cursor->x) - grabc->geom.x; +- grabcy = (int)round(cursor->y) - grabc->geom.y; +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); +- break; +- case CurResize: +- /* Doesn't work for X11 output - the next absolute motion event +- * returns the cursor to where it started */ +- wlr_cursor_warp_closest(cursor, NULL, +- grabc->geom.x + grabc->geom.width, +- grabc->geom.y + grabc->geom.height); +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); +- break; ++ cursor_mode = arg->ui; ++ grabc->was_tiled = (!grabc->isfloating && !grabc->isfullscreen); ++ ++ if (grabc->was_tiled) { ++ switch (cursor_mode) { ++ case CurMove: ++ setfloating(grabc, 1); ++ grabcx = (int)round(cursor->x) - grabc->geom.x; ++ grabcy = (int)round(cursor->y) - grabc->geom.y; ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); ++ break; ++ case CurResize: ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); ++ resize_last_update_x = cursor->x; ++ resize_last_update_y = cursor->y; ++ resizing_from_mouse = 1; ++ break; ++ } ++ } else { ++ /* Default floating logic */ ++ /* Float the window and tell motionnotify to grab it */ ++ setfloating(grabc, 1); ++ switch (cursor_mode) { ++ case CurMove: ++ grabcx = (int)round(cursor->x) - grabc->geom.x; ++ grabcy = (int)round(cursor->y) - grabc->geom.y; ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); ++ break; ++ case CurResize: ++ wlr_cursor_warp_closest(cursor, NULL, ++ grabc->geom.x + grabc->geom.width, ++ grabc->geom.y + grabc->geom.height); ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); ++ break; ++ } + } + } + +-- +2.45.3 + diff --git a/dwl/dwl-patches/patches/buttonbystate/README.md b/dwl/dwl-patches/patches/buttonbystate/README.md new file mode 100755 index 0000000..cbb0eee --- /dev/null +++ b/dwl/dwl-patches/patches/buttonbystate/README.md @@ -0,0 +1,10 @@ +### Description +Adds "state" (`enum wlr_button_state`) to configure a button action on either press or release. +This basically enables release to be used for button actions. + +### Download +- [git branch](https://codeberg.org/nullsystem/dwl/src/branch/main_buttonbystate) +- [2024-04-06](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/buttonbystate/buttonbystate.patch) + +### Authors +- [nullsystem](https://codeberg.org/nullsystem) diff --git a/dwl/dwl-patches/patches/buttonbystate/buttonbystate.patch b/dwl/dwl-patches/patches/buttonbystate/buttonbystate.patch new file mode 100755 index 0000000..d669aff --- /dev/null +++ b/dwl/dwl-patches/patches/buttonbystate/buttonbystate.patch @@ -0,0 +1,78 @@ +From 4141aa9455e4b4a5b4a235475c70e8c100ec663e Mon Sep 17 00:00:00 2001 +From: nullsystem +Date: Sat, 6 Apr 2024 02:03:49 +0100 +Subject: [PATCH] buttonbystate - allow config for release (and press) + +- Adds "state" (enum wlr_button_state) to configure a button action on + either press or release. This basically enables release to be used + for button actions. +--- + config.def.h | 6 +++--- + dwl.c | 22 ++++++++++++---------- + 2 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 8847e58..cc989cf 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -165,7 +165,7 @@ static const Key keys[] = { + }; + + static const Button buttons[] = { +- { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, +- { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove}, WLR_BUTTON_PRESSED }, ++ { MODKEY, BTN_MIDDLE, togglefloating, {0}, WLR_BUTTON_PRESSED }, ++ { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize}, WLR_BUTTON_PRESSED }, + }; +diff --git a/dwl.c b/dwl.c +index bf763df..6b60ccf 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -99,6 +99,7 @@ typedef struct { + unsigned int button; + void (*func)(const Arg *); + const Arg arg; ++ enum wlr_button_state state; + } Button; + + typedef struct Monitor Monitor; +@@ -595,16 +596,6 @@ buttonpress(struct wl_listener *listener, void *data) + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); + if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); +- +- keyboard = wlr_seat_get_keyboard(seat); +- mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; +- for (b = buttons; b < END(buttons); b++) { +- if (CLEANMASK(mods) == CLEANMASK(b->mod) && +- event->button == b->button && b->func) { +- b->func(&b->arg); +- return; +- } +- } + break; + case WLR_BUTTON_RELEASED: + held_grab = NULL; +@@ -622,6 +613,17 @@ buttonpress(struct wl_listener *listener, void *data) + } + break; + } ++ ++ keyboard = wlr_seat_get_keyboard(seat); ++ mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; ++ for (b = buttons; b < END(buttons); b++) { ++ if (b->state == event->state && CLEANMASK(mods) == CLEANMASK(b->mod) && ++ event->button == b->button && b->func) { ++ b->func(&b->arg); ++ return; ++ } ++ } ++ + /* If the event wasn't handled by the compositor, notify the client with + * pointer focus that a button press has occurred */ + wlr_seat_pointer_notify_button(seat, +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/center-terminal/README.md b/dwl/dwl-patches/patches/center-terminal/README.md new file mode 100755 index 0000000..cfd70a2 --- /dev/null +++ b/dwl/dwl-patches/patches/center-terminal/README.md @@ -0,0 +1,13 @@ +### Description +Add a keybinding that toggles centering the terminally horizontally when +it's the only window, while still tiling multiple windows. + +This limits the width of long text making it easier to read, and avoids +covering the wallpaper more than necessary. + +### Download +- [git branch](https://codeberg.org/guidocella/dwl/src/branch/center-terminal) +- [2024-02-06](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/center-terminal/center-terminal.patch) + +### Authors +- [Guido Cella](https://codeberg.org/guidocella) diff --git a/dwl/dwl-patches/patches/center-terminal/center-terminal.patch b/dwl/dwl-patches/patches/center-terminal/center-terminal.patch new file mode 100755 index 0000000..214eaf2 --- /dev/null +++ b/dwl/dwl-patches/patches/center-terminal/center-terminal.patch @@ -0,0 +1,103 @@ +From 340cc5ef90dfcc495bdad045f3f76ae07405cffd Mon Sep 17 00:00:00 2001 +From: Guido Cella +Date: Tue, 6 Feb 2024 09:20:48 +0100 +Subject: [PATCH] add a keybinding to center the terminal + +Add a keybinding that toggles centering the terminally horizontally when +it's the only window, while still tiling multiple windows. + +This limits the width of long text making it easier to read, and avoids +covering the wallpaper more than necessary. +--- + config.def.h | 1 + + dwl.c | 20 ++++++++++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..8229fcc 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -142,6 +142,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_v, togglecenter, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index 12f441e..3b15748 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -138,6 +139,7 @@ typedef struct { + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; ++ bool centered; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -334,6 +336,7 @@ static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void togglecenter(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -436,6 +439,8 @@ static struct wl_listener request_start_drag = {.notify = requeststartdrag}; + static struct wl_listener start_drag = {.notify = startdrag}; + static struct wl_listener new_session_lock = {.notify = locksession}; + ++static bool center; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -499,6 +504,9 @@ applyrules(Client *c) + } + } + ++ if (!strcasecmp(appid, termcmd[0])) ++ c->centered = true; ++ + c->isfloating |= client_is_float_type(c); + setmon(c, mon, newtags); + } +@@ -2730,6 +2738,11 @@ tile(Monitor *m) + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { ++ if (n == 1 && center && c->centered) { ++ resize(c, (struct wlr_box){.x = m->w.width / 4, .y = m->w.y, ++ .width = m->w.width / 2, .height = m->w.height - 2 * c->bw}, 0); ++ return; ++ } + resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, + .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); + my += c->geom.height; +@@ -2742,6 +2755,13 @@ tile(Monitor *m) + } + } + ++void ++togglecenter(const Arg *arg) ++{ ++ center = !center; ++ tile(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/centeredmaster/README.md b/dwl/dwl-patches/patches/centeredmaster/README.md new file mode 100755 index 0000000..2ba6dd9 --- /dev/null +++ b/dwl/dwl-patches/patches/centeredmaster/README.md @@ -0,0 +1,33 @@ +### Description +This is a port of centeredmaster patch for dwm: + +centeredmaster centers the nmaster area on screen, using mfact * monitor +width & height, with the stacked windows distributed to the left and +right. It can be selected with `Alt+c`. + +With one and two clients in master respectively this results in: + +``` ++------------------------------+ +------------------------------+ +|+--------++--------++--------+| |+--------++--------++--------+| +|| || || || || || || || +|| || || || || || M1 || || +|| || || || || || || || +|| S2 || M || S1 || || |+--------+| || +|| || || || || |+--------+| || +|| || || || || || || || +|| || || || || || M2 || || +|| || || || || || || || +|+--------++--------++--------+| |+--------++--------++--------+| ++------------------------------+ +------------------------------+ +``` + + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/centeredmaster/centeredmaster.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/b104a580a80ebaf9f7e8917fe574e3e97ddd019a/centeredmaster/centeredmaster.patch) +- [0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/0f4e40fee49d1b8b430778e241b29496ae3b3b70/centeredmaster/centeredmaster.patch) + +### Authors +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/centeredmaster/centeredmaster.patch b/dwl/dwl-patches/patches/centeredmaster/centeredmaster.patch new file mode 100755 index 0000000..c29bd5f --- /dev/null +++ b/dwl/dwl-patches/patches/centeredmaster/centeredmaster.patch @@ -0,0 +1,135 @@ +From b1ca46930756b59c1ebba0b8c7871b85ff84f62f Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Sat, 8 Feb 2025 16:10:25 +0100 +Subject: [PATCH] Add centeredmaster layout + +This is a port of centeredmaster patch for dwm: + https://dwm.suckless.org/patches/centeredmaster + +centeredmaster centers the nmaster area on screen, using mfact * monitor +width & height, with the stacked windows distributed to the left and +right. It can be selected with [Alt]+[c]. + +With one and two clients in master respectively this results in: + ++------------------------------+ +------------------------------+ +|+--------++--------++--------+| |+--------++--------++--------+| +|| || || || || || || || +|| || || || || || M1 || || +|| || || || || || || || +|| S2 || M || S1 || || |+--------+| || +|| || || || || |+--------+| || +|| || || || || || || || +|| || || || || || M2 || || +|| || || || || || || || +|+--------++--------++--------+| |+--------++--------++--------+| ++------------------------------+ +------------------------------+ +--- + config.def.h | 2 ++ + dwl.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 65 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..9a3b0c5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "|M|", centeredmaster }, + }; + + /* monitors */ +@@ -139,6 +140,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index def2562..c2456dd 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -251,6 +251,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); ++static void centeredmaster(Monitor *m); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); + static void cleanup(void); +@@ -649,6 +650,68 @@ buttonpress(struct wl_listener *listener, void *data) + event->time_msec, event->button, event->state); + } + ++void ++centeredmaster(Monitor *m) ++{ ++ int i, n, h, mw, mx, my, oty, ety, tw; ++ Client *c; ++ ++ n = 0; ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ if (n == 0) ++ return; ++ ++ /* initialize areas */ ++ mw = m->w.width; ++ mx = 0; ++ my = 0; ++ tw = mw; ++ ++ if (n > m->nmaster) { ++ /* go mfact box in the center if more than nmaster clients */ ++ mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; ++ tw = m->w.width - mw; ++ ++ if (n - m->nmaster > 1) { ++ /* only one client */ ++ mx = (m->w.width - mw) / 2; ++ tw = (m->w.width - mw) / 2; ++ } ++ } ++ ++ i = 0; ++ oty = 0; ++ ety = 0; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (i < m->nmaster) { ++ /* nmaster clients are stacked vertically, in the center ++ * of the screen */ ++ h = (m->w.height - my) / (MIN(n, m->nmaster) - i); ++ resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y + my, .width = mw, ++ .height = h}, 0); ++ my += c->geom.height; ++ } else { ++ /* stack clients are stacked vertically */ ++ if ((i - m->nmaster) % 2) { ++ h = (m->w.height - ety) / ( (1 + n - i) / 2); ++ resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ety, .width = tw, ++ .height = h}, 0); ++ ety += c->geom.height; ++ } else { ++ h = (m->w.height - oty) / ((1 + n - i) / 2); ++ resize(c, (struct wlr_box){.x = m->w.x + mx + mw, .y = m->w.y + oty, .width = tw, ++ .height = h}, 0); ++ oty += c->geom.height; ++ } ++ } ++ i++; ++ } ++} ++ + void + chvt(const Arg *arg) + { +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/cfact-snail/README.md b/dwl/dwl-patches/patches/cfact-snail/README.md new file mode 100755 index 0000000..488ab98 --- /dev/null +++ b/dwl/dwl-patches/patches/cfact-snail/README.md @@ -0,0 +1,13 @@ +### Description +This patch implements [cfact][cfact] for [snail][snail] layout. +This patch must be applied on top of cfact and snail patches. + +[cfact]: /dwl/dwl-patches/src/branch/main/patches/cfact +[snail]: /dwl/dwl-patches/src/branch/main/patches/snail + + +### Download + - [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact-snail/cfact-snail.patch) + +### Authors +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) diff --git a/dwl/dwl-patches/patches/cfact-snail/cfact-snail.patch b/dwl/dwl-patches/patches/cfact-snail/cfact-snail.patch new file mode 100755 index 0000000..213c3fd --- /dev/null +++ b/dwl/dwl-patches/patches/cfact-snail/cfact-snail.patch @@ -0,0 +1,68 @@ +From 9f8109182a7d173d2a2cb30c089a7e7b9ffe0a5e Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Tue, 25 Mar 2025 02:24:32 +0100 +Subject: [PATCH] cfact patch for snail layout + +--- + dwl.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 4f8c493..37aa935 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2699,10 +2699,10 @@ snail(Monitor *m) + * Split the previous horizontally and put the current window on the right + */ + } else if (dir == WLR_DIRECTION_RIGHT) { +- c->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; ++ c->geom = (struct wlr_box){.x = prev->geom.x + (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.width), .y = prev->geom.y, ++ .width = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.width), .height = prev->geom.height}; + prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; ++ .width = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.width), .height = prev->geom.height}; + /* + * If it's a stack window or the first narrow window in the master + * area, put the next one below it +@@ -2713,28 +2713,28 @@ snail(Monitor *m) + * Split the previous vertically and put the current window below it + */ + } else if (dir == WLR_DIRECTION_DOWN) { +- c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2, +- .width = prev->geom.width, .height = prev->geom.height / 2}; ++ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.height), ++ .width = prev->geom.width, .height = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.height)}; + prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width, .height = prev->geom.height / 2}; ++ .width = prev->geom.width, .height = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.height)}; + dir = WLR_DIRECTION_LEFT; + /* + * Split the previous horizontally and put the current window on the left + */ + } else if (dir == WLR_DIRECTION_LEFT) { + c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; +- prev->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; ++ .width = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.width), .height = prev->geom.height}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x + (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.width), .y = prev->geom.y, ++ .width = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.width), .height = prev->geom.height}; + dir = WLR_DIRECTION_UP; + /* + * Split the previous vertically and put the current window above it + */ + } else { + c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width, .height = prev->geom.height / 2}; +- prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2, +- .width = prev->geom.width, .height = prev->geom.height / 2}; ++ .width = prev->geom.width, .height = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.height)}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.height), ++ .width = prev->geom.width, .height = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.height)}; + dir = WLR_DIRECTION_RIGHT; + } + i++; +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/cfact/README.md b/dwl/dwl-patches/patches/cfact/README.md new file mode 100755 index 0000000..166b4e2 --- /dev/null +++ b/dwl/dwl-patches/patches/cfact/README.md @@ -0,0 +1,25 @@ +### Description +A port of the [dwm cfacts patch](https://dwm.suckless.org/patches/cfacts/) (with the limits removed) + +Clients with higher weight are allocated more space! +``` ++---------------------+ +| | 0.5 | +| 1.0 +----------+ ++----------+ | +| | 1.0 | +| +----------+ +| 2.0 | | +| | 1.0 | ++----------+----------+` +``` +### Download +- [git branch](https://codeberg.org/Palanix/dwl/src/branch/cfact) +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact-v0.7.patch) +- [v0.7-gaps](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact-v0.7-gaps.patch) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact-v0.6.patch) +- [2024-02-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact.patch) + +### Authors +- [dev-gm](https://codeberg.org/dev-gm) +- [Palanix](https://codeberg.org/Palanix) diff --git a/dwl/dwl-patches/patches/cfact/cfact-v0.6.patch b/dwl/dwl-patches/patches/cfact/cfact-v0.6.patch new file mode 100755 index 0000000..c1505fb --- /dev/null +++ b/dwl/dwl-patches/patches/cfact/cfact-v0.6.patch @@ -0,0 +1,121 @@ +From 52d8ed5ece7c96ea02441faaa4da2b0f51c8ebc4 Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 24 Nov 2023 21:16:56 +0100 +Subject: [PATCH] cweights to allow different size clients in normal layouts + +--- + config.def.h | 3 +++ + dwl.c | 32 ++++++++++++++++++++++++++++++-- + 2 files changed, 33 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..d1bc596 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -133,6 +133,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index 145fd01..68e35d2 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -140,6 +140,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ float cweight; + } Client; + + typedef struct { +@@ -318,6 +319,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void setcfact(const Arg *arg); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -1041,6 +1043,7 @@ createnotify(struct wl_listener *listener, void *data) + c = xdg_surface->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = xdg_surface; + c->bw = borderpx; ++ c->cweight = 1.0; + + wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); +@@ -2218,6 +2221,19 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++void ++setcfact(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ ++ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0); ++ if (sel->cweight < 0) ++ sel->cweight = 0; ++ arrange(selmon); ++} ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2637,6 +2653,7 @@ tile(Monitor *m) + { + unsigned int mw, my, ty; + int i, n = 0; ++ float mweight = 0, tweight = 0; + Client *c; + + wl_list_for_each(c, &clients, link) +@@ -2649,17 +2666,27 @@ tile(Monitor *m) + mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; + else + mw = m->w.width; ++ i = 0; ++ wl_list_for_each(c, &clients, link){ ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (i < m->nmaster) ++ mweight += c->cweight; ++ else ++ tweight += c->cweight; ++ i++; ++ } + i = my = ty = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { + resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); ++ .height = (int) ((c->cweight / mweight) * m->w.height)}, 0); + my += c->geom.height; + } else { + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); ++ .width = m->w.width - mw, .height = (int) ((c->cweight / tweight) * m->w.height) }, 0); + ty += c->geom.height; + } + i++; +@@ -3047,6 +3074,7 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; ++ c->cweight = 1.0; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/cfact/cfact-v0.7-gaps.patch b/dwl/dwl-patches/patches/cfact/cfact-v0.7-gaps.patch new file mode 100755 index 0000000..e080238 --- /dev/null +++ b/dwl/dwl-patches/patches/cfact/cfact-v0.7-gaps.patch @@ -0,0 +1,155 @@ +From 31d0ceb3f7dea83282e61e556d71d06b7f43d753 Mon Sep 17 00:00:00 2001 +From: Gavin M +Date: Sat, 16 Nov 2024 08:47:02 -0500 +Subject: [PATCH] Add cfact to gaps + +--- + config.def.h | 3 +++ + dwl.c | 63 +++++++++++++++++++++++++++++++++++++++++----------- + 2 files changed, 53 insertions(+), 13 deletions(-) + +diff --git a/config.def.h b/config.def.h +index b388b4e..a871364 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -136,6 +136,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY, XKB_KEY_g, togglegaps, {0} }, +diff --git a/dwl.c b/dwl.c +index dc851df..b5313c1 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -140,6 +140,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ float cweight; + } Client; + + typedef struct { +@@ -319,6 +320,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void setcfact(const Arg *arg); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -1045,6 +1047,7 @@ createnotify(struct wl_listener *listener, void *data) + c = xdg_surface->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = xdg_surface; + c->bw = borderpx; ++ c->cweight = 1.0; + + wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); +@@ -2223,6 +2226,19 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++void ++setcfact(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ ++ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0); ++ if (sel->cweight < 0) ++ sel->cweight = 0; ++ arrange(selmon); ++} ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2642,38 +2658,58 @@ tagmon(const Arg *arg) + void + tile(Monitor *m) + { +- unsigned int h, r, e = m->gaps, mw, my, ty; ++ unsigned int e = m->gaps, mw, my, ty; + int i, n = 0; +- Client *c; ++ float mweight = 0, tweight = 0; ++ Client *c, *sel = NULL; ++ ++ wl_list_for_each(c, &fstack, flink) { ++ if (VISIBLEON(c, m) && !c->isfullscreen) { ++ if (!sel) ++ sel = c; ++ if (!c->isfloating) ++ n++; ++ } ++ } + +- wl_list_for_each(c, &clients, link) +- if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) +- n++; + if (n == 0) + return; ++ + if (smartgaps == n) + e = 0; + + if (n > m->nmaster) + mw = m->nmaster ? (int)roundf((m->w.width + gappx*e) * m->mfact) : 0; + else +- mw = m->w.width; ++ mw = m->w.width - gappx*e; ++ ++ i = 0; ++ wl_list_for_each(c, &clients, link){ ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (i < m->nmaster) ++ mweight += c->cweight; ++ else ++ tweight += c->cweight; ++ i++; ++ } ++ + i = 0; + my = ty = gappx*e; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- r = MIN(n, m->nmaster) - i; +- h = (m->w.height - my - gappx*e - gappx*e * (r - 1)) / r; + resize(c, (struct wlr_box){.x = m->w.x + gappx*e, .y = m->w.y + my, +- .width = mw - 2*gappx*e, .height = h}, 0); ++ .width = mw - gappx*e, ++ .height = (int)((c->cweight / mweight) * (float)(m->w.height - gappx*e)) - gappx*e ++ }, 0); + my += c->geom.height + gappx*e; + } else { +- r = n - i; +- h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r; +- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw - gappx*e, .height = h}, 0); ++ resize(c, (struct wlr_box){.x = m->w.x + mw + gappx*e, .y = m->w.y + ty, ++ .width = m->w.width - mw - 2*gappx*e, ++ .height = (int)((c->cweight / tweight) * (float)(m->w.height - gappx*e)) - gappx*e ++ }, 0); + ty += c->geom.height + gappx*e; + } + i++; +@@ -3068,6 +3104,7 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; ++ c->cweight = 1.0; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +-- +2.47.0 + diff --git a/dwl/dwl-patches/patches/cfact/cfact-v0.7.patch b/dwl/dwl-patches/patches/cfact/cfact-v0.7.patch new file mode 100755 index 0000000..7d28a8b --- /dev/null +++ b/dwl/dwl-patches/patches/cfact/cfact-v0.7.patch @@ -0,0 +1,121 @@ +From e82e15860c36a70539625b8fe7b4bd54d0721705 Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 24 Nov 2023 21:16:56 +0100 +Subject: [PATCH] cweights to allow different size clients in normal layouts + +--- + config.def.h | 3 +++ + dwl.c | 32 ++++++++++++++++++++++++++++++-- + 2 files changed, 33 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..d1bc596 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -133,6 +133,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index 5bf995e..5a17343 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -141,6 +141,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ float cweight; + } Client; + + typedef struct { +@@ -322,6 +323,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void setcfact(const Arg *arg); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -1060,6 +1062,7 @@ createnotify(struct wl_listener *listener, void *data) + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; ++ c->cweight = 1.0; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); +@@ -2268,6 +2271,19 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++void ++setcfact(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ ++ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0); ++ if (sel->cweight < 0) ++ sel->cweight = 0; ++ arrange(selmon); ++} ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2692,6 +2708,7 @@ tile(Monitor *m) + { + unsigned int mw, my, ty; + int i, n = 0; ++ float mweight = 0, tweight = 0; + Client *c; + + wl_list_for_each(c, &clients, link) +@@ -2704,17 +2721,27 @@ tile(Monitor *m) + mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; + else + mw = m->w.width; ++ i = 0; ++ wl_list_for_each(c, &clients, link){ ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (i < m->nmaster) ++ mweight += c->cweight; ++ else ++ tweight += c->cweight; ++ i++; ++ } + i = my = ty = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { + resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); ++ .height = (int) ((c->cweight / mweight) * m->w.height)}, 0); + my += c->geom.height; + } else { + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); ++ .width = m->w.width - mw, .height = (int) ((c->cweight / tweight) * m->w.height) }, 0); + ty += c->geom.height; + } + i++; +@@ -3102,6 +3129,7 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; ++ c->cweight = 1.0; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/cfact/cfact.patch b/dwl/dwl-patches/patches/cfact/cfact.patch new file mode 100755 index 0000000..c91d3c0 --- /dev/null +++ b/dwl/dwl-patches/patches/cfact/cfact.patch @@ -0,0 +1,121 @@ +From 98fe302cd240b519c28c886250273854844ab2c7 Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 24 Nov 2023 21:16:56 +0100 +Subject: [PATCH] cweights to allow different size clients in normal layouts + +--- + config.def.h | 3 +++ + dwl.c | 32 ++++++++++++++++++++++++++++++-- + 2 files changed, 33 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9009517..27ff521 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -128,6 +128,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index fa76db2..9bdb438 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -136,6 +136,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ float cweight; + } Client; + + typedef struct { +@@ -301,6 +302,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void setcfact(const Arg *arg); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -956,6 +958,7 @@ createnotify(struct wl_listener *listener, void *data) + c = xdg_surface->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = xdg_surface; + c->bw = borderpx; ++ c->cweight = 1.0; + + wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); +@@ -2009,6 +2012,19 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++void ++setcfact(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ ++ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0); ++ if (sel->cweight < 0) ++ sel->cweight = 0; ++ arrange(selmon); ++} ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2468,6 +2484,7 @@ tile(Monitor *m) + { + unsigned int mw, my, ty; + int i, n = 0; ++ float mweight = 0, tweight = 0; + Client *c; + + wl_list_for_each(c, &clients, link) +@@ -2480,17 +2497,27 @@ tile(Monitor *m) + mw = m->nmaster ? ROUND(m->w.width * m->mfact) : 0; + else + mw = m->w.width; ++ i = 0; ++ wl_list_for_each(c, &clients, link){ ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (i < m->nmaster) ++ mweight += c->cweight; ++ else ++ tweight += c->cweight; ++ i++; ++ } + i = my = ty = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { + resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); ++ .height = (int) ((c->cweight / mweight) * m->w.height)}, 0); + my += c->geom.height; + } else { + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); ++ .width = m->w.width - mw, .height = (int) ((c->cweight / tweight) * m->w.height) }, 0); + ty += c->geom.height; + } + i++; +@@ -2872,6 +2899,7 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = borderpx; ++ c->cweight = 1.0; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +-- +2.43.1 + diff --git a/dwl/dwl-patches/patches/chainkeys/README.md b/dwl/dwl-patches/patches/chainkeys/README.md new file mode 100755 index 0000000..fa6d185 --- /dev/null +++ b/dwl/dwl-patches/patches/chainkeys/README.md @@ -0,0 +1,15 @@ +### Description +Implements chained keybindings (like the dwm +[keychain](https://dwm.suckless.org/patches/keychain/) patch). + +Bindings can share a leading chain key. This chain key will be triggered when +Mod+chain is pressed. A subsequent keypress will be matched against bindings +for that chain key. If it is configured the action will be triggered, otherwise +the keypress will be ignored. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/chainkeys) +- [2024-05-20](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/chainkeys/chainkeys.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) diff --git a/dwl/dwl-patches/patches/chainkeys/chainkeys.patch b/dwl/dwl-patches/patches/chainkeys/chainkeys.patch new file mode 100755 index 0000000..a0daefd --- /dev/null +++ b/dwl/dwl-patches/patches/chainkeys/chainkeys.patch @@ -0,0 +1,157 @@ +From 226e204ec7fb6d6840a984ef8e8ec1d2514e985f Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Tue, 2 Jan 2024 10:33:59 +1000 +Subject: [PATCH] chainkeys + +--- + config.def.h | 62 ++++++++++++++++++++++++++-------------------------- + dwl.c | 23 ++++++++++++++++++- + 2 files changed, 53 insertions(+), 32 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 8f498d2f..1c182547 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -105,10 +105,10 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + #define MODKEY WLR_MODIFIER_ALT + + #define TAGKEYS(KEY,SKEY,TAG) \ +- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } ++ { MODKEY, -1, KEY, view, {.ui = 1 << TAG} }, \ ++ { MODKEY|WLR_MODIFIER_CTRL, -1, KEY, toggleview, {.ui = 1 << TAG} }, \ ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, SKEY, tag, {.ui = 1 << TAG} }, \ ++ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,-1,SKEY,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 } } +@@ -119,30 +119,30 @@ static const char *menucmd[] = { "wmenu-run", NULL }; + + static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ +- /* modifier key function argument */ +- { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, +- { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, +- { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, +- { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +- { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, +- { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +- { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, +- { MODKEY, XKB_KEY_Return, zoom, {0} }, +- { MODKEY, XKB_KEY_Tab, view, {0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +- { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, +- { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, +- { MODKEY, XKB_KEY_space, setlayout, {0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +- { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, +- { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +- { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ /* modifier chain, key function argument */ ++ { MODKEY, -1, XKB_KEY_p, spawn, {.v = menucmd} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY, -1, XKB_KEY_j, focusstack, {.i = +1} }, ++ { MODKEY, -1, XKB_KEY_k, focusstack, {.i = -1} }, ++ { MODKEY, -1, XKB_KEY_i, incnmaster, {.i = +1} }, ++ { MODKEY, -1, XKB_KEY_d, incnmaster, {.i = -1} }, ++ { MODKEY, -1, XKB_KEY_h, setmfact, {.f = -0.05f} }, ++ { MODKEY, -1, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY, -1, XKB_KEY_Return, zoom, {0} }, ++ { MODKEY, -1, XKB_KEY_Tab, view, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_C, killclient, {0} }, ++ { MODKEY, -1, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, ++ { MODKEY, -1, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, ++ { MODKEY, -1, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, -1, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_space, togglefloating, {0} }, ++ { MODKEY, -1, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, -1, XKB_KEY_0, view, {.ui = ~0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_parenright, tag, {.ui = ~0} }, ++ { MODKEY, -1, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, ++ { MODKEY, -1, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +@@ -152,14 +152,14 @@ static const Key keys[] = { + TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), + TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), + TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_Q, quit, {0} }, + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ +- { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, ++ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,-1,XKB_KEY_Terminate_Server, quit, {0} }, + /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is + * do not remove them. + */ +-#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } ++#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,-1,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } + CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), + CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), + }; +diff --git a/dwl.c b/dwl.c +index bf763dfc..05e667f8 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -143,6 +143,7 @@ typedef struct { + + typedef struct { + uint32_t mod; ++ int chain; + xkb_keysym_t keysym; + void (*func)(const Arg *); + const Arg arg; +@@ -353,6 +354,7 @@ static const char broken[] = "broken"; + static pid_t child_pid = -1; + static int locked; + static void *exclusive_focus; ++static int chainkey = -1; + static struct wl_display *dpy; + static struct wlr_backend *backend; + static struct wlr_scene *scene; +@@ -1438,11 +1440,30 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + const Key *k; + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) +- && sym == k->keysym && k->func) { ++ && sym == k->keysym ++ && chainkey == -1 ++ && k->chain == -1 ++ && k->func) { + k->func(&k->arg); + return 1; + } ++ else if (sym == k->keysym ++ && chainkey != -1 ++ && k->chain == chainkey ++ && k->func) { ++ k->func(&k->arg); ++ chainkey = -1; ++ return 1; ++ } ++ else if (CLEANMASK(mods) == CLEANMASK(k->mod) ++ && k->chain == (int)sym ++ && chainkey == -1 ++ && k->func) { ++ chainkey = sym; ++ return 1; ++ } + } ++ chainkey = -1; + return 0; + } + +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/client-opacity/README.md b/dwl/dwl-patches/patches/client-opacity/README.md new file mode 100755 index 0000000..ed82d81 --- /dev/null +++ b/dwl/dwl-patches/patches/client-opacity/README.md @@ -0,0 +1,18 @@ +### Description +This patch adds default transparency parameters to config.h which specify the starting transparencies of all windows. + +It also adds opacities to the ruleset, enabling override of the opacities on a per client basis. + +Additionally, it adds some shortcuts: +``` +[MODKEY]+[o] -> increase focus opacity of currently focused window +[MODKEY]+[Shift]+[o] -> decrease focus opacity of currently focused window +``` + + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/client-opacity) +- [2025-01-20](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/client-opacity/client-opacity.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) diff --git a/dwl/dwl-patches/patches/client-opacity/client-opacity.patch b/dwl/dwl-patches/patches/client-opacity/client-opacity.patch new file mode 100755 index 0000000..da2faf7 --- /dev/null +++ b/dwl/dwl-patches/patches/client-opacity/client-opacity.patch @@ -0,0 +1,181 @@ +From ba3172875d379ff4f2db69753f50067cecfc8293 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Tue, 25 Jul 2023 12:48:22 -0600 +Subject: [PATCH] add default transparency for windows and rules for override + the transparency +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 9 ++++++--- + dwl.c | 39 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 45 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..0eb86874 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const float default_opacity = 0.75; + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +@@ -22,10 +23,10 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating alpha monitor */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 1, default_opacity, -1 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 1.0, -1 }, /* Start on ONLY tag "9" */ + }; + + /* layout(s) */ +@@ -133,6 +134,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY, XKB_KEY_o, setopacity, {.f = +0.1f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, setopacity, {.f = -0.1f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index ad21e1ba..0554fcdf 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -138,6 +138,7 @@ typedef struct { + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; ++ float opacity; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -227,6 +228,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ float opacity; + int monitor; + } Rule; + +@@ -319,6 +321,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void scenebuffersetopacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -326,6 +329,7 @@ static void setfullscreen(Client *c, int fullscreen); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); ++static void setopacity(const Arg *arg); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); +@@ -491,6 +495,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->opacity = r->opacity; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -499,6 +504,8 @@ applyrules(Client *c) + } + } + } ++ if (c->scene_surface) ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c); + setmon(c, mon, newtags); + } + +@@ -874,6 +881,9 @@ commitnotify(struct wl_listener *listener, void *data) + + resize(c, c->geom, (c->isfloating && !c->isfullscreen)); + ++ if (c->scene_surface) ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c); ++ + /* mark a pending resize as completed */ + if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) + c->resize = 0; +@@ -1120,6 +1130,7 @@ createnotify(struct wl_listener *listener, void *data) + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; ++ c->opacity = default_opacity; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); +@@ -2285,6 +2296,15 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++void ++scenebuffersetopacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *data) ++{ ++ Client *c = data; ++ /* xdg-popups are children of Client.scene, we do not have to worry about ++ messing with them. */ ++ wlr_scene_buffer_set_opacity(buffer, c->isfullscreen ? 1 : c->opacity); ++} ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2353,6 +2373,7 @@ setfullscreen(Client *c, int fullscreen) + * client positions are set by the user and cannot be recalculated */ + resize(c, c->prev, 0); + } ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c); + arrange(c->mon); + printstatus(); + } +@@ -2409,6 +2430,23 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + focusclient(focustop(selmon), 1); + } + ++void ++setopacity(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ if (!sel) ++ return; ++ ++ sel->opacity += arg->f; ++ if (sel->opacity > 1.0) ++ sel->opacity = 1.0f; ++ ++ if (sel->opacity < 0.1) ++ sel->opacity = 0.1f; ++ ++ wlr_scene_node_for_each_buffer(&sel->scene_surface->node, scenebuffersetopacity, sel); ++} ++ + void + setpsel(struct wl_listener *listener, void *data) + { +@@ -3120,6 +3158,7 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; ++ c->opacity = default_opacity; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/column/README.md b/dwl/dwl-patches/patches/column/README.md new file mode 100755 index 0000000..9d1b205 --- /dev/null +++ b/dwl/dwl-patches/patches/column/README.md @@ -0,0 +1,9 @@ +### Description +A column layout patch. This patch just puts the visible clients into equal-width columns on the screen. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/column) +- [2024-01-02](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/column/column.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/column/column.patch b/dwl/dwl-patches/patches/column/column.patch new file mode 100755 index 0000000..0f6a531 --- /dev/null +++ b/dwl/dwl-patches/patches/column/column.patch @@ -0,0 +1,79 @@ +From d1eb2061c619d0bbd7a0ecda0fe77409f3a6c399 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Fri, 29 Dec 2023 19:02:11 +1000 +Subject: [PATCH] column layout + +--- + config.def.h | 2 ++ + dwl.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a8ed61d9..edb30cae 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "||", col }, + }; + + /* monitors */ +@@ -134,6 +135,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index 4d19357f..63d80da7 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -243,6 +243,7 @@ static void checkidleinhibitor(struct wlr_surface *exclude); + static void cleanup(void); + static void cleanupmon(struct wl_listener *listener, void *data); + static void closemon(Monitor *m); ++static void col(Monitor *m); + static void commitlayersurfacenotify(struct wl_listener *listener, void *data); + static void commitnotify(struct wl_listener *listener, void *data); + static void createdecoration(struct wl_listener *listener, void *data); +@@ -704,6 +705,33 @@ closemon(Monitor *m) + printstatus(); + } + ++void ++col(Monitor *m) ++{ ++ Client *c; ++ unsigned int n = 0, i = 0; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ resize( ++ c, ++ (struct wlr_box){ ++ .x = m->w.x + i * m->w.width / n, ++ .y = m->w.y, ++ .width = m->w.width / n, ++ .height = m->w.height ++ }, ++ 0 ++ ); ++ i++; ++ } ++} ++ + void + commitlayersurfacenotify(struct wl_listener *listener, void *data) + { +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/coredump/README.md b/dwl/dwl-patches/patches/coredump/README.md new file mode 100755 index 0000000..5300890 --- /dev/null +++ b/dwl/dwl-patches/patches/coredump/README.md @@ -0,0 +1,11 @@ +### Description +Generate a coredump if dwl exited abnormally (to be more usefull you need to +compile dwl and wlroots with debug symbols) + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/coredump) +- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/coredump/coredump.patch) +- [coredump-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/coredump/coredump-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) diff --git a/dwl/dwl-patches/patches/coredump/coredump-0.7.patch b/dwl/dwl-patches/patches/coredump/coredump-0.7.patch new file mode 100755 index 0000000..f39e7af --- /dev/null +++ b/dwl/dwl-patches/patches/coredump/coredump-0.7.patch @@ -0,0 +1,65 @@ +From 2abde87f9159ec3318a0489ac0ed512f166ef8c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Wed, 5 Oct 2022 23:07:13 -0500 +Subject: [PATCH] increase RLIMIT_CORE (generate a coredump) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + dwl.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/dwl.c b/dwl.c +index a2711f67..cfbb0bb8 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -358,6 +359,8 @@ static void zoom(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; ++static struct rlimit oldrlimit; ++static struct rlimit newrlimit; + static pid_t child_pid = -1; + static int locked; + static void *exclusive_focus; +@@ -2232,6 +2235,7 @@ run(char *startup_cmd) + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { ++ setrlimit(RLIMIT_CORE, &oldrlimit); + setsid(); + dup2(piperw[0], STDIN_FILENO); + close(piperw[0]); +@@ -2649,6 +2653,7 @@ void + spawn(const Arg *arg) + { + if (fork() == 0) { ++ setrlimit(RLIMIT_CORE, &oldrlimit); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); +@@ -3189,6 +3194,10 @@ main(int argc, char *argv[]) + char *startup_cmd = NULL; + int c; + ++ getrlimit(RLIMIT_CORE, &oldrlimit); ++ newrlimit.rlim_cur = newrlimit.rlim_max = oldrlimit.rlim_max; ++ setrlimit(RLIMIT_CORE, &newrlimit); ++ + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') + startup_cmd = optarg; +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/coredump/coredump.patch b/dwl/dwl-patches/patches/coredump/coredump.patch new file mode 100755 index 0000000..98ffbd8 --- /dev/null +++ b/dwl/dwl-patches/patches/coredump/coredump.patch @@ -0,0 +1,65 @@ +From 6d5017888891957615160fe7c015adf7a6f0fd45 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Wed, 5 Oct 2022 23:07:13 -0500 +Subject: [PATCH] increase RLIMIT_CORE (generate a coredump) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + dwl.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/dwl.c b/dwl.c +index ad21e1ba..940fbeff 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -353,6 +354,8 @@ static void xytonode(double x, double y, struct wlr_surface **psurface, + static void zoom(const Arg *arg); + + /* variables */ ++static struct rlimit oldrlimit; ++static struct rlimit newrlimit; + static pid_t child_pid = -1; + static int locked; + static void *exclusive_focus; +@@ -2248,6 +2251,7 @@ run(char *startup_cmd) + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { ++ setrlimit(RLIMIT_CORE, &oldrlimit); + setsid(); + dup2(piperw[0], STDIN_FILENO); + close(piperw[0]); +@@ -2659,6 +2663,7 @@ void + spawn(const Arg *arg) + { + if (fork() == 0) { ++ setrlimit(RLIMIT_CORE, &oldrlimit); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); +@@ -3178,6 +3183,10 @@ main(int argc, char *argv[]) + char *startup_cmd = NULL; + int c; + ++ getrlimit(RLIMIT_CORE, &oldrlimit); ++ newrlimit.rlim_cur = newrlimit.rlim_max = oldrlimit.rlim_max; ++ setrlimit(RLIMIT_CORE, &newrlimit); ++ + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') + startup_cmd = optarg; +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/cursortheme/README.md b/dwl/dwl-patches/patches/cursortheme/README.md new file mode 100755 index 0000000..ac94800 --- /dev/null +++ b/dwl/dwl-patches/patches/cursortheme/README.md @@ -0,0 +1,17 @@ +### Description +Adds ability to change cursor's theme and size. + +```c +static const char *cursor_theme = NULL; +static const char cursor_size[] = "24"; /* Make sure it's a valid integer, otherwise things will break */ +``` + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/cursortheme) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/cursortheme/cursortheme.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/b828e21717fa584affeb3245359c3ab615759fa4/cursortheme/cursortheme.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/c676de59d51e613bd52ac46c77a24b1cac9a61a1/cursortheme/cursortheme.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [egorguslyan](https://github.com/egorguslyan) diff --git a/dwl/dwl-patches/patches/cursortheme/cursortheme.patch b/dwl/dwl-patches/patches/cursortheme/cursortheme.patch new file mode 100755 index 0000000..3c34222 --- /dev/null +++ b/dwl/dwl-patches/patches/cursortheme/cursortheme.patch @@ -0,0 +1,46 @@ +From f08376a2a04929a3907612e6c1f980ad3cdf939f Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 5 Jul 2024 11:10:39 -0500 +Subject: [PATCH] implement cursortheme + +--- + config.def.h | 2 ++ + dwl.c | 8 ++++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..1f9ff56 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,6 +13,8 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const char *cursor_theme = NULL; ++static const char cursor_size[] = "24"; /* Make sure it's a valid integer, otherwise things will break */ + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +diff --git a/dwl.c b/dwl.c +index dc0437e..a91d42b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2522,8 +2522,12 @@ setup(void) + * Xcursor themes to source cursor images from and makes sure that cursor + * images are available at all scale factors on the screen (necessary for + * HiDPI support). Scaled cursors will be loaded with each output. */ +- cursor_mgr = wlr_xcursor_manager_create(NULL, 24); +- setenv("XCURSOR_SIZE", "24", 1); ++ cursor_mgr = wlr_xcursor_manager_create(cursor_theme, atoi(cursor_size)); ++ setenv("XCURSOR_SIZE", cursor_size, 1); ++ if (cursor_theme) ++ setenv("XCURSOR_THEME", cursor_theme, 1); ++ else ++ unsetenv("XCURSOR_THEME"); + + /* + * wlr_cursor *only* displays an image on screen. It does not move around +-- +2.45.1 + + diff --git a/dwl/dwl-patches/patches/customfloat/README.md b/dwl/dwl-patches/patches/customfloat/README.md new file mode 100755 index 0000000..9f2bda5 --- /dev/null +++ b/dwl/dwl-patches/patches/customfloat/README.md @@ -0,0 +1,24 @@ +### Description +Rules for floating windows support default x, y, width, height. Defaults to the center of the screen and the client size. + +If the width or height is less than or equal to 1, then the value will be interpreted as a percentage. For example, 0.5 represents 50%, 0.25 represents 25%, and 1 represents 100%. **NOTE**: Some clients, like Thunar, have minimum width/height + +The variable `center_relative_to_monitor` allows the user to choose whether to center relative to the monitor or relative to the window area. + +
+Explanation of center_relative_to_monitor: +
+The "Monitor area" refers to the space enclosed by the green rectangle, while the "Window area" refers to the space enclosed by the red rectangle.
+
+
+
+ +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/customfloat) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/customfloat/customfloat.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/98cba933c9f4099202e54f39acbf17e05bde828a/customfloat/customfloat.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/bf098459219e7a473d8edb4c0435aeb6a4b82e38/customfloat/customfloat.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [Stivvo](https://github.com/Stivvo) diff --git a/dwl/dwl-patches/patches/customfloat/customfloat.patch b/dwl/dwl-patches/patches/customfloat/customfloat.patch new file mode 100755 index 0000000..d295571 --- /dev/null +++ b/dwl/dwl-patches/patches/customfloat/customfloat.patch @@ -0,0 +1,93 @@ +From 4f19f5499610d56f2616da5d44039403ac9d4c06 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Tue, 9 Jul 2024 10:52:37 -0500 +Subject: [PATCH] implement customfloat and generate patches + +--- + config.def.h | 7 ++++--- + dwl.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 31 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..dee53f4 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const int respect_monitor_reserved_area = 0; /* 1 to monitor center while respecting the monitor's reserved area, 0 to monitor center */ + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +@@ -22,10 +23,10 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating monitor x y width height */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 1, -1, 0, 0, 1000, 0.75 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1, 0, 0, 0, 0 },/* Start on ONLY tag "9" */ + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index dc0437e..be0340f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -230,6 +230,10 @@ typedef struct { + uint32_t tags; + int isfloating; + int monitor; ++ int x; ++ int y; ++ float w; ++ float h; + } Rule; + + typedef struct { +@@ -454,6 +458,11 @@ applyrules(Client *c) + int i; + const Rule *r; + Monitor *mon = selmon, *m; ++ int newwidth; ++ int newheight; ++ int newx; ++ int newy; ++ int apply_resize = 0; + + c->isfloating = client_is_float_type(c); + if (!(appid = client_get_appid(c))) +@@ -471,9 +480,27 @@ applyrules(Client *c) + if (r->monitor == i++) + mon = m; + } ++ if (c->isfloating || !mon->lt[mon->sellt]->arrange) { ++ /* client is floating or in floating layout */ ++ struct wlr_box b = respect_monitor_reserved_area ? mon->w : mon->m; ++ newwidth = (int)round(r->w ? (r->w <= 1 ? b.width * r->w : r->w) : c->geom.width); ++ newheight = (int)round(r->h ? (r->h <= 1 ? b.height * r->h : r->h) : c->geom.height); ++ newx = (int)round(r->x ? (r->x <= 1 ? b.width * r->x + b.x : r->x + b.x) : c->geom.x); ++ newy = (int)round(r->y ? (r->y <= 1 ? b.height * r->y + b.y : r->y + b.y) : c->geom.y); ++ apply_resize = 1; ++ ++ } + } + } + setmon(c, mon, newtags); ++ if (apply_resize) { ++ resize(c, (struct wlr_box){ ++ .x = newx, ++ .y = newy, ++ .width = newwidth, ++ .height = newheight, ++ }, 1); ++ } + } + + void +-- +2.45.1 diff --git a/dwl/dwl-patches/patches/dim-unfocused/README.md b/dwl/dwl-patches/patches/dim-unfocused/README.md new file mode 100755 index 0000000..dad3ef0 --- /dev/null +++ b/dwl/dwl-patches/patches/dim-unfocused/README.md @@ -0,0 +1,19 @@ +### Description +Implements dimming of clients which are unfocused. + +The code also allows any color dimming. There is also an additional option in `Rule`, which allows you to keep the client `neverdim`, that is, as if it is focused. + +There are also two functions that can be bound to a `Key` or `Button`, +1. `toggledimming`: Which toggles dimming for all windows (except for `Rule`s) +2. `toggledimmingclient`: Which toggles dimming for the focused window, as if the client had `neverdim` applied to it. This overwrites an applied `Rule`. + +### Download +- [2024-09-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused.patch) +- [2024-09-03](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240903.patch) +- [2024-07-14](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240714.patch) +- [2024-05-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240516.patch) +- [2024-04-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240416.patch) +- [git branch](https://codeberg.org/dhruva_sambrani/dwl/src/branch/dim-unfocused) + +### Authors +- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani) diff --git a/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20230516.patch b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20230516.patch new file mode 100755 index 0000000..88504cd --- /dev/null +++ b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20230516.patch @@ -0,0 +1,213 @@ +From cd3b5580dbf38f54b54d5bfb6039e0039cbd6b21 Mon Sep 17 00:00:00 2001 +From: Dhruva Sambrani <44899822+DhruvaSambrani@users.noreply.github.com> +Date: Thu, 16 May 2024 12:26:05 +0200 +Subject: [PATCH] clean git history + +--- + client.h | 6 ++++++ + config.def.h | 13 ++++++++----- + dwl.c | 40 +++++++++++++++++++++++++++++++++++----- + 3 files changed, 49 insertions(+), 10 deletions(-) + +diff --git a/client.h b/client.h +index 800b867..4d83248 100644 +--- a/client.h ++++ b/client.h +@@ -332,6 +332,12 @@ client_set_border_color(Client *c, const float color[static 4]) + wlr_scene_rect_set_color(c->border[i], color); + } + ++static inline void ++client_set_dimmer_state(Client *c, const int dim) ++{ ++ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim); ++} ++ + static inline void + client_set_fullscreen(Client *c, int fullscreen) + { +diff --git a/config.def.h b/config.def.h +index 8f498d2..d3950f9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); ++static const float unfocuseddim[] = COLOR(0x00000088); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +@@ -21,10 +22,11 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + static int log_level = WLR_ERROR; + + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ +- /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ /* app_id title tags mask isfloating neverdim monitor */ ++ /* examples: ++ { "Gimp_example", NULL, 0, 1, 0, -1 }, ++ */ ++ { "firefox_example", NULL, 1 << 8, 0, 1, -1 }, + }; + + /* layout(s) */ +@@ -135,8 +137,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index bf763df..ca88ad0 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -109,6 +109,7 @@ typedef struct { + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ ++ struct wlr_scene_rect *dimmer; + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; +@@ -137,7 +138,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, neverdim; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -227,6 +228,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int neverdim; + int monitor; + } Rule; + +@@ -330,6 +332,7 @@ static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void toggledimming(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -404,6 +407,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static int DIMOPT = 1; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -462,6 +466,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->neverdim = r-> neverdim; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1267,8 +1272,10 @@ focusclient(Client *c, int lift) + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +- if (!exclusive_focus && !seat->drag) ++ if (!exclusive_focus && !seat->drag) { + client_set_border_color(c, focuscolor); ++ client_set_dimmer_state(c, 0); ++ } + } + + /* Deactivate old client if focus is changing */ +@@ -1286,7 +1293,7 @@ focusclient(Client *c, int lift) + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, bordercolor); +- ++ client_set_dimmer_state(old_c, 1); + client_activate_surface(old, 0); + } + } +@@ -1566,7 +1573,7 @@ mapnotify(struct wl_listener *listener, void *data) + { + /* Called when the surface is mapped, or ready to display on-screen. */ + Client *p = NULL; +- Client *w, *c = wl_container_of(listener, c, map); ++ Client *w, *d, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; + +@@ -1599,6 +1606,10 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim); ++ c->dimmer->node.data = c; ++ client_set_dimmer_state(c, 1); ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -1617,6 +1628,10 @@ mapnotify(struct wl_listener *listener, void *data) + setmon(c, p->mon, p->tags); + } else { + applyrules(c); ++ d = focustop(selmon); ++ if (d) { ++ client_set_dimmer_state(d, 0); ++ } + } + printstatus(); + +@@ -2040,7 +2055,7 @@ resize(Client *c, struct wlr_box geo, int interact) + c->geom = geo; + applybounds(c, bbox); + +- /* Update scene-graph, including borders */ ++ /* Update scene-graph, including borders and dimmer*/ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +@@ -2050,6 +2065,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_rect_set_size(c->dimmer, c->geom.width, c-> geom.height); ++ wlr_scene_node_set_position(&c->dimmer->node, 0, 0); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +@@ -2603,6 +2620,19 @@ tile(Monitor *m) + } + } + ++void toggledimming(const Arg *arg) ++{ ++ Client *c; ++ DIMOPT ^= 1; ++ wl_list_for_each(c, &clients, link) ++ { ++ client_set_dimmer_state(c, 1); ++ } ++ c = focustop(selmon); ++ if (c) ++ client_set_dimmer_state(c, 0); ++} ++ + void + togglefloating(const Arg *arg) + { +-- +2.45.1 + diff --git a/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240416.patch b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240416.patch new file mode 100755 index 0000000..701c450 --- /dev/null +++ b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240416.patch @@ -0,0 +1,177 @@ +diff --git a/client.h b/client.h +index 800b867..4d83248 100644 +--- a/client.h ++++ b/client.h +@@ -332,6 +332,12 @@ client_set_border_color(Client *c, const float color[static 4]) + wlr_scene_rect_set_color(c->border[i], color); + } + ++static inline void ++client_set_dimmer_state(Client *c, const int dim) ++{ ++ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim); ++} ++ + static inline void + client_set_fullscreen(Client *c, int fullscreen) + { +diff --git a/config.def.h b/config.def.h +index 8847e58..36ac2a1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); ++static const float unfocuseddim[] = COLOR(0x00000088); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +@@ -21,10 +22,11 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + static int log_level = WLR_ERROR; + + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ +- /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ /* app_id title tags mask isfloating neverdim monitor */ ++ /* examples: ++ { "Gimp_example", NULL, 0, 1, 0, -1 }, ++ */ ++ { "firefox_example", NULL, 1 << 8, 0, 1, -1 }, + }; + + /* layout(s) */ +@@ -135,8 +137,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index bf763df..abd7112 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -109,6 +109,7 @@ typedef struct { + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ ++ struct wlr_scene_rect *dimmer; + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; +@@ -137,7 +138,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, neverdim; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -227,6 +228,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int neverdim; + int monitor; + } Rule; + +@@ -330,6 +332,7 @@ static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void toggledimming(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -404,6 +407,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static int DIMOPT = 1; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -462,6 +466,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->neverdim = r-> neverdim; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1267,8 +1272,10 @@ focusclient(Client *c, int lift) + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +- if (!exclusive_focus && !seat->drag) ++ if (!exclusive_focus && !seat->drag) { + client_set_border_color(c, focuscolor); ++ client_set_dimmer_state(c, 0); ++ } + } + + /* Deactivate old client if focus is changing */ +@@ -1286,7 +1293,7 @@ focusclient(Client *c, int lift) + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, bordercolor); +- ++ client_set_dimmer_state(old_c, 1); + client_activate_surface(old, 0); + } + } +@@ -1599,6 +1606,10 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim); ++ c->dimmer->node.data = c; ++ client_set_dimmer_state(c, 1); ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -2040,7 +2051,7 @@ resize(Client *c, struct wlr_box geo, int interact) + c->geom = geo; + applybounds(c, bbox); + +- /* Update scene-graph, including borders */ ++ /* Update scene-graph, including borders and dimmer*/ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +@@ -2050,6 +2061,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_rect_set_size(c->dimmer, c->geom.width, c-> geom.height); ++ wlr_scene_node_set_position(&c->dimmer->node, 0, 0); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +@@ -2603,6 +2616,17 @@ tile(Monitor *m) + } + } + ++void toggledimming(const Arg *arg) ++{ ++ Client *c; ++ DIMOPT ^= 1; ++ wl_list_for_each(c, &clients, link) ++ { ++ client_set_dimmer_state(c, 1); ++ } ++ client_set_dimmer_state(focustop(selmon), 0); ++} ++ + void + togglefloating(const Arg *arg) + { diff --git a/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240714.patch b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240714.patch new file mode 100755 index 0000000..0b60d60 --- /dev/null +++ b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240714.patch @@ -0,0 +1,199 @@ +diff --git a/client.h b/client.h +index f0e5445..04b8d31 100644 +--- a/client.h ++++ b/client.h +@@ -320,6 +320,12 @@ client_set_border_color(Client *c, const float color[static 4]) + wlr_scene_rect_set_color(c->border[i], color); + } + ++static inline void ++client_set_dimmer_state(Client *c, const int dim) ++{ ++ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim); ++} ++ + static inline void + client_set_fullscreen(Client *c, int fullscreen) + { +diff --git a/config.def.h b/config.def.h +index 22d2171..e1b2bf0 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); ++static const float unfocuseddim[] = COLOR(0x00000088); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ +- /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ /* app_id title tags mask isfloating neverdim monitor */ ++ /* examples: ++ { "Gimp_example", NULL, 0, 1, 0, -1 }, ++ */ ++ { "firefox_example", NULL, 1 << 8, 0, 1, -1 }, + }; + + /* layout(s) */ +@@ -140,8 +142,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index 145fd01..6c65860 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -110,6 +110,7 @@ typedef struct { + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ ++ struct wlr_scene_rect *dimmer; + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; +@@ -138,7 +139,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, neverdim; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -229,6 +230,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int neverdim; + int monitor; + } Rule; + +@@ -334,6 +336,7 @@ static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void toggledimming(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -407,6 +410,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static int DIMOPT = 1; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -465,6 +469,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->neverdim = r-> neverdim; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1346,8 +1351,10 @@ focusclient(Client *c, int lift) + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +- if (!exclusive_focus && !seat->drag) ++ if (!exclusive_focus && !seat->drag) { + client_set_border_color(c, focuscolor); ++ client_set_dimmer_state(c, 0); ++ } + } + + /* Deactivate old client if focus is changing */ +@@ -1365,7 +1372,7 @@ focusclient(Client *c, int lift) + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, bordercolor); +- ++ client_set_dimmer_state(old_c, 1); + client_activate_surface(old, 0); + } + } +@@ -1638,7 +1645,7 @@ void + mapnotify(struct wl_listener *listener, void *data) + { + /* Called when the surface is mapped, or ready to display on-screen. */ +- Client *p, *w, *c = wl_container_of(listener, c, map); ++ Client *p, *w, *d, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; + +@@ -1670,6 +1677,10 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim); ++ c->dimmer->node.data = c; ++ client_set_dimmer_state(c, 1); ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -1688,6 +1699,10 @@ mapnotify(struct wl_listener *listener, void *data) + setmon(c, p->mon, p->tags); + } else { + applyrules(c); ++ d = focustop(selmon); ++ if (d) { ++ client_set_dimmer_state(d, 0); ++ } + } + printstatus(); + +@@ -2141,7 +2156,7 @@ resize(Client *c, struct wlr_box geo, int interact) + c->geom = geo; + applybounds(c, bbox); + +- /* Update scene-graph, including borders */ ++ /* Update scene-graph, including borders and dimmer*/ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +@@ -2151,6 +2166,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_rect_set_size(c->dimmer, c->geom.width - 2*c->bw, c-> geom.height - 2*c->bw); ++ wlr_scene_node_set_position(&c->dimmer->node, c->bw, c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +@@ -2666,6 +2683,19 @@ tile(Monitor *m) + } + } + ++void toggledimming(const Arg *arg) ++{ ++ Client *c; ++ DIMOPT ^= 1; ++ wl_list_for_each(c, &clients, link) ++ { ++ client_set_dimmer_state(c, 1); ++ } ++ c = focustop(selmon); ++ if (c) ++ client_set_dimmer_state(c, 0); ++} ++ + void + togglefloating(const Arg *arg) + { diff --git a/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240903.patch b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240903.patch new file mode 100755 index 0000000..fc48b0b --- /dev/null +++ b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused-20240903.patch @@ -0,0 +1,216 @@ +diff --git a/client.h b/client.h +index dabea35..3a31c25 100644 +--- a/client.h ++++ b/client.h +@@ -319,6 +319,12 @@ client_set_border_color(Client *c, const float color[static 4]) + wlr_scene_rect_set_color(c->border[i], color); + } + ++static inline void ++client_set_dimmer_state(Client *c, const int dim) ++{ ++ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim); ++} ++ + static inline void + client_set_fullscreen(Client *c, int fullscreen) + { +diff --git a/config.def.h b/config.def.h +index 22d2171..4ca21c9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); ++static const float unfocuseddim[] = COLOR(0x00000088); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ +- /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ /* app_id title tags mask isfloating neverdim monitor */ ++ /* examples: ++ { "Gimp_example", NULL, 0, 1, 0, -1 }, ++ */ ++ { "firefox_example", NULL, 1 << 8, 0, 1, -1 }, + }; + + /* layout(s) */ +@@ -140,8 +142,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +@@ -172,5 +175,6 @@ static const Key keys[] = { + static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, + { MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { MODKEY|ShiftMask, BTN_MIDDLE, toggledimmingclient, {0} }, + { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + }; +diff --git a/dwl.c b/dwl.c +index 9021e44..e1f32e9 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -112,6 +112,7 @@ typedef struct { + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ ++ struct wlr_scene_rect *dimmer; + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; +@@ -141,7 +142,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, neverdim; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -231,6 +232,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int neverdim; + int monitor; + } Rule; + +@@ -338,6 +340,8 @@ static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void toggledimming(const Arg *arg); ++static void toggledimmingclient(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -410,6 +414,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static int DIMOPT = 1; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -466,6 +471,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->neverdim = r-> neverdim; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1366,8 +1372,10 @@ focusclient(Client *c, int lift) + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +- if (!exclusive_focus && !seat->drag) ++ if (!exclusive_focus && !seat->drag) { + client_set_border_color(c, focuscolor); ++ client_set_dimmer_state(c, 0); ++ } + } + + /* Deactivate old client if focus is changing */ +@@ -1385,7 +1393,7 @@ focusclient(Client *c, int lift) + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, bordercolor); +- ++ client_set_dimmer_state(old_c, 1); + client_activate_surface(old, 0); + } + } +@@ -1682,8 +1690,7 @@ void + mapnotify(struct wl_listener *listener, void *data) + { + /* Called when the surface is mapped, or ready to display on-screen. */ +- Client *p = NULL; +- Client *w, *c = wl_container_of(listener, c, map); ++ Client *p, *w, *d, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; + +@@ -1717,6 +1724,10 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim); ++ c->dimmer->node.data = c; ++ client_set_dimmer_state(c, 1); ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -1735,6 +1746,10 @@ mapnotify(struct wl_listener *listener, void *data) + setmon(c, p->mon, p->tags); + } else { + applyrules(c); ++ d = focustop(selmon); ++ if (d) { ++ client_set_dimmer_state(d, 0); ++ } + } + printstatus(); + +@@ -2161,7 +2176,7 @@ resize(Client *c, struct wlr_box geo, int interact) + c->geom = geo; + applybounds(c, bbox); + +- /* Update scene-graph, including borders */ ++ /* Update scene-graph, including borders and dimmer*/ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +@@ -2171,6 +2186,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_rect_set_size(c->dimmer, c->geom.width - 2*c->bw, c-> geom.height - 2*c->bw); ++ wlr_scene_node_set_position(&c->dimmer->node, c->bw, c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +@@ -2682,6 +2699,27 @@ tile(Monitor *m) + } + } + ++void toggledimming(const Arg *arg) ++{ ++ Client *c; ++ DIMOPT ^= 1; ++ wl_list_for_each(c, &clients, link) ++ { ++ client_set_dimmer_state(c, 1); ++ } ++ c = focustop(selmon); ++ if (c) ++ client_set_dimmer_state(c, 0); ++} ++ ++void ++toggledimmingclient(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ if (sel) ++ sel -> neverdim ^= 1; ++} ++ + void + togglefloating(const Arg *arg) + { diff --git a/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused.patch b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused.patch new file mode 100755 index 0000000..f73d886 --- /dev/null +++ b/dwl/dwl-patches/patches/dim-unfocused/dim-unfocused.patch @@ -0,0 +1,216 @@ +diff --git a/client.h b/client.h +index dabea35..3a31c25 100644 +--- a/client.h ++++ b/client.h +@@ -319,6 +319,12 @@ client_set_border_color(Client *c, const float color[static 4]) + wlr_scene_rect_set_color(c->border[i], color); + } + ++static inline void ++client_set_dimmer_state(Client *c, const int dim) ++{ ++ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim); ++} ++ + static inline void + client_set_fullscreen(Client *c, int fullscreen) + { +diff --git a/config.def.h b/config.def.h +index 22d2171..4ca21c9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); ++static const float unfocuseddim[] = COLOR(0x00000088); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ +- /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ /* app_id title tags mask isfloating neverdim monitor */ ++ /* examples: ++ { "Gimp_example", NULL, 0, 1, 0, -1 }, ++ */ ++ { "firefox_example", NULL, 1 << 8, 0, 1, -1 }, + }; + + /* layout(s) */ +@@ -140,8 +142,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +@@ -172,5 +175,6 @@ static const Key keys[] = { + static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, + { MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { MODKEY|ShiftMask, BTN_MIDDLE, toggledimmingclient, {0} }, + { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + }; +diff --git a/dwl.c b/dwl.c +index dc0c861..dcc3ece 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -112,6 +112,7 @@ typedef struct { + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ ++ struct wlr_scene_rect *dimmer; + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; +@@ -141,7 +142,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, neverdim; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -231,6 +232,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int neverdim; + int monitor; + } Rule; + +@@ -338,6 +340,8 @@ static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void toggledimming(const Arg *arg); ++static void toggledimmingclient(const Arg *arg); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -410,6 +414,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static int DIMOPT = 1; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -466,6 +471,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->neverdim = r-> neverdim; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1365,8 +1371,10 @@ focusclient(Client *c, int lift) + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +- if (!exclusive_focus && !seat->drag) ++ if (!exclusive_focus && !seat->drag) { + client_set_border_color(c, focuscolor); ++ client_set_dimmer_state(c, 0); ++ } + } + + /* Deactivate old client if focus is changing */ +@@ -1384,7 +1392,7 @@ focusclient(Client *c, int lift) + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, bordercolor); +- ++ client_set_dimmer_state(old_c, 1); + client_activate_surface(old, 0); + } + } +@@ -1681,8 +1689,7 @@ void + mapnotify(struct wl_listener *listener, void *data) + { + /* Called when the surface is mapped, or ready to display on-screen. */ +- Client *p = NULL; +- Client *w, *c = wl_container_of(listener, c, map); ++ Client *p, *w, *d, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; + +@@ -1716,6 +1723,10 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim); ++ c->dimmer->node.data = c; ++ client_set_dimmer_state(c, 1); ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -1734,6 +1745,10 @@ mapnotify(struct wl_listener *listener, void *data) + setmon(c, p->mon, p->tags); + } else { + applyrules(c); ++ d = focustop(selmon); ++ if (d) { ++ client_set_dimmer_state(d, 0); ++ } + } + printstatus(); + +@@ -2160,7 +2175,7 @@ resize(Client *c, struct wlr_box geo, int interact) + c->geom = geo; + applybounds(c, bbox); + +- /* Update scene-graph, including borders */ ++ /* Update scene-graph, including borders and dimmer*/ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +@@ -2170,6 +2185,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_rect_set_size(c->dimmer, c->geom.width - 2*c->bw, c-> geom.height - 2*c->bw); ++ wlr_scene_node_set_position(&c->dimmer->node, c->bw, c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +@@ -2681,6 +2698,27 @@ tile(Monitor *m) + } + } + ++void toggledimming(const Arg *arg) ++{ ++ Client *c; ++ DIMOPT ^= 1; ++ wl_list_for_each(c, &clients, link) ++ { ++ client_set_dimmer_state(c, 1); ++ } ++ c = focustop(selmon); ++ if (c) ++ client_set_dimmer_state(c, 0); ++} ++ ++void ++toggledimmingclient(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ if (sel) ++ sel -> neverdim ^= 1; ++} ++ + void + togglefloating(const Arg *arg) + { diff --git a/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/README.md b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/README.md new file mode 100755 index 0000000..c6588ee --- /dev/null +++ b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/README.md @@ -0,0 +1,11 @@ +### Description +This patch changes the default behavior of the [disable-keybindings-on-fullscreen](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/disable-keybindings-on-fullscreen) patch by only taking effect when you explicitly toggle the functionality. +You must apply that patch prior to applying this one. + +### Download +- [git branch](https://github.com/Shringe/dwl/tree/disable-keybindings-on-fullscreen-toggle) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/disable-keybindings-on-fullscreen-toggle/disable-keybindings-on-fullscreen-toggle-0.7.patch) + +### Authors +- [Shringe](https://codeberg.org/Shringe) +- shringe_ at [dwl Discord](https://discord.gg/jJxZnrGPWN) diff --git a/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/disable-keybindings-on-fullscreen-toggle-0.7.patch b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/disable-keybindings-on-fullscreen-toggle-0.7.patch new file mode 100755 index 0000000..272d906 --- /dev/null +++ b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen-toggle/disable-keybindings-on-fullscreen-toggle-0.7.patch @@ -0,0 +1,71 @@ +From 71809cee0e27f1b3620773e1745afed8023f71c9 Mon Sep 17 00:00:00 2001 +From: Shringe +Date: Mon, 23 Jun 2025 18:50:40 -0500 +Subject: [PATCH] Implemented functionality for patch + +--- + config.def.h | 1 + + dwl.c | 14 ++++++++++++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..dda4ad0 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -142,6 +142,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_G, togglefullscreenkeyinhibit, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index f11de4b..5deb9c7 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -341,6 +341,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglefullscreenkeyinhibit(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -414,6 +415,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static int fullscreen_key_inhibit_enabled = 0; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -1583,8 +1586,9 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) + && sym == k->keysym && k->func) { +- if (c && c->isfullscreen) { +- if (k->func == togglefullscreen) { ++ if (fullscreen_key_inhibit_enabled ++ && c && c->isfullscreen) { ++ if (k->func == togglefullscreenkeyinhibit) { + k->func(&k->arg); + return 1; + } +@@ -2763,6 +2767,12 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglefullscreenkeyinhibit(const Arg *arg) ++{ ++ fullscreen_key_inhibit_enabled = !fullscreen_key_inhibit_enabled; ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/README.md b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/README.md new file mode 100755 index 0000000..9c438bb --- /dev/null +++ b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/README.md @@ -0,0 +1,9 @@ +### Description +This patch disables all keybindings except `togglefullscreen` when the focused window is fullscreen. +Might help prevent fat-fingering. + +### Download +- [git branch](https://codeberg.org/korei999/dwl/src/branch/disable-keybindings-on-fullscreen) +- [2025-02-09](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/disable-keybindings-on-fullscreen/disable-keybindings-on-fullscreen.patch) +### Authors +- [korei999](https://codeberg.org/korei999) diff --git a/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/disable-keybindings-on-fullscreen.patch b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/disable-keybindings-on-fullscreen.patch new file mode 100755 index 0000000..57a18e1 --- /dev/null +++ b/dwl/dwl-patches/patches/disable-keybindings-on-fullscreen/disable-keybindings-on-fullscreen.patch @@ -0,0 +1,82 @@ +From 2d6b845701091d3238774747c718df7fef135986 Mon Sep 17 00:00:00 2001 +From: korei999 +Date: Sun, 9 Feb 2025 14:59:33 +0200 +Subject: [PATCH] disable keybindings on fullscreen + +--- + dwl.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index ec4ca86..8c771e8 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -282,6 +282,7 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data); + static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static Client *firstfocused(void); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -620,11 +621,15 @@ buttonpress(struct wl_listener *listener, void *data) + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; + uint32_t mods; +- Client *c; ++ Client *c, *focused; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + ++ focused = firstfocused(); ++ if (focused && focused->isfullscreen) ++ goto skip_click; ++ + switch (event->state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + cursor_mode = CurPressed; +@@ -664,6 +669,7 @@ buttonpress(struct wl_listener *listener, void *data) + } + /* If the event wasn't handled by the compositor, notify the client with + * pointer focus that a button press has occurred */ ++skip_click: + wlr_seat_pointer_notify_button(seat, + event->time_msec, event->button, event->state); + } +@@ -1393,6 +1399,13 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++Client * ++firstfocused(void) ++{ ++ Client *c = wl_container_of(fstack.next, c, flink); ++ return c; ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1607,10 +1620,18 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + * processing keys, rather than passing them on to the client for its own + * processing. + */ ++ Client *c = firstfocused(); + const Key *k; + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) + && sym == k->keysym && k->func) { ++ if (c && c->isfullscreen) { ++ if (k->func == togglefullscreen) { ++ k->func(&k->arg); ++ return 1; ++ } ++ return 0; ++ } + k->func(&k->arg); + return 1; + } +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/dragmfact/README.md b/dwl/dwl-patches/patches/dragmfact/README.md new file mode 100755 index 0000000..3112d44 --- /dev/null +++ b/dwl/dwl-patches/patches/dragmfact/README.md @@ -0,0 +1,11 @@ +### Description +Change mfact by dragging the mouse. + +### Download +- [git branch](https://codeberg.org/Palanix/dwl/src/branch/dragmfact) +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragmfact/dragmfact-v0.7.patch) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragmfact/dragmfact-v0.6.patch) +- [2024-02-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragmfact/dragmfact.patch) + +### Authors +- [Palanix](https://codeberg.org/Palanix) diff --git a/dwl/dwl-patches/patches/dragmfact/dragmfact-v0.6.patch b/dwl/dwl-patches/patches/dragmfact/dragmfact-v0.6.patch new file mode 100755 index 0000000..2435cbf --- /dev/null +++ b/dwl/dwl-patches/patches/dragmfact/dragmfact-v0.6.patch @@ -0,0 +1,59 @@ +From aeee958aec3e0774f3ea8baefe028e1a8cc2d2ce Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 25 Mar 2022 23:45:10 +0100 +Subject: [PATCH] Change mfact using Middle mouse + +--- + config.def.h | 2 +- + dwl.c | 9 ++++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..c9071a5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -171,6 +171,6 @@ static const Key keys[] = { + + static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { MODKEY, BTN_MIDDLE, moveresize, {.ui = Curmfact} }, + { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + }; +diff --git a/dwl.c b/dwl.c +index 145fd01..0a3d140 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -80,7 +80,7 @@ + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) + + /* enums */ +-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ ++enum { CurNormal, CurPressed, CurMove, CurResize, Curmfact }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ + #ifdef XWAYLAND +@@ -1823,6 +1823,9 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, + .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); + return; ++ } else if (cursor_mode == Curmfact && time) { ++ selmon->mfact = (float) (cursor->x / selmon->m.width); ++ arrange(selmon); + } + + /* If there's no client surface under the cursor, set the cursor image to a +@@ -1874,6 +1877,10 @@ moveresize(const Arg *arg) + grabc->geom.y + grabc->geom.height); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); + break; ++ case Curmfact: ++ setfloating(grabc, 0); ++ selmon->mfact = (float) (cursor->x / selmon->m.width); ++ arrange(selmon); + } + } + +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/dragmfact/dragmfact-v0.7.patch b/dwl/dwl-patches/patches/dragmfact/dragmfact-v0.7.patch new file mode 100755 index 0000000..f0ea5d3 --- /dev/null +++ b/dwl/dwl-patches/patches/dragmfact/dragmfact-v0.7.patch @@ -0,0 +1,59 @@ +From ae44bfc181fc1532d2f0c4deb20e20634050a661 Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 25 Mar 2022 23:45:10 +0100 +Subject: [PATCH] Change mfact using Middle mouse + +--- + config.def.h | 2 +- + dwl.c | 9 ++++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..c9071a5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -171,6 +171,6 @@ static const Key keys[] = { + + static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { MODKEY, BTN_MIDDLE, moveresize, {.ui = Curmfact} }, + { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + }; +diff --git a/dwl.c b/dwl.c +index 5bf995e..dfb0754 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -81,7 +81,7 @@ + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) + + /* enums */ +-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ ++enum { CurNormal, CurPressed, CurMove, CurResize, Curmfact }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ + #ifdef XWAYLAND +@@ -1872,6 +1872,9 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, + .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); + return; ++ } else if (cursor_mode == Curmfact && time) { ++ selmon->mfact = (float) (cursor->x / selmon->m.width); ++ arrange(selmon); + } + + /* If there's no client surface under the cursor, set the cursor image to a +@@ -1923,6 +1926,10 @@ moveresize(const Arg *arg) + grabc->geom.y + grabc->geom.height); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); + break; ++ case Curmfact: ++ setfloating(grabc, 0); ++ selmon->mfact = (float) (cursor->x / selmon->m.width); ++ arrange(selmon); + } + } + +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/dragmfact/dragmfact.patch b/dwl/dwl-patches/patches/dragmfact/dragmfact.patch new file mode 100755 index 0000000..e2fdbac --- /dev/null +++ b/dwl/dwl-patches/patches/dragmfact/dragmfact.patch @@ -0,0 +1,59 @@ +From 435cdf673e5a8080123109dbf874aac2ccef1498 Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 25 Mar 2022 23:45:10 +0100 +Subject: [PATCH] Change mfact using Middle mouse + +--- + config.def.h | 2 +- + dwl.c | 9 ++++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9009517..3c26522 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -166,6 +166,6 @@ static const Key keys[] = { + + static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { MODKEY, BTN_MIDDLE, moveresize, {.ui = Curmfact} }, + { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + }; +diff --git a/dwl.c b/dwl.c +index fa76db2..528e102 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -76,7 +76,7 @@ + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) + + /* enums */ +-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ ++enum { CurNormal, CurPressed, CurMove, CurResize, Curmfact }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ + #ifdef XWAYLAND +@@ -1639,6 +1639,9 @@ motionnotify(uint32_t time) + resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, + .width = ROUND(cursor->x) - grabc->geom.x, .height = ROUND(cursor->y) - grabc->geom.y}, 1); + return; ++ } else if (cursor_mode == Curmfact && time) { ++ selmon->mfact = (float) (cursor->x / selmon->m.width); ++ arrange(selmon); + } + + /* Find the client under the pointer and send the event along. */ +@@ -1701,6 +1704,10 @@ moveresize(const Arg *arg) + grabc->geom.y + grabc->geom.height); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); + break; ++ case Curmfact: ++ setfloating(grabc, 0); ++ selmon->mfact = (float) (cursor->x / selmon->m.width); ++ arrange(selmon); + } + } + +-- +2.43.2 + diff --git a/dwl/dwl-patches/patches/dragresize/README.md b/dwl/dwl-patches/patches/dragresize/README.md new file mode 100755 index 0000000..c890ce7 --- /dev/null +++ b/dwl/dwl-patches/patches/dragresize/README.md @@ -0,0 +1,12 @@ +### Description +implement rio-like window resizing + +select window to resize (mod+middleclick by default) then drag out an area for it to occupy + +### Download +- [git branch](https://codeberg.org/notchoc/dwl/src/branch/dragresize) +- [2024-07-10](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragresize/dragresize.patch) +- [2024-06-19](https://codeberg.org/dwl/dwl-patches/raw/commit/8c75e6dbc1728bf70d42547222464f496d9ea613/patches/dragresize/dragresize.patch) + +### Authors +- [notchoc](https://codeberg.org/notchoc) diff --git a/dwl/dwl-patches/patches/dragresize/dragresize.patch b/dwl/dwl-patches/patches/dragresize/dragresize.patch new file mode 100755 index 0000000..1e4cfe0 --- /dev/null +++ b/dwl/dwl-patches/patches/dragresize/dragresize.patch @@ -0,0 +1,210 @@ +From 83ae7d4816a49f46063ab16ffecd32b2e7e61784 Mon Sep 17 00:00:00 2001 +From: choc +Date: Fri, 15 Sep 2023 11:45:16 +0800 +Subject: [PATCH] dragresize: implement rio-like window resizing + +select window to resize then drag out an area for it to occupy +--- + dwl.c | 132 +++++++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 98 insertions(+), 34 deletions(-) + +diff --git a/dwl.c b/dwl.c +index dc0437e..843aa7a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -80,7 +80,7 @@ + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) + + /* enums */ +-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ ++enum { CurNormal, CurPressed, CurSelect, CurMove, CurResize, CurBind }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ + #ifdef XWAYLAND +@@ -603,15 +603,21 @@ buttonpress(struct wl_listener *listener, void *data) + + switch (event->state) { + case WLR_BUTTON_PRESSED: +- cursor_mode = CurPressed; + selmon = xytomon(cursor->x, cursor->y); +- if (locked) ++ if (locked) { ++ cursor_mode = CurPressed; + break; ++ } + +- /* Change focus if the button was _pressed_ over a client */ +- xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); +- if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) +- focusclient(c, 1); ++ if (cursor_mode == CurNormal) ++ cursor_mode = CurPressed; ++ ++ if (cursor_mode != CurResize) { ++ /* Change focus if the button was _pressed_ over a client */ ++ xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); ++ if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) ++ focusclient(c, 1); ++ } + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; +@@ -624,17 +630,42 @@ buttonpress(struct wl_listener *listener, void *data) + } + break; + case WLR_BUTTON_RELEASED: ++ if (locked) { ++ cursor_mode = CurNormal; ++ break; ++ } + /* If you released any buttons, we exit interactive move/resize mode. */ +- /* TODO should reset to the pointer focus's current setcursor */ +- if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); ++ switch (cursor_mode) { ++ case CurPressed: + cursor_mode = CurNormal; +- /* Drop the window off on its new monitor */ +- selmon = xytomon(cursor->x, cursor->y); +- setmon(grabc, selmon, 0); ++ case CurNormal: ++ break; ++ case CurSelect: + return; +- } else { ++ case CurResize: ++ /* a label can only be part of a statement - Wpedantic */ ++ { ++ int nw = abs((int) cursor->x - grabcx); ++ int nh = abs((int) cursor->y - grabcy); ++ if (nw > 1 && nh > 1) { ++ setfloating(grabc, 1); ++ resize(grabc, (struct wlr_box){.x = MIN(ROUND(cursor->x), grabcx), ++ .y = MIN(ROUND(cursor->y), grabcy), ++ .width = nw, .height = nh}, 1); ++ } ++ } ++ /* fallthrough */ ++ default: ++ /* TODO should reset to the pointer focus's current setcursor */ ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); ++ /* Drop the window off on its new monitor */ ++ if (grabc && cursor_mode != CurBind) { ++ selmon = xytomon(cursor->x, cursor->y); ++ setmon(grabc, selmon, 0); ++ grabc = NULL; ++ } + cursor_mode = CurNormal; ++ return; + } + break; + } +@@ -1815,15 +1846,33 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); + + /* If we are currently grabbing the mouse, handle and return */ +- if (cursor_mode == CurMove) { ++ switch (cursor_mode) { ++ case CurSelect: ++ return; ++ case CurMove: + /* Move the grabbed client to the new position. */ + resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, + .width = grabc->geom.width, .height = grabc->geom.height}, 1); + return; +- } else if (cursor_mode == CurResize) { +- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); +- return; ++ case CurResize: ++ { ++ int w, h, x, y; ++ if (!grabc) ++ return; ++ w = abs(grabcx - (int)round(cursor->x)); ++ h = abs(grabcy - (int)round(cursor->y)); ++ x = MIN(grabcx, (int)round(cursor->x)) - grabc->geom.x; ++ y = MIN(grabcy, (int)round(cursor->y)) - grabc->geom.y; ++ wlr_scene_rect_set_size(grabc->border[0], w, grabc->bw); ++ wlr_scene_rect_set_size(grabc->border[1], w, grabc->bw); ++ wlr_scene_rect_set_size(grabc->border[2], grabc->bw, h - 2 * grabc->bw); ++ wlr_scene_rect_set_size(grabc->border[3], grabc->bw, h - 2 * grabc->bw); ++ wlr_scene_node_set_position(&grabc->border[0]->node, x, y); ++ wlr_scene_node_set_position(&grabc->border[1]->node, x, y + h - grabc->bw); ++ wlr_scene_node_set_position(&grabc->border[2]->node, x, y + grabc->bw); ++ wlr_scene_node_set_position(&grabc->border[3]->node, x + w - grabc->bw, y + grabc->bw); ++ return; ++ } + } + + /* If there's no client surface under the cursor, set the cursor image to a +@@ -1853,29 +1902,43 @@ motionrelative(struct wl_listener *listener, void *data) + void + moveresize(const Arg *arg) + { +- if (cursor_mode != CurNormal && cursor_mode != CurPressed) +- return; +- xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); +- if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) ++ /* Consider global select bool instead of this + CurSelect enum */ ++ bool selected = (cursor_mode == CurSelect); ++ if (!selected) { ++ if (cursor_mode != CurNormal && cursor_mode != CurPressed) ++ return; ++ xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); ++ } ++ ++ if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) { ++ grabc = NULL; ++ cursor_mode = CurNormal; + return; ++ } + +- /* Float the window and tell motionnotify to grab it */ +- setfloating(grabc, 1); ++ /* TODO: factor out selected bool */ + switch (cursor_mode = arg->ui) { ++ case CurResize: ++ if (!selected) break; ++ grabcx = ROUND(cursor->x); ++ grabcy = ROUND(cursor->y); ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "tcross"); ++ return; + case CurMove: + grabcx = (int)round(cursor->x) - grabc->geom.x; + grabcy = (int)round(cursor->y) - grabc->geom.y; ++ setfloating(grabc, 1); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); +- break; +- case CurResize: +- /* Doesn't work for X11 output - the next absolute motion event +- * returns the cursor to where it started */ +- wlr_cursor_warp_closest(cursor, NULL, +- grabc->geom.x + grabc->geom.width, +- grabc->geom.y + grabc->geom.height); +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); +- break; ++ return; ++ default: ++ grabc = NULL; ++ cursor_mode = CurNormal; ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); ++ return; + } ++ ++ cursor_mode = CurSelect; ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "crosshair"); + } + + void +@@ -2149,6 +2212,7 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); + wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); + wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); ++ wlr_scene_node_set_position(&c->border[0]->node, 0, 0); + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/en-keycodes/README.md b/dwl/dwl-patches/patches/en-keycodes/README.md new file mode 100755 index 0000000..ee3aae4 --- /dev/null +++ b/dwl/dwl-patches/patches/en-keycodes/README.md @@ -0,0 +1,11 @@ +### Description +Always use the English keymap to get keycodes, so key bindings work even when using a non-English keyboard layout. + +### Download +- [git branch](https://codeberg.org/ForzCross/dwl/src/branch/en-keycodes.patch) +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/en-keycodes/en-keycodes.patch) + +### Authors +- [ForzCross](https://codeberg.org/ForzCross) +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) +- [dimkr](https://codeberg.org/dimkr) () diff --git a/dwl/dwl-patches/patches/en-keycodes/en-keycodes.patch b/dwl/dwl-patches/patches/en-keycodes/en-keycodes.patch new file mode 100755 index 0000000..445d900 --- /dev/null +++ b/dwl/dwl-patches/patches/en-keycodes/en-keycodes.patch @@ -0,0 +1,73 @@ +From cd61fac9cb6e9d0172e2f7a01e6a514d676ba5f0 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Tue, 4 Feb 2025 23:53:11 +0100 +Subject: [PATCH] Always use the English keymap to get keycodes + +--- + dwl.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/dwl.c b/dwl.c +index def2562..c299365 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -413,6 +413,11 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static const struct xkb_rule_names en_rules = {.layout = "us"}; ++static struct xkb_context *en_context; ++static struct xkb_keymap *en_keymap; ++static struct xkb_state *en_state; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -694,6 +699,9 @@ cleanup(void) + wlr_backend_destroy(backend); + + wl_display_destroy(dpy); ++ xkb_state_unref(en_state); ++ xkb_keymap_unref(en_keymap); ++ xkb_context_unref(en_context); + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); +@@ -1582,16 +1590,19 @@ keypress(struct wl_listener *listener, void *data) + /* This event is raised when a key is pressed or released. */ + KeyboardGroup *group = wl_container_of(listener, group, key); + struct wlr_keyboard_key_event *event = data; ++ int nsyms, handled; + + /* Translate libinput keycode -> xkbcommon */ + uint32_t keycode = event->keycode + 8; + /* Get a list of keysyms based on the keymap for this keyboard */ + const xkb_keysym_t *syms; +- int nsyms = xkb_state_key_get_syms( +- group->wlr_group->keyboard.xkb_state, keycode, &syms); +- +- int handled = 0; + uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); ++ xkb_state_update_key(en_state, keycode, ++ (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) ++ ? XKB_KEY_DOWN : XKB_KEY_UP); ++ nsyms = xkb_state_key_get_syms(en_state, keycode, &syms); ++ ++ handled = 0; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + +@@ -2607,6 +2618,10 @@ setup(void) + * pointer, touch, and drawing tablet device. We also rig up a listener to + * let us know when new input devices are available on the backend. + */ ++ en_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); ++ en_keymap = xkb_keymap_new_from_names(en_context, &en_rules, ++ XKB_KEYMAP_COMPILE_NO_FLAGS); ++ en_state = xkb_state_new(en_keymap); + LISTEN_STATIC(&backend->events.new_input, inputdevice); + virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/envcfg/README.md b/dwl/dwl-patches/patches/envcfg/README.md new file mode 100755 index 0000000..07e5547 --- /dev/null +++ b/dwl/dwl-patches/patches/envcfg/README.md @@ -0,0 +1,8 @@ +### Description +Input device configuration (click method, tap-and-drag, acceleration, etc), border size and colors via environment variables. + +### Download +- [2024-02-11](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/envcfg/envcfg.patch) + +### Authors +- [Dima Krasner](https://codeberg.org/dimkr) () diff --git a/dwl/dwl-patches/patches/envcfg/envcfg.patch b/dwl/dwl-patches/patches/envcfg/envcfg.patch new file mode 100755 index 0000000..ca9328d --- /dev/null +++ b/dwl/dwl-patches/patches/envcfg/envcfg.patch @@ -0,0 +1,302 @@ +From 3c3ea42cd50bfa5111be69b3c1f71afa0443bb53 Mon Sep 17 00:00:00 2001 +From: Dima Krasner +Date: Sat, 30 Dec 2023 10:49:48 +0200 +Subject: [PATCH] allow environment variables to override config.h + +--- + Makefile | 1 + + config.def.h | 10 +-- + dwl.c | 5 ++ + env.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 228 insertions(+), 5 deletions(-) + create mode 100644 env.c + +diff --git a/Makefile b/Makefile +index 9308656..c66d376 100644 +--- a/Makefile ++++ b/Makefile +@@ -22,6 +22,7 @@ dwl: dwl.o util.o + dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++dwl.o: env.c + util.o: util.c util.h + + # wayland-scanner is a tool which generates C headers and rigging for Wayland +diff --git a/config.def.h b/config.def.h +index a784eb4..e0f10de 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,11 +6,11 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ +-static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); +-static const float bordercolor[] = COLOR(0x444444ff); +-static const float focuscolor[] = COLOR(0x005577ff); +-static const float urgentcolor[] = COLOR(0xff0000ff); ++static unsigned int borderpx = 1; /* border pixel of windows */ ++static float rootcolor[] = COLOR(0x222222ff); ++static float bordercolor[] = COLOR(0x444444ff); ++static float focuscolor[] = COLOR(0x005577ff); ++static float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ + +diff --git a/dwl.c b/dwl.c +index d48bf40..de33dfe 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -429,6 +429,8 @@ static xcb_atom_t netatom[NetLast]; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++#include "env.c" ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -1082,6 +1084,8 @@ createpointer(struct wlr_pointer *pointer) + libinput_device_config_accel_set_profile(device, accel_profile); + libinput_device_config_accel_set_speed(device, accel_speed); + } ++ ++ inputconfig(device); + } + + wlr_cursor_attach_input_device(cursor, &pointer->base); +@@ -3141,6 +3145,7 @@ main(int argc, char *argv[]) + /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */ + if (!getenv("XDG_RUNTIME_DIR")) + die("XDG_RUNTIME_DIR must be set"); ++ loadtheme(); + setup(); + run(startup_cmd); + cleanup(); +diff --git a/env.c b/env.c +new file mode 100644 +index 0000000..618f81e +--- /dev/null ++++ b/env.c +@@ -0,0 +1,217 @@ ++static int ++isenabled(const char *val, int def) ++{ ++ return ((def && (!val || !val[0] || (val[0] != '0'))) || (!def && (val && val[0] && (val[0] != '0')))); ++} ++ ++static void ++setclickmethod(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ long l; ++ char *end = NULL; ++ ++ val = getenv("LIBINPUT_DEFAULT_CLICK_METHOD"); ++ if (!val || !val[0]) ++ return; ++ ++ errno = 0; ++ l = strtol(val, &end, 10); ++ if (errno || (end && *end)) ++ return; ++ ++ libinput_device_config_click_set_method(libinput_device, ++ (enum libinput_config_click_method)l); ++} ++ ++static void ++settap(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ ++ val = getenv("LIBINPUT_DEFAULT_TAP"); ++ if (val) { ++ if (!val[0]) ++ return; ++ ++ libinput_device_config_tap_set_enabled(libinput_device, ++ isenabled(val, 1) ? LIBINPUT_CONFIG_TAP_ENABLED : ++ LIBINPUT_CONFIG_TAP_DISABLED); ++ } else if (tap_to_click && libinput_device_config_tap_get_finger_count(libinput_device)) ++ libinput_device_config_tap_set_enabled(libinput_device, ++ LIBINPUT_CONFIG_TAP_ENABLED); ++} ++ ++static void ++settapanddrag(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ ++ val = getenv("LIBINPUT_DEFAULT_DRAG"); ++ if (val && val[0]) ++ libinput_device_config_tap_set_drag_enabled(libinput_device, ++ isenabled(val, 1) ? LIBINPUT_CONFIG_DRAG_ENABLED : ++ LIBINPUT_CONFIG_DRAG_DISABLED); ++} ++ ++static void ++setnaturalscroll(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ ++ val = getenv("LIBINPUT_DEFAULT_NATURAL_SCROLL"); ++ if (val && val[0]) ++ libinput_device_config_scroll_set_natural_scroll_enabled( ++ libinput_device, isenabled(val, 0)); ++ else if (!val && libinput_device_config_scroll_has_natural_scroll(libinput_device)) ++ libinput_device_config_scroll_set_natural_scroll_enabled( ++ libinput_device, natural_scrolling); ++} ++ ++static void ++setaccelprofile(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ double profile; ++ char *end = NULL; ++ ++ val = getenv("LIBINPUT_DEFAULT_ACCELERATION_PROFILE"); ++ if (!val || !val[0]) ++ return; ++ ++ errno = 0; ++ profile = strtod(val, &end); ++ if (errno || (end && *end)) ++ return; ++ ++ libinput_device_config_accel_set_profile(libinput_device, ++ (enum libinput_config_accel_profile)profile); ++} ++ ++static void ++setaccelspeed(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ double accel = 0; ++ char *end = NULL; ++ ++ val = getenv("LIBINPUT_DEFAULT_ACCELERATION"); ++ if (!val || !val[0]) ++ return; ++ ++ errno = 0; ++ accel = strtod(val, &end); ++ if (errno || (end && *end) || (accel < -1) || (accel > 1)) ++ return; ++ ++ libinput_device_config_accel_set_speed(libinput_device, accel); ++} ++ ++static void ++setscrollmethod(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ long l; ++ char *end = NULL; ++ ++ val = getenv("LIBINPUT_DEFAULT_SCROLL_METHOD"); ++ if (!val || !val[0]) ++ return; ++ ++ errno = 0; ++ l = strtol(val, &end, 10); ++ if (errno || (end && *end)) ++ return; ++ ++ libinput_device_config_scroll_set_method(libinput_device, ++ (enum libinput_config_scroll_method)l); ++} ++ ++static void ++setdwt(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ ++ val = getenv("LIBINPUT_DEFAULT_DISABLE_WHILE_TYPING"); ++ if (val && val[0]) ++ libinput_device_config_dwt_set_enabled(libinput_device, ++ isenabled(val, false) ? LIBINPUT_CONFIG_DWT_ENABLED : ++ LIBINPUT_CONFIG_DWT_DISABLED); ++} ++ ++static void ++setmiddleemul(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ ++ val = getenv("LIBINPUT_DEFAULT_MIDDLE_EMULATION"); ++ if (val && val[0]) ++ libinput_device_config_middle_emulation_set_enabled(libinput_device, ++ isenabled(val, false) ? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED : ++ LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); ++} ++ ++static void ++setlefthanded(struct libinput_device *libinput_device) ++{ ++ const char *val; ++ ++ val = getenv("LIBINPUT_DEFAULT_LEFT_HANDED"); ++ if (val && val[0]) ++ libinput_device_config_left_handed_set(libinput_device, ++ isenabled(val, 0)); ++} ++ ++static void ++inputconfig(struct libinput_device *libinput_device) ++{ ++ setclickmethod(libinput_device); ++ settap(libinput_device); ++ settapanddrag(libinput_device); ++ setnaturalscroll(libinput_device); ++ setaccelprofile(libinput_device); ++ setaccelspeed(libinput_device); ++ setscrollmethod(libinput_device); ++ setdwt(libinput_device); ++ setmiddleemul(libinput_device); ++ setlefthanded(libinput_device); ++} ++ ++static void ++parsecolor(const char *val, float color[4]) ++{ ++ uint8_t r, g, b; ++ if (sscanf(val, "#%02hhx%02hhx%02hhx", &r, &g, &b) == 3) { ++ color[0] = (float)r / 0xFF; ++ color[1] = (float)g / 0xFF; ++ color[2] = (float)b / 0xFF; ++ color[3] = 1.0; ++ } ++} ++ ++static void ++loadtheme(void) ++{ ++ const char *val; ++ unsigned int tmp; ++ ++ val = getenv("DWL_ROOT_COLOR"); ++ if (val) ++ parsecolor(val, rootcolor); ++ ++ val = getenv("DWL_BORDER_COLOR"); ++ if (val) ++ parsecolor(val, bordercolor); ++ ++ val = getenv("DWL_FOCUS_COLOR"); ++ if (val) ++ parsecolor(val, focuscolor); ++ ++ val = getenv("DWL_URGENT_COLOR"); ++ if (val) ++ parsecolor(val, urgentcolor); ++ ++ val = getenv("DWL_BORDER"); ++ if (val && sscanf(val, "%u", &tmp) == 1) ++ borderpx = tmp; ++} +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/fakefullscreenclient/README.md b/dwl/dwl-patches/patches/fakefullscreenclient/README.md new file mode 100755 index 0000000..6a98f0d --- /dev/null +++ b/dwl/dwl-patches/patches/fakefullscreenclient/README.md @@ -0,0 +1,8 @@ +### Description +Allow setting fake fullscreen per client + +### Download +- [git branch](https://codeberg.org/notchoc/dwl/src/branch/fakefullscreenclient) +- [2024-03-29](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fakefullscreenclient/fakefullscreenclient.patch) +### Authors +- [notchoc](https://codeberg.org/notchoc) diff --git a/dwl/dwl-patches/patches/fakefullscreenclient/fakefullscreenclient.patch b/dwl/dwl-patches/patches/fakefullscreenclient/fakefullscreenclient.patch new file mode 100755 index 0000000..848f350 --- /dev/null +++ b/dwl/dwl-patches/patches/fakefullscreenclient/fakefullscreenclient.patch @@ -0,0 +1,87 @@ +From 2ec6d0c668b4daee601337f8da45ccfa3a7d5fc6 Mon Sep 17 00:00:00 2001 +From: choc +Date: Fri, 29 Mar 2024 22:50:00 +0800 +Subject: [PATCH] implement fakefullscreenclient + +--- + config.def.h | 1 + + dwl.c | 23 ++++++++++++++++++++++- + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 9009517..8c220eb 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -137,6 +137,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_E, togglefakefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index 5867b0c..1e78491 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -137,7 +137,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, isfakefullscreen; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -318,6 +318,7 @@ static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); + static void setfullscreen(Client *c, int fullscreen); ++static void setfakefullscreen(Client *c, int fullscreen); + static void setgamma(struct wl_listener *listener, void *data); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); +@@ -332,6 +333,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglefakefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -2181,6 +2183,17 @@ setfullscreen(Client *c, int fullscreen) + printstatus(); + } + ++void ++setfakefullscreen(Client *c, int fullscreen) ++{ ++ c->isfakefullscreen = fullscreen; ++ if (!c->mon) ++ return; ++ if (c->isfullscreen) ++ setfullscreen(c, 0); ++ client_set_fullscreen(c, fullscreen); ++} ++ + void + setgamma(struct wl_listener *listener, void *data) + { +@@ -2620,6 +2633,14 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglefakefullscreen(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ if (sel) ++ setfakefullscreen(sel, !sel->isfakefullscreen); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/fallback/README.md b/dwl/dwl-patches/patches/fallback/README.md new file mode 100755 index 0000000..e9de8f4 --- /dev/null +++ b/dwl/dwl-patches/patches/fallback/README.md @@ -0,0 +1,8 @@ +### Description +Tries a different display mode if the preferred mode doesn't work. + +### Download +- [2024-02-11](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fallback/fallback.patch) + +### Authors +- [Dima Krasner](https://codeberg.org/dimkr) () diff --git a/dwl/dwl-patches/patches/fallback/fallback.patch b/dwl/dwl-patches/patches/fallback/fallback.patch new file mode 100755 index 0000000..b734625 --- /dev/null +++ b/dwl/dwl-patches/patches/fallback/fallback.patch @@ -0,0 +1,44 @@ +From a94c52af879027e654f67c36621a8c9b2f338f56 Mon Sep 17 00:00:00 2001 +From: Dima Krasner +Date: Sat, 2 Dec 2023 10:36:35 +0200 +Subject: [PATCH] fall back to a lower output mode if needed + (swaywm/sway@4cdc4ac) + +--- + dwl.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index d48bf40..7719f7e 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -920,6 +920,7 @@ createmon(struct wl_listener *listener, void *data) + /* This event is raised by the backend when a new output (aka a display or + * monitor) becomes available. */ + struct wlr_output *wlr_output = data; ++ struct wlr_output_mode *preferred_mode, *mode; + const MonitorRule *r; + size_t i; + struct wlr_output_state state; +@@ -956,7 +957,17 @@ createmon(struct wl_listener *listener, void *data) + * monitor supports only a specific set of modes. We just pick the + * monitor's preferred mode; a more sophisticated compositor would let + * the user configure it. */ +- wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); ++ preferred_mode = wlr_output_preferred_mode(wlr_output); ++ wlr_output_state_set_mode(&state, preferred_mode); ++ if (!wlr_output_test_state(wlr_output, &state) && !wl_list_empty(&wlr_output->modes)) { ++ wl_list_for_each(mode, &wlr_output->modes, link) { ++ if (mode != preferred_mode) { ++ wlr_output_state_set_mode(&state, mode); ++ if (wlr_output_test_state(wlr_output, &state)) ++ break; ++ } ++ } ++ } + + /* Set up event listeners */ + LISTEN(&wlr_output->events.frame, &m->frame, rendermon); +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/focusdir/README.md b/dwl/dwl-patches/patches/focusdir/README.md new file mode 100755 index 0000000..a2ed478 --- /dev/null +++ b/dwl/dwl-patches/patches/focusdir/README.md @@ -0,0 +1,9 @@ +### Description +Focus the window to the left, right, above or below the current focused window + +### Download +- [git branch](https://codeberg.org/ldev105/dwl/src/branch/focusdir) +- [2023-01-22](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/focusdir/focusdir.patch) + +### Authors +- [ldev105](https://codeberg.org/ldev105) diff --git a/dwl/dwl-patches/patches/focusdir/focusdir.patch b/dwl/dwl-patches/patches/focusdir/focusdir.patch new file mode 100755 index 0000000..72b8c5a --- /dev/null +++ b/dwl/dwl-patches/patches/focusdir/focusdir.patch @@ -0,0 +1,98 @@ +From a0e71a687b7fcaebdaf1da80c09bf5563bff46b1 Mon Sep 17 00:00:00 2001 +From: ldev +Date: Mon, 12 Feb 2024 21:50:24 +0100 +Subject: [PATCH] focusdir + +--- + config.def.h | 4 ++++ + dwl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 9009517..2a1a82e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -124,6 +124,10 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_h, focusdir, {.ui = 0} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_l, focusdir, {.ui = 1} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_k, focusdir, {.ui = 2} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_j, focusdir, {.ui = 3} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +diff --git a/dwl.c b/dwl.c +index bf02a6d..64d5de7 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1,6 +1,7 @@ + /* + * See LICENSE file for copyright and license details. + */ ++#include + #include + #include + #include +@@ -268,6 +269,7 @@ static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); ++static void focusdir(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); +@@ -1271,6 +1273,49 @@ focusstack(const Arg *arg) + focusclient(c, 1); + } + ++void focusdir(const Arg *arg) ++{ ++ /* Focus the left, right, up, down client relative to the current focused client on selmon */ ++ Client *c, *sel = focustop(selmon); ++ if (!sel || sel->isfullscreen) ++ return; ++ ++ int dist=INT_MAX; ++ Client *newsel = NULL; ++ int newdist=INT_MAX; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, selmon)) ++ continue; /* skip non visible windows */ ++ ++ if (arg->ui == 0 && sel->geom.x <= c->geom.x) { ++ /* Client isn't on our left */ ++ continue; ++ } ++ if (arg->ui == 1 && sel->geom.x >= c->geom.x) { ++ /* Client isn't on our right */ ++ continue; ++ } ++ if (arg->ui == 2 && sel->geom.y <= c->geom.y) { ++ /* Client isn't above us */ ++ continue; ++ } ++ if (arg->ui == 3 && sel->geom.y >= c->geom.y) { ++ /* Client isn't below us */ ++ continue; ++ } ++ ++ dist=abs(sel->geom.x-c->geom.x)+abs(sel->geom.y-c->geom.y); ++ if (dist < newdist){ ++ newdist = dist; ++ newsel=c; ++ } ++ } ++ if (newsel != NULL){ ++ focusclient(newsel, 1); ++ } ++} ++ ++ + /* We probably should change the name of this, it sounds like + * will focus the topmost client of this mon, when actually will + * only return that client */ +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/follow/README.md b/dwl/dwl-patches/patches/follow/README.md new file mode 100755 index 0000000..d2597cd --- /dev/null +++ b/dwl/dwl-patches/patches/follow/README.md @@ -0,0 +1,10 @@ +### Description +An extremely simple patch that adds the option to change DWL's window sending behavior; when active, sent windows will be followed, i.e. when a window is sent to another tag, the view changes to that tag.
No dependencies. + +![](follow.webp) + +### Download +- [v0.7](/dwl/dwl-patches/raw/branch/main/patches/follow/follow.patch)
Targets tag v0.7, but also works on git master and v0.6. + +### Author +- [moonsabre](https://codeberg.org/moonsabre) diff --git a/dwl/dwl-patches/patches/follow/follow.patch b/dwl/dwl-patches/patches/follow/follow.patch new file mode 100755 index 0000000..d260a75 --- /dev/null +++ b/dwl/dwl-patches/patches/follow/follow.patch @@ -0,0 +1,38 @@ +From c4de366aa5e2a465f5e2963f4ffed7adde77929a Mon Sep 17 00:00:00 2001 +From: moonsabre +Date: Thu, 13 Mar 2025 14:36:49 -0700 +Subject: [PATCH] Add parameter for following sent windows. + +--- + config.def.h | 1 + + dwl.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..cdbdc72 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,6 +6,7 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ ++static const int follow = 1; /* 1 means follow windows when sent to another tag */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); +diff --git a/dwl.c b/dwl.c +index a2711f6..d2cf8ba 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2677,6 +2677,8 @@ tag(const Arg *arg) + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); ++ if (follow == 1) ++ view(arg); + printstatus(); + } + +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/follow/follow.webp b/dwl/dwl-patches/patches/follow/follow.webp new file mode 100755 index 0000000..b629315 Binary files /dev/null and b/dwl/dwl-patches/patches/follow/follow.webp differ diff --git a/dwl/dwl-patches/patches/foreign-toplevel-management/README.md b/dwl/dwl-patches/patches/foreign-toplevel-management/README.md new file mode 100755 index 0000000..6e30328 --- /dev/null +++ b/dwl/dwl-patches/patches/foreign-toplevel-management/README.md @@ -0,0 +1,9 @@ +### Description +Implement `foreign-toplevel-management`, it add handlers for activate, close, fullscreen and destroy request events, it's missing minimize and maximize request handlers. + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.6-a/foreign-toplevel-management) +- [2024-05-02](https://codeberg.org/dwl/dwl-patches/raw/commit/e58c3ec41a39df934d2998161d7187ac965ea77a/foreign-toplevel-management/foreign-toplevel-management.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/foreign-toplevel-management/foreign-toplevel-management.patch b/dwl/dwl-patches/patches/foreign-toplevel-management/foreign-toplevel-management.patch new file mode 100755 index 0000000..3dfa14f --- /dev/null +++ b/dwl/dwl-patches/patches/foreign-toplevel-management/foreign-toplevel-management.patch @@ -0,0 +1,507 @@ +From dc63d64cd69f515013464b3feb8acb411f5a348f Mon Sep 17 00:00:00 2001 +From: wochap +Date: Thu, 2 May 2024 17:25:45 -0500 +Subject: [PATCH] implement foreign toplevel management + +--- + Makefile | 5 +- + dwl.c | 93 +++++- + ...oreign-toplevel-management-unstable-v1.xml | 270 ++++++++++++++++++ + 3 files changed, 366 insertions(+), 2 deletions(-) + create mode 100644 protocols/wlr-foreign-toplevel-management-unstable-v1.xml + +diff --git a/Makefile b/Makefile +index a67fdd3..e0e1260 100644 +--- a/Makefile ++++ b/Makefile +@@ -16,7 +16,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS) + all: dwl + dwl: dwl.o util.o + $(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@ +-dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h ++dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h wlr-foreign-toplevel-management-unstable-v1-protocol.h + util.o: util.c util.h + + # wayland-scanner is a tool which generates C headers and rigging for Wayland +@@ -37,6 +37,9 @@ wlr-layer-shell-unstable-v1-protocol.h: + xdg-shell-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ ++wlr-foreign-toplevel-management-unstable-v1-protocol.h: ++ $(WAYLAND_SCANNER) server-header \ ++ protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@ + + config.h: + cp config.def.h $@ +diff --git a/dwl.c b/dwl.c +index bf763df..648616d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -126,6 +127,11 @@ typedef struct { + struct wl_listener fullscreen; + struct wl_listener set_decoration_mode; + struct wl_listener destroy_decoration; ++ struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; ++ struct wl_listener factivate; ++ struct wl_listener fclose; ++ struct wl_listener ffullscreen; ++ struct wl_listener fdestroy; + struct wlr_box prev; /* layout-relative, includes border */ + struct wlr_box bounds; + #ifdef XWAYLAND +@@ -347,6 +353,11 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void createforeigntoplevel(Client *c); ++static void factivatenotify(struct wl_listener *listener, void *data); ++static void fclosenotify(struct wl_listener *listener, void *data); ++static void fdestroynotify(struct wl_listener *listener, void *data); ++static void ffullscreennotify(struct wl_listener *listener, void *data); + + /* variables */ + static const char broken[] = "broken"; +@@ -392,6 +403,8 @@ static struct wlr_scene_rect *locked_bg; + static struct wlr_session_lock_v1 *cur_lock; + static struct wl_listener lock_listener = {.notify = locksession}; + ++static struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_mgr; ++ + static struct wlr_seat *seat; + static KeyboardGroup kb_group = {0}; + static KeyboardGroup vkb_group = {0}; +@@ -458,6 +471,11 @@ applyrules(Client *c) + if (!(title = client_get_title(c))) + title = broken; + ++ if (c->foreign_toplevel) { ++ wlr_foreign_toplevel_handle_v1_set_app_id(c->foreign_toplevel, appid); ++ wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title); ++ } ++ + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { +@@ -1288,6 +1306,8 @@ focusclient(Client *c, int lift) + client_set_border_color(old_c, bordercolor); + + client_activate_surface(old, 0); ++ if (old_c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_set_activated(old_c->foreign_toplevel, 0); + } + } + printstatus(); +@@ -1306,6 +1326,8 @@ focusclient(Client *c, int lift) + + /* Activate the new client */ + client_activate_surface(client_surface(c), 1); ++ if (c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, 1); + } + + void +@@ -1599,6 +1621,8 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ createforeigntoplevel(c); ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -2232,12 +2256,17 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + c->prev = c->geom; + + /* Scene graph sends surface leave/enter events on move and resize */ +- if (oldmon) ++ if (oldmon) { ++ if (c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_output_leave(c->foreign_toplevel, oldmon->wlr_output); + arrange(oldmon); ++ } + if (m) { + /* Make sure window actually overlaps with the monitor */ + resize(c, c->geom, 0); + c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ ++ if (c->foreign_toplevel) ++ wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel, m->wlr_output); + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); + } +@@ -2351,6 +2380,9 @@ setup(void) + gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy); + LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma); + ++ /* Initializes foreign toplevel management */ ++ foreign_toplevel_mgr = wlr_foreign_toplevel_manager_v1_create(dpy); ++ + /* Creates an output layout, which a wlroots utility for working with an + * arrangement of screens in a physical layout. */ + output_layout = wlr_output_layout_create(); +@@ -2691,6 +2723,11 @@ unmapnotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->flink); + } + ++ if (c->foreign_toplevel) { ++ wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel); ++ c->foreign_toplevel = NULL; ++ } ++ + wlr_scene_node_destroy(&c->scene->node); + printstatus(); + motionnotify(0, NULL, 0, 0, 0, 0); +@@ -2802,6 +2839,12 @@ void + updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); ++ if (c->foreign_toplevel) { ++ const char *title; ++ if (!(title = client_get_title(c))) ++ title = broken; ++ wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title); ++ } + if (c == focustop(c->mon)) + printstatus(); + } +@@ -2929,6 +2972,54 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++void ++createforeigntoplevel(Client *c) ++{ ++ c->foreign_toplevel = wlr_foreign_toplevel_handle_v1_create(foreign_toplevel_mgr); ++ ++ LISTEN(&c->foreign_toplevel->events.request_activate, &c->factivate, factivatenotify); ++ LISTEN(&c->foreign_toplevel->events.request_close, &c->fclose, fclosenotify); ++ LISTEN(&c->foreign_toplevel->events.request_fullscreen, &c->ffullscreen, ffullscreennotify); ++ LISTEN(&c->foreign_toplevel->events.destroy, &c->fdestroy, fdestroynotify); ++} ++ ++void ++factivatenotify(struct wl_listener *listener, void *data) ++{ ++ Client *c = wl_container_of(listener, c, factivate); ++ if (c->mon == selmon) { ++ c->tags = c->mon->tagset[c->mon->seltags]; ++ } else { ++ setmon(c, selmon, 0); ++ } ++ focusclient(c, 1); ++ arrange(c->mon); ++} ++ ++void ++fclosenotify(struct wl_listener *listener, void *data) ++{ ++ Client *c = wl_container_of(listener, c, fclose); ++ client_send_close(c); ++} ++ ++void ++ffullscreennotify(struct wl_listener *listener, void *data) { ++ Client *c = wl_container_of(listener, c, ffullscreen); ++ struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data; ++ setfullscreen(c, event->fullscreen); ++} ++ ++void ++fdestroynotify(struct wl_listener *listener, void *data) ++{ ++ Client *c = wl_container_of(listener, c, fdestroy); ++ wl_list_remove(&c->factivate.link); ++ wl_list_remove(&c->fclose.link); ++ wl_list_remove(&c->ffullscreen.link); ++ wl_list_remove(&c->fdestroy.link); ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +diff --git a/protocols/wlr-foreign-toplevel-management-unstable-v1.xml b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml +new file mode 100644 +index 0000000..44505bb +--- /dev/null ++++ b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml +@@ -0,0 +1,270 @@ ++ ++ ++ ++ Copyright © 2018 Ilia Bozhinov ++ ++ Permission to use, copy, modify, distribute, and sell this ++ software and its documentation for any purpose is hereby granted ++ without fee, provided that the above copyright notice appear in ++ all copies and that both that copyright notice and this permission ++ notice appear in supporting documentation, and that the name of ++ the copyright holders not be used in advertising or publicity ++ pertaining to distribution of the software without specific, ++ written prior permission. The copyright holders make no ++ representations about the suitability of this software for any ++ purpose. It is provided "as is" without express or implied ++ warranty. ++ ++ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS ++ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY ++ SPECIAL, 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. ++ ++ ++ ++ ++ The purpose of this protocol is to enable the creation of taskbars ++ and docks by providing them with a list of opened applications and ++ letting them request certain actions on them, like maximizing, etc. ++ ++ After a client binds the zwlr_foreign_toplevel_manager_v1, each opened ++ toplevel window will be sent via the toplevel event ++ ++ ++ ++ ++ This event is emitted whenever a new toplevel window is created. It ++ is emitted for all toplevels, regardless of the app that has created ++ them. ++ ++ All initial details of the toplevel(title, app_id, states, etc.) will ++ be sent immediately after this event via the corresponding events in ++ zwlr_foreign_toplevel_handle_v1. ++ ++ ++ ++ ++ ++ ++ Indicates the client no longer wishes to receive events for new toplevels. ++ However the compositor may emit further toplevel_created events, until ++ the finished event is emitted. ++ ++ The client must not send any more requests after this one. ++ ++ ++ ++ ++ ++ This event indicates that the compositor is done sending events to the ++ zwlr_foreign_toplevel_manager_v1. The server will destroy the object ++ immediately after sending this request, so it will become invalid and ++ the client should free any resources associated with it. ++ ++ ++ ++ ++ ++ ++ A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel ++ window. Each app may have multiple opened toplevels. ++ ++ Each toplevel has a list of outputs it is visible on, conveyed to the ++ client with the output_enter and output_leave events. ++ ++ ++ ++ ++ This event is emitted whenever the title of the toplevel changes. ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the app-id of the toplevel changes. ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the toplevel becomes visible on ++ the given output. A toplevel may be visible on multiple outputs. ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the toplevel stops being visible on ++ the given output. It is guaranteed that an entered-output event ++ with the same output has been emitted before this event. ++ ++ ++ ++ ++ ++ ++ Requests that the toplevel be maximized. If the maximized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Requests that the toplevel be unmaximized. If the maximized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Requests that the toplevel be minimized. If the minimized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Requests that the toplevel be unminimized. If the minimized state actually ++ changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ Request that this toplevel be activated on the given seat. ++ There is no guarantee the toplevel will be actually activated. ++ ++ ++ ++ ++ ++ ++ The different states that a toplevel can have. These have the same meaning ++ as the states with the same names defined in xdg-toplevel ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This event is emitted immediately after the zlw_foreign_toplevel_handle_v1 ++ is created and each time the toplevel state changes, either because of a ++ compositor action or because of a request in this protocol. ++ ++ ++ ++ ++ ++ ++ ++ This event is sent after all changes in the toplevel state have been ++ sent. ++ ++ This allows changes to the zwlr_foreign_toplevel_handle_v1 properties ++ to be seen as atomic, even if they happen via multiple events. ++ ++ ++ ++ ++ ++ Send a request to the toplevel to close itself. The compositor would ++ typically use a shell-specific method to carry out this request, for ++ example by sending the xdg_toplevel.close event. However, this gives ++ no guarantees the toplevel will actually be destroyed. If and when ++ this happens, the zwlr_foreign_toplevel_handle_v1.closed event will ++ be emitted. ++ ++ ++ ++ ++ ++ The rectangle of the surface specified in this request corresponds to ++ the place where the app using this protocol represents the given toplevel. ++ It can be used by the compositor as a hint for some operations, e.g ++ minimizing. The client is however not required to set this, in which ++ case the compositor is free to decide some default value. ++ ++ If the client specifies more than one rectangle, only the last one is ++ considered. ++ ++ The dimensions are given in surface-local coordinates. ++ Setting width=height=0 removes the already-set rectangle. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This event means the toplevel has been destroyed. It is guaranteed there ++ won't be any more events for this zwlr_foreign_toplevel_handle_v1. The ++ toplevel itself becomes inert so any requests will be ignored except the ++ destroy request. ++ ++ ++ ++ ++ ++ Destroys the zwlr_foreign_toplevel_handle_v1 object. ++ ++ This request should be called either when the client does not want to ++ use the toplevel anymore or after the closed event to finalize the ++ destruction of the object. ++ ++ ++ ++ ++ ++ ++ ++ Requests that the toplevel be fullscreened on the given output. If the ++ fullscreen state and/or the outputs the toplevel is visible on actually ++ change, this will be indicated by the state and output_enter/leave ++ events. ++ ++ The output parameter is only a hint to the compositor. Also, if output ++ is NULL, the compositor should decide which output the toplevel will be ++ fullscreened on, if at all. ++ ++ ++ ++ ++ ++ ++ Requests that the toplevel be unfullscreened. If the fullscreen state ++ actually changes, this will be indicated by the state event. ++ ++ ++ ++ ++ ++ ++ ++ This event is emitted whenever the parent of the toplevel changes. ++ ++ No event is emitted when the parent handle is destroyed by the client. ++ ++ ++ ++ ++ +-- +2.43.2 + diff --git a/dwl/dwl-patches/patches/fullscreenadaptivesync/README.md b/dwl/dwl-patches/patches/fullscreenadaptivesync/README.md new file mode 100755 index 0000000..6f7118c --- /dev/null +++ b/dwl/dwl-patches/patches/fullscreenadaptivesync/README.md @@ -0,0 +1,29 @@ +### Description + +# fullscreenadaptivesync — Enables adaptive sync/VRR when a client is fullscreen. + +Adds a function that automatically enables adaptive sync/VRR when a fullscreen client is detected, and disables it once the client exits fullscreen. + +--- + +1. **Why** + - Some VRR implementations can introduce distracting flickering when the display’s refresh rate is synced with the application’s framerate. While VRR is useful for some applications (especially fullscreen games), this patch automates the toggling of VRR whenever a client enters or exits fullscreen. + +2. **Requirements** + - A FreeSync/G-Sync capable monitor + - GPU/driver support for adaptive sync + +3. **How it works** + - When a client enters fullscreen, adaptive sync is automatically enabled. + - When the client exits fullscreen, adaptive sync is disabled again. + +4. **togglefullscreenadaptivesync** + - Adds a switch to enable or disable the fullscreenadaptivesync behavior. + - Enabled by default. + +### Download +- [git branch](https://codeberg.org/julmajustus/dwl/src/branch/fullscreenadaptivesync) +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fullscreenadaptivesync/fullscreenadaptivesync-v0.7.patch) + +### Authors +- [julmajustus](https://codeberg.org/julmajustus) diff --git a/dwl/dwl-patches/patches/fullscreenadaptivesync/fullscreenadaptivesync-v0.7.patch b/dwl/dwl-patches/patches/fullscreenadaptivesync/fullscreenadaptivesync-v0.7.patch new file mode 100755 index 0000000..ccc012b --- /dev/null +++ b/dwl/dwl-patches/patches/fullscreenadaptivesync/fullscreenadaptivesync-v0.7.patch @@ -0,0 +1,122 @@ +From c003f450c197a0c960bbb355511f8dca7a35e3c3 Mon Sep 17 00:00:00 2001 +From: julmajustus +Date: Sat, 4 Jan 2025 14:24:59 +0200 +Subject: [PATCH] add fullscreenadaptivesync + +--- + config.def.h | 1 + + dwl.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 41 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..886f1ab 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -142,6 +142,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_F5, togglefullscreenadaptivesync, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index a2711f6..7be05ef 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -322,6 +322,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void set_adaptive_sync(Monitor *m, int enabled); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -340,6 +341,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglefullscreenadaptivesync(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -413,6 +415,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static int fullscreen_adaptive_sync_enabled = 1; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -2269,6 +2273,31 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++void ++set_adaptive_sync(Monitor *m, int enable) ++{ ++ struct wlr_output_state state; ++ struct wlr_output_configuration_v1 *config; ++ struct wlr_output_configuration_head_v1 *config_head; ++ ++ if (!m || !m->wlr_output || !m->wlr_output->enabled ++ || !fullscreen_adaptive_sync_enabled) ++ return; ++ ++ config = wlr_output_configuration_v1_create(); ++ config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); ++ ++ /* Set and commit the adaptive sync state change */ ++ wlr_output_state_init(&state); ++ wlr_output_state_set_adaptive_sync_enabled(&state, enable); ++ wlr_output_commit_state(m->wlr_output, &state); ++ wlr_output_state_finish(&state); ++ ++ /* Broadcast the adaptive sync state change to output_mgr */ ++ config_head->state.adaptive_sync_enabled = enable; ++ wlr_output_manager_v1_set_configuration(output_mgr, config); ++} ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2332,10 +2361,12 @@ setfullscreen(Client *c, int fullscreen) + if (fullscreen) { + c->prev = c->geom; + resize(c, c->mon->m, 0); ++ set_adaptive_sync(c->mon, 1); + } else { + /* restore previous size instead of arrange for floating windows since + * client positions are set by the user and cannot be recalculated */ + resize(c, c->prev, 0); ++ set_adaptive_sync(c->mon, 0); + } + arrange(c->mon); + printstatus(); +@@ -2739,6 +2770,12 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglefullscreenadaptivesync(const Arg *arg) ++{ ++ fullscreen_adaptive_sync_enabled = !fullscreen_adaptive_sync_enabled; ++} ++ + void + toggletag(const Arg *arg) + { +@@ -2809,6 +2846,9 @@ unmapnotify(struct wl_listener *listener, void *data) + setmon(c, NULL, 0); + wl_list_remove(&c->flink); + } ++ /* Toggle adaptive sync off when fullscreen client is unmapped */ ++ if (c->isfullscreen) ++ set_adaptive_sync(selmon, 0); + + wlr_scene_node_destroy(&c->scene->node); + printstatus(); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/gaplessgrid/README.md b/dwl/dwl-patches/patches/gaplessgrid/README.md new file mode 100755 index 0000000..6921d54 --- /dev/null +++ b/dwl/dwl-patches/patches/gaplessgrid/README.md @@ -0,0 +1,19 @@ +### Description +Arranges windows in a grid. Except it adjusts the number of windows in the first few columns to avoid empty cells. + +On widescreens (w > 2*h), it splits to three columns before splitting rows. + +### Download +- [2024-09-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid.patch) +- [2024-07-14](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid-20240714.patch) +- [2023-08-01](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaplessgrid/gaplessgrid-20230801.patch) +- [git branch](https://codeberg.org/dhruva_sambrani/dwl/src/branch/gaplessgrid) + +## Pre-codeberg +- [2023-11-14](https://github.com/djpohly/dwl/compare/main...Sneethe:gaplessgrid.patch) +- [2021-07-27](https://github.com/djpohly/dwl/compare/main...vnepogodin:gaplessgrid.patch) + +### Authors +- [Sneethe](https://github.com/Sneethe/) +- [Vladislav Nepogodin](https://github.com/vnepogodin) +- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani/) (Revived to codeberg) diff --git a/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20230801.patch b/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20230801.patch new file mode 100755 index 0000000..2ade7da --- /dev/null +++ b/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20230801.patch @@ -0,0 +1,97 @@ +From 958cf2c2415927e2f7b471da9ada7c6e7d169a63 Mon Sep 17 00:00:00 2001 +From: Dhruva Sambrani <44899822+DhruvaSambrani@users.noreply.github.com> +Date: Mon, 8 Jan 2024 16:11:30 +0100 +Subject: [PATCH] revive gaplessgrid + +--- + config.def.h | 2 ++ + dwl.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a8ed61d..7400b7f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "###", gaplessgrid }, + }; + + /* monitors */ +@@ -134,6 +135,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_g, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index 632dabf..4d810f7 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -268,6 +268,7 @@ static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); ++static void gaplessgrid(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); +@@ -1311,6 +1312,51 @@ handlesig(int signo) + } + } + ++void ++gaplessgrid(Monitor *m) ++{ ++ unsigned int n = 0, i = 0, ch, cw, cn, rn, rows, cols; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating) ++ n++; ++ if (n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for (cols = 0; cols <= (n / 2); cols++) ++ if ((cols * cols) >= n) ++ break; ++ ++ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = n / cols; ++ ++ /* window geometries */ ++ cw = cols ? m->w.width / cols : m->w.width; ++ cn = 0; /* current column number */ ++ rn = 0; /* current row number */ ++ wl_list_for_each(c, &clients, link) { ++ unsigned int cx, cy; ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ ++ if ((i / rows + 1) > (cols - n % cols)) ++ rows = n / cols + 1; ++ ch = rows ? m->w.height / rows : m->w.height; ++ cx = m->w.x + cn * cw; ++ cy = m->w.y + rn * ch; ++ resize(c, (struct wlr_box) { cx, cy, cw, ch}, 0); ++ rn++; ++ if (rn >= rows) { ++ rn = 0; ++ cn++; ++ } ++ i++; ++ } ++} ++ + void + incnmaster(const Arg *arg) + { +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20240714.patch b/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20240714.patch new file mode 100755 index 0000000..cf430b9 --- /dev/null +++ b/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid-20240714.patch @@ -0,0 +1,89 @@ +diff --git a/config.def.h b/config.def.h +index 22d2171..014a909 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "###", gaplessgrid }, + }; + + /* monitors */ +@@ -139,6 +140,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_g, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index 145fd01..dae1d1a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -287,6 +287,7 @@ static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); ++static void gaplessgrid(Monitor *m); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +@@ -1467,6 +1468,56 @@ handlesig(int signo) + } + } + ++void ++gaplessgrid(Monitor *m) ++{ ++ unsigned int n = 0, i = 0, ch, cw, cn, rn, rows, cols; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating) ++ n++; ++ if (n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for (cols = 0; cols <= (n / 2); cols++) ++ if ((cols * cols) >= n) ++ break; ++ ++ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ ++ /* widescreen is better if 3 columns */ ++ if (n >= 3 && n <= 6 && (m->w.width / m->w.height) > 1) ++ cols = 3; ++ ++ rows = n / cols; ++ ++ /* window geometries */ ++ cw = cols ? m->w.width / cols : m->w.width; ++ cn = 0; /* current column number */ ++ rn = 0; /* current row number */ ++ wl_list_for_each(c, &clients, link) { ++ unsigned int cx, cy; ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ ++ if ((i / rows + 1) > (cols - n % cols)) ++ rows = n / cols + 1; ++ ch = rows ? m->w.height / rows : m->w.height; ++ cx = m->w.x + cn * cw; ++ cy = m->w.y + rn * ch; ++ resize(c, (struct wlr_box) { cx, cy, cw, ch}, 0); ++ rn++; ++ if (rn >= rows) { ++ rn = 0; ++ cn++; ++ } ++ i++; ++ } ++} ++ + void + incnmaster(const Arg *arg) + { diff --git a/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid.patch b/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid.patch new file mode 100755 index 0000000..2af1072 --- /dev/null +++ b/dwl/dwl-patches/patches/gaplessgrid/gaplessgrid.patch @@ -0,0 +1,89 @@ +diff --git a/config.def.h b/config.def.h +index 22d2171..014a909 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "###", gaplessgrid }, + }; + + /* monitors */ +@@ -139,6 +140,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_g, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index dc0c861..875d8cd 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -292,6 +292,7 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); ++static void gaplessgrid(Monitor *m); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +@@ -1510,6 +1511,56 @@ handlesig(int signo) + } + } + ++void ++gaplessgrid(Monitor *m) ++{ ++ unsigned int n = 0, i = 0, ch, cw, cn, rn, rows, cols; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating) ++ n++; ++ if (n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for (cols = 0; cols <= (n / 2); cols++) ++ if ((cols * cols) >= n) ++ break; ++ ++ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ ++ /* widescreen is better if 3 columns */ ++ if (n >= 3 && n <= 6 && (m->w.width / m->w.height) > 1) ++ cols = 3; ++ ++ rows = n / cols; ++ ++ /* window geometries */ ++ cw = cols ? m->w.width / cols : m->w.width; ++ cn = 0; /* current column number */ ++ rn = 0; /* current row number */ ++ wl_list_for_each(c, &clients, link) { ++ unsigned int cx, cy; ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ ++ if ((i / rows + 1) > (cols - n % cols)) ++ rows = n / cols + 1; ++ ch = rows ? m->w.height / rows : m->w.height; ++ cx = m->w.x + cn * cw; ++ cy = m->w.y + rn * ch; ++ resize(c, (struct wlr_box) { cx, cy, cw, ch}, 0); ++ rn++; ++ if (rn >= rows) { ++ rn = 0; ++ cn++; ++ } ++ i++; ++ } ++} ++ + void + incnmaster(const Arg *arg) + { diff --git a/dwl/dwl-patches/patches/gaps/README.md b/dwl/dwl-patches/patches/gaps/README.md new file mode 100755 index 0000000..4925a47 --- /dev/null +++ b/dwl/dwl-patches/patches/gaps/README.md @@ -0,0 +1,14 @@ +### Description +Adds gaps between clients, providing the ability to disable them at run-time. + +`smartgaps` can also be changed to remove gaps when there is only one client present. + +### Download +- [git branch](https://codeberg.org/bigman/dwl/src/branch/gaps) +- [2024-07-12](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/gaps/gaps.patch) + +### Authors +- [peesock](https://codeberg.org/bigman) +- [sewn](https://codeberg.org/sewn) +- [Serene Void](https://github.com/serenevoid) +- [Rayan Nakib](https://nakibrayan2.pages.dev) diff --git a/dwl/dwl-patches/patches/gaps/gaps.patch b/dwl/dwl-patches/patches/gaps/gaps.patch new file mode 100755 index 0000000..c025baf --- /dev/null +++ b/dwl/dwl-patches/patches/gaps/gaps.patch @@ -0,0 +1,127 @@ +From 50e3dd4746b6cb719efb9f8213b94ac52a5320d9 Mon Sep 17 00:00:00 2001 +From: peesock +Date: Mon, 24 Jun 2024 20:06:42 -0700 +Subject: [PATCH] gaps! + +Co-authored-by: sewn +Co-authored-by: serenevoid +--- + config.def.h | 4 ++++ + dwl.c | 34 ++++++++++++++++++++++++++-------- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..b388b4e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,6 +6,9 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ ++static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ ++static int gaps = 1; /* 1 means gaps between windows are added */ ++static const unsigned int gappx = 10; /* gap pixel between windows */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); +@@ -135,6 +138,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, ++ { MODKEY, XKB_KEY_g, togglegaps, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, +diff --git a/dwl.c b/dwl.c +index dc0437e..dc851df 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -199,6 +199,7 @@ struct Monitor { + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; ++ int gaps; + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; +@@ -336,6 +337,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglegaps(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -949,6 +951,8 @@ createmon(struct wl_listener *listener, void *data) + + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ ++ m->gaps = gaps; ++ + m->tagset[0] = m->tagset[1] = 1; + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { +@@ -2638,7 +2642,7 @@ tagmon(const Arg *arg) + void + tile(Monitor *m) + { +- unsigned int mw, my, ty; ++ unsigned int h, r, e = m->gaps, mw, my, ty; + int i, n = 0; + Client *c; + +@@ -2647,23 +2651,30 @@ tile(Monitor *m) + n++; + if (n == 0) + return; ++ if (smartgaps == n) ++ e = 0; + + if (n > m->nmaster) +- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; ++ mw = m->nmaster ? (int)roundf((m->w.width + gappx*e) * m->mfact) : 0; + else + mw = m->w.width; +- i = my = ty = 0; ++ i = 0; ++ my = ty = gappx*e; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); +- my += c->geom.height; ++ r = MIN(n, m->nmaster) - i; ++ h = (m->w.height - my - gappx*e - gappx*e * (r - 1)) / r; ++ resize(c, (struct wlr_box){.x = m->w.x + gappx*e, .y = m->w.y + my, ++ .width = mw - 2*gappx*e, .height = h}, 0); ++ my += c->geom.height + gappx*e; + } else { ++ r = n - i; ++ h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r; + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); +- ty += c->geom.height; ++ .width = m->w.width - mw - gappx*e, .height = h}, 0); ++ ty += c->geom.height + gappx*e; + } + i++; + } +@@ -2686,6 +2697,13 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglegaps(const Arg *arg) ++{ ++ selmon->gaps = !selmon->gaps; ++ arrange(selmon); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/genericgaps/README.md b/dwl/dwl-patches/patches/genericgaps/README.md new file mode 100755 index 0000000..f27897d --- /dev/null +++ b/dwl/dwl-patches/patches/genericgaps/README.md @@ -0,0 +1,25 @@ +### Description + +This patch adds gaps around windows and works with any layout (the layout code +does not need to know about the gaps). This patch is a modified version of +[vanitygaps][vanitygaps] patch. + +This works by allowing layout code to place clients normally without gaps, and +then correcting positions and sizes of clients afterwards to add gaps around +them. This approach is very flexible but there is one small downside: you will +always have "outer" gaps (between edges of a monitor and a window) if "inner" +gaps are non-zero. But for me it's not a problem because I always want "outer" +gaps to be as big or bigger than "inner" gaps anyway. + +[vanitygaps]: /dwl/dwl-patches/src/branch/main/patches/vanitygaps + +### Download + +- [0.7 2025-02-11](/dwl/dwl-patches/raw/branch/main/patches/genericgaps/genericgaps-0.7.patch): + added support for `smartgaps` and `monoclegaps` settings and removed the suck + from `arrange()` function +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/genericgaps/genericgaps.patch) + +### Authors + +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) diff --git a/dwl/dwl-patches/patches/genericgaps/genericgaps-0.7.patch b/dwl/dwl-patches/patches/genericgaps/genericgaps-0.7.patch new file mode 100755 index 0000000..ff27889 --- /dev/null +++ b/dwl/dwl-patches/patches/genericgaps/genericgaps-0.7.patch @@ -0,0 +1,375 @@ +From a11488df97c0592486c3ce86d9c5dbddb0f88524 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Mon, 10 Feb 2025 23:32:59 +0100 +Subject: [PATCH] Add gaps to windows regardless of layout + +--- + config.def.h | 23 ++++++ + dwl.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 221 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..7b50d9d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,7 +6,14 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ ++static const int enablegaps = 1; /* 1 means gaps are enabled */ ++static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ ++static const int monoclegaps = 0; /* 1 means outer gaps in monocle layout */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappih = 10; /* horiz inner gap between windows */ ++static const unsigned int gappiv = 10; /* vert inner gap between windows */ ++static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ ++static const unsigned int gappov = 10; /* vert outer gap between windows and screen edge */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); +@@ -133,6 +140,22 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_h, incgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_l, incgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_H, incogaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_L, incogaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_h, incigaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_l, incigaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_0, togglegaps, {0} }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_parenright,defaultgaps, {0} }, ++ { MODKEY, XKB_KEY_y, incihgaps, {.i = +1 } }, ++ { MODKEY, XKB_KEY_o, incihgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_y, incivgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_o, incivgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_y, incohgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_o, incohgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Y, incovgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, incovgaps, {.i = -1 } }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index def2562..9bf4651 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -200,6 +200,11 @@ struct Monitor { + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; ++ int enablegaps; /* enable gaps, used by togglegaps */ ++ int gappih; /* horizontal gap between windows */ ++ int gappiv; /* vertical gap between windows */ ++ int gappoh; /* horizontal outer gaps */ ++ int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; +@@ -246,6 +251,7 @@ typedef struct { + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); + static void arrange(Monitor *m); ++void arrangegaps(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); +@@ -273,6 +279,7 @@ static void createpopup(struct wl_listener *listener, void *data); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); ++static void defaultgaps(const Arg *arg); + static void destroydecoration(struct wl_listener *listener, void *data); + static void destroydragicon(struct wl_listener *listener, void *data); + static void destroyidleinhibitor(struct wl_listener *listener, void *data); +@@ -293,6 +300,13 @@ static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); ++static void incgaps(const Arg *arg); ++static void incigaps(const Arg *arg); ++static void incihgaps(const Arg *arg); ++static void incivgaps(const Arg *arg); ++static void incogaps(const Arg *arg); ++static void incohgaps(const Arg *arg); ++static void incovgaps(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); +@@ -313,6 +327,7 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int + static void outputmgrtest(struct wl_listener *listener, void *data); + static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); ++static void preparegaps(Monitor *m); + static void printstatus(void); + static void powermgrsetmode(struct wl_listener *listener, void *data); + static void quit(const Arg *arg); +@@ -327,6 +342,7 @@ static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); + static void setfullscreen(Client *c, int fullscreen); + static void setgamma(struct wl_listener *listener, void *data); ++static void setgaps(int oh, int ov, int ih, int iv); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); +@@ -340,6 +356,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglegaps(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -413,6 +430,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static int resizelock = 0; /* do not actually resize during arrange */ ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -515,12 +534,52 @@ arrange(Monitor *m) + : c->scene->node.parent); + } + +- if (m->lt[m->sellt]->arrange) ++ if (m->lt[m->sellt]->arrange) { ++ preparegaps(m); + m->lt[m->sellt]->arrange(m); ++ arrangegaps(m); ++ } + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + } + ++void ++arrangegaps(Monitor *m) ++{ ++ Client *c; ++ int n, gaps; ++ ++ if (!m->enablegaps) ++ return; ++ ++ resizelock = 0; ++ ++ n = 0; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ n++; ++ } ++ ++ gaps = !(smartgaps && n == 1) && ++ (monoclegaps || m->lt[m->sellt]->arrange != monocle); ++ if (gaps) { ++ m->w.width += m->gappih + 2 * m->gappoh; ++ m->w.height += m->gappiv + 2 * m->gappov; ++ } ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (gaps) { ++ c->geom.x += c->mon->gappih + c->mon->gappoh; ++ c->geom.y += c->mon->gappiv + c->mon->gappov; ++ c->geom.width -= c->mon->gappih; ++ c->geom.height -= c->mon->gappiv; ++ } ++ resize(c, c->geom, 0); ++ } ++} ++ + void + arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive) + { +@@ -991,6 +1050,12 @@ createmon(struct wl_listener *listener, void *data) + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); + ++ m->enablegaps = enablegaps; ++ m->gappih = gappih; ++ m->gappiv = gappiv; ++ m->gappoh = gappoh; ++ m->gappov = gappov; ++ + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->tagset[0] = m->tagset[1] = 1; +@@ -1173,6 +1238,12 @@ cursorwarptohint(void) + } + } + ++void ++defaultgaps(const Arg *arg) ++{ ++ setgaps(gappoh, gappov, gappih, gappiv); ++} ++ + void + destroydecoration(struct wl_listener *listener, void *data) + { +@@ -1526,6 +1597,83 @@ incnmaster(const Arg *arg) + arrange(selmon); + } + ++void ++incgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incigaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incihgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv ++ ); ++} ++ ++void ++incivgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incogaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incohgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incovgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ + void + inputdevice(struct wl_listener *listener, void *data) + { +@@ -2034,6 +2182,31 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + } + ++void ++preparegaps(Monitor *m) ++{ ++ Client *c; ++ int n; ++ ++ if (!m->enablegaps) ++ return; ++ ++ n = 0; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ n++; ++ } ++ ++ resizelock = 1; ++ ++ if ((smartgaps && n == 1) || (!monoclegaps && m->lt[m->sellt]->arrange == monocle)) ++ return; ++ ++ m->w.width -= m->gappih + 2 * m->gappoh; ++ m->w.height -= m->gappiv + 2 * m->gappov; ++} ++ + void + printstatus(void) + { +@@ -2185,6 +2358,11 @@ resize(Client *c, struct wlr_box geo, int interact) + struct wlr_box *bbox; + struct wlr_box clip; + ++ if (resizelock) { ++ c->geom = geo; ++ return; ++ } ++ + if (!c->mon || !client_surface(c)->mapped) + return; + +@@ -2354,6 +2532,16 @@ setgamma(struct wl_listener *listener, void *data) + wlr_output_schedule_frame(m->wlr_output); + } + ++void ++setgaps(int oh, int ov, int ih, int iv) ++{ ++ selmon->gappoh = MAX(oh, 0); ++ selmon->gappov = MAX(ov, 0); ++ selmon->gappih = MAX(ih, 0); ++ selmon->gappiv = MAX(iv, 0); ++ arrange(selmon); ++} ++ + void + setlayout(const Arg *arg) + { +@@ -2741,6 +2929,15 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglegaps(const Arg *arg) ++{ ++ if (!selmon) ++ return; ++ selmon->enablegaps = !selmon->enablegaps; ++ arrange(selmon); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/genericgaps/genericgaps.patch b/dwl/dwl-patches/patches/genericgaps/genericgaps.patch new file mode 100755 index 0000000..aa62b92 --- /dev/null +++ b/dwl/dwl-patches/patches/genericgaps/genericgaps.patch @@ -0,0 +1,350 @@ +From f2a1b84369266d252fbea57c6f1eb64253617452 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Thu, 12 Dec 2024 22:44:53 +0100 +Subject: [PATCH] Add genericgaps + +--- + config.def.h | 22 +++++++ + dwl.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 190 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..930af12 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,12 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ ++static const int monoclegaps = 0; /* 1 means outer gaps in monocle layout */ ++static const unsigned int gappih = 10; /* horiz inner gap between windows */ ++static const unsigned int gappiv = 10; /* vert inner gap between windows */ ++static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ ++static const unsigned int gappov = 10; /* vert outer gap between windows and screen edge */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); +@@ -133,6 +139,22 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_h, incgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_l, incgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_H, incogaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_L, incogaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_h, incigaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_l, incigaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_0, togglegaps, {0} }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_parenright,defaultgaps, {0} }, ++ { MODKEY, XKB_KEY_y, incihgaps, {.i = +1 } }, ++ { MODKEY, XKB_KEY_o, incihgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_y, incivgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_o, incivgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_y, incohgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_o, incohgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Y, incovgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, incovgaps, {.i = -1 } }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index def2562..c14ae43 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -107,6 +107,7 @@ typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ + unsigned int type; /* XDGShell or X11* */ ++ int interact; + struct wlr_box geom; /* layout-relative, includes border */ + Monitor *mon; + struct wlr_scene_tree *scene; +@@ -200,6 +201,10 @@ struct Monitor { + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; ++ int gappih; /* horizontal gap between windows */ ++ int gappiv; /* vertical gap between windows */ ++ int gappoh; /* horizontal outer gaps */ ++ int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; +@@ -273,6 +278,7 @@ static void createpopup(struct wl_listener *listener, void *data); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); ++static void defaultgaps(const Arg *arg); + static void destroydecoration(struct wl_listener *listener, void *data); + static void destroydragicon(struct wl_listener *listener, void *data); + static void destroyidleinhibitor(struct wl_listener *listener, void *data); +@@ -293,6 +299,13 @@ static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); ++static void incgaps(const Arg *arg); ++static void incigaps(const Arg *arg); ++static void incihgaps(const Arg *arg); ++static void incivgaps(const Arg *arg); ++static void incogaps(const Arg *arg); ++static void incohgaps(const Arg *arg); ++static void incovgaps(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); +@@ -320,13 +333,15 @@ static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); +-static void resize(Client *c, struct wlr_box geo, int interact); ++static void resizeapply(Client *c, struct wlr_box geo, int interact); ++static void resizenoapply(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); + static void setfullscreen(Client *c, int fullscreen); + static void setgamma(struct wl_listener *listener, void *data); ++static void setgaps(int oh, int ov, int ih, int iv); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); +@@ -340,6 +355,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglegaps(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -413,6 +429,9 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static int enablegaps = 1; /* enables gaps, used by togglegaps */ ++static void (*resize)(Client *c, struct wlr_box geo, int interact) = resizeapply; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -481,9 +500,25 @@ applyrules(Client *c) + setmon(c, mon, newtags); + } + ++void ++applygaps(Client *c) ++{ ++ struct wlr_box geom = c->geom; ++ ++ if (!c->mon) ++ return; ++ ++ geom.x += c->mon->gappih + c->mon->gappoh; ++ geom.y += c->mon->gappiv + c->mon->gappov; ++ geom.width -= c->mon->gappih; ++ geom.height -= c->mon->gappiv; ++ resize(c, geom, 0); ++} ++ + void + arrange(Monitor *m) + { ++ int save_width, save_height; + Client *c; + + if (!m->wlr_output->enabled) +@@ -515,8 +550,26 @@ arrange(Monitor *m) + : c->scene->node.parent); + } + +- if (m->lt[m->sellt]->arrange) ++ if (m->lt[m->sellt]->arrange) { ++ save_width = m->w.width; ++ save_height = m->w.height; ++ if (enablegaps) { ++ m->w.width -= m->gappih + 2 * m->gappoh; ++ m->w.height -= m->gappiv + 2 * m->gappov; ++ } ++ resize = resizenoapply; + m->lt[m->sellt]->arrange(m); ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (enablegaps) ++ applygaps(c); ++ resizeapply(c, c->geom, c->interact); ++ } ++ m->w.width = save_width; ++ m->w.height = save_height; ++ resize = resizeapply; ++ } + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + } +@@ -993,6 +1046,11 @@ createmon(struct wl_listener *listener, void *data) + + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ ++ ++ m->gappih = gappih; ++ m->gappiv = gappiv; ++ m->gappoh = gappoh; ++ m->gappov = gappov; + m->tagset[0] = m->tagset[1] = 1; + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { +@@ -1173,6 +1231,12 @@ cursorwarptohint(void) + } + } + ++void ++defaultgaps(const Arg *arg) ++{ ++ setgaps(gappoh, gappov, gappih, gappiv); ++} ++ + void + destroydecoration(struct wl_listener *listener, void *data) + { +@@ -1526,6 +1590,83 @@ incnmaster(const Arg *arg) + arrange(selmon); + } + ++void ++incgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incigaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incihgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv ++ ); ++} ++ ++void ++incivgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incogaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incohgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incovgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ + void + inputdevice(struct wl_listener *listener, void *data) + { +@@ -2180,7 +2321,7 @@ requestmonstate(struct wl_listener *listener, void *data) + } + + void +-resize(Client *c, struct wlr_box geo, int interact) ++resizeapply(Client *c, struct wlr_box geo, int interact) + { + struct wlr_box *bbox; + struct wlr_box clip; +@@ -2212,6 +2353,13 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + } + ++void ++resizenoapply(Client *c, struct wlr_box geo, int interact) ++{ ++ c->geom = geo; ++ c->interact = interact; ++} ++ + void + run(char *startup_cmd) + { +@@ -2354,6 +2502,16 @@ setgamma(struct wl_listener *listener, void *data) + wlr_output_schedule_frame(m->wlr_output); + } + ++void ++setgaps(int oh, int ov, int ih, int iv) ++{ ++ selmon->gappoh = MAX(oh, 0); ++ selmon->gappov = MAX(ov, 0); ++ selmon->gappih = MAX(ih, 0); ++ selmon->gappiv = MAX(iv, 0); ++ arrange(selmon); ++} ++ + void + setlayout(const Arg *arg) + { +@@ -2741,6 +2899,13 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglegaps(const Arg *arg) ++{ ++ enablegaps = !enablegaps; ++ arrange(selmon); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.47.1 + diff --git a/dwl/dwl-patches/patches/gestures/README.md b/dwl/dwl-patches/patches/gestures/README.md new file mode 100755 index 0000000..0fbe418 --- /dev/null +++ b/dwl/dwl-patches/patches/gestures/README.md @@ -0,0 +1,23 @@ +### Description +Add swipe gestures to trigger functions, similar to [libinput-gestures](https://github.com/bulletmark/libinput-gestures/tree/master). It supports the following gestures: `SWIPE_UP`, `SWIPE_DOWN`, `SWIPE_LEFT` and `SWIPE_RIGHT` + +> NOTE: It requires that you have previously applied [pointer-gestures-unstable-v1](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/pointer-gestures-unstable-v1) + +```c +static const Gesture gestures[] = { + /* modifier gesture fingers_count function argument */ + { MODKEY, SWIPE_LEFT, 4, shiftview, { .i = 1 } }, + { 0, SWIPE_RIGHT, 4, shiftview, { .i = -1 } }, +}; +``` + +**NOTE:** the example above requires the following patch [shiftview](https://codeberg.org/dwl/dwl-patches/wiki/shiftview) + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/gestures) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/gestures/gestures.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/be3735bc6a5c64ff76c200a8679453bd179be456/gestures/gestures.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/655fd2916c1bcaa022ce6dcdfb370051cf64df66/gestures/gestures.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/gestures/gestures.patch b/dwl/dwl-patches/patches/gestures/gestures.patch new file mode 100755 index 0000000..4f74325 --- /dev/null +++ b/dwl/dwl-patches/patches/gestures/gestures.patch @@ -0,0 +1,169 @@ +From 42f97e88bd901d81b81da61c44a790b583706308 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 5 Jul 2024 11:18:49 -0500 +Subject: [PATCH] implement gestures + +--- + config.def.h | 9 +++++++ + dwl.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 77 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..8b75564 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -14,6 +14,8 @@ static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ + ++static const unsigned int swipe_min_threshold = 0; ++ + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + +@@ -174,3 +176,10 @@ static const Button buttons[] = { + { MODKEY, BTN_MIDDLE, togglefloating, {0} }, + { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, + }; ++ ++static const Gesture gestures[] = { ++ // { MODKEY, SWIPE_LEFT, 4, shiftview, { .i = 1 } }, ++ // { MODKEY, SWIPE_RIGHT, 4, shiftview, { .i = -1 } }, ++ { MODKEY, SWIPE_UP, 3, focusstack, {.i = 1} }, ++ { MODKEY, SWIPE_DOWN, 3, focusstack, {.i = -1} }, ++}; +diff --git a/dwl.c b/dwl.c +index ded83e2..5d861e8 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -88,6 +88,7 @@ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ + #endif ++enum { SWIPE_LEFT, SWIPE_RIGHT, SWIPE_DOWN, SWIPE_UP }; + + typedef union { + int i; +@@ -103,6 +104,14 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct { ++ unsigned int mod; ++ unsigned int motion; ++ unsigned int fingers_count; ++ void (*func)(const Arg *); ++ const Arg arg; ++} Gesture; ++ + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -251,6 +260,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); ++static int ongesture(struct wlr_pointer_swipe_end_event *event); + static void swipe_begin(struct wl_listener *listener, void *data); + static void swipe_update(struct wl_listener *listener, void *data); + static void swipe_end(struct wl_listener *listener, void *data); +@@ -416,6 +426,10 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static uint32_t swipe_fingers = 0; ++static double swipe_dx = 0; ++static double swipe_dy = 0; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -435,6 +449,8 @@ static xcb_atom_t netatom[NetLast]; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++static const unsigned int abzsquare = swipe_min_threshold * swipe_min_threshold; ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -657,6 +673,11 @@ swipe_begin(struct wl_listener *listener, void *data) + { + struct wlr_pointer_swipe_begin_event *event = data; + ++ swipe_fingers = event->fingers; ++ // Reset swipe distance at the beginning of a swipe ++ swipe_dx = 0; ++ swipe_dy = 0; ++ + // Forward swipe begin event to client + wlr_pointer_gestures_v1_send_swipe_begin( + pointer_gestures, +@@ -671,6 +692,11 @@ swipe_update(struct wl_listener *listener, void *data) + { + struct wlr_pointer_swipe_update_event *event = data; + ++ swipe_fingers = event->fingers; ++ // Accumulate swipe distance ++ swipe_dx += event->dx; ++ swipe_dy += event->dy; ++ + // Forward swipe update event to client + wlr_pointer_gestures_v1_send_swipe_update( + pointer_gestures, +@@ -681,11 +707,53 @@ swipe_update(struct wl_listener *listener, void *data) + ); + } + ++int ++ongesture(struct wlr_pointer_swipe_end_event *event) ++{ ++ struct wlr_keyboard *keyboard; ++ uint32_t mods; ++ const Gesture *g; ++ unsigned int motion; ++ unsigned int adx = (int)round(fabs(swipe_dx)); ++ unsigned int ady = (int)round(fabs(swipe_dy)); ++ int handled = 0; ++ ++ if (event->cancelled) { ++ return handled; ++ } ++ ++ // Require absolute distance movement beyond a small thresh-hold ++ if (adx * adx + ady * ady < abzsquare) { ++ return handled; ++ } ++ ++ if (adx > ady) { ++ motion = swipe_dx < 0 ? SWIPE_LEFT : SWIPE_RIGHT; ++ } else { ++ motion = swipe_dy < 0 ? SWIPE_UP : SWIPE_DOWN; ++ } ++ ++ keyboard = wlr_seat_get_keyboard(seat); ++ mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; ++ for (g = gestures; g < END(gestures); g++) { ++ if (CLEANMASK(mods) == CLEANMASK(g->mod) && ++ swipe_fingers == g->fingers_count && ++ motion == g->motion && g->func) { ++ g->func(&g->arg); ++ handled = 1; ++ } ++ } ++ return handled; ++} ++ + void + swipe_end(struct wl_listener *listener, void *data) + { + struct wlr_pointer_swipe_end_event *event = data; + ++ // TODO: should we stop here if the event has been handled? ++ ongesture(event); ++ + // Forward swipe end event to client + wlr_pointer_gestures_v1_send_swipe_end( + pointer_gestures, +-- +2.45.1 diff --git a/dwl/dwl-patches/patches/globalkey/README.md b/dwl/dwl-patches/patches/globalkey/README.md new file mode 100755 index 0000000..d250f92 --- /dev/null +++ b/dwl/dwl-patches/patches/globalkey/README.md @@ -0,0 +1,33 @@ +### Description + +This patch adds the ability to pass keys that are specified in the config header globally, similar to Hyprland's approach. +This might deal with Wayland's lack of global shortcuts. + +Example: +``` +static const PassKeypressRule pass_rules[] = { + ADDPASSRULE("com.obsproject.Studio", XKB_KEY_Home), + ADDPASSRULE("WebCord", XKB_KEY_n), + /* xkb key is case-insensitive */ +}; +``` + +This will pass the `Home` key (alongside with mods) to OBS regardless of what client is currently focused, if any. +The string "com.obsproject.Studio" should match the exact appid of the client. + +To get the appid use [dwlmsg](https://codeberg.org/notchoc/dwlmsg) or run stock dwl from a terminal then launch the needed application inside, dwl will print all the info to the stdout. + +Note that if a popup (like [fuzzel](https://codeberg.org/dnkl/fuzzel)) is focused, no keys will be globally passed. +This is done so these menus don't get closed after hitting some of the global keys. + +## Warning +This patch is a stupid hack, it doesn't work all the time. +Examples: obs needs to be clicked on once before applying global hotkeys. +Electron (discord/webcord/chromium) with wayland backend ignores the very first press. +Other programs might not work at all. + +### Download +- [git branch](https://codeberg.org/korei999/dwl/src/branch/globalkey) +- [2024-06-08](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/globalkey/globalkey.patch) +### Authors +- [korei999](https://codeberg.org/korei999) diff --git a/dwl/dwl-patches/patches/globalkey/globalkey.patch b/dwl/dwl-patches/patches/globalkey/globalkey.patch new file mode 100755 index 0000000..07d3856 --- /dev/null +++ b/dwl/dwl-patches/patches/globalkey/globalkey.patch @@ -0,0 +1,131 @@ +From f36e3f134c9f14a9821783d9908471ed0bdca0ed Mon Sep 17 00:00:00 2001 +From: korei999 +Date: Fri, 14 Mar 2025 20:05:45 +0200 +Subject: [PATCH] implement globalkey patch + +--- + config.def.h | 8 +++++++ + dwl.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 69 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..25486c8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -122,6 +122,14 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + static const char *termcmd[] = { "foot", NULL }; + static const char *menucmd[] = { "wmenu-run", NULL }; + ++#define ADDPASSRULE(S, K) {.appid = S, .len = LENGTH(S), .key = K} ++static const PassKeypressRule pass_rules[] = { ++ ADDPASSRULE("com.obsproject.Studio", XKB_KEY_Home), ++ ADDPASSRULE("com.obsproject.Studio", XKB_KEY_End), ++ ADDPASSRULE("com.obsproject.Studio", XKB_KEY_F12), ++ ADDPASSRULE("WebCord", XKB_KEY_n), ++}; ++ + static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ + /* modifier key function argument */ +diff --git a/dwl.c b/dwl.c +index 4816159..9ad64dd 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -217,6 +217,12 @@ typedef struct { + int x, y; + } MonitorRule; + ++typedef struct { ++ const char* appid; ++ size_t len; ++ uint32_t key; ++} PassKeypressRule; ++ + typedef struct { + struct wlr_pointer_constraint_v1 *constraint; + struct wl_listener destroy; +@@ -293,6 +299,7 @@ static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); ++static void keypressglobal(struct wlr_surface *last_surface, struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event, uint32_t mods, xkb_keysym_t keysym); + static void keypressmod(struct wl_listener *listener, void *data); + static int keyrepeat(void *data); + static void killclient(const Arg *arg); +@@ -1628,6 +1635,12 @@ keypress(struct wl_listener *listener, void *data) + /* This event is raised when a key is pressed or released. */ + KeyboardGroup *group = wl_container_of(listener, group, key); + struct wlr_keyboard_key_event *event = data; ++ struct wlr_surface *last_surface = seat->keyboard_state.focused_surface; ++ struct wlr_xdg_surface *xdg_surface = last_surface ? wlr_xdg_surface_try_from_wlr_surface(last_surface) : NULL; ++ int pass = 0; ++#ifdef XWAYLAND ++ struct wlr_xwayland_surface *xsurface = last_surface ? wlr_xwayland_surface_try_from_wlr_surface(last_surface) : NULL; ++#endif + + /* Translate libinput keycode -> xkbcommon */ + uint32_t keycode = event->keycode + 8; +@@ -1662,12 +1675,60 @@ keypress(struct wl_listener *listener, void *data) + if (handled) + return; + ++ /* don't pass when popup is focused ++ * this is better than having popups (like fuzzel or wmenu) closing while typing in a passed keybind */ ++ pass = (xdg_surface && xdg_surface->role != WLR_XDG_SURFACE_ROLE_POPUP) || !last_surface ++#ifdef XWAYLAND ++ || xsurface ++#endif ++ ; ++ /* passed keys don't get repeated */ ++ if (!locked && pass) { ++ for (i = 0; i < nsyms; ++i) ++ keypressglobal(last_surface, &group->wlr_group->keyboard, event, mods, syms[i]); ++ } ++ + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); + /* Pass unhandled keycodes along to the client. */ + wlr_seat_keyboard_notify_key(seat, event->time_msec, + event->keycode, event->state); + } + ++void ++keypressglobal(struct wlr_surface *last_surface, struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event, uint32_t mods, xkb_keysym_t keysym) ++{ ++ Client *c = NULL, *lastc = focustop(selmon); ++ int reset = false; ++ const char *appid = NULL; ++ ++ for (size_t r = 0; r < LENGTH(pass_rules); r++) { ++ uint32_t rcode = xkb_keysym_to_upper(pass_rules[r].key); ++ uint32_t pcode = xkb_keysym_to_upper(keysym); ++ ++ /* match key only (case insensitive) ignoring mods */ ++ if (rcode == pcode) { ++ wl_list_for_each(c, &clients, link) { ++ if (c && c != lastc) { ++ appid = client_get_appid(c); ++ if (appid && strncmp(appid, pass_rules[r].appid, pass_rules[r].len) == 0) { ++ reset = true; ++ ++ client_notify_enter(client_surface(c), keyboard); ++ client_activate_surface(client_surface(c), 1); ++ wlr_seat_keyboard_send_key(seat, event->time_msec, event->keycode, event->state); ++ ++ goto done; ++ } ++ } ++ } ++ } ++ } ++ ++done: ++ if (reset && last_surface) ++ client_notify_enter(last_surface, keyboard); ++} ++ + void + keypressmod(struct wl_listener *listener, void *data) + { +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/headless/README.md b/dwl/dwl-patches/patches/headless/README.md new file mode 100755 index 0000000..990a5d9 --- /dev/null +++ b/dwl/dwl-patches/patches/headless/README.md @@ -0,0 +1,11 @@ +### Description +Implements `swaymsg create_output` command, it allows you to create virtual/headless outputs. But in combination with a VNC server (for example wayvnc), this allows you to essentially have additional monitors, by connecting to the VNC server with an appropiate client (for example on an tablet or laptop). + +If you plan to use wayvnc, you'll need [virtual-pointer](https://codeberg.org/dwl/dwl-patches/wiki/virtual-pointer.-) patch as well + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/v0.5/headless) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/0096e49402bc59b4050e12cdb9befb79d0011006/headless/headless.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/headless/headless.patch b/dwl/dwl-patches/patches/headless/headless.patch new file mode 100755 index 0000000..fb01fda --- /dev/null +++ b/dwl/dwl-patches/patches/headless/headless.patch @@ -0,0 +1,130 @@ +From 2e1123af5c7ae4354ec997d59cb36143fb2fdd27 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Mon, 8 Apr 2024 10:23:40 -0500 +Subject: [PATCH] feat: implement headless backend + +--- + config.def.h | 1 + + dwl.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 59 insertions(+) + +diff --git a/config.def.h b/config.def.h +index db0babc..f0a2080 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -141,6 +141,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT, XKB_KEY_M, create_output, {0} }, + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +diff --git a/dwl.c b/dwl.c +index ef27a1d..79a63b0 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -12,7 +12,10 @@ + #include + #include + #include ++#include + #include ++#include ++#include + #include + #include + #include +@@ -58,6 +61,9 @@ + #include + #include + #endif ++#if WLR_HAS_X11_BACKEND ++#include ++#endif + + #include "util.h" + +@@ -327,6 +333,8 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void _create_output(struct wlr_backend *backend, void *data); ++static void create_output(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +@@ -335,6 +343,7 @@ static int locked; + static void *exclusive_focus; + static struct wl_display *dpy; + static struct wlr_backend *backend; ++static struct wlr_backend *headless_backend; + static struct wlr_scene *scene; + static struct wlr_scene_tree *layers[NUM_LAYERS]; + static struct wlr_scene_tree *drag_icon; +@@ -2321,6 +2330,16 @@ setup(void) + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape); + ++ /** ++ * Initialize headless backend ++ */ ++ headless_backend = wlr_headless_backend_create(dpy); ++ if (!headless_backend) { ++ die("Failed to create secondary headless backend"); ++ } else { ++ wlr_multi_backend_add(backend, headless_backend); ++ } ++ + /* + * Configures a seat, which is a single "seat" at which a user sits and + * operates the computer. This conceptually includes up to one keyboard, +@@ -2746,6 +2765,45 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++void ++_create_output(struct wlr_backend *_backend, void *data) ++{ ++ bool *done = data; ++ if (*done) { ++ return; ++ } ++ ++ if (wlr_backend_is_wl(_backend)) { ++ wlr_wl_output_create(_backend); ++ *done = true; ++ } else if (wlr_backend_is_headless(_backend)) { ++ wlr_headless_add_output(_backend, 1920, 1080); ++ *done = true; ++ } ++#if WLR_HAS_X11_BACKEND ++ else if (wlr_backend_is_x11(backend)) { ++ wlr_x11_output_create(backend); ++ *done = true; ++ } ++#endif ++} ++ ++void ++create_output(const Arg *arg) ++{ ++ bool done = false; ++ ++ if (!wlr_backend_is_multi(backend)) { ++ die("Expected a multi backend"); ++ } ++ ++ wlr_multi_for_each_backend(backend, _create_output, &done); ++ ++ if (!done) { ++ die("Can only create outputs for Wayland, X11 or headless backends"); ++ } ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +-- +2.43.2 + diff --git a/dwl/dwl-patches/patches/hide-behind-fullscreen/README.md b/dwl/dwl-patches/patches/hide-behind-fullscreen/README.md new file mode 100755 index 0000000..0b4bebe --- /dev/null +++ b/dwl/dwl-patches/patches/hide-behind-fullscreen/README.md @@ -0,0 +1,12 @@ +### Description +Hide all clients (and layer surfaces) behind the current client if it is +fullscreen, only the background (layer surfaces at the background layer) will +be shown + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/hide-behind-fullscreen) +- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/hide-behind-fullscreen/hide-behind-fullscreen.patch) +- [hide-behind-fullscreen-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/hide-behind-fullscreen/hide-behind-fullscreen-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) diff --git a/dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen-0.7.patch b/dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen-0.7.patch new file mode 100755 index 0000000..de2dfc6 --- /dev/null +++ b/dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen-0.7.patch @@ -0,0 +1,73 @@ +From 78e5c4b42cf125be70814fd65a09cbcf0a18aa7e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sun, 10 Apr 2022 22:38:53 -0500 +Subject: [PATCH] hide-behind-fullscreen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 2 +- + dwl.c | 24 +++++++++++++++++++++++- + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..1d5a4c84 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,7 +12,7 @@ static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +-static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 0.0f}; /* You can also use glsl colors */ + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +diff --git a/dwl.c b/dwl.c +index a2711f67..56356f29 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -484,7 +484,9 @@ applyrules(Client *c) + void + arrange(Monitor *m) + { +- Client *c; ++ LayerSurface *l; ++ Client *c, *sel = focustop(m); ++ int i; + + if (!m->wlr_output->enabled) + return; +@@ -515,6 +517,26 @@ arrange(Monitor *m) + : c->scene->node.parent); + } + ++ if (sel && sel->isfullscreen && VISIBLEON(sel, m)) { ++ for (i = 2; i > ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; i--) { ++ wl_list_for_each(l, &sel->mon->layers[i], link) ++ wlr_scene_node_set_enabled(&l->scene->node, 0); ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != m) ++ continue; ++ wlr_scene_node_set_enabled(&c->scene->node, (sel->isfullscreen && c == sel) ++ || !sel->isfullscreen); ++ } ++ } ++ if (!sel || (!sel->isfullscreen && VISIBLEON(sel, m))) { ++ for (i = 2; i > ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; i--) { ++ wl_list_for_each(l, &m->layers[i], link) ++ wlr_scene_node_set_enabled(&l->scene->node, 1); ++ } ++ } ++ + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); + motionnotify(0, NULL, 0, 0, 0, 0); +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen.patch b/dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen.patch new file mode 100755 index 0000000..f82d0e6 --- /dev/null +++ b/dwl/dwl-patches/patches/hide-behind-fullscreen/hide-behind-fullscreen.patch @@ -0,0 +1,73 @@ +From ac1537f068ea626f1984803ed8db08faf7943b18 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sun, 10 Apr 2022 22:38:53 -0500 +Subject: [PATCH] hide-behind-fullscreen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 2 +- + dwl.c | 24 +++++++++++++++++++++++- + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..1d5a4c84 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,7 +12,7 @@ static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +-static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 0.0f}; /* You can also use glsl colors */ + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +diff --git a/dwl.c b/dwl.c +index ad21e1ba..f5395fe6 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -505,7 +505,9 @@ applyrules(Client *c) + void + arrange(Monitor *m) + { +- Client *c; ++ LayerSurface *l; ++ Client *c, *sel = focustop(m); ++ int i; + + if (!m->wlr_output->enabled) + return; +@@ -536,6 +538,26 @@ arrange(Monitor *m) + : c->scene->node.parent); + } + ++ if (sel && sel->isfullscreen && VISIBLEON(sel, m)) { ++ for (i = 2; i > ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; i--) { ++ wl_list_for_each(l, &sel->mon->layers[i], link) ++ wlr_scene_node_set_enabled(&l->scene->node, 0); ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != m) ++ continue; ++ wlr_scene_node_set_enabled(&c->scene->node, (sel->isfullscreen && c == sel) ++ || !sel->isfullscreen); ++ } ++ } ++ if (!sel || (!sel->isfullscreen && VISIBLEON(sel, m))) { ++ for (i = 2; i > ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; i--) { ++ wl_list_for_each(l, &m->layers[i], link) ++ wlr_scene_node_set_enabled(&l->scene->node, 1); ++ } ++ } ++ + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); + motionnotify(0, NULL, 0, 0, 0, 0); +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/hide-behind-monocle/README.md b/dwl/dwl-patches/patches/hide-behind-monocle/README.md new file mode 100755 index 0000000..507d2e1 --- /dev/null +++ b/dwl/dwl-patches/patches/hide-behind-monocle/README.md @@ -0,0 +1,10 @@ +### Description +Hide all clients behind the focused one in the monocle layout + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/hide-behind-monocle) +- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/hide-behind-monocle/hide-behind-monocle.patch) +- [hide-behind-monocle-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/hide-behind-monocle/hide-behind-monocle-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) diff --git a/dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle-0.7.patch b/dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle-0.7.patch new file mode 100755 index 0000000..76b6e96 --- /dev/null +++ b/dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle-0.7.patch @@ -0,0 +1,332 @@ +From 9bb408e6921b582dbcf5adfc36a7618086219998 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sat, 8 Jul 2023 17:25:16 -0600 +Subject: [PATCH] hide behind monocle +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + dwl.c | 87 +++++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 55 insertions(+), 32 deletions(-) + +diff --git a/dwl.c b/dwl.c +index a2711f67..70687178 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -288,10 +288,11 @@ static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +-static Client *focustop(Monitor *m); ++static Client *focustop(Monitor *m, int onlytiled); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); ++static void hidebehindmonocle(Monitor *m); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); +@@ -497,7 +498,7 @@ arrange(Monitor *m) + } + + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, +- (c = focustop(m)) && c->isfullscreen); ++ (c = focustop(m, 0)) && c->isfullscreen); + + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + +@@ -750,7 +751,7 @@ closemon(Monitor *m) + if (c->mon == m) + setmon(c, selmon, c->tags); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + printstatus(); + } + +@@ -1185,7 +1186,7 @@ void + destroydragicon(struct wl_listener *listener, void *data) + { + /* Focus enter isn't sent during drag, so refocus the focused node. */ +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -1220,7 +1221,7 @@ destroylock(SessionLock *lock, int unlock) + + wlr_scene_node_set_enabled(&locked_bg->node, 0); + +- focusclient(focustop(selmon), 0); ++ focusclient(focustop(selmon, 0), 0); + motionnotify(0, NULL, 0, 0, 0, 0); + + destroy: +@@ -1249,7 +1250,7 @@ destroylocksurface(struct wl_listener *listener, void *data) + surface = wl_container_of(cur_lock->surfaces.next, surface, link); + client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); + } else if (!locked) { +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } else { + wlr_seat_keyboard_clear_focus(seat); + } +@@ -1366,6 +1367,7 @@ focusclient(Client *c, int lift) + wl_list_insert(&fstack, &c->flink); + selmon = c->mon; + c->isurgent = 0; ++ hidebehindmonocle(c->mon); + client_restack_surface(c); + + /* Don't change border color if there is an exclusive focus or we are +@@ -1420,14 +1422,14 @@ focusmon(const Arg *arg) + selmon = dirtomon(arg->i); + while (!selmon->wlr_output->enabled && i++ < nmons); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } + + void + focusstack(const Arg *arg) + { + /* Focus the next or previous client (in tiling order) on selmon */ +- Client *c, *sel = focustop(selmon); ++ Client *c, *sel = focustop(selmon, 0); + if (!sel || (sel->isfullscreen && !client_has_children(sel))) + return; + if (arg->i > 0) { +@@ -1453,12 +1455,15 @@ focusstack(const Arg *arg) + * will focus the topmost client of this mon, when actually will + * only return that client */ + Client * +-focustop(Monitor *m) ++focustop(Monitor *m, int onlytiled) + { + Client *c; + wl_list_for_each(c, &fstack, flink) { +- if (VISIBLEON(c, m)) ++ if (VISIBLEON(c, m)) { ++ if (onlytiled && c->isfloating) ++ continue; + return c; ++ } + } + return NULL; + } +@@ -1515,6 +1520,25 @@ handlesig(int signo) + } + } + ++void ++hidebehindmonocle(Monitor *m) ++{ ++ Client *c; ++ if (m && m->lt[m->sellt]->arrange == monocle) { ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != m) ++ continue; ++ wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m) && c->isfloating); ++ } ++ ++ c = NULL; ++ ++ /* Enable top tiled client, fullscreen is considered tiled */ ++ if ((c = focustop(m, 1))) ++ wlr_scene_node_set_enabled(&c->scene->node, 1); ++ } ++} ++ + void + incnmaster(const Arg *arg) + { +@@ -1653,7 +1677,7 @@ keyrepeat(void *data) + void + killclient(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (sel) + client_send_close(sel); + } +@@ -1780,8 +1804,7 @@ monocle(Monitor *m) + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); +- if ((c = focustop(m))) +- wlr_scene_node_raise_to_top(&c->scene->node); ++ hidebehindmonocle(m); + } + + void +@@ -2049,7 +2072,7 @@ printstatus(void) + if (c->isurgent) + urg |= c->tags; + } +- if ((c = focustop(m))) { ++ if ((c = focustop(m, 0))) { + title = client_get_title(c); + appid = client_get_appid(c); + printf("%s title %s\n", m->wlr_output->name, title ? title : broken); +@@ -2401,7 +2424,7 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } + + void +@@ -2670,12 +2693,12 @@ startdrag(struct wl_listener *listener, void *data) + void + tag(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (!sel || (arg->ui & TAGMASK) == 0) + return; + + sel->tags = arg->ui & TAGMASK; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -2683,7 +2706,7 @@ tag(const Arg *arg) + void + tagmon(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (sel) + setmon(sel, dirtomon(arg->i), 0); + } +@@ -2725,7 +2748,7 @@ tile(Monitor *m) + void + togglefloating(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + /* return if fullscreen */ + if (sel && !sel->isfullscreen) + setfloating(sel, !sel->isfloating); +@@ -2734,7 +2757,7 @@ togglefloating(const Arg *arg) + void + togglefullscreen(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (sel) + setfullscreen(sel, !sel->isfullscreen); + } +@@ -2743,12 +2766,12 @@ void + toggletag(const Arg *arg) + { + uint32_t newtags; +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) + return; + + sel->tags = newtags; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -2761,7 +2784,7 @@ toggleview(const Arg *arg) + return; + + selmon->tagset[selmon->seltags] = newtagset; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -2785,7 +2808,7 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data) + if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) + arrangelayers(l->mon); + if (l->layer_surface->surface == seat->keyboard_state.focused_surface) +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -2802,7 +2825,7 @@ unmapnotify(struct wl_listener *listener, void *data) + if (client_is_unmanaged(c)) { + if (c == exclusive_focus) { + exclusive_focus = NULL; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } + } else { + wl_list_remove(&c->link); +@@ -2883,7 +2906,7 @@ updatemons(struct wl_listener *listener, void *data) + /* Don't move clients to the left output when plugging monitors */ + arrange(m); + /* make sure fullscreen clients have the right size */ +- if ((c = focustop(m)) && c->isfullscreen) ++ if ((c = focustop(m, 0)) && c->isfullscreen) + resize(c, m->m, 0); + + /* Try to re-set the gamma LUT when updating monitors, +@@ -2903,7 +2926,7 @@ updatemons(struct wl_listener *listener, void *data) + if (!c->mon && client_surface(c)->mapped) + setmon(c, selmon, c->tags); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + if (selmon->lock_surface) { + client_notify_enter(selmon->lock_surface->surface, + wlr_seat_get_keyboard(seat)); +@@ -2925,7 +2948,7 @@ void + updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); +- if (c == focustop(c->mon)) ++ if (c == focustop(c->mon, 0)) + printstatus(); + } + +@@ -2935,7 +2958,7 @@ urgent(struct wl_listener *listener, void *data) + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *c = NULL; + toplevel_from_wlr_surface(event->surface, &c, NULL); +- if (!c || c == focustop(selmon)) ++ if (!c || c == focustop(selmon, 0)) + return; + + c->isurgent = 1; +@@ -2953,7 +2976,7 @@ view(const Arg *arg) + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -3024,7 +3047,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + void + zoom(const Arg *arg) + { +- Client *c, *sel = focustop(selmon); ++ Client *c, *sel = focustop(selmon, 0); + + if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) + return; +@@ -3141,7 +3164,7 @@ sethints(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_hints); + struct wlr_surface *surface = client_surface(c); +- if (c == focustop(selmon)) ++ if (c == focustop(selmon, 0)) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle.patch b/dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle.patch new file mode 100755 index 0000000..dfe23dd --- /dev/null +++ b/dwl/dwl-patches/patches/hide-behind-monocle/hide-behind-monocle.patch @@ -0,0 +1,332 @@ +From 8022376ee59d616831271dbc9f289a8bfd4fedda Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sat, 8 Jul 2023 17:25:16 -0600 +Subject: [PATCH] hide behind monocle +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + dwl.c | 87 +++++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 55 insertions(+), 32 deletions(-) + +diff --git a/dwl.c b/dwl.c +index ad21e1ba..cad3b0b2 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -285,10 +285,11 @@ static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +-static Client *focustop(Monitor *m); ++static Client *focustop(Monitor *m, int onlytiled); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); ++static void hidebehindmonocle(Monitor *m); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); +@@ -518,7 +519,7 @@ arrange(Monitor *m) + } + + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, +- (c = focustop(m)) && c->isfullscreen); ++ (c = focustop(m, 0)) && c->isfullscreen); + + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + +@@ -807,7 +808,7 @@ closemon(Monitor *m) + if (c->mon == m) + setmon(c, selmon, c->tags); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + printstatus(); + } + +@@ -1243,7 +1244,7 @@ void + destroydragicon(struct wl_listener *listener, void *data) + { + /* Focus enter isn't sent during drag, so refocus the focused node. */ +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + motionnotify(0, NULL, 0, 0, 0, 0); + wl_list_remove(&listener->link); + } +@@ -1280,7 +1281,7 @@ destroylock(SessionLock *lock, int unlock) + + wlr_scene_node_set_enabled(&locked_bg->node, 0); + +- focusclient(focustop(selmon), 0); ++ focusclient(focustop(selmon, 0), 0); + motionnotify(0, NULL, 0, 0, 0, 0); + + destroy: +@@ -1309,7 +1310,7 @@ destroylocksurface(struct wl_listener *listener, void *data) + surface = wl_container_of(cur_lock->surfaces.next, surface, link); + client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); + } else if (!locked) { +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } else { + wlr_seat_keyboard_clear_focus(seat); + } +@@ -1420,6 +1421,7 @@ focusclient(Client *c, int lift) + wl_list_insert(&fstack, &c->flink); + selmon = c->mon; + c->isurgent = 0; ++ hidebehindmonocle(c->mon); + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +@@ -1473,14 +1475,14 @@ focusmon(const Arg *arg) + selmon = dirtomon(arg->i); + while (!selmon->wlr_output->enabled && i++ < nmons); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } + + void + focusstack(const Arg *arg) + { + /* Focus the next or previous client (in tiling order) on selmon */ +- Client *c, *sel = focustop(selmon); ++ Client *c, *sel = focustop(selmon, 0); + if (!sel || (sel->isfullscreen && !client_has_children(sel))) + return; + if (arg->i > 0) { +@@ -1506,12 +1508,15 @@ focusstack(const Arg *arg) + * will focus the topmost client of this mon, when actually will + * only return that client */ + Client * +-focustop(Monitor *m) ++focustop(Monitor *m, int onlytiled) + { + Client *c; + wl_list_for_each(c, &fstack, flink) { +- if (VISIBLEON(c, m)) ++ if (VISIBLEON(c, m)) { ++ if (onlytiled && c->isfloating) ++ continue; + return c; ++ } + } + return NULL; + } +@@ -1557,6 +1562,25 @@ handlesig(int signo) + quit(NULL); + } + ++void ++hidebehindmonocle(Monitor *m) ++{ ++ Client *c; ++ if (m && m->lt[m->sellt]->arrange == monocle) { ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != m) ++ continue; ++ wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m) && c->isfloating); ++ } ++ ++ c = NULL; ++ ++ /* Enable top tiled client, fullscreen is considered tiled */ ++ if ((c = focustop(m, 1))) ++ wlr_scene_node_set_enabled(&c->scene->node, 1); ++ } ++} ++ + void + incnmaster(const Arg *arg) + { +@@ -1695,7 +1719,7 @@ keyrepeat(void *data) + void + killclient(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (sel) + client_send_close(sel); + } +@@ -1824,8 +1848,7 @@ monocle(Monitor *m) + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); +- if ((c = focustop(m))) +- wlr_scene_node_raise_to_top(&c->scene->node); ++ hidebehindmonocle(m); + } + + void +@@ -2092,7 +2115,7 @@ printstatus(void) + if (c->isurgent) + urg |= c->tags; + } +- if ((c = focustop(m))) { ++ if ((c = focustop(m, 0))) { + printf("%s title %s\n", m->wlr_output->name, client_get_title(c)); + printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c)); + printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); +@@ -2406,7 +2429,7 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } + + void +@@ -2680,12 +2703,12 @@ startdrag(struct wl_listener *listener, void *data) + void + tag(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (!sel || (arg->ui & TAGMASK) == 0) + return; + + sel->tags = arg->ui & TAGMASK; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -2693,7 +2716,7 @@ tag(const Arg *arg) + void + tagmon(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (sel) + setmon(sel, dirtomon(arg->i), 0); + } +@@ -2735,7 +2758,7 @@ tile(Monitor *m) + void + togglefloating(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + /* return if fullscreen */ + if (sel && !sel->isfullscreen) + setfloating(sel, !sel->isfloating); +@@ -2744,7 +2767,7 @@ togglefloating(const Arg *arg) + void + togglefullscreen(const Arg *arg) + { +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (sel) + setfullscreen(sel, !sel->isfullscreen); + } +@@ -2753,12 +2776,12 @@ void + toggletag(const Arg *arg) + { + uint32_t newtags; +- Client *sel = focustop(selmon); ++ Client *sel = focustop(selmon, 0); + if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) + return; + + sel->tags = newtags; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -2771,7 +2794,7 @@ toggleview(const Arg *arg) + return; + + selmon->tagset[selmon->seltags] = newtagset; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -2795,7 +2818,7 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data) + if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) + arrangelayers(l->mon); + if (l->layer_surface->surface == seat->keyboard_state.focused_surface) +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + motionnotify(0, NULL, 0, 0, 0, 0); + } + +@@ -2812,7 +2835,7 @@ unmapnotify(struct wl_listener *listener, void *data) + if (client_is_unmanaged(c)) { + if (c == exclusive_focus) { + exclusive_focus = NULL; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + } + } else { + wl_list_remove(&c->link); +@@ -2893,7 +2916,7 @@ updatemons(struct wl_listener *listener, void *data) + /* Don't move clients to the left output when plugging monitors */ + arrange(m); + /* make sure fullscreen clients have the right size */ +- if ((c = focustop(m)) && c->isfullscreen) ++ if ((c = focustop(m, 0)) && c->isfullscreen) + resize(c, m->m, 0); + + /* Try to re-set the gamma LUT when updating monitors, +@@ -2913,7 +2936,7 @@ updatemons(struct wl_listener *listener, void *data) + if (!c->mon && client_surface(c)->mapped) + setmon(c, selmon, c->tags); + } +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + if (selmon->lock_surface) { + client_notify_enter(selmon->lock_surface->surface, + wlr_seat_get_keyboard(seat)); +@@ -2935,7 +2958,7 @@ void + updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); +- if (c == focustop(c->mon)) ++ if (c == focustop(c->mon, 0)) + printstatus(); + } + +@@ -2945,7 +2968,7 @@ urgent(struct wl_listener *listener, void *data) + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *c = NULL; + toplevel_from_wlr_surface(event->surface, &c, NULL); +- if (!c || c == focustop(selmon)) ++ if (!c || c == focustop(selmon, 0)) + return; + + c->isurgent = 1; +@@ -2963,7 +2986,7 @@ view(const Arg *arg) + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; +- focusclient(focustop(selmon), 1); ++ focusclient(focustop(selmon, 0), 1); + arrange(selmon); + printstatus(); + } +@@ -3034,7 +3057,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + void + zoom(const Arg *arg) + { +- Client *c, *sel = focustop(selmon); ++ Client *c, *sel = focustop(selmon, 0); + + if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) + return; +@@ -3145,7 +3168,7 @@ sethints(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_hints); + struct wlr_surface *surface = client_surface(c); +- if (c == focustop(selmon)) ++ if (c == focustop(selmon, 0)) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/hide_vacant_tags/README.md b/dwl/dwl-patches/patches/hide_vacant_tags/README.md new file mode 100755 index 0000000..fae2a4d --- /dev/null +++ b/dwl/dwl-patches/patches/hide_vacant_tags/README.md @@ -0,0 +1,11 @@ +### Description + +Prevent [bar](/dwl/dwl-patches/wiki/bar) from drawing tags with no clients (i.e. vacant). +It also stops drawing empty rectangles on the bar for non-vacant tags as there is no need anymore to distinguish vacant tags and it offers a more visible contrast than if there were filled/empty rectangles. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/hide_vacant_tags/hide_vacant_tags.patch) + +### Authors +- [sewn](https://codeberg.org/sewn) + diff --git a/dwl/dwl-patches/patches/hide_vacant_tags/hide_vacant_tags.patch b/dwl/dwl-patches/patches/hide_vacant_tags/hide_vacant_tags.patch new file mode 100755 index 0000000..ae3966e --- /dev/null +++ b/dwl/dwl-patches/patches/hide_vacant_tags/hide_vacant_tags.patch @@ -0,0 +1,69 @@ +From 54b75630d9f93bd1a8ab5949df64f086043e96eb Mon Sep 17 00:00:00 2001 +From: sewn +Date: Fri, 13 Dec 2024 17:31:33 +0300 +Subject: [PATCH] hide vacant tags + +https://dwm.suckless.org/patches/hide_vacant_tags/ +--- + dwl.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 1e199f3..24d4b20 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -721,7 +721,7 @@ bufrelease(struct wl_listener *listener, void *data) + void + buttonpress(struct wl_listener *listener, void *data) + { +- unsigned int i = 0, x = 0; ++ unsigned int i = 0, x = 0, occ = 0; + double cx; + unsigned int click; + struct wlr_pointer_button_event *event = data; +@@ -751,9 +751,16 @@ buttonpress(struct wl_listener *listener, void *data) + (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && + (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { + cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; +- do ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != selmon) ++ continue; ++ occ |= c->tags == TAGMASK ? 0 : c->tags; ++ } ++ do { ++ if (!(occ & 1 << i || selmon->tagset[selmon->seltags] & 1 << i)) ++ continue; + x += TEXTW(selmon, tags[i]); +- while (cx >= x && ++i < LENGTH(tags)); ++ } while (cx >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; +@@ -1530,20 +1537,18 @@ drawbar(Monitor *m) + wl_list_for_each(c, &clients, link) { + if (c->mon != m) + continue; +- occ |= c->tags; ++ occ |= c->tags == TAGMASK ? 0 : c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + c = focustop(m); + for (i = 0; i < LENGTH(tags); i++) { ++ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) ++ continue; + w = TEXTW(m, tags[i]); + drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i); +- if (occ & 1 << i) +- drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, +- m == selmon && c && c->tags & 1 << i, +- urg & 1 << i); + x += w; + } + w = TEXTW(m, m->ltsymbol); +-- +2.47.1 + diff --git a/dwl/dwl-patches/patches/hiderule/README.md b/dwl/dwl-patches/patches/hiderule/README.md new file mode 100755 index 0000000..bed2475 --- /dev/null +++ b/dwl/dwl-patches/patches/hiderule/README.md @@ -0,0 +1,9 @@ +### Description +Adds a `ishidden` option to client rules, that allows hiding any matching clients entirely. + +### Download +- [git branch](https://codeberg.org/minego/dwl/src/branch/hiderule) +- [yyyy-mm-dd](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/hiderule/hiderule.patch) + +### Authors +- [minego](https://codeberg.org/minego) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/hiderule/hiderule.patch b/dwl/dwl-patches/patches/hiderule/hiderule.patch new file mode 100755 index 0000000..8ed1a84 --- /dev/null +++ b/dwl/dwl-patches/patches/hiderule/hiderule.patch @@ -0,0 +1,57 @@ +From fb48ec754d63b3d8e40fff2d047050675887d7f4 Mon Sep 17 00:00:00 2001 +From: Micah N Gorrell +Date: Wed, 27 Mar 2024 12:53:18 -0600 +Subject: [PATCH] hiderule + +--- + config.def.h | 9 ++++++--- + dwl.c | 4 ++++ + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9009517..c476057 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -21,11 +21,14 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + static int log_level = WLR_ERROR; + + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating monitor ishidden */ + /* examples: +- { "Gimp", NULL, 0, 1, -1 }, ++ { "Gimp", NULL, 0, 1, -1, 0 }, + */ +- { "firefox", NULL, 1 << 8, 0, -1 }, ++ { "firefox", NULL, 1 << 8, 0, -1, 0 }, ++ ++ { "firefox", "Sharing Indicator", ++ 0, 1, -1, 1 }, + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index 5867b0c..799fd89 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -228,6 +228,7 @@ typedef struct { + uint32_t tags; + int isfloating; + int monitor; ++ int ishidden; + } Rule; + + typedef struct { +@@ -464,6 +465,9 @@ applyrules(Client *c) + c->isfloating = r->isfloating; + newtags |= r->tags; + i = 0; ++ if (r->ishidden) { ++ mon = NULL; ++ } + wl_list_for_each(m, &mons, link) { + if (r->monitor == i++) + mon = m; +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/hot-reload/README.md b/dwl/dwl-patches/patches/hot-reload/README.md new file mode 100755 index 0000000..e387ca4 --- /dev/null +++ b/dwl/dwl-patches/patches/hot-reload/README.md @@ -0,0 +1,110 @@ +### Description +Enables hot-reloading of dwl; meaning almost all logic can be changed at runtime. +This obviously requires some black magic so for now there's a glibc 2.0 or later +dependency to this. +In particular this allows for every option in config.h to be changed at runtime. + +#### Reloading +To reload rebuild dwl.so, perhaps reinstall it and then run trigger reload function (bound to Mod+Shift+R by default). +This currently calls `notify-send` in order to inform you of a reloading taking place. +So in short: +1. make changes to `config.h` or `dwl.c` +2. run `make` to rebuild dwl.so +3. run `sudo make install` to reinstall dwl + + +#### Limitations +Reloading the compositor will replace all functionality except for `main`, `setup`, `run` and the reload logic. +Note that you're responsible yourself for reloading ressources like fonts, which may only get acquired once. +A lot of components of dwl will also only get run on a trigger (the tiling for example). +So not every change will be immediate. +Furthermore, any patch adding more global state to dwl cannot currently be reloaded properly since +we keep state in the cold part. These patches will still work and their functionality will (hopefully) be +reloadable but you will need to restart the compositor once. + +#### Notes +##### reduce compile errors +This patch triggers `-Wpedantic` a bunch (I don't think there's a way around this, `dlsym` yields `void*` pointers to functions). +This will show a lot of warnings but cause no errors. +So you may want to disable this compile option in order to get readable compiler output. +##### runtime dependencies +This does depend on you having a notification daemon like `dunst` or `mako` running as well as +having `notify-send` installed in order for the compositor to inform you of the reload. + + +#### How? +Most of all dwl functionality is moved into a shared object file `dwl.so`, which can be reloaded at runtime. + +#### How do I make this work with other patches? +Most patches should already put everything in more or less the correct place but if they don't, then here is +where you learn how to fix it. + +The concept itself is quite simple. We compile dwl.c twice once normally and once with the `HOT` macro defined. +The first run will yield the executable and the second will yield a shared object file to be reloaded at runtime. +From the cold part there are some newly available macros: +> symbol names are written as-is, never as string literals +* `TSYM(T, s)` dynamically loads the symbol `s` with type `T` from the shared object file use this if you need to call functions in the cold part (i.e. the `setup` function). +* `CSYM(T, v)` dynamically accesses the value of the symbol `v` of type `T` from the shared object. Use this to query values from config.h for example. +* `LISTEN_GLOBAL(E, L)` is similar to the `LISTEN` macro. `E` is an event and `L` the name of a global +listener. Current implementation is a bit messy and I may fix it if someone bothers me about it. +* `UNLISTEN(L)` takes a listener and unregisteres it. This is important for reloading. + +When adding new code there are some considerations to be made. Since dwl decorates all symbols with `static` by default, we cannot access them as-is. +C's macro system is a bit too powerful though and we use this to our advantage. We will repeatedly define and +undefine a macro called `static` in order to replace the `static` keyword inside some sections. +This allows us to do less refactoring and preserve a lot of the original patch compatability since we're only +strategically adding lines. We're tring to be as minimally invasive as we can. +As a general guide: +* global state should be global for the cold part and `extern` in the cold part meaning it should be inside a block like this: + ```C + #ifdef HOT + #define static extern + #else + #define static + #endif + ... // your global variables go here + #undef static + ``` +* function declarations should be visible in the hot part but not included in the cold part meaning they should be enclosed like this: + ```C + #ifdef HOT + #define static + ... // your function declarations go here + #undef static + #endif + ``` +* static data like the event handler structs in the current `main` branch are a bit more difficult but we will let them reside inside the hot part. +Thus, we enclose them the same way we do functions: + ```C + #ifdef HOT + #define static + ... // your struct wl_listener event handlers go here + #undef static + #endif + ``` +* function definitions should go in the hot part, so they need to be inside a big block like this: + ```C + #ifdef HOT + ... // function definitions here + #endif +* enfore use of the `LISTEN_GLOBAL` and `UNLISTEN` macros (I know this sucks but what can I do, I need to get +access to the callbacks somehow). So you want + * `wl_list_remove(listener.link)` to become `UNLISTEN(listener)` and + * `wl_signal_add(event, global_listener)` to become `LISTEN_GLOBAL(event, global_listener)`. +* Make sure that any patch you're using also uses static everywhere. +* If a patch adds any config variables that are accessed in the cold part (i.e. probably `setup`), +then you'll have to manually remove the `static` keyword from them. + +Note that usually you do not have to create the big `#ifdef` blocks yourself. +There is for example already a huge `#ifdef HOT`-delimited codeblock at the bottom +of dwl.c where all the function definitions go. + +If you have any troubles, feel free to reach out. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/hot-reload/hot-reload-0.7.patch) +- [main 2025-05-30](/dwl/dwl-patches/raw/branch/main/patches/hot-reload/hot-reload.patch) +- find the repo for the patch [here](/Sivecano/dwl/src/branch/hot-reload) +### Authors +- [Sivecano](https://codeberg.org/Sivecano) +- Sérécano at [dwl Discord](https://discord.gg/jJxZnrGPWN) diff --git a/dwl/dwl-patches/patches/hot-reload/hot-reload-0.7.patch b/dwl/dwl-patches/patches/hot-reload/hot-reload-0.7.patch new file mode 100755 index 0000000..1611684 --- /dev/null +++ b/dwl/dwl-patches/patches/hot-reload/hot-reload-0.7.patch @@ -0,0 +1,770 @@ +From 559c635056f23d55df3f83c12d1201a7328f648f Mon Sep 17 00:00:00 2001 +From: Sivecano +Date: Sun, 26 Jan 2025 18:30:02 +0100 +Subject: [PATCH] redo hot-reloading in one file + +--- + Makefile | 19 ++- + config.def.h | 5 +- + dwl.c | 337 ++++++++++++++++++++++++++++++++++++++++++++------- + util.c | 34 ++++++ + util.h | 6 + + 5 files changed, 351 insertions(+), 50 deletions(-) + +diff --git a/Makefile b/Makefile +index 3358bae..e7ee9ff 100644 +--- a/Makefile ++++ b/Makefile +@@ -13,13 +13,16 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + + # CFLAGS / LDFLAGS + PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) +-DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) ++DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) -fPIC -rdynamic + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + +-all: dwl ++all: dwl dwl.so + dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ +-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ ++dwl.o: dwl.c config.mk cursor-shape-v1-protocol.h \ ++ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++dwl.so: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h + util.o: util.c util.h +@@ -49,7 +52,7 @@ xdg-shell-protocol.h: + config.h: + cp config.def.h $@ + clean: +- rm -f dwl *.o *-protocol.h ++ rm -f dwl *.o *-protocol.h *.so + + dist: clean + mkdir -p dwl-$(VERSION) +@@ -63,6 +66,8 @@ install: dwl + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f dwl $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl ++ mkdir -p $(DESTDIR)$(PREFIX)/lib ++ install -m 744 dwl.so $(DESTDIR)$(PREFIX)/lib + mkdir -p $(DESTDIR)$(MANDIR)/man1 + cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 + chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 +@@ -70,9 +75,13 @@ install: dwl + cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + uninstall: +- rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \ ++ rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(PREFIX)/lib/dwl.so $(DESTDIR)$(MANDIR)/man1/dwl.1 \ + $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + + .SUFFIXES: .c .o + .c.o: + $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -c $< ++ ++.SUFFIXES: .c .so ++.c.so: ++ $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -shared -DHOT $< +diff --git a/config.def.h b/config.def.h +index 22d2171..6e3dda1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,7 +7,7 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); ++const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); +@@ -18,7 +18,7 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + #define TAGCOUNT (9) + + /* logging */ +-static int log_level = WLR_ERROR; ++int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +@@ -127,6 +127,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, reload, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index def2562..1c9ab67 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1,6 +1,15 @@ + /* + * See LICENSE file for copyright and license details. + */ ++ ++/* stuff for hot-reload */ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++ + #include + #include + #include +@@ -67,6 +76,7 @@ + #include + #endif + ++ + #include "util.h" + + /* macros */ +@@ -77,8 +87,34 @@ + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) +-#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) +-#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) ++ ++#define SYM(a) dlsym(dwl_module, #a) ++#define TSYM(T, a) ((T)SYM(a)) ++#define CSYM(T, a) *(TSYM(T*, a)) ++ ++#define LISTEN(E, L, H) do { \ ++ (L)->notify = SYM(H); \ ++ listeners = append_listener((L), listeners); \ ++ wl_signal_add((E), (L)); \ ++ } while(0) ++ ++#define LISTEN_GLOBAL(E, L) do { \ ++ struct wl_listener* l = SYM(L); \ ++ listeners = append_listener(l, listeners); \ ++ wl_signal_add((E), l); \ ++ } while (0) ++ ++#define LISTEN_STATIC(E, H) do { \ ++ struct wl_listener* _l = malloc(sizeof(struct wl_listener)); \ ++ _l->notify = SYM(H); \ ++ listeners = append_listener(_l, listeners); \ ++ wl_signal_add((E), _l); \ ++ } while (0) ++ ++#define UNLISTEN(L) do { \ ++ wl_list_remove(&(L)->link); \ ++ listeners = remove_listener((L), listeners);\ ++ } while (0) + + /* enums */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ +@@ -242,6 +278,9 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++#define static ++ ++#ifdef HOT + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -253,7 +292,18 @@ static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void cleanup(void); ++ ++#undef static ++#define static ++#ifdef HOT ++ + static void cleanupmon(struct wl_listener *listener, void *data); + static void closemon(Monitor *m); + static void commitlayersurfacenotify(struct wl_listener *listener, void *data); +@@ -321,7 +371,18 @@ static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void run(char *startup_cmd); ++ ++#ifdef HOT ++#undef static ++#define static ++ + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -332,7 +393,18 @@ static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void setup(void); ++ ++#ifdef HOT ++#undef static ++#define static ++ + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -356,6 +428,16 @@ static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); + ++#endif ++ ++#ifdef HOT ++ #undef static ++ #define static extern ++#else ++ #undef static ++ #define static ++#endif ++ + /* variables */ + static const char broken[] = "broken"; + static pid_t child_pid = -1; +@@ -400,7 +482,9 @@ static struct wlr_scene_rect *root_bg; + static struct wlr_session_lock_manager_v1 *session_lock_mgr; + static struct wlr_scene_rect *locked_bg; + static struct wlr_session_lock_v1 *cur_lock; ++#ifdef HOT + static struct wl_listener lock_listener = {.notify = locksession}; ++#endif + + static struct wlr_seat *seat; + static KeyboardGroup *kb_group; +@@ -426,6 +510,33 @@ static struct wlr_xwayland *xwayland; + static xcb_atom_t netatom[NetLast]; + #endif + ++/* undoes the shadowing of static from above */ ++#undef static ++ ++/* this is where we put global hot-reload state */ ++#ifdef HOT ++#define COLD extern ++#else ++#define COLD ++ ++static void* load(void); ++static const char* get_module_path(void); ++ ++#endif ++ ++COLD void * dwl_module = NULL; ++COLD void * last_module = NULL; ++COLD struct listens* listeners = NULL; ++COLD void reload(const Arg* arg); ++ ++#ifndef HOT ++static char* runpath; ++ ++#endif ++ ++ ++#ifdef HOT ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -673,6 +784,8 @@ checkidleinhibitor(struct wlr_surface *exclude) + wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); + } + ++#endif ++ + void + cleanup(void) + { +@@ -687,7 +800,7 @@ cleanup(void) + } + wlr_xcursor_manager_destroy(cursor_mgr); + +- destroykeyboardgroup(&kb_group->destroy, NULL); ++ TSYM(void (*)(struct wl_listener*, void*), destroykeyboardgroup)(&kb_group->destroy, NULL); + + /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. + * Destroy it until it's fixed in the wlroots side */ +@@ -699,6 +812,8 @@ cleanup(void) + wlr_scene_node_destroy(&scene->tree.node); + } + ++#ifdef HOT ++ + void + cleanupmon(struct wl_listener *listener, void *data) + { +@@ -712,10 +827,10 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + +- wl_list_remove(&m->destroy.link); +- wl_list_remove(&m->frame.link); ++ UNLISTEN(&m->destroy); ++ UNLISTEN(&m->frame); + wl_list_remove(&m->link); +- wl_list_remove(&m->request_state.link); ++ UNLISTEN(&m->request_state); + m->wlr_output->data = NULL; + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); +@@ -848,7 +963,7 @@ commitpopup(struct wl_listener *listener, void *data) + box.x -= (type == LayerShell ? l->geom.x : c->geom.x); + box.y -= (type == LayerShell ? l->geom.y : c->geom.y); + wlr_xdg_popup_unconstrain_from_box(popup, &box); +- wl_list_remove(&listener->link); ++ UNLISTEN(listener); + } + + void +@@ -1179,8 +1294,8 @@ destroydecoration(struct wl_listener *listener, void *data) + Client *c = wl_container_of(listener, c, destroy_decoration); + c->decoration = NULL; + +- wl_list_remove(&c->destroy_decoration.link); +- wl_list_remove(&c->set_decoration_mode.link); ++ UNLISTEN(&c->destroy_decoration); ++ UNLISTEN(&c->set_decoration_mode); + } + + void +@@ -1205,9 +1320,9 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data) + LayerSurface *l = wl_container_of(listener, l, destroy); + + wl_list_remove(&l->link); +- wl_list_remove(&l->destroy.link); +- wl_list_remove(&l->unmap.link); +- wl_list_remove(&l->surface_commit.link); ++ UNLISTEN(&l->destroy); ++ UNLISTEN(&l->unmap); ++ UNLISTEN(&l->surface_commit); + wlr_scene_node_destroy(&l->scene->node); + wlr_scene_node_destroy(&l->popups->node); + free(l); +@@ -1226,9 +1341,9 @@ destroylock(SessionLock *lock, int unlock) + motionnotify(0, NULL, 0, 0, 0, 0); + + destroy: +- wl_list_remove(&lock->new_surface.link); +- wl_list_remove(&lock->unlock.link); +- wl_list_remove(&lock->destroy.link); ++ UNLISTEN(&lock->new_surface); ++ UNLISTEN(&lock->unlock); ++ UNLISTEN(&lock->destroy); + + wlr_scene_node_destroy(&lock->scene->node); + cur_lock = NULL; +@@ -1242,7 +1357,7 @@ destroylocksurface(struct wl_listener *listener, void *data) + struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; + + m->lock_surface = NULL; +- wl_list_remove(&m->destroy_lock_surface.link); ++ UNLISTEN(&m->destroy_lock_surface); + + if (lock_surface->surface != seat->keyboard_state.focused_surface) + return; +@@ -1262,22 +1377,22 @@ destroynotify(struct wl_listener *listener, void *data) + { + /* Called when the xdg_toplevel is destroyed. */ + Client *c = wl_container_of(listener, c, destroy); +- wl_list_remove(&c->destroy.link); +- wl_list_remove(&c->set_title.link); +- wl_list_remove(&c->fullscreen.link); ++ UNLISTEN(&c->destroy); ++ UNLISTEN(&c->set_title); ++ UNLISTEN(&c->fullscreen); + #ifdef XWAYLAND + if (c->type != XDGShell) { +- wl_list_remove(&c->activate.link); +- wl_list_remove(&c->associate.link); +- wl_list_remove(&c->configure.link); +- wl_list_remove(&c->dissociate.link); +- wl_list_remove(&c->set_hints.link); ++ UNLISTEN(&c->activate); ++ UNLISTEN(&c->associate); ++ UNLISTEN(&c->configure); ++ UNLISTEN(&c->dissociate); ++ UNLISTEN(&c->set_hints); + } else + #endif + { +- wl_list_remove(&c->commit.link); +- wl_list_remove(&c->map.link); +- wl_list_remove(&c->unmap.link); ++ UNLISTEN(&c->commit); ++ UNLISTEN(&c->map); ++ UNLISTEN(&c->unmap); + } + free(c); + } +@@ -1292,7 +1407,7 @@ destroypointerconstraint(struct wl_listener *listener, void *data) + active_constraint = NULL; + } + +- wl_list_remove(&pointer_constraint->destroy.link); ++ UNLISTEN(&pointer_constraint->destroy); + free(pointer_constraint); + } + +@@ -1306,8 +1421,8 @@ destroysessionlock(struct wl_listener *listener, void *data) + void + destroysessionmgr(struct wl_listener *listener, void *data) + { +- wl_list_remove(&lock_listener.link); +- wl_list_remove(&listener->link); ++ UNLISTEN(&lock_listener); ++ UNLISTEN(listener); + } + + void +@@ -1315,10 +1430,10 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) + { + KeyboardGroup *group = wl_container_of(listener, group, destroy); + wl_event_source_remove(group->key_repeat_source); ++ UNLISTEN(&group->key); ++ UNLISTEN(&group->modifiers); ++ UNLISTEN(&group->destroy); + wlr_keyboard_group_destroy(group->wlr_group); +- wl_list_remove(&group->key.link); +- wl_list_remove(&group->modifiers.link); +- wl_list_remove(&group->destroy.link); + free(group); + } + +@@ -2212,6 +2327,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + } + ++#else /*HOT*/ ++ + void + run(char *startup_cmd) + { +@@ -2251,11 +2368,11 @@ run(char *startup_cmd) + if (fd_set_nonblock(STDOUT_FILENO) < 0) + close(STDOUT_FILENO); + +- printstatus(); ++ TSYM(void (*)(void), printstatus)(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ +- selmon = xytomon(cursor->x, cursor->y); ++ selmon = TSYM(Monitor* (*)(double x, double y), xytomon)(cursor->x, cursor->y); + + /* TODO hack to get cursor to display in its initial location (100, 100) + * instead of (0, 0) and then jumping. still may not be fully +@@ -2271,6 +2388,9 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++#endif ++#ifdef HOT ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2428,17 +2548,19 @@ setsel(struct wl_listener *listener, void *data) + wlr_seat_set_selection(seat, event->source, event->serial); + } + ++#else /*HOT*/ ++ + void + setup(void) + { + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; +- struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; ++ struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SYM(handlesig)}; + sigemptyset(&sa.sa_mask); + + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + +- wlr_log_init(log_level, NULL); ++ wlr_log_init(CSYM(enum wlr_log_importance, log_level), NULL); + + /* The Wayland display is managed by libwayland. It handles accepting + * clients from the Unix socket, manging Wayland globals, and so on. */ +@@ -2454,7 +2576,7 @@ setup(void) + + /* Initialize the scene graph used to lay out windows */ + scene = wlr_scene_create(); +- root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor); ++ root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, TSYM(float*, rootcolor)); + for (i = 0; i < NUM_LAYERS; i++) + layers[i] = wlr_scene_tree_create(&scene->tree); + drag_icon = wlr_scene_tree_create(&scene->tree); +@@ -2550,7 +2672,7 @@ setup(void) + LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); + + session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); +- wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener); ++ LISTEN_GLOBAL(&session_lock_mgr->events.new_lock, lock_listener); + LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr); + locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height, + (float [4]){0.1f, 0.1f, 0.1f, 1.0f}); +@@ -2620,7 +2742,7 @@ setup(void) + LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); + LISTEN_STATIC(&seat->events.start_drag, startdrag); + +- kb_group = createkeyboardgroup(); ++ kb_group = TSYM(KeyboardGroup *(*)(void), createkeyboardgroup)(); + wl_list_init(&kb_group->destroy.link); + + output_mgr = wlr_output_manager_v1_create(dpy); +@@ -2647,6 +2769,9 @@ setup(void) + #endif + } + ++#endif ++#ifdef HOT ++ + void + spawn(const Arg *arg) + { +@@ -3121,8 +3246,8 @@ void + dissociatex11(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, dissociate); +- wl_list_remove(&c->map.link); +- wl_list_remove(&c->unmap.link); ++ UNLISTEN(&c->map); ++ UNLISTEN(&c->unmap); + } + + xcb_atom_t +@@ -3185,17 +3310,141 @@ xwaylandready(struct wl_listener *listener, void *data) + } + #endif + ++#else /* HOT */ ++void* ++load(void) ++{ ++ const char* path = get_module_path(); ++ char load[PATH_MAX] = "/tmp/dwl.soXXXXXX"; ++ void* new; ++ ++ if (!path) { ++ fprintf(stderr, "cannot find dwl.so\n"); ++ } ++ ++ do { ++ mktemp(load); ++ errno = 0; ++ symlink(path, load); ++ } while(errno == EEXIST); ++ ++ new = dlopen(load, RTLD_NOW|RTLD_LOCAL); ++ ++ unlink(load); ++ if (new == NULL) ++ fprintf(stderr, "error while loading %s: %s\n", path, dlerror()); ++ else ++ printf("loaded: %s\n", path); ++ ++ return new; ++} ++ ++const char * ++get_module_path(void) { ++ char home[PATH_MAX]; ++ strcpy(home, getenv("HOME")); ++ strcat(home, "/.local/lib"); ++ const char* abspaths[] = {".", home, "/usr/share/lib", "/usr/local/lib", "/usr/local/share/lib"}; ++ const char* relpaths[] = {"", "/../lib"}; ++ char paths[LENGTH(abspaths) + LENGTH(relpaths)][PATH_MAX]; ++ static char out[PATH_MAX] = "./"; ++ ++ for (size_t i = 0; i < LENGTH(abspaths); i++) ++ realpath(abspaths[i], paths[i]); ++ ++ for (size_t i = 0; i < LENGTH(relpaths); i++) ++ { ++ char tmp[PATH_MAX]; ++ strcpy(tmp, runpath); ++ strcat(tmp, relpaths[i]); ++ realpath(tmp, paths[LENGTH(abspaths) + i]); ++ } ++ ++ ++ ++ for (size_t i = 0; i < LENGTH(paths); i++) ++ { ++ char tmp[PATH_MAX]; ++ printf("checking path: %s\n", paths[i]); ++ strcpy(tmp, paths[i]); ++ strcat(tmp, "/dwl.so"); ++ if (access(tmp, F_OK|R_OK) == 0) ++ { ++ strcpy(out, tmp); ++ return out; ++ } ++ } ++ ++ return NULL; ++} ++ ++void ++reload(const Arg* arg) ++{ ++ char* error; ++ void* new; ++ size_t i = 0; ++ ++ // deinitialize previous module ++ if (last_module) { ++ // dlclose(last_module); ++ last_module = NULL; ++ } ++ ++ wlr_log(WLR_INFO, "reloading"); ++ ++ new = load(); ++ ++ if (new == NULL) ++ { ++ wlr_log(WLR_ERROR, "couldn't load new dwl module from %s", get_module_path()); ++ ++ if (fork() == 0) ++ execl("/bin/env", "--", "notify-send", "-u", "low", "failed to reload dwl", NULL); ++ return; ++ } ++ ++ wlr_log(WLR_DEBUG, "---------- listens ---------"); ++ for(listens* a = listeners; a != NULL; a = a->next) ++ { ++ Dl_info info; ++ void* old = a->listen->notify; ++ dladdr(a->listen->notify, &info); ++ a->listen->notify = dlsym(new, info.dli_sname); ++ if ((error = dlerror()) != NULL){ ++ fprintf(stderr, "reload failure: %s", error); ++ a->listen->notify = old; ++ return; ++ } ++ wlr_log(WLR_DEBUG, "replaced listener: %s", info.dli_sname); ++ i++; ++ } ++ ++ wlr_log(WLR_DEBUG, "---------- done! ---------"); ++ wlr_log(WLR_DEBUG, "replaced %zu listeners", i); ++ ++ last_module = dwl_module; ++ dwl_module = new; ++ ++ if (fork() == 0) ++ execl("/bin/env", "--", "notify-send", "-u", "low", "reloaded dwl", NULL); ++ ++} ++ + int + main(int argc, char *argv[]) + { + char *startup_cmd = NULL; + int c; + ++ runpath = dirname(argv[0]); ++ dwl_module = load(); ++ + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') + startup_cmd = optarg; + else if (c == 'd') +- log_level = WLR_DEBUG; ++ CSYM(enum wlr_log_importance, log_level) = WLR_DEBUG; + else if (c == 'v') + die("dwl " VERSION); + else +@@ -3215,3 +3464,5 @@ main(int argc, char *argv[]) + usage: + die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); + } ++ ++#endif +diff --git a/util.c b/util.c +index 51130af..2000731 100644 +--- a/util.c ++++ b/util.c +@@ -49,3 +49,37 @@ fd_set_nonblock(int fd) { + + return 0; + } ++ ++struct listens* ++append_listener(struct wl_listener* new, struct listens* list) ++{ ++ struct listens* l = malloc(sizeof(struct listens)); ++ l->listen = new; ++ l->next = list; ++ return l; ++} ++ ++struct listens* ++remove_listener(struct wl_listener* l, struct listens* ls) ++{ ++ struct listens* out = ls; ++ struct listens* f = NULL; ++ for(struct listens* last = NULL; ls != NULL; ls = ls->next) ++ { ++ if (ls->listen == l) ++ { ++ if (last != NULL) ++ last->next = ls->next; ++ else ++ out = ls->next; ++ ++ f = ls; ++ } ++ else ++ last = ls; ++ } ++ ++ free(f); ++ ++ return out; ++} +diff --git a/util.h b/util.h +index 226980d..11aab34 100644 +--- a/util.h ++++ b/util.h +@@ -1,5 +1,11 @@ + /* See LICENSE.dwm file for copyright and license details. */ ++typedef struct listens { ++ struct wl_listener* listen; ++ struct listens* next; ++} listens; + + void die(const char *fmt, ...); + void *ecalloc(size_t nmemb, size_t size); + int fd_set_nonblock(int fd); ++struct listens* append_listener(struct wl_listener* l, struct listens* ls); ++struct listens* remove_listener(struct wl_listener* l, struct listens* ls); +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/hot-reload/hot-reload.patch b/dwl/dwl-patches/patches/hot-reload/hot-reload.patch new file mode 100755 index 0000000..627fa88 --- /dev/null +++ b/dwl/dwl-patches/patches/hot-reload/hot-reload.patch @@ -0,0 +1,1029 @@ +From 44ce31430dd7d2c0a6c1dc29534f22fb33b25bca Mon Sep 17 00:00:00 2001 +From: Sivecano +Date: Sun, 26 Jan 2025 18:30:02 +0100 +Subject: [PATCH] redo hot-reloading in one file + +--- + Makefile | 19 +- + config.def.h | 5 +- + dwl.c | 484 +++++++++++++++++++++++++++++++++++++++------------ + util.c | 34 ++++ + util.h | 6 + + 5 files changed, 433 insertions(+), 115 deletions(-) + +diff --git a/Makefile b/Makefile +index 578194f..69c1b54 100644 +--- a/Makefile ++++ b/Makefile +@@ -13,13 +13,16 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ + + # CFLAGS / LDFLAGS + PKGS = wayland-server xkbcommon libinput $(XLIBS) +-DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) ++DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) -fPIC -rdynamic + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) + +-all: dwl ++all: dwl dwl.so + dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ +-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ ++dwl.o: dwl.c config.mk cursor-shape-v1-protocol.h \ ++ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++dwl.so: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h + util.o: util.c util.h +@@ -49,7 +52,7 @@ xdg-shell-protocol.h: + config.h: + cp config.def.h $@ + clean: +- rm -f dwl *.o *-protocol.h ++ rm -f dwl *.o *-protocol.h *.so + + dist: clean + mkdir -p dwl-$(VERSION) +@@ -64,6 +67,8 @@ install: dwl + rm -f $(DESTDIR)$(PREFIX)/bin/dwl + cp -f dwl $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl ++ mkdir -p $(DESTDIR)$(PREFIX)/lib ++ install -m 744 dwl.so $(DESTDIR)$(PREFIX)/lib + mkdir -p $(DESTDIR)$(MANDIR)/man1 + cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 + chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 +@@ -71,9 +76,13 @@ install: dwl + cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + uninstall: +- rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \ ++ rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(PREFIX)/lib/dwl.so $(DESTDIR)$(MANDIR)/man1/dwl.1 \ + $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + + .SUFFIXES: .c .o + .c.o: + $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -c $< ++ ++.SUFFIXES: .c .so ++.c.so: ++ $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -shared -DHOT $< +diff --git a/config.def.h b/config.def.h +index 22d2171..6e3dda1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,7 +7,7 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); ++const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); +@@ -18,7 +18,7 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + #define TAGCOUNT (9) + + /* logging */ +-static int log_level = WLR_ERROR; ++int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +@@ -127,6 +127,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, reload, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index 4816159..70e99be 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1,6 +1,15 @@ + /* + * See LICENSE file for copyright and license details. + */ ++ ++/* stuff for hot-reload */ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++ + #include + #include + #include +@@ -68,6 +77,7 @@ + #include + #endif + ++ + #include "util.h" + + /* macros */ +@@ -78,8 +88,33 @@ + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) +-#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) +-#define LISTEN_STATIC(E, H) do { struct wl_listener *_l = ecalloc(1, sizeof(*_l)); _l->notify = (H); wl_signal_add((E), _l); } while (0) ++#define SYM(a) dlsym(dwl_module, #a) ++#define TSYM(T, a) ((T)SYM(a)) ++#define CSYM(T, a) *(TSYM(T*, a)) ++ ++#define LISTEN(E, L, H) do { \ ++ (L)->notify = SYM(H); \ ++ listeners = append_listener((L), listeners); \ ++ wl_signal_add((E), (L)); \ ++ } while(0) ++ ++#define LISTEN_GLOBAL(E, L) do { \ ++ struct wl_listener* l = SYM(L); \ ++ listeners = append_listener(l, listeners); \ ++ wl_signal_add((E), l); \ ++ } while (0) ++ ++#define LISTEN_STATIC(E, H) do { \ ++ struct wl_listener* _l = ecalloc(1, sizeof(struct wl_listener)); \ ++ _l->notify = SYM(H); \ ++ listeners = append_listener(_l, listeners); \ ++ wl_signal_add((E), _l); \ ++ } while (0) ++ ++#define UNLISTEN(L) do { \ ++ wl_list_remove(&(L)->link); \ ++ listeners = remove_listener((L), listeners);\ ++ } while (0) + + /* enums */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ +@@ -239,6 +274,9 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++#define static ++ ++#ifdef HOT + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -250,7 +288,18 @@ static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void cleanup(void); ++ ++#undef static ++#define static ++#ifdef HOT ++ + static void cleanupmon(struct wl_listener *listener, void *data); + static void cleanuplisteners(void); + static void closemon(Monitor *m); +@@ -318,7 +367,18 @@ static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void run(char *startup_cmd); ++ ++#ifdef HOT ++#undef static ++#define static ++ + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -328,7 +388,18 @@ static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void setup(void); ++ ++#ifdef HOT ++#undef static ++#define static ++ + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -352,6 +423,16 @@ static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); + ++#endif ++ ++#ifdef HOT ++ #undef static ++ #define static extern ++#else ++ #undef static ++ #define static ++#endif ++ + /* variables */ + static pid_t child_pid = -1; + static int locked; +@@ -406,6 +487,10 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++#ifdef HOT ++#undef static ++#define static ++ + /* global event handlers */ + static struct wl_listener cursor_axis = {.notify = axisnotify}; + static struct wl_listener cursor_button = {.notify = buttonpress}; +@@ -429,6 +514,7 @@ static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; + static struct wl_listener output_power_mgr_set_mode = {.notify = powermgrsetmode}; + static struct wl_listener request_activate = {.notify = urgent}; + static struct wl_listener request_cursor = {.notify = setcursor}; ++ + static struct wl_listener request_set_psel = {.notify = setpsel}; + static struct wl_listener request_set_sel = {.notify = setsel}; + static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape}; +@@ -436,7 +522,15 @@ static struct wl_listener request_start_drag = {.notify = requeststartdrag}; + static struct wl_listener start_drag = {.notify = startdrag}; + static struct wl_listener new_session_lock = {.notify = locksession}; + ++/* undoes the shadowing of static from above */ ++#endif ++#undef static ++ ++ + #ifdef XWAYLAND ++#ifdef HOT ++#define static ++ + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); + static void configurex11(struct wl_listener *listener, void *data); +@@ -446,11 +540,45 @@ static void sethints(struct wl_listener *listener, void *data); + static void xwaylandready(struct wl_listener *listener, void *data); + static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; + static struct wl_listener xwayland_ready = {.notify = xwaylandready}; ++ ++#define static extern ++#else ++#define static ++#endif ++ + static struct wlr_xwayland *xwayland; ++ ++#undef static ++#endif ++ ++/* this is where we put global hot-reload state */ ++#ifdef HOT ++#define COLD extern ++#else ++#define COLD ++ ++static void* load(void); ++static const char* get_module_path(void); ++ ++#endif ++ ++COLD void * dwl_module = NULL; ++COLD void * last_module = NULL; ++COLD struct listens* listeners = NULL; ++COLD void reload(const Arg* arg); ++ ++#ifndef HOT ++static char* runpath; ++ + #endif + ++ ++#ifdef HOT ++ ++#define static + /* configuration, allows nested code to access above variables */ + #include "config.h" ++#undef static + + /* attempt to encapsulate suck into one file */ + #include "client.h" +@@ -695,10 +823,12 @@ checkidleinhibitor(struct wlr_surface *exclude) + wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); + } + ++#endif ++ + void + cleanup(void) + { +- cleanuplisteners(); ++ TSYM(void (*)(void), cleanuplisteners)(); + #ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; +@@ -710,7 +840,7 @@ cleanup(void) + } + wlr_xcursor_manager_destroy(cursor_mgr); + +- destroykeyboardgroup(&kb_group->destroy, NULL); ++ TSYM(void (*)(struct wl_listener*, void*), destroykeyboardgroup)(&kb_group->destroy, NULL); + + /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. + * Destroy it until it's fixed in the wlroots side */ +@@ -722,6 +852,8 @@ cleanup(void) + wlr_scene_node_destroy(&scene->tree.node); + } + ++#ifdef HOT ++ + void + cleanupmon(struct wl_listener *listener, void *data) + { +@@ -735,10 +867,10 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + +- wl_list_remove(&m->destroy.link); +- wl_list_remove(&m->frame.link); ++ UNLISTEN(&m->destroy); ++ UNLISTEN(&m->frame); + wl_list_remove(&m->link); +- wl_list_remove(&m->request_state.link); ++ UNLISTEN(&m->request_state); + m->wlr_output->data = NULL; + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); +@@ -751,37 +883,37 @@ cleanupmon(struct wl_listener *listener, void *data) + void + cleanuplisteners(void) + { +- wl_list_remove(&cursor_axis.link); +- wl_list_remove(&cursor_button.link); +- wl_list_remove(&cursor_frame.link); +- wl_list_remove(&cursor_motion.link); +- wl_list_remove(&cursor_motion_absolute.link); +- wl_list_remove(&gpu_reset.link); +- wl_list_remove(&new_idle_inhibitor.link); +- wl_list_remove(&layout_change.link); +- wl_list_remove(&new_input_device.link); +- wl_list_remove(&new_virtual_keyboard.link); +- wl_list_remove(&new_virtual_pointer.link); +- wl_list_remove(&new_pointer_constraint.link); +- wl_list_remove(&new_output.link); +- wl_list_remove(&new_xdg_toplevel.link); +- wl_list_remove(&new_xdg_decoration.link); +- wl_list_remove(&new_xdg_popup.link); +- wl_list_remove(&new_layer_surface.link); +- wl_list_remove(&output_mgr_apply.link); +- wl_list_remove(&output_mgr_test.link); +- wl_list_remove(&output_power_mgr_set_mode.link); +- wl_list_remove(&request_activate.link); +- wl_list_remove(&request_cursor.link); +- wl_list_remove(&request_set_psel.link); +- wl_list_remove(&request_set_sel.link); +- wl_list_remove(&request_set_cursor_shape.link); +- wl_list_remove(&request_start_drag.link); +- wl_list_remove(&start_drag.link); +- wl_list_remove(&new_session_lock.link); ++ UNLISTEN(&cursor_axis); ++ UNLISTEN(&cursor_button); ++ UNLISTEN(&cursor_frame); ++ UNLISTEN(&cursor_motion); ++ UNLISTEN(&cursor_motion_absolute); ++ UNLISTEN(&gpu_reset); ++ UNLISTEN(&new_idle_inhibitor); ++ UNLISTEN(&layout_change); ++ UNLISTEN(&new_input_device); ++ UNLISTEN(&new_virtual_keyboard); ++ UNLISTEN(&new_virtual_pointer); ++ UNLISTEN(&new_pointer_constraint); ++ UNLISTEN(&new_output); ++ UNLISTEN(&new_xdg_toplevel); ++ UNLISTEN(&new_xdg_decoration); ++ UNLISTEN(&new_xdg_popup); ++ UNLISTEN(&new_layer_surface); ++ UNLISTEN(&output_mgr_apply); ++ UNLISTEN(&output_mgr_test); ++ UNLISTEN(&output_power_mgr_set_mode); ++ UNLISTEN(&request_activate); ++ UNLISTEN(&request_cursor); ++ UNLISTEN(&request_set_psel); ++ UNLISTEN(&request_set_sel); ++ UNLISTEN(&request_set_cursor_shape); ++ UNLISTEN(&request_start_drag); ++ UNLISTEN(&start_drag); ++ UNLISTEN(&new_session_lock); + #ifdef XWAYLAND +- wl_list_remove(&new_xwayland_surface.link); +- wl_list_remove(&xwayland_ready.link); ++ UNLISTEN(&new_xwayland_surface); ++ UNLISTEN(&xwayland_ready); + #endif + } + +@@ -908,7 +1040,7 @@ commitpopup(struct wl_listener *listener, void *data) + box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x); + box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y); + wlr_xdg_popup_unconstrain_from_box(popup, &box); +- wl_list_remove(&listener->link); ++ UNLISTEN(listener); + free(listener); + } + +@@ -1239,8 +1371,8 @@ destroydecoration(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, destroy_decoration); + +- wl_list_remove(&c->destroy_decoration.link); +- wl_list_remove(&c->set_decoration_mode.link); ++ UNLISTEN(&c->destroy_decoration); ++ UNLISTEN(&c->set_decoration_mode); + } + + void +@@ -1249,7 +1381,7 @@ destroydragicon(struct wl_listener *listener, void *data) + /* Focus enter isn't sent during drag, so refocus the focused node. */ + focusclient(focustop(selmon), 1); + motionnotify(0, NULL, 0, 0, 0, 0); +- wl_list_remove(&listener->link); ++ UNLISTEN(listener); + free(listener); + } + +@@ -1259,7 +1391,7 @@ destroyidleinhibitor(struct wl_listener *listener, void *data) + /* `data` is the wlr_surface of the idle inhibitor being destroyed, + * at this point the idle inhibitor is still in the list of the manager */ + checkidleinhibitor(wlr_surface_get_root_surface(data)); +- wl_list_remove(&listener->link); ++ UNLISTEN(listener); + free(listener); + } + +@@ -1269,9 +1401,9 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data) + LayerSurface *l = wl_container_of(listener, l, destroy); + + wl_list_remove(&l->link); +- wl_list_remove(&l->destroy.link); +- wl_list_remove(&l->unmap.link); +- wl_list_remove(&l->surface_commit.link); ++ UNLISTEN(&l->destroy); ++ UNLISTEN(&l->unmap); ++ UNLISTEN(&l->surface_commit); + wlr_scene_node_destroy(&l->scene->node); + wlr_scene_node_destroy(&l->popups->node); + free(l); +@@ -1290,9 +1422,9 @@ destroylock(SessionLock *lock, int unlock) + motionnotify(0, NULL, 0, 0, 0, 0); + + destroy: +- wl_list_remove(&lock->new_surface.link); +- wl_list_remove(&lock->unlock.link); +- wl_list_remove(&lock->destroy.link); ++ UNLISTEN(&lock->new_surface); ++ UNLISTEN(&lock->unlock); ++ UNLISTEN(&lock->destroy); + + wlr_scene_node_destroy(&lock->scene->node); + cur_lock = NULL; +@@ -1306,7 +1438,7 @@ destroylocksurface(struct wl_listener *listener, void *data) + struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; + + m->lock_surface = NULL; +- wl_list_remove(&m->destroy_lock_surface.link); ++ UNLISTEN(&m->destroy_lock_surface); + + if (lock_surface->surface != seat->keyboard_state.focused_surface) + return; +@@ -1326,23 +1458,23 @@ destroynotify(struct wl_listener *listener, void *data) + { + /* Called when the xdg_toplevel is destroyed. */ + Client *c = wl_container_of(listener, c, destroy); +- wl_list_remove(&c->destroy.link); +- wl_list_remove(&c->set_title.link); +- wl_list_remove(&c->fullscreen.link); ++ UNLISTEN(&c->destroy); ++ UNLISTEN(&c->set_title); ++ UNLISTEN(&c->fullscreen); + #ifdef XWAYLAND + if (c->type != XDGShell) { +- wl_list_remove(&c->activate.link); +- wl_list_remove(&c->associate.link); +- wl_list_remove(&c->configure.link); +- wl_list_remove(&c->dissociate.link); +- wl_list_remove(&c->set_hints.link); ++ UNLISTEN(&c->activate); ++ UNLISTEN(&c->associate); ++ UNLISTEN(&c->configure); ++ UNLISTEN(&c->dissociate); ++ UNLISTEN(&c->set_hints); + } else + #endif + { +- wl_list_remove(&c->commit.link); +- wl_list_remove(&c->map.link); +- wl_list_remove(&c->unmap.link); +- wl_list_remove(&c->maximize.link); ++ UNLISTEN(&c->commit); ++ UNLISTEN(&c->map); ++ UNLISTEN(&c->unmap); ++ UNLISTEN(&c->maximize); + } + free(c); + } +@@ -1357,7 +1489,7 @@ destroypointerconstraint(struct wl_listener *listener, void *data) + active_constraint = NULL; + } + +- wl_list_remove(&pointer_constraint->destroy.link); ++ UNLISTEN(&pointer_constraint->destroy); + free(pointer_constraint); + } + +@@ -1373,9 +1505,9 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) + { + KeyboardGroup *group = wl_container_of(listener, group, destroy); + wl_event_source_remove(group->key_repeat_source); +- wl_list_remove(&group->key.link); +- wl_list_remove(&group->modifiers.link); +- wl_list_remove(&group->destroy.link); ++ UNLISTEN(&group->key); ++ UNLISTEN(&group->modifiers); ++ UNLISTEN(&group->destroy); + wlr_keyboard_group_destroy(group->wlr_group); + free(group); + } +@@ -1541,8 +1673,8 @@ gpureset(struct wl_listener *listener, void *data) + if (!(alloc = wlr_allocator_autocreate(backend, drw))) + die("couldn't recreate allocator"); + +- wl_list_remove(&gpu_reset.link); +- wl_signal_add(&drw->events.lost, &gpu_reset); ++ UNLISTEN(&gpu_reset); ++ LISTEN_GLOBAL(&drw->events.lost, gpu_reset); + + wlr_compositor_set_renderer(compositor, drw); + +@@ -2232,6 +2364,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + } + ++#else /*HOT*/ ++ + void + run(char *startup_cmd) + { +@@ -2271,11 +2405,11 @@ run(char *startup_cmd) + if (fd_set_nonblock(STDOUT_FILENO) < 0) + close(STDOUT_FILENO); + +- printstatus(); ++ TSYM(void (*)(void), printstatus)(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ +- selmon = xytomon(cursor->x, cursor->y); ++ selmon = TSYM(Monitor* (*)(double x, double y), xytomon)(cursor->x, cursor->y); + + /* TODO hack to get cursor to display in its initial location (100, 100) + * instead of (0, 0) and then jumping. still may not be fully +@@ -2291,6 +2425,9 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++#endif ++#ifdef HOT ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2437,17 +2574,19 @@ setsel(struct wl_listener *listener, void *data) + wlr_seat_set_selection(seat, event->source, event->serial); + } + ++#else /*HOT*/ ++ + void + setup(void) + { + int drm_fd, i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; +- struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; ++ struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SYM(handlesig)}; + sigemptyset(&sa.sa_mask); + + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + +- wlr_log_init(log_level, NULL); ++ wlr_log_init(CSYM(enum wlr_log_importance, log_level), NULL); + + /* The Wayland display is managed by libwayland. It handles accepting + * clients from the Unix socket, manging Wayland globals, and so on. */ +@@ -2463,7 +2602,7 @@ setup(void) + + /* Initialize the scene graph used to lay out windows */ + scene = wlr_scene_create(); +- root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor); ++ root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, TSYM(float*, rootcolor)); + for (i = 0; i < NUM_LAYERS; i++) + layers[i] = wlr_scene_tree_create(&scene->tree); + drag_icon = wlr_scene_tree_create(&scene->tree); +@@ -2475,7 +2614,7 @@ setup(void) + * supports for shared memory, this configures that for clients. */ + if (!(drw = wlr_renderer_autocreate(backend))) + die("couldn't create renderer"); +- wl_signal_add(&drw->events.lost, &gpu_reset); ++ LISTEN_GLOBAL(&drw->events.lost, gpu_reset); + + /* Create shm, drm and linux_dmabuf interfaces by ourselves. + * The simplest way is call: +@@ -2522,24 +2661,24 @@ setup(void) + + /* Initializes the interface used to implement urgency hints */ + activation = wlr_xdg_activation_v1_create(dpy); +- wl_signal_add(&activation->events.request_activate, &request_activate); ++ LISTEN_GLOBAL(&activation->events.request_activate, request_activate); + + wlr_scene_set_gamma_control_manager_v1(scene, wlr_gamma_control_manager_v1_create(dpy)); + + power_mgr = wlr_output_power_manager_v1_create(dpy); +- wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode); ++ LISTEN_GLOBAL(&power_mgr->events.set_mode, output_power_mgr_set_mode); + + /* Creates an output layout, which a wlroots utility for working with an + * arrangement of screens in a physical layout. */ + output_layout = wlr_output_layout_create(dpy); +- wl_signal_add(&output_layout->events.change, &layout_change); ++ LISTEN_GLOBAL(&output_layout->events.change, layout_change); + + wlr_xdg_output_manager_v1_create(dpy, output_layout); + + /* Configure a listener to be notified when new outputs are available on the + * backend. */ + wl_list_init(&mons); +- wl_signal_add(&backend->events.new_output, &new_output); ++ LISTEN_GLOBAL(&backend->events.new_output, new_output); + + /* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a + * Wayland protocol which is used for application windows. For more +@@ -2551,19 +2690,19 @@ setup(void) + wl_list_init(&fstack); + + xdg_shell = wlr_xdg_shell_create(dpy, 6); +- wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel); +- wl_signal_add(&xdg_shell->events.new_popup, &new_xdg_popup); ++ LISTEN_GLOBAL(&xdg_shell->events.new_toplevel, new_xdg_toplevel); ++ LISTEN_GLOBAL(&xdg_shell->events.new_popup, new_xdg_popup); + + layer_shell = wlr_layer_shell_v1_create(dpy, 3); +- wl_signal_add(&layer_shell->events.new_surface, &new_layer_surface); ++ LISTEN_GLOBAL(&layer_shell->events.new_surface, new_layer_surface); + + idle_notifier = wlr_idle_notifier_v1_create(dpy); + + idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); +- wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &new_idle_inhibitor); ++ LISTEN_GLOBAL(&idle_inhibit_mgr->events.new_inhibitor, new_idle_inhibitor); + + session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); +- wl_signal_add(&session_lock_mgr->events.new_lock, &new_session_lock); ++ LISTEN_GLOBAL(&session_lock_mgr->events.new_lock, new_session_lock); + locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height, + (float [4]){0.1f, 0.1f, 0.1f, 1.0f}); + wlr_scene_node_set_enabled(&locked_bg->node, 0); +@@ -2573,10 +2712,10 @@ setup(void) + wlr_server_decoration_manager_create(dpy), + WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); +- wl_signal_add(&xdg_decoration_mgr->events.new_toplevel_decoration, &new_xdg_decoration); ++ LISTEN_GLOBAL(&xdg_decoration_mgr->events.new_toplevel_decoration, new_xdg_decoration); + + pointer_constraints = wlr_pointer_constraints_v1_create(dpy); +- wl_signal_add(&pointer_constraints->events.new_constraint, &new_pointer_constraint); ++ LISTEN_GLOBAL(&pointer_constraints->events.new_constraint, new_pointer_constraint); + + relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); + +@@ -2604,14 +2743,14 @@ setup(void) + * + * And more comments are sprinkled throughout the notify functions above. + */ +- wl_signal_add(&cursor->events.motion, &cursor_motion); +- wl_signal_add(&cursor->events.motion_absolute, &cursor_motion_absolute); +- wl_signal_add(&cursor->events.button, &cursor_button); +- wl_signal_add(&cursor->events.axis, &cursor_axis); +- wl_signal_add(&cursor->events.frame, &cursor_frame); ++ LISTEN_GLOBAL(&cursor->events.motion, cursor_motion); ++ LISTEN_GLOBAL(&cursor->events.motion_absolute, cursor_motion_absolute); ++ LISTEN_GLOBAL(&cursor->events.button, cursor_button); ++ LISTEN_GLOBAL(&cursor->events.axis, cursor_axis); ++ LISTEN_GLOBAL(&cursor->events.frame, cursor_frame); + + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); +- wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape); ++ LISTEN_GLOBAL(&cursor_shape_mgr->events.request_set_shape, request_set_cursor_shape); + + /* + * Configures a seat, which is a single "seat" at which a user sits and +@@ -2619,27 +2758,27 @@ setup(void) + * pointer, touch, and drawing tablet device. We also rig up a listener to + * let us know when new input devices are available on the backend. + */ +- wl_signal_add(&backend->events.new_input, &new_input_device); ++ LISTEN_GLOBAL(&backend->events.new_input, new_input_device); + virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); +- wl_signal_add(&virtual_keyboard_mgr->events.new_virtual_keyboard, +- &new_virtual_keyboard); ++ LISTEN_GLOBAL(&virtual_keyboard_mgr->events.new_virtual_keyboard, ++ new_virtual_keyboard); + virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); +- wl_signal_add(&virtual_pointer_mgr->events.new_virtual_pointer, +- &new_virtual_pointer); ++ LISTEN_GLOBAL(&virtual_pointer_mgr->events.new_virtual_pointer, ++ new_virtual_pointer); + + seat = wlr_seat_create(dpy, "seat0"); +- wl_signal_add(&seat->events.request_set_cursor, &request_cursor); +- wl_signal_add(&seat->events.request_set_selection, &request_set_sel); +- wl_signal_add(&seat->events.request_set_primary_selection, &request_set_psel); +- wl_signal_add(&seat->events.request_start_drag, &request_start_drag); +- wl_signal_add(&seat->events.start_drag, &start_drag); ++ LISTEN_GLOBAL(&seat->events.request_set_cursor, request_cursor); ++ LISTEN_GLOBAL(&seat->events.request_set_selection, request_set_sel); ++ LISTEN_GLOBAL(&seat->events.request_set_primary_selection, request_set_psel); ++ LISTEN_GLOBAL(&seat->events.request_start_drag, request_start_drag); ++ LISTEN_GLOBAL(&seat->events.start_drag, start_drag); + +- kb_group = createkeyboardgroup(); ++ kb_group = TSYM(KeyboardGroup *(*)(void), createkeyboardgroup)(); + wl_list_init(&kb_group->destroy.link); + + output_mgr = wlr_output_manager_v1_create(dpy); +- wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); +- wl_signal_add(&output_mgr->events.test, &output_mgr_test); ++ LISTEN_GLOBAL(&output_mgr->events.apply, output_mgr_apply); ++ LISTEN_GLOBAL(&output_mgr->events.test, output_mgr_test); + + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the +@@ -2651,8 +2790,8 @@ setup(void) + * It will be started when the first X client is started. + */ + if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) { +- wl_signal_add(&xwayland->events.ready, &xwayland_ready); +- wl_signal_add(&xwayland->events.new_surface, &new_xwayland_surface); ++ LISTEN_GLOBAL(&xwayland->events.ready, xwayland_ready); ++ LISTEN_GLOBAL(&xwayland->events.new_surface, new_xwayland_surface); + + setenv("DISPLAY", xwayland->display_name, 1); + } else { +@@ -2661,6 +2800,9 @@ setup(void) + #endif + } + ++#endif ++#ifdef HOT ++ + void + spawn(const Arg *arg) + { +@@ -3142,8 +3284,8 @@ void + dissociatex11(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, dissociate); +- wl_list_remove(&c->map.link); +- wl_list_remove(&c->unmap.link); ++ UNLISTEN(&c->map); ++ UNLISTEN(&c->unmap); + } + + void +@@ -3178,17 +3320,141 @@ xwaylandready(struct wl_listener *listener, void *data) + } + #endif + ++#else /* HOT */ ++void* ++load(void) ++{ ++ const char* path = get_module_path(); ++ char load[PATH_MAX] = "/tmp/dwl.soXXXXXX"; ++ void* new; ++ ++ if (!path) { ++ fprintf(stderr, "cannot find dwl.so\n"); ++ } ++ ++ do { ++ mktemp(load); ++ errno = 0; ++ symlink(path, load); ++ } while(errno == EEXIST); ++ ++ new = dlopen(load, RTLD_NOW|RTLD_LOCAL); ++ ++ unlink(load); ++ if (new == NULL) ++ fprintf(stderr, "error while loading %s: %s\n", path, dlerror()); ++ else ++ printf("loaded: %s\n", path); ++ ++ return new; ++} ++ ++const char * ++get_module_path(void) { ++ char home[PATH_MAX]; ++ strcpy(home, getenv("HOME")); ++ strcat(home, "/.local/lib"); ++ const char* abspaths[] = {".", home, "/usr/share/lib", "/usr/local/lib", "/usr/local/share/lib"}; ++ const char* relpaths[] = {"", "/../lib"}; ++ char paths[LENGTH(abspaths) + LENGTH(relpaths)][PATH_MAX]; ++ static char out[PATH_MAX] = "./"; ++ ++ for (size_t i = 0; i < LENGTH(abspaths); i++) ++ realpath(abspaths[i], paths[i]); ++ ++ for (size_t i = 0; i < LENGTH(relpaths); i++) ++ { ++ char tmp[PATH_MAX]; ++ strcpy(tmp, runpath); ++ strcat(tmp, relpaths[i]); ++ realpath(tmp, paths[LENGTH(abspaths) + i]); ++ } ++ ++ ++ ++ for (size_t i = 0; i < LENGTH(paths); i++) ++ { ++ char tmp[PATH_MAX]; ++ printf("checking path: %s\n", paths[i]); ++ strcpy(tmp, paths[i]); ++ strcat(tmp, "/dwl.so"); ++ if (access(tmp, F_OK|R_OK) == 0) ++ { ++ strcpy(out, tmp); ++ return out; ++ } ++ } ++ ++ return NULL; ++} ++ ++void ++reload(const Arg* arg) ++{ ++ char* error; ++ void* new; ++ size_t i = 0; ++ ++ // deinitialize previous module ++ if (last_module) { ++ // dlclose(last_module); ++ last_module = NULL; ++ } ++ ++ wlr_log(WLR_INFO, "reloading"); ++ ++ new = load(); ++ ++ if (new == NULL) ++ { ++ wlr_log(WLR_ERROR, "couldn't load new dwl module from %s", get_module_path()); ++ ++ if (fork() == 0) ++ execl("/bin/env", "--", "notify-send", "-u", "low", "failed to reload dwl", NULL); ++ return; ++ } ++ ++ wlr_log(WLR_DEBUG, "---------- listens ---------"); ++ for(listens* a = listeners; a != NULL; a = a->next) ++ { ++ Dl_info info; ++ void* old = a->listen->notify; ++ dladdr(a->listen->notify, &info); ++ a->listen->notify = dlsym(new, info.dli_sname); ++ if ((error = dlerror()) != NULL){ ++ fprintf(stderr, "reload failure: %s", error); ++ a->listen->notify = old; ++ return; ++ } ++ wlr_log(WLR_DEBUG, "replaced listener: %s", info.dli_sname); ++ i++; ++ } ++ ++ wlr_log(WLR_DEBUG, "---------- done! ---------"); ++ wlr_log(WLR_DEBUG, "replaced %zu listeners", i); ++ ++ last_module = dwl_module; ++ dwl_module = new; ++ ++ if (fork() == 0) ++ execl("/bin/env", "--", "notify-send", "-u", "low", "reloaded dwl", NULL); ++ ++} ++ + int + main(int argc, char *argv[]) + { + char *startup_cmd = NULL; + int c; + ++ runpath = dirname(argv[0]); ++ dwl_module = load(); ++ + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') + startup_cmd = optarg; + else if (c == 'd') +- log_level = WLR_DEBUG; ++ CSYM(enum wlr_log_importance, log_level) = WLR_DEBUG; + else if (c == 'v') + die("dwl " VERSION); + else +@@ -3208,3 +3474,5 @@ main(int argc, char *argv[]) + usage: + die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); + } ++ ++#endif +diff --git a/util.c b/util.c +index b925987..8fb9b77 100644 +--- a/util.c ++++ b/util.c +@@ -49,3 +49,37 @@ fd_set_nonblock(int fd) { + + return 0; + } ++ ++struct listens* ++append_listener(struct wl_listener* new, struct listens* list) ++{ ++ struct listens* l = malloc(sizeof(struct listens)); ++ l->listen = new; ++ l->next = list; ++ return l; ++} ++ ++struct listens* ++remove_listener(struct wl_listener* l, struct listens* ls) ++{ ++ struct listens* out = ls; ++ struct listens* f = NULL; ++ for(struct listens* last = NULL; ls != NULL; ls = ls->next) ++ { ++ if (ls->listen == l) ++ { ++ if (last != NULL) ++ last->next = ls->next; ++ else ++ out = ls->next; ++ ++ f = ls; ++ } ++ else ++ last = ls; ++ } ++ ++ free(f); ++ ++ return out; ++} +diff --git a/util.h b/util.h +index 226980d..11aab34 100644 +--- a/util.h ++++ b/util.h +@@ -1,5 +1,11 @@ + /* See LICENSE.dwm file for copyright and license details. */ ++typedef struct listens { ++ struct wl_listener* listen; ++ struct listens* next; ++} listens; + + void die(const char *fmt, ...); + void *ecalloc(size_t nmemb, size_t size); + int fd_set_nonblock(int fd); ++struct listens* append_listener(struct wl_listener* l, struct listens* ls); ++struct listens* remove_listener(struct wl_listener* l, struct listens* ls); +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/inputdevicerules/README.md b/dwl/dwl-patches/patches/inputdevicerules/README.md new file mode 100755 index 0000000..3f87ef9 --- /dev/null +++ b/dwl/dwl-patches/patches/inputdevicerules/README.md @@ -0,0 +1,18 @@ +### Description + +Input device rules implemented using custom device create functions for +keyboards and pointing devices. + +Examples provided: + +- ignore unwanted input devices +- configure a toggle input device +- exclude certain keyboards (eg ydotool) from keyboard group + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/inputdevicerules) +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/inputdevicerules/inputdevicerules-v0.7.patch) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/inputdevicerules/inputdevicerules-v0.6.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) diff --git a/dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.6.patch b/dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.6.patch new file mode 100755 index 0000000..b9e9fd2 --- /dev/null +++ b/dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.6.patch @@ -0,0 +1,173 @@ +From 620a68ffbcecf996916a8fd637f0bcff7a72e004 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Sat, 15 Jun 2024 12:34:01 +1000 +Subject: [PATCH] input device rules + +* customise input device handling +* ignore unwanted input devices +* configure a toggle for an input device +--- + config.def.h | 13 ++++++++++ + dwl.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 79 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a784eb4f..88006d79 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -57,6 +57,18 @@ static const struct xkb_rule_names xkb_rules = { + .options = NULL, + }; + ++/* input devices */ ++static const InputRule inputrules[] = { ++ /* name kbcreate ptrcreate */ ++ /* ignore bad device - like a touchpad ;) */ ++ { "BAD DEVICE", NULL, NULL }, ++ /* ungroup ydotool device - fixes a bug */ ++ { "ydotoold virtual device", createungroupedkeyboard, createpointer }, ++ /* put your touchpad name here to enable toggle touchpad */ ++ { "Elan Touchpad", createkeyboard, createtogglepointer }, ++ { NULL, createkeyboard, createpointer }, ++}; ++ + static const int repeat_rate = 25; + static const int repeat_delay = 600; + +@@ -139,6 +151,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_u, togglepointer, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index 3dba2bf5..a11c7587 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -141,6 +141,12 @@ typedef struct { + uint32_t resize; /* configure serial of a pending resize */ + } Client; + ++typedef struct { ++ const char *name; ++ void (*kbcreate)(struct wlr_keyboard *); ++ void (*ptrcreate)(struct wlr_pointer *); ++} InputRule; ++ + typedef struct { + uint32_t mod; + xkb_keysym_t keysym; +@@ -266,6 +272,8 @@ static void createmon(struct wl_listener *listener, void *data); + static void createnotify(struct wl_listener *listener, void *data); + static void createpointer(struct wlr_pointer *pointer); + static void createpointerconstraint(struct wl_listener *listener, void *data); ++static void createtogglepointer(struct wlr_pointer *pointer); ++static void createungroupedkeyboard(struct wlr_keyboard *keyboard); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); +@@ -335,6 +343,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglepointer(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -406,6 +415,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static struct libinput_device *togglepointerdevice = NULL; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -1092,6 +1103,33 @@ createpointerconstraint(struct wl_listener *listener, void *data) + &pointer_constraint->destroy, destroypointerconstraint); + } + ++void ++createtogglepointer(struct wlr_pointer *pointer) ++{ ++ struct libinput_device *device; ++ ++ createpointer(pointer); ++ ++ if (wlr_input_device_is_libinput(&pointer->base) ++ && (device = wlr_libinput_get_device_handle(&pointer->base))) { ++ togglepointerdevice = device; ++ } ++} ++ ++void ++createungroupedkeyboard(struct wlr_keyboard *keyboard) ++{ ++ /* for keyboards that need their own keyboard group */ ++ KeyboardGroup *group = createkeyboardgroup(); ++ ++ /* Set the keymap to match the group keymap */ ++ wlr_keyboard_set_keymap(keyboard, group->wlr_group->keyboard.keymap); ++ LISTEN(&keyboard->base.events.destroy, &group->destroy, destroykeyboardgroup); ++ ++ /* Add the new keyboard to the group */ ++ wlr_keyboard_group_add_keyboard(group->wlr_group, keyboard); ++} ++ + void + cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) + { +@@ -1467,13 +1505,27 @@ inputdevice(struct wl_listener *listener, void *data) + * available. */ + struct wlr_input_device *device = data; + uint32_t caps; ++ const InputRule *r; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: +- createkeyboard(wlr_keyboard_from_input_device(device)); ++ for (r = inputrules; r < END(inputrules); r++) { ++ if (!r->name || strstr(device->name, r->name)) { ++ if (r->kbcreate) ++ r->kbcreate(wlr_keyboard_from_input_device(device)); ++ break; ++ } ++ } ++ + break; + case WLR_INPUT_DEVICE_POINTER: +- createpointer(wlr_pointer_from_input_device(device)); ++ for (r = inputrules; r < END(inputrules); r++) { ++ if (!r->name || strstr(device->name, r->name)) { ++ if (r->ptrcreate) ++ r->ptrcreate(wlr_pointer_from_input_device(device)); ++ break; ++ } ++ } + break; + default: + /* TODO handle other input device types */ +@@ -2647,6 +2699,18 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglepointer(const Arg *arg) ++{ ++ if (!togglepointerdevice) ++ return; ++ ++ libinput_device_config_send_events_set_mode( ++ togglepointerdevice, ++ libinput_device_config_send_events_get_mode(togglepointerdevice) ^ LIBINPUT_CONFIG_SEND_EVENTS_DISABLED ++ ); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.7.patch b/dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.7.patch new file mode 100755 index 0000000..18f6f9e --- /dev/null +++ b/dwl/dwl-patches/patches/inputdevicerules/inputdevicerules-v0.7.patch @@ -0,0 +1,173 @@ +From 89f870a04f903681b0a7a0ac4eb1ae70c4984b46 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Sat, 15 Jun 2024 12:34:01 +1000 +Subject: [PATCH] input device rules + +* customise input device handling +* ignore unwanted input devices +* configure a toggle for an input device +--- + config.def.h | 13 ++++++++++ + dwl.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 79 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..0b287ab5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -60,6 +60,18 @@ static const struct xkb_rule_names xkb_rules = { + .options = NULL, + }; + ++/* input devices */ ++static const InputRule inputrules[] = { ++ /* name kbcreate ptrcreate */ ++ /* ignore bad device - like a touchpad ;) */ ++ { "BAD DEVICE", NULL, NULL }, ++ /* ungroup ydotool device - fixes a bug */ ++ { "ydotoold virtual device", createungroupedkeyboard, createpointer }, ++ /* put your touchpad name here to enable toggle touchpad */ ++ { "Elan Touchpad", createkeyboard, createtogglepointer }, ++ { NULL, createkeyboard, createpointer }, ++}; ++ + static const int repeat_rate = 25; + static const int repeat_delay = 600; + +@@ -142,6 +154,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_u, togglepointer, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index a2711f67..f6f91938 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -143,6 +143,12 @@ typedef struct { + uint32_t resize; /* configure serial of a pending resize */ + } Client; + ++typedef struct { ++ const char *name; ++ void (*kbcreate)(struct wlr_keyboard *); ++ void (*ptrcreate)(struct wlr_pointer *); ++} InputRule; ++ + typedef struct { + uint32_t mod; + xkb_keysym_t keysym; +@@ -270,6 +276,8 @@ static void createnotify(struct wl_listener *listener, void *data); + static void createpointer(struct wlr_pointer *pointer); + static void createpointerconstraint(struct wl_listener *listener, void *data); + static void createpopup(struct wl_listener *listener, void *data); ++static void createtogglepointer(struct wlr_pointer *pointer); ++static void createungroupedkeyboard(struct wlr_keyboard *keyboard); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); +@@ -340,6 +348,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglepointer(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -413,6 +422,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static struct libinput_device *togglepointerdevice = NULL; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -1133,6 +1144,33 @@ createpopup(struct wl_listener *listener, void *data) + LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); + } + ++void ++createtogglepointer(struct wlr_pointer *pointer) ++{ ++ struct libinput_device *device; ++ ++ createpointer(pointer); ++ ++ if (wlr_input_device_is_libinput(&pointer->base) ++ && (device = wlr_libinput_get_device_handle(&pointer->base))) { ++ togglepointerdevice = device; ++ } ++} ++ ++void ++createungroupedkeyboard(struct wlr_keyboard *keyboard) ++{ ++ /* for keyboards that need their own keyboard group */ ++ KeyboardGroup *group = createkeyboardgroup(); ++ ++ /* Set the keymap to match the group keymap */ ++ wlr_keyboard_set_keymap(keyboard, group->wlr_group->keyboard.keymap); ++ LISTEN(&keyboard->base.events.destroy, &group->destroy, destroykeyboardgroup); ++ ++ /* Add the new keyboard to the group */ ++ wlr_keyboard_group_add_keyboard(group->wlr_group, keyboard); ++} ++ + void + cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) + { +@@ -1531,13 +1569,27 @@ inputdevice(struct wl_listener *listener, void *data) + * available. */ + struct wlr_input_device *device = data; + uint32_t caps; ++ const InputRule *r; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: +- createkeyboard(wlr_keyboard_from_input_device(device)); ++ for (r = inputrules; r < END(inputrules); r++) { ++ if (!r->name || strstr(device->name, r->name)) { ++ if (r->kbcreate) ++ r->kbcreate(wlr_keyboard_from_input_device(device)); ++ break; ++ } ++ } ++ + break; + case WLR_INPUT_DEVICE_POINTER: +- createpointer(wlr_pointer_from_input_device(device)); ++ for (r = inputrules; r < END(inputrules); r++) { ++ if (!r->name || strstr(device->name, r->name)) { ++ if (r->ptrcreate) ++ r->ptrcreate(wlr_pointer_from_input_device(device)); ++ break; ++ } ++ } + break; + default: + /* TODO handle other input device types */ +@@ -2739,6 +2791,18 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglepointer(const Arg *arg) ++{ ++ if (!togglepointerdevice) ++ return; ++ ++ libinput_device_config_send_events_set_mode( ++ togglepointerdevice, ++ libinput_device_config_send_events_get_mode(togglepointerdevice) ^ LIBINPUT_CONFIG_SEND_EVENTS_DISABLED ++ ); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/ipc/README.md b/dwl/dwl-patches/patches/ipc/README.md new file mode 100755 index 0000000..bf648a4 --- /dev/null +++ b/dwl/dwl-patches/patches/ipc/README.md @@ -0,0 +1,28 @@ +### Description +Largely based on [raphi](https://sr.ht/~raphi/)'s [somebar](https://sr.ht/~raphi/somebar/), this patch provides an ipc for wayland clients to get and set dwl state. The ipc is intended for status bars, but can also be scripted with tools like [dwlmsg](https://codeberg.org/notchoc/dwlmsg). + +Status information to stdout is currently disabled as dwl tends to freeze. For now, `dwlmsg -w` should act as a drop-in replacement. + +Note to [pertag](../pertag/) users: apply [this](./ipcpertag.patch) for ipc tagsetting to work as expected + +### Download +- [git branch](https://codeberg.org/notchoc/dwl/src/branch/ipc) +- [2024-08-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/ipc/ipc.patch) +- [2024-07-29](https://codeberg.org/dwl/dwl-patches/raw/commit/d235f0f88ed069eca234da5a544fb1c6e19f1d33/patches/ipc/ipc.patch) don't focus other outputs (apply [this minipatch](./focus-tagset-output.patch) if you'd prefer that) +- [2024-07-16](https://codeberg.org/dwl/dwl-patches/raw/commit/642b2559d522034785c1c1203c6d426855ec19ca/patches/ipc/ipc.patch) +- [2024-06-30](https://codeberg.org/dwl/dwl-patches/raw/commit/9a751e5020133d3ab9219e68a43109c6f3c931a7/patches/ipc/ipc.patch) +- [2024-06-21](https://codeberg.org/dwl/dwl-patches/raw/commit/f96ee44cbaef06bd38b8fa29ac7ecba8b1b5abd5/patches/ipc/ipc.patch) +- [2024-06-19](https://codeberg.org/dwl/dwl-patches/raw/commit/e69afc7263b8d982a7923e5d4910f2e1f7140bb8/patches/ipc/ipc.patch) +- [2024-06-08](https://codeberg.org/dwl/dwl-patches/raw/commit/f8598a91b44acc3bd7e9041be97265bbce8fa219/patches/ipc/ipc.patch) +- [2024-03-13](https://codeberg.org/dwl/dwl-patches/raw/commit/0150cfebbcd85f2d6e6728afad345a11a0c45947/ipc/ipc.patch) +- [2024-02-20](https://codeberg.org/dwl/dwl-patches/raw/commit/0c5ae06e4bc1d7f641376e8fcb86b43bd48ce2ee/ipc/ipc.patch) +- [2023-10-28](https://gist.githubusercontent.com/fbushstone/b116c44340eb7a7878de1119dd931ca5/raw/ee66ac9e2a5dddd9b528df553e21080c2811e974/ipc-v2-fixed.patch) Updated version of 2023-04-29, prevents ipc from freezing the compositor in printstatus. +- [2023-04-29](https://github.com/djpohly/dwl/compare/main...madcowog:ipc-v2.patch) Use this for dwl-ipc-unstable-v2. If you are using commit [9d68554](https://github.com/djpohly/dwl/commit/9d68554c59a886b641d27a364884fb461af2d4f1) or later, use this. For status bars this protocol is supported by dwlb, Waybar and dwl-bar. +- [2023-04-29](https://github.com/djpohly/dwl/compare/main...madcowog:ipc-bbdf2.patch) Use this for dwl-ipc-unstable-v1. If you are using commit [bbdaf2a9](https://github.com/djpohly/dwl/commit/bbdf2a913b72e7a308ee0dfde6518a4285d4a775), [release 0.4](https://github.com/djpohly/dwl/releases/tag/v0.4) or earlier, use this. For status bars, this protocol is supported by dwl-bar. +- [2023-02-20](https://lists.sr.ht/~raphi/public-inbox/patches/39166) Use this for net-tapesoftware-dwl-wm-unstable-v1. If you are using commit [c69a2bec](https://github.com/djpohly/dwl/commit/c69a2bec3ff417fbc4ea8fec0a49096773e01e7d) or later, use this. For status bars this protocol is supported by somebar. + +### Authors +- [MadcowOG](https://github.com/MadcowOG) +- [fbushstone](https://github.com/fbushstone) +- [notchoc](https://codeberg.org/notchoc) +- [snuk](https://codeberg.org/snuk) diff --git a/dwl/dwl-patches/patches/ipc/focus-tagset-output.patch b/dwl/dwl-patches/patches/ipc/focus-tagset-output.patch new file mode 100755 index 0000000..2ea3015 --- /dev/null +++ b/dwl/dwl-patches/patches/ipc/focus-tagset-output.patch @@ -0,0 +1,24 @@ +From b65477621f0438b0ed6c405f74c9d15e8fb57e96 Mon Sep 17 00:00:00 2001 +From: choc +Date: Mon, 29 Jul 2024 21:26:06 +0800 +Subject: [PATCH] ipc: focus set_tag'd output + +--- + dwl.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dwl.c b/dwl.c +index 4a025f0..dcbb063 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1533,6 +1533,7 @@ dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, + if (!ipc_output) + return; + monitor = ipc_output->mon; ++ selmon = monitor; + + if (!newtags || newtags == monitor->tagset[monitor->seltags]) + return; +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/ipc/ipc.patch b/dwl/dwl-patches/patches/ipc/ipc.patch new file mode 100755 index 0000000..9f989e7 --- /dev/null +++ b/dwl/dwl-patches/patches/ipc/ipc.patch @@ -0,0 +1,597 @@ +From 6c6d655b68770ce82a24fde9b58c4d97b672553a Mon Sep 17 00:00:00 2001 +From: choc +Date: Mon, 23 Oct 2023 10:35:17 +0800 +Subject: [PATCH] implement dwl-ipc-unstable-v2 + https://codeberg.org/dwl/dwl-patches/wiki/ipc + +--- + Makefile | 14 +- + config.def.h | 1 + + dwl.c | 257 ++++++++++++++++++++++++++---- + protocols/dwl-ipc-unstable-v2.xml | 181 +++++++++++++++++++++ + 4 files changed, 419 insertions(+), 34 deletions(-) + create mode 100644 protocols/dwl-ipc-unstable-v2.xml + +diff --git a/Makefile b/Makefile +index 8db7409..a79a080 100644 +--- a/Makefile ++++ b/Makefile +@@ -17,12 +17,14 @@ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEV + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) + + all: dwl +-dwl: dwl.o util.o +- $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ ++dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o ++ $(CC) dwl.o util.o dwl-ipc-unstable-v2-protocol.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ + dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ +- wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ ++ dwl-ipc-unstable-v2-protocol.h + util.o: util.c util.h ++dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.c dwl-ipc-unstable-v2-protocol.h + + # wayland-scanner is a tool which generates C headers and rigging for Wayland + # protocols, which are specified in XML. wlroots requires you to rig these up +@@ -45,6 +47,12 @@ wlr-output-power-management-unstable-v1-protocol.h: + xdg-shell-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ ++dwl-ipc-unstable-v2-protocol.h: ++ $(WAYLAND_SCANNER) server-header \ ++ protocols/dwl-ipc-unstable-v2.xml $@ ++dwl-ipc-unstable-v2-protocol.c: ++ $(WAYLAND_SCANNER) private-code \ ++ protocols/dwl-ipc-unstable-v2.xml $@ + + config.h: + cp config.def.h $@ +diff --git a/config.def.h b/config.def.h +index 22d2171..1593033 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -127,6 +127,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY, XKB_KEY_b, togglebar, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index 8a587d1..7a4949b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -68,6 +68,7 @@ + #include + #endif + ++#include "dwl-ipc-unstable-v2-protocol.h" + #include "util.h" + + /* macros */ +@@ -144,6 +145,12 @@ typedef struct { + uint32_t resize; /* configure serial of a pending resize */ + } Client; + ++typedef struct { ++ struct wl_list link; ++ struct wl_resource *resource; ++ Monitor *mon; ++} DwlIpcOutput; ++ + typedef struct { + uint32_t mod; + xkb_keysym_t keysym; +@@ -189,6 +196,7 @@ typedef struct { + + struct Monitor { + struct wl_list link; ++ struct wl_list dwl_ipc_outputs; + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ +@@ -286,6 +294,17 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id); ++static void dwl_ipc_manager_destroy(struct wl_resource *resource); ++static void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output); ++static void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource); ++static void dwl_ipc_output_destroy(struct wl_resource *resource); ++static void dwl_ipc_output_printstatus(Monitor *monitor); ++static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output); ++static void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags); ++static void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index); ++static void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset); ++static void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -338,6 +357,7 @@ static void startdrag(struct wl_listener *listener, void *data); + 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 togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -411,6 +431,9 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output}; ++static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags}; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -703,6 +726,10 @@ cleanupmon(struct wl_listener *listener, void *data) + LayerSurface *l, *tmp; + size_t i; + ++ DwlIpcOutput *ipc_output, *ipc_output_tmp; ++ wl_list_for_each_safe(ipc_output, ipc_output_tmp, &m->dwl_ipc_outputs, link) ++ wl_resource_destroy(ipc_output->resource); ++ + /* m->layers[i] are intentionally not unlinked */ + for (i = 0; i < LENGTH(m->layers); i++) { + wl_list_for_each_safe(l, tmp, &m->layers[i], link) +@@ -983,6 +1010,8 @@ createmon(struct wl_listener *listener, void *data) + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; + ++ wl_list_init(&m->dwl_ipc_outputs); ++ + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); + +@@ -1334,6 +1363,192 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++void ++dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) ++{ ++ struct wl_resource *manager_resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id); ++ if (!manager_resource) { ++ wl_client_post_no_memory(client); ++ return; ++ } ++ wl_resource_set_implementation(manager_resource, &dwl_manager_implementation, NULL, dwl_ipc_manager_destroy); ++ ++ zdwl_ipc_manager_v2_send_tags(manager_resource, TAGCOUNT); ++ ++ for (unsigned int i = 0; i < LENGTH(layouts); i++) ++ zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol); ++} ++ ++void ++dwl_ipc_manager_destroy(struct wl_resource *resource) ++{ ++ /* No state to destroy */ ++} ++ ++void ++dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output) ++{ ++ DwlIpcOutput *ipc_output; ++ Monitor *monitor = wlr_output_from_resource(output)->data; ++ struct wl_resource *output_resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, wl_resource_get_version(resource), id); ++ if (!output_resource) ++ return; ++ ++ ipc_output = ecalloc(1, sizeof(*ipc_output)); ++ ipc_output->resource = output_resource; ++ ipc_output->mon = monitor; ++ wl_resource_set_implementation(output_resource, &dwl_output_implementation, ipc_output, dwl_ipc_output_destroy); ++ wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link); ++ dwl_ipc_output_printstatus_to(ipc_output); ++} ++ ++void ++dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource) ++{ ++ wl_resource_destroy(resource); ++} ++ ++static void ++dwl_ipc_output_destroy(struct wl_resource *resource) ++{ ++ DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource); ++ wl_list_remove(&ipc_output->link); ++ free(ipc_output); ++} ++ ++void ++dwl_ipc_output_printstatus(Monitor *monitor) ++{ ++ DwlIpcOutput *ipc_output; ++ wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link) ++ dwl_ipc_output_printstatus_to(ipc_output); ++} ++ ++void ++dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) ++{ ++ Monitor *monitor = ipc_output->mon; ++ Client *c, *focused; ++ int tagmask, state, numclients, focused_client, tag; ++ const char *title, *appid; ++ focused = focustop(monitor); ++ zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon); ++ ++ for (tag = 0 ; tag < TAGCOUNT; tag++) { ++ numclients = state = focused_client = 0; ++ tagmask = 1 << tag; ++ if ((tagmask & monitor->tagset[monitor->seltags]) != 0) ++ state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != monitor) ++ continue; ++ if (!(c->tags & tagmask)) ++ continue; ++ if (c == focused) ++ focused_client = 1; ++ if (c->isurgent) ++ state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT; ++ ++ numclients++; ++ } ++ zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state, numclients, focused_client); ++ } ++ title = focused ? client_get_title(focused) : ""; ++ appid = focused ? client_get_appid(focused) : ""; ++ ++ zdwl_ipc_output_v2_send_layout(ipc_output->resource, monitor->lt[monitor->sellt] - layouts); ++ zdwl_ipc_output_v2_send_title(ipc_output->resource, title); ++ zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid); ++ zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->ltsymbol); ++ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) { ++ zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource, focused ? focused->isfullscreen : 0); ++ } ++ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) { ++ zdwl_ipc_output_v2_send_floating(ipc_output->resource, focused ? focused->isfloating : 0); ++ } ++ zdwl_ipc_output_v2_send_frame(ipc_output->resource); ++} ++ ++void ++dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags) ++{ ++ DwlIpcOutput *ipc_output; ++ Monitor *monitor; ++ Client *selected_client; ++ unsigned int newtags = 0; ++ ++ ipc_output = wl_resource_get_user_data(resource); ++ if (!ipc_output) ++ return; ++ ++ monitor = ipc_output->mon; ++ selected_client = focustop(monitor); ++ if (!selected_client) ++ return; ++ ++ newtags = (selected_client->tags & and_tags) ^ xor_tags; ++ if (!newtags) ++ return; ++ ++ selected_client->tags = newtags; ++ if (selmon == monitor) ++ focusclient(focustop(monitor), 1); ++ arrange(selmon); ++ printstatus(); ++} ++ ++void ++dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index) ++{ ++ DwlIpcOutput *ipc_output; ++ Monitor *monitor; ++ ++ ipc_output = wl_resource_get_user_data(resource); ++ if (!ipc_output) ++ return; ++ ++ monitor = ipc_output->mon; ++ if (index >= LENGTH(layouts)) ++ return; ++ if (index != monitor->lt[monitor->sellt] - layouts) ++ monitor->sellt ^= 1; ++ ++ monitor->lt[monitor->sellt] = &layouts[index]; ++ arrange(monitor); ++ printstatus(); ++} ++ ++void ++dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset) ++{ ++ DwlIpcOutput *ipc_output; ++ Monitor *monitor; ++ unsigned int newtags = tagmask & TAGMASK; ++ ++ ipc_output = wl_resource_get_user_data(resource); ++ if (!ipc_output) ++ return; ++ monitor = ipc_output->mon; ++ ++ if (!newtags || newtags == monitor->tagset[monitor->seltags]) ++ return; ++ if (toggle_tagset) ++ monitor->seltags ^= 1; ++ ++ monitor->tagset[monitor->seltags] = newtags; ++ if (selmon == monitor) ++ focusclient(focustop(monitor), 1); ++ arrange(monitor); ++ printstatus(); ++} ++ ++void ++dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource) ++{ ++ wl_resource_destroy(resource); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -2033,38 +2248,9 @@ void + printstatus(void) + { + Monitor *m = NULL; +- Client *c; +- uint32_t occ, urg, sel; + +- wl_list_for_each(m, &mons, link) { +- occ = urg = 0; +- wl_list_for_each(c, &clients, link) { +- if (c->mon != m) +- continue; +- occ |= c->tags; +- if (c->isurgent) +- urg |= c->tags; +- } +- if ((c = focustop(m))) { +- printf("%s title %s\n", m->wlr_output->name, client_get_title(c)); +- printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c)); +- printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); +- printf("%s floating %d\n", m->wlr_output->name, c->isfloating); +- sel = c->tags; +- } else { +- printf("%s title \n", m->wlr_output->name); +- printf("%s appid \n", m->wlr_output->name); +- printf("%s fullscreen \n", m->wlr_output->name); +- printf("%s floating \n", m->wlr_output->name); +- sel = 0; +- } +- +- printf("%s selmon %u\n", m->wlr_output->name, m == selmon); +- printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", +- m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); +- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); +- } +- fflush(stdout); ++ wl_list_for_each(m, &mons, link) ++ dwl_ipc_output_printstatus(m); + } + + void +@@ -2584,6 +2770,8 @@ setup(void) + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); + LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); + ++ wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, dwl_ipc_manager_bind); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2681,6 +2869,13 @@ tile(Monitor *m) + } + } + ++void ++togglebar(const Arg *arg) { ++ DwlIpcOutput *ipc_output; ++ wl_list_for_each(ipc_output, &selmon->dwl_ipc_outputs, link) ++ zdwl_ipc_output_v2_send_toggle_visibility(ipc_output->resource); ++} ++ + void + togglefloating(const Arg *arg) + { +diff --git a/protocols/dwl-ipc-unstable-v2.xml b/protocols/dwl-ipc-unstable-v2.xml +new file mode 100644 +index 0000000..0a6e7e5 +--- /dev/null ++++ b/protocols/dwl-ipc-unstable-v2.xml +@@ -0,0 +1,181 @@ ++ ++ ++ ++ ++ This protocol allows clients to update and get updates from dwl. ++ ++ Warning! The protocol described in this file is experimental and ++ backward incompatible changes may be made. Backward compatible ++ changes may be added together with the corresponding interface ++ version bump. ++ Backward incompatible changes are done by bumping the version ++ number in the protocol and interface names and resetting the ++ interface version. Once the protocol is to be declared stable, ++ the 'z' prefix and the version number in the protocol and ++ interface names are removed and the interface version number is ++ reset. ++ ++ ++ ++ ++ This interface is exposed as a global in wl_registry. ++ ++ Clients can use this interface to get a dwl_ipc_output. ++ After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events. ++ The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client. ++ ++ ++ ++ ++ Indicates that the client will not the dwl_ipc_manager object anymore. ++ Objects created through this instance are not affected. ++ ++ ++ ++ ++ ++ Get a dwl_ipc_outout for the specified wl_output. ++ ++ ++ ++ ++ ++ ++ ++ This event is sent after binding. ++ A roundtrip after binding guarantees the client recieved all tags. ++ ++ ++ ++ ++ ++ ++ This event is sent after binding. ++ A roundtrip after binding guarantees the client recieved all layouts. ++ ++ ++ ++ ++ ++ ++ ++ Observe and control a dwl output. ++ ++ Events are double-buffered: ++ Clients should cache events and redraw when a dwl_ipc_output.frame event is sent. ++ ++ Request are not double-buffered: ++ The compositor will update immediately upon request. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Indicates to that the client no longer needs this dwl_ipc_output. ++ ++ ++ ++ ++ ++ Indicates the client should hide or show themselves. ++ If the client is visible then hide, if hidden then show. ++ ++ ++ ++ ++ ++ Indicates if the output is active. Zero is invalid, nonzero is valid. ++ ++ ++ ++ ++ ++ ++ Indicates that a tag has been updated. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Indicates a new layout is selected. ++ ++ ++ ++ ++ ++ ++ Indicates the title has changed. ++ ++ ++ ++ ++ ++ ++ Indicates the appid has changed. ++ ++ ++ ++ ++ ++ ++ Indicates the layout has changed. Since layout symbols are dynamic. ++ As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying. ++ You can ignore the zdwl_ipc_output.layout event. ++ ++ ++ ++ ++ ++ ++ Indicates that a sequence of status updates have finished and the client should redraw. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The tags are updated as follows: ++ new_tags = (current_tags AND and_tags) XOR xor_tags ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Indicates if the selected client on this output is fullscreen. ++ ++ ++ ++ ++ ++ ++ Indicates if the selected client on this output is floating. ++ ++ ++ ++ ++ +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/ipc/ipcpertag.patch b/dwl/dwl-patches/patches/ipc/ipcpertag.patch new file mode 100755 index 0000000..97e3c33 --- /dev/null +++ b/dwl/dwl-patches/patches/ipc/ipcpertag.patch @@ -0,0 +1,97 @@ +From c7d77ff4dec1da5a68b4da8aa42d4ed78dc41a00 Mon Sep 17 00:00:00 2001 +From: choc +Date: Thu, 14 Mar 2024 11:18:37 +0800 +Subject: [PATCH] fix ipc to work with pertag + +--- + dwl.c | 50 +++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 35 insertions(+), 15 deletions(-) + +diff --git a/dwl.c b/dwl.c +index a1a7809..d86e6e2 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1526,28 +1526,37 @@ void + dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index) + { + DwlIpcOutput *ipc_output; +- Monitor *monitor; ++ Client *c = NULL; ++ Monitor *monitor = NULL; + + ipc_output = wl_resource_get_user_data(resource); + if (!ipc_output) + return; +- + monitor = ipc_output->mon; ++ ++ if (monitor != selmon) ++ c = focustop(selmon); ++ + if (index >= LENGTH(layouts)) + return; +- if (index != monitor->lt[monitor->sellt] - layouts) +- monitor->sellt ^= 1; + +- monitor->lt[monitor->sellt] = &layouts[index]; +- arrange(monitor); +- printstatus(); ++ if (c) { ++ monitor = selmon; ++ selmon = ipc_output->mon; ++ } ++ setlayout(&(Arg){.v = &layouts[index]}); ++ if (c) { ++ selmon = monitor; ++ focusclient(c, 0); ++ } + } + + void + dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset) + { + DwlIpcOutput *ipc_output; +- Monitor *monitor; ++ Client *c = NULL; ++ Monitor *monitor = NULL; + unsigned int newtags = tagmask & TAGMASK; + + ipc_output = wl_resource_get_user_data(resource); +@@ -1555,16 +1564,27 @@ dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, + return; + monitor = ipc_output->mon; + +- if (!newtags || newtags == monitor->tagset[monitor->seltags]) ++ if (monitor != selmon) ++ c = focustop(selmon); ++ ++ if (!newtags) + return; +- if (toggle_tagset) ++ ++ /* view toggles seltags for us so we un-toggle it */ ++ if (!toggle_tagset) { + monitor->seltags ^= 1; ++ monitor->tagset[monitor->seltags] = 0; ++ } + +- monitor->tagset[monitor->seltags] = newtags; +- if (selmon == monitor) +- focusclient(focustop(monitor), 1); +- arrange(monitor); +- printstatus(); ++ if (c) { ++ monitor = selmon; ++ selmon = ipc_output->mon; ++ } ++ view(&(Arg){.ui = newtags}); ++ if (c) { ++ selmon = monitor; ++ focusclient(c, 0); ++ } + } + + void +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/kblayout/README.md b/dwl/dwl-patches/patches/kblayout/README.md new file mode 100755 index 0000000..259694c --- /dev/null +++ b/dwl/dwl-patches/patches/kblayout/README.md @@ -0,0 +1,32 @@ +### Description + +This patch adds per-client keyboard layout and ability to send current +keyboard layout information to a status bar. + +Only per-client feature is enabled by default. You can edit +`kblayout_file` and `kblayout_cmd` variables to notify a status bar +about keyboard layout. + +[Someblocks](https://sr.ht/~raphi/someblocks) config that works +with the example settings in `config.h`: + +```c +static const Block blocks[] = { + /*Icon*/ /*Command*/ /*Update Interval*/ /*Update Signal*/ + {"", "cat /tmp/dwl-kblayout", 0, 3}, +}; +``` + +Both of these features are included in one patch because their +implementation happens to share some code. If you don't need +any of these features, just disable it in `config.h`. + +### Download + +- [git branch](https://codeberg.org/nikitaivanov/dwl/src/branch/kblayout) +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/kblayout/kblayout.patch) + +### Authors + +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) +- [ForzCross](https://codeberg.org/ForzCross) diff --git a/dwl/dwl-patches/patches/kblayout/kblayout.patch b/dwl/dwl-patches/patches/kblayout/kblayout.patch new file mode 100755 index 0000000..707a4fc --- /dev/null +++ b/dwl/dwl-patches/patches/kblayout/kblayout.patch @@ -0,0 +1,187 @@ +From ad18a8b8e9de138c3d89246ac0e25c0467ff5971 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Fri, 11 Oct 2024 10:50:14 +0200 +Subject: [PATCH] Add per client keyboard layout and status bar info + +--- + config.def.h | 3 +++ + dwl.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 72 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..862c104 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,6 +13,9 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++/* keyboard layout change notification for status bar */ ++static const char kblayout_file[] = "/tmp/dwl-keymap"; ++static const char *kblayout_cmd[] = {"pkill", "-RTMIN+3", "someblocks", NULL}; + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +diff --git a/dwl.c b/dwl.c +index a2711f6..95ca3d3 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -141,6 +142,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ unsigned int kblayout_idx; + } Client; + + typedef struct { +@@ -294,6 +296,7 @@ static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); ++static void kblayout(KeyboardGroup *kb); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); + static void keypressmod(struct wl_listener *listener, void *data); +@@ -413,6 +416,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static unsigned int kblayout_idx = -1; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -879,6 +884,8 @@ createkeyboard(struct wlr_keyboard *keyboard) + + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard); ++ ++ kblayout(kb_group); + } + + KeyboardGroup * +@@ -1056,11 +1063,13 @@ createnotify(struct wl_listener *listener, void *data) + /* This event is raised when a client creates a new toplevel (application window). */ + struct wlr_xdg_toplevel *toplevel = data; + Client *c = NULL; ++ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat); + + /* Allocate a Client for this surface */ + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; ++ c->kblayout_idx = kb ? kb->modifiers.group : 0; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); +@@ -1339,10 +1348,24 @@ dirtomon(enum wlr_direction dir) + void + focusclient(Client *c, int lift) + { ++ /* Copied from wlroots/types/wlr_keyboard_group.c */ ++ struct keyboard_group_device { ++ struct wlr_keyboard *keyboard; ++ struct wl_listener key; ++ struct wl_listener modifiers; ++ struct wl_listener keymap; ++ struct wl_listener repeat_info; ++ struct wl_listener destroy; ++ struct wl_list link; // wlr_keyboard_group.devices ++ }; ++ + struct wlr_surface *old = seat->keyboard_state.focused_surface; + int unused_lx, unused_ly, old_client_type; + Client *old_c = NULL; + LayerSurface *old_l = NULL; ++ struct keyboard_group_device *device; ++ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat); ++ struct wlr_keyboard_group *group = kb ? wlr_keyboard_group_from_wlr_keyboard(kb) : NULL; + + if (locked) + return; +@@ -1395,6 +1418,19 @@ focusclient(Client *c, int lift) + } + printstatus(); + ++ /* Update keyboard layout */ ++ if (group) { ++ // Update the first real device, because kb or group->kb is not a real ++ // keyboard and its effective layout gets overwritten ++ device = wl_container_of(group->devices.next, device, link); ++ wlr_keyboard_notify_modifiers(device->keyboard, ++ device->keyboard->modifiers.depressed, ++ device->keyboard->modifiers.latched, ++ device->keyboard->modifiers.locked, ++ c ? c->kblayout_idx : 0 ++ ); ++ } ++ + if (!c) { + /* With no client, all we have left is to clear focus */ + wlr_seat_keyboard_notify_clear_focus(seat); +@@ -1405,7 +1441,7 @@ focusclient(Client *c, int lift) + motionnotify(0, NULL, 0, 0, 0, 0); + + /* Have a client, so focus its top-level wlr_surface */ +- client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat)); ++ client_notify_enter(client_surface(c), kb); + + /* Activate the new client */ + client_activate_surface(client_surface(c), 1); +@@ -1554,6 +1590,36 @@ inputdevice(struct wl_listener *listener, void *data) + wlr_seat_set_capabilities(seat, caps); + } + ++void ++kblayout(KeyboardGroup *kb) ++{ ++ FILE *f; ++ Client *c; ++ unsigned int idx = kb->wlr_group->keyboard.modifiers.group; ++ ++ // If layout did not change, do nothing ++ if (kblayout_idx == idx) ++ return; ++ kblayout_idx = idx; ++ ++ // Update client layout ++ if ((c = focustop(selmon))) ++ c->kblayout_idx = kblayout_idx; ++ ++ // Save current layout to kblayout_file ++ if (*kblayout_file && (f = fopen(kblayout_file, "w"))) { ++ fputs(xkb_keymap_layout_get_name(kb->wlr_group->keyboard.keymap, ++ idx), f); ++ fclose(f); ++ } ++ ++ // Run kblayout_cmd ++ if (kblayout_cmd[0] && fork() == 0) { ++ execvp(kblayout_cmd[0], (char *const *)kblayout_cmd); ++ die("dwl: execvp %s failed:", kblayout_cmd[0]); ++ } ++} ++ + int + keybinding(uint32_t mods, xkb_keysym_t sym) + { +@@ -1631,6 +1697,8 @@ keypressmod(struct wl_listener *listener, void *data) + /* Send modifiers to the client. */ + wlr_seat_keyboard_notify_modifiers(seat, + &group->wlr_group->keyboard.modifiers); ++ ++ kblayout(group); + } + + int +-- +2.46.2 + diff --git a/dwl/dwl-patches/patches/keyboardshortcutsinhibit/README.md b/dwl/dwl-patches/patches/keyboardshortcutsinhibit/README.md new file mode 100755 index 0000000..c52de56 --- /dev/null +++ b/dwl/dwl-patches/patches/keyboardshortcutsinhibit/README.md @@ -0,0 +1,11 @@ +### Description +Allows clients to use the keyboard-shortcuts-inhibit protocol to block the compositor from using keybinds. This is useful for virtualization software like looking-glass which requires this protocol to run. + +### Download +- [git branch](https://codeberg.org/Rutherther/dwl/src/branch/patch/keyboard-shortcuts-inhibit) +- [2024-05-10](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/keyboardshortcutsinhibit/keyboardshortcutsinhibit.patch) +- [2023-05-01](https://github.com/djpohly/dwl/compare/main...madcowog:keyboard-shortcuts-inhibit.patch) + +### Authors +- [Rutherther](https://codeberg.org/Rutherther) +- [MadcowOG](https://github.com/MadcowOG) diff --git a/dwl/dwl-patches/patches/keyboardshortcutsinhibit/keyboardshortcutsinhibit.patch b/dwl/dwl-patches/patches/keyboardshortcutsinhibit/keyboardshortcutsinhibit.patch new file mode 100755 index 0000000..bea327e --- /dev/null +++ b/dwl/dwl-patches/patches/keyboardshortcutsinhibit/keyboardshortcutsinhibit.patch @@ -0,0 +1,101 @@ +From ac1fa09172a401427cabbda045688903bdd3cbe7 Mon Sep 17 00:00:00 2001 +From: Rutherther +Date: Wed, 12 Jun 2024 20:05:40 +0200 +Subject: [PATCH] feat: apply keyboard shortcuts inhibit patch + +--- + dwl.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index 6f041a0..8cab9e0 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -267,6 +268,7 @@ static void createnotify(struct wl_listener *listener, void *data); + static void createpointer(struct wlr_pointer *pointer); + static void createpointerconstraint(struct wl_listener *listener, void *data); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); ++static void createshortcutsinhibitor(struct wl_listener *listener, void *data); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); + static void destroydecoration(struct wl_listener *listener, void *data); +@@ -280,6 +282,7 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data); + static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); ++static void destroyshortcutsinhibitmgr(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); +@@ -375,6 +378,7 @@ static struct wl_list clients; /* tiling order */ + static struct wl_list fstack; /* focus order */ + static struct wlr_idle_notifier_v1 *idle_notifier; + static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; ++static struct wlr_keyboard_shortcuts_inhibit_manager_v1 *shortcuts_inhibit_mgr; + static struct wlr_layer_shell_v1 *layer_shell; + static struct wlr_output_manager_v1 *output_mgr; + static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; +@@ -394,6 +398,7 @@ static struct wlr_session_lock_manager_v1 *session_lock_mgr; + static struct wlr_scene_rect *locked_bg; + static struct wlr_session_lock_v1 *cur_lock; + static struct wl_listener lock_listener = {.notify = locksession}; ++static struct wl_listener new_shortcuts_inhibitor = {.notify = createshortcutsinhibitor}; + + static struct wlr_seat *seat; + static KeyboardGroup *kb_group; +@@ -1083,6 +1088,10 @@ createpointer(struct wlr_pointer *pointer) + wlr_cursor_attach_input_device(cursor, &pointer->base); + } + ++void createshortcutsinhibitor(struct wl_listener *listener, void *data) { ++ wlr_keyboard_shortcuts_inhibitor_v1_activate(data); ++} ++ + void + createpointerconstraint(struct wl_listener *listener, void *data) + { +@@ -1280,6 +1289,11 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) + free(group); + } + ++void destroyshortcutsinhibitmgr(struct wl_listener *listener, void *data) { ++ wl_list_remove(&new_shortcuts_inhibitor.link); ++ wl_list_remove(&listener->link); ++} ++ + Monitor * + dirtomon(enum wlr_direction dir) + { +@@ -1531,7 +1545,9 @@ keypress(struct wl_listener *listener, void *data) + + /* On _press_ if there is no active screen locker, + * attempt to process a compositor keybinding. */ +- if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { ++ if (!locked ++ && event->state == WL_KEYBOARD_KEY_STATE_PRESSED ++ && wl_list_empty(&shortcuts_inhibit_mgr->inhibitors)) { + for (i = 0; i < nsyms; i++) + handled = keybinding(mods, syms[i]) || handled; + } +@@ -2450,6 +2466,10 @@ setup(void) + (float [4]){0.1f, 0.1f, 0.1f, 1.0f}); + wlr_scene_node_set_enabled(&locked_bg->node, 0); + ++ shortcuts_inhibit_mgr = wlr_keyboard_shortcuts_inhibit_v1_create(dpy); ++ wl_signal_add(&shortcuts_inhibit_mgr->events.new_inhibitor, &new_shortcuts_inhibitor); ++ LISTEN_STATIC(&shortcuts_inhibit_mgr->events.destroy, destroyshortcutsinhibitmgr); ++ + /* Use decoration protocols to negotiate server-side decorations */ + wlr_server_decoration_manager_set_default_mode( + wlr_server_decoration_manager_create(dpy), +-- +2.44.1 + diff --git a/dwl/dwl-patches/patches/keycodes/README.md b/dwl/dwl-patches/patches/keycodes/README.md new file mode 100755 index 0000000..b56adc3 --- /dev/null +++ b/dwl/dwl-patches/patches/keycodes/README.md @@ -0,0 +1,20 @@ +### Description +Use keycodes instead of keysyms. This way, input is independent from keyboard +layout (you can use the keys.h file to customize, or get the keycodes with +`wev` or `xkbcli interactive-wayland` (x11-libs/libxkbcommon[tools] in gentoo)). + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/keycodes) +- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/keycodes/keycodes.patch) +- [keycodes-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/keycodes/keycodes-0.7.patch) + +### Config after patching +(run in DWL source directory) +``` +export XKB_DEFAULT_VARIANT=yourbestkeyboardlayout +cc -lxkbcommon -o generate-keys generate-keys.c +./generate-keys +``` + +### Authors +- [sevz](https://codeberg.org/sevz) diff --git a/dwl/dwl-patches/patches/keycodes/keycodes-0.7.patch b/dwl/dwl-patches/patches/keycodes/keycodes-0.7.patch new file mode 100755 index 0000000..7852307 --- /dev/null +++ b/dwl/dwl-patches/patches/keycodes/keycodes-0.7.patch @@ -0,0 +1,883 @@ +From 4985178cfed599c9a32d154f42e02cb66db7a82d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Fri, 4 Jun 2021 16:51:01 -0500 +Subject: [PATCH 1/2] allow use keycodes instead keysyms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 85 ++++----- + dwl.c | 35 ++-- + keys.h | 514 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 569 insertions(+), 65 deletions(-) + create mode 100644 keys.h + +diff --git a/config.def.h b/config.def.h +index 22d2171d..87a6e60f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -109,11 +109,11 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ + #define MODKEY WLR_MODIFIER_ALT + +-#define TAGKEYS(KEY,SKEY,TAG) \ ++#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } ++ { MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \ ++ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,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 } } +@@ -122,51 +122,52 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + static const char *termcmd[] = { "foot", NULL }; + static const char *menucmd[] = { "wmenu-run", NULL }; + ++#include "keys.h" + static const Key keys[] = { +- /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ +- /* modifier key function argument */ +- { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, +- { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, +- { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, +- { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +- { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, +- { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +- { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, +- { MODKEY, XKB_KEY_Return, zoom, {0} }, +- { MODKEY, XKB_KEY_Tab, view, {0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +- { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, +- { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, +- { MODKEY, XKB_KEY_space, setlayout, {0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +- { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, +- { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +- { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, +- TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), +- TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), +- TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +- TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), +- TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), +- TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), +- TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), +- TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), +- TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, ++ /* modifier key function argument */ ++ { MODKEY, Key_p, spawn, {.v = menucmd} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_Return, spawn, {.v = termcmd} }, ++ { MODKEY, Key_j, focusstack, {.i = +1} }, ++ { MODKEY, Key_k, focusstack, {.i = -1} }, ++ { MODKEY, Key_i, incnmaster, {.i = +1} }, ++ { MODKEY, Key_d, incnmaster, {.i = -1} }, ++ { MODKEY, Key_h, setmfact, {.f = -0.05f} }, ++ { MODKEY, Key_l, setmfact, {.f = +0.05f} }, ++ { MODKEY, Key_Return, zoom, {0} }, ++ { MODKEY, Key_Tab, view, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_c, killclient, {0} }, ++ { MODKEY, Key_t, setlayout, {.v = &layouts[0]} }, ++ { MODKEY, Key_f, setlayout, {.v = &layouts[1]} }, ++ { MODKEY, Key_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, Key_space, setlayout, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_space, togglefloating, {0} }, ++ { MODKEY, Key_e, togglefullscreen, {0} }, ++ { MODKEY, Key_0, view, {.ui = ~0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_0, tag, {.ui = ~0} }, ++ { MODKEY, Key_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, ++ { MODKEY, Key_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_comma, tagmon, {.i = WLR_DIRECTION_LEFT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_period, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ TAGKEYS( Key_1, 0), ++ TAGKEYS( Key_2, 1), ++ TAGKEYS( Key_3, 2), ++ TAGKEYS( Key_4, 3), ++ TAGKEYS( Key_5, 4), ++ TAGKEYS( Key_6, 5), ++ TAGKEYS( Key_7, 6), ++ TAGKEYS( Key_8, 7), ++ TAGKEYS( Key_9, 8), ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_q, quit, {0} }, + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ +- { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, ++ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,Key_BackSpace, quit, {0} }, ++#define CHVT(KEY,n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT, KEY, chvt, {.ui = (n)} } + /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is + * do not remove them. + */ +-#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } +- CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), +- CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), ++ CHVT(Key_F1, 1), CHVT(Key_F2, 2), CHVT(Key_F3, 3), CHVT(Key_F4, 4), ++ CHVT(Key_F5, 5), CHVT(Key_F6, 6), CHVT(Key_F7, 7), CHVT(Key_F8, 8), ++ CHVT(Key_F9, 9), CHVT(Key_F10, 10), CHVT(Key_F11, 11), CHVT(Key_F12, 12), + }; + + static const Button buttons[] = { +diff --git a/dwl.c b/dwl.c +index a2711f67..68860d4e 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -145,7 +145,7 @@ typedef struct { + + typedef struct { + uint32_t mod; +- xkb_keysym_t keysym; ++ xkb_keycode_t keycode; + void (*func)(const Arg *); + const Arg arg; + } Key; +@@ -154,9 +154,8 @@ typedef struct { + struct wl_list link; + struct wlr_keyboard_group *wlr_group; + +- int nsyms; +- const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */ +- uint32_t mods; /* invalid if nsyms == 0 */ ++ xkb_keycode_t keycode; ++ uint32_t mods; /* invalid if keycode == 0 */ + struct wl_event_source *key_repeat_source; + + struct wl_listener modifiers; +@@ -294,7 +293,7 @@ static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +-static int keybinding(uint32_t mods, xkb_keysym_t sym); ++static int keybinding(uint32_t mods, xkb_keycode_t keycode); + static void keypress(struct wl_listener *listener, void *data); + static void keypressmod(struct wl_listener *listener, void *data); + static int keyrepeat(void *data); +@@ -1555,7 +1554,7 @@ inputdevice(struct wl_listener *listener, void *data) + } + + int +-keybinding(uint32_t mods, xkb_keysym_t sym) ++keybinding(uint32_t mods, xkb_keycode_t keycode) + { + /* + * Here we handle compositor keybindings. This is when the compositor is +@@ -1565,7 +1564,7 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + const Key *k; + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) +- && sym == k->keysym && k->func) { ++ && keycode == k->keycode && k->func) { + k->func(&k->arg); + return 1; + } +@@ -1576,17 +1575,12 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + void + keypress(struct wl_listener *listener, void *data) + { +- int i; + /* This event is raised when a key is pressed or released. */ + KeyboardGroup *group = wl_container_of(listener, group, key); + struct wlr_keyboard_key_event *event = data; + + /* Translate libinput keycode -> xkbcommon */ + uint32_t keycode = event->keycode + 8; +- /* Get a list of keysyms based on the keymap for this keyboard */ +- const xkb_keysym_t *syms; +- int nsyms = xkb_state_key_get_syms( +- group->wlr_group->keyboard.xkb_state, keycode, &syms); + + int handled = 0; + uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); +@@ -1595,19 +1589,16 @@ keypress(struct wl_listener *listener, void *data) + + /* On _press_ if there is no active screen locker, + * attempt to process a compositor keybinding. */ +- if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { +- for (i = 0; i < nsyms; i++) +- handled = keybinding(mods, syms[i]) || handled; +- } ++ if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) ++ handled = keybinding(mods, keycode); + + if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { + group->mods = mods; +- group->keysyms = syms; +- group->nsyms = nsyms; ++ group->keycode = keycode; + wl_event_source_timer_update(group->key_repeat_source, + group->wlr_group->keyboard.repeat_info.delay); + } else { +- group->nsyms = 0; ++ group->keycode = 0; + wl_event_source_timer_update(group->key_repeat_source, 0); + } + +@@ -1637,15 +1628,13 @@ int + keyrepeat(void *data) + { + KeyboardGroup *group = data; +- int i; +- if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0) ++ if (!group->keycode || group->wlr_group->keyboard.repeat_info.rate <= 0) + return 0; + + wl_event_source_timer_update(group->key_repeat_source, + 1000 / group->wlr_group->keyboard.repeat_info.rate); + +- for (i = 0; i < group->nsyms; i++) +- keybinding(group->mods, group->keysyms[i]); ++ keybinding(group->mods, group->keycode); + + return 0; + } +diff --git a/keys.h b/keys.h +new file mode 100644 +index 00000000..047b76b0 +--- /dev/null ++++ b/keys.h +@@ -0,0 +1,514 @@ ++/* You can use the macros within this file ++ * instead of search the keycodes yourself ++ * with wev or something like that ++ * You probably are also searching these: ++ * Key_XF86AudioMute ++ * Key_XF86AudioLowerVolume ++ * Key_XF86AudioRaiseVolume ++ * Key_XF86MonBrightnessDown ++ * Key_XF86MonBrightnessUp ++*/ ++ ++#define Key_Escape 0x009 ++#define Key_1 0x00a ++#define Key_exclam 0x00a ++#define Key_2 0x00b ++#define Key_at 0x00b ++#define Key_3 0x00c ++#define Key_numbersign 0x00c ++#define Key_4 0x00d ++#define Key_dollar 0x00d ++#define Key_5 0x00e ++#define Key_percent 0x00e ++#define Key_6 0x00f ++#define Key_asciicircum 0x00f ++#define Key_7 0x010 ++#define Key_ampersand 0x010 ++#define Key_8 0x011 ++#define Key_asterisk 0x011 ++#define Key_9 0x012 ++#define Key_parenleft 0x012 ++#define Key_0 0x013 ++#define Key_parenright 0x013 ++#define Key_minus 0x014 ++#define Key_underscore 0x014 ++#define Key_equal 0x015 ++#define Key_plus 0x015 ++#define Key_BackSpace 0x016 ++#define Key_Tab 0x017 ++#define Key_ISO_Left_Tab 0x017 ++#define Key_q 0x018 ++#define Key_Q 0x018 ++#define Key_w 0x019 ++#define Key_W 0x019 ++#define Key_e 0x01a ++#define Key_E 0x01a ++#define Key_r 0x01b ++#define Key_R 0x01b ++#define Key_t 0x01c ++#define Key_T 0x01c ++#define Key_y 0x01d ++#define Key_Y 0x01d ++#define Key_u 0x01e ++#define Key_U 0x01e ++#define Key_i 0x01f ++#define Key_I 0x01f ++#define Key_o 0x020 ++#define Key_O 0x020 ++#define Key_p 0x021 ++#define Key_P 0x021 ++#define Key_bracketleft 0x022 ++#define Key_braceleft 0x022 ++#define Key_bracketright 0x023 ++#define Key_braceright 0x023 ++#define Key_Return 0x024 ++#define Key_Control_L 0x025 ++#define Key_a 0x026 ++#define Key_A 0x026 ++#define Key_s 0x027 ++#define Key_S 0x027 ++#define Key_d 0x028 ++#define Key_D 0x028 ++#define Key_f 0x029 ++#define Key_F 0x029 ++#define Key_g 0x02a ++#define Key_G 0x02a ++#define Key_h 0x02b ++#define Key_H 0x02b ++#define Key_j 0x02c ++#define Key_J 0x02c ++#define Key_k 0x02d ++#define Key_K 0x02d ++#define Key_l 0x02e ++#define Key_L 0x02e ++#define Key_semicolon 0x02f ++#define Key_colon 0x02f ++#define Key_apostrophe 0x030 ++#define Key_quotedbl 0x030 ++#define Key_grave 0x031 ++#define Key_asciitilde 0x031 ++#define Key_Shift_L 0x032 ++#define Key_backslash 0x033 ++#define Key_bar 0x033 ++#define Key_z 0x034 ++#define Key_Z 0x034 ++#define Key_x 0x035 ++#define Key_X 0x035 ++#define Key_c 0x036 ++#define Key_C 0x036 ++#define Key_v 0x037 ++#define Key_V 0x037 ++#define Key_b 0x038 ++#define Key_B 0x038 ++#define Key_n 0x039 ++#define Key_N 0x039 ++#define Key_m 0x03a ++#define Key_M 0x03a ++#define Key_comma 0x03b ++#define Key_less 0x03b ++#define Key_period 0x03c ++#define Key_greater 0x03c ++#define Key_slash 0x03d ++#define Key_question 0x03d ++#define Key_Shift_R 0x03e ++#define Key_KP_Multiply 0x03f ++#define Key_XF86ClearGrab 0x03f ++#define Key_Alt_L 0x040 ++#define Key_Meta_L 0x040 ++#define Key_space 0x041 ++#define Key_Caps_Lock 0x042 ++#define Key_F1 0x043 ++#define Key_XF86Switch_VT_1 0x043 ++#define Key_F2 0x044 ++#define Key_XF86Switch_VT_2 0x044 ++#define Key_F3 0x045 ++#define Key_XF86Switch_VT_3 0x045 ++#define Key_F4 0x046 ++#define Key_XF86Switch_VT_4 0x046 ++#define Key_F5 0x047 ++#define Key_XF86Switch_VT_5 0x047 ++#define Key_F6 0x048 ++#define Key_XF86Switch_VT_6 0x048 ++#define Key_F7 0x049 ++#define Key_XF86Switch_VT_7 0x049 ++#define Key_F8 0x04a ++#define Key_XF86Switch_VT_8 0x04a ++#define Key_F9 0x04b ++#define Key_XF86Switch_VT_9 0x04b ++#define Key_F10 0x04c ++#define Key_XF86Switch_VT_10 0x04c ++#define Key_Num_Lock 0x04d ++#define Key_Scroll_Lock 0x04e ++#define Key_KP_Home 0x04f ++#define Key_KP_7 0x04f ++#define Key_KP_Up 0x050 ++#define Key_KP_8 0x050 ++#define Key_KP_Prior 0x051 ++#define Key_KP_9 0x051 ++#define Key_KP_Subtract 0x052 ++#define Key_XF86Prev_VMode 0x052 ++#define Key_KP_Left 0x053 ++#define Key_KP_4 0x053 ++#define Key_KP_Begin 0x054 ++#define Key_KP_5 0x054 ++#define Key_KP_Right 0x055 ++#define Key_KP_6 0x055 ++#define Key_KP_Add 0x056 ++#define Key_XF86Next_VMode 0x056 ++#define Key_KP_End 0x057 ++#define Key_KP_1 0x057 ++#define Key_KP_Down 0x058 ++#define Key_KP_2 0x058 ++#define Key_KP_Next 0x059 ++#define Key_KP_3 0x059 ++#define Key_KP_Insert 0x05a ++#define Key_KP_0 0x05a ++#define Key_KP_Delete 0x05b ++#define Key_KP_Decimal 0x05b ++#define Key_ISO_Level3_Shift 0x05c ++#define Key_less2 0x05e ++#define Key_greater2 0x05e ++#define Key_bar2 0x05e ++#define Key_brokenbar 0x05e ++#define Key_F11 0x05f ++#define Key_XF86Switch_VT_11 0x05f ++#define Key_F12 0x060 ++#define Key_XF86Switch_VT_12 0x060 ++#define Key_Katakana 0x062 ++#define Key_Hiragana 0x063 ++#define Key_Henkan_Mode 0x064 ++#define Key_Hiragana_Katakana 0x065 ++#define Key_Muhenkan 0x066 ++#define Key_KP_Enter 0x068 ++#define Key_Control_R 0x069 ++#define Key_KP_Divide 0x06a ++#define Key_XF86Ungrab 0x06a ++#define Key_Print 0x06b ++#define Key_Sys_Req 0x06b ++#define Key_Alt_R 0x06c ++#define Key_Meta_R 0x06c ++#define Key_Linefeed 0x06d ++#define Key_Home 0x06e ++#define Key_Up 0x06f ++#define Key_Prior 0x070 ++#define Key_Left 0x071 ++#define Key_Right 0x072 ++#define Key_End 0x073 ++#define Key_Down 0x074 ++#define Key_Next 0x075 ++#define Key_Insert 0x076 ++#define Key_Delete 0x077 ++#define Key_XF86AudioMute 0x079 ++#define Key_XF86AudioLowerVolume 0x07a ++#define Key_XF86AudioRaiseVolume 0x07b ++#define Key_XF86PowerOff 0x07c ++#define Key_KP_Equal 0x07d ++#define Key_plusminus 0x07e ++#define Key_Pause 0x07f ++#define Key_Break 0x07f ++#define Key_XF86LaunchA 0x080 ++#define Key_KP_Decimal2 0x081 ++#define Key_Hangul 0x082 ++#define Key_Hangul_Hanja 0x083 ++#define Key_Super_L 0x085 ++#define Key_Super_R 0x086 ++#define Key_Menu 0x087 ++#define Key_Cancel 0x088 ++#define Key_Redo 0x089 ++#define Key_SunProps 0x08a ++#define Key_Undo 0x08b ++#define Key_SunFront 0x08c ++#define Key_XF86Copy 0x08d ++#define Key_XF86Open 0x08e ++#define Key_XF86Paste 0x08f ++#define Key_Find 0x090 ++#define Key_XF86Cut 0x091 ++#define Key_Help 0x092 ++#define Key_XF86MenuKB 0x093 ++#define Key_XF86Calculator 0x094 ++#define Key_XF86Sleep 0x096 ++#define Key_XF86WakeUp 0x097 ++#define Key_XF86Explorer 0x098 ++#define Key_XF86Send 0x099 ++#define Key_XF86Xfer 0x09b ++#define Key_XF86Launch1 0x09c ++#define Key_XF86Launch2 0x09d ++#define Key_XF86WWW 0x09e ++#define Key_XF86DOS 0x09f ++#define Key_XF86ScreenSaver 0x0a0 ++#define Key_XF86RotateWindows 0x0a1 ++#define Key_XF86TaskPane 0x0a2 ++#define Key_XF86Mail 0x0a3 ++#define Key_XF86Favorites 0x0a4 ++#define Key_XF86MyComputer 0x0a5 ++#define Key_XF86Back 0x0a6 ++#define Key_XF86Forward 0x0a7 ++#define Key_XF86Eject 0x0a9 ++#define Key_XF86Eject2 0x0aa ++#define Key_XF86AudioNext 0x0ab ++#define Key_XF86AudioPlay 0x0ac ++#define Key_XF86AudioPause 0x0ac ++#define Key_XF86AudioPrev 0x0ad ++#define Key_XF86AudioStop 0x0ae ++#define Key_XF86Eject3 0x0ae ++#define Key_XF86AudioRecord 0x0af ++#define Key_XF86AudioRewind 0x0b0 ++#define Key_XF86Phone 0x0b1 ++#define Key_XF86Tools 0x0b3 ++#define Key_XF86HomePage 0x0b4 ++#define Key_XF86Reload 0x0b5 ++#define Key_XF86Close 0x0b6 ++#define Key_XF86ScrollUp 0x0b9 ++#define Key_XF86ScrollDown 0x0ba ++#define Key_parenleft2 0x0bb ++#define Key_parenright2 0x0bc ++#define Key_XF86New 0x0bd ++#define Key_Redo2 0x0be ++#define Key_XF86Tools2 0x0bf ++#define Key_XF86Launch5 0x0c0 ++#define Key_XF86Launch6 0x0c1 ++#define Key_XF86Launch7 0x0c2 ++#define Key_XF86Launch8 0x0c3 ++#define Key_XF86Launch9 0x0c4 ++#define Key_XF86AudioMicMute 0x0c6 ++#define Key_XF86TouchpadToggle 0x0c7 ++#define Key_XF86TouchpadOn 0x0c8 ++#define Key_XF86TouchpadOff 0x0c9 ++#define Key_ISO_Level5_Shift 0x0cb ++#define Key_Alt_L2 0x0cc ++#define Key_Meta_L2 0x0cd ++#define Key_Super_L2 0x0ce ++#define Key_Hyper_L 0x0cf ++#define Key_XF86AudioPlay2 0x0d0 ++#define Key_XF86AudioPause2 0x0d1 ++#define Key_XF86Launch3 0x0d2 ++#define Key_XF86Launch4 0x0d3 ++#define Key_XF86LaunchB 0x0d4 ++#define Key_XF86Suspend 0x0d5 ++#define Key_XF86Close2 0x0d6 ++#define Key_XF86AudioPlay3 0x0d7 ++#define Key_XF86AudioForward 0x0d8 ++#define Key_Print2 0x0da ++#define Key_XF86WebCam 0x0dc ++#define Key_XF86AudioPreset 0x0dd ++#define Key_XF86Mail2 0x0df ++#define Key_XF86Messenger 0x0e0 ++#define Key_XF86Search 0x0e1 ++#define Key_XF86Go 0x0e2 ++#define Key_XF86Finance 0x0e3 ++#define Key_XF86Game 0x0e4 ++#define Key_XF86Shop 0x0e5 ++#define Key_Cancel2 0x0e7 ++#define Key_XF86MonBrightnessDown 0x0e8 ++#define Key_XF86MonBrightnessUp 0x0e9 ++#define Key_XF86AudioMedia 0x0ea ++#define Key_XF86Display 0x0eb ++#define Key_XF86KbdLightOnOff 0x0ec ++#define Key_XF86KbdBrightnessDown 0x0ed ++#define Key_XF86KbdBrightnessUp 0x0ee ++#define Key_XF86Send2 0x0ef ++#define Key_XF86Reply 0x0f0 ++#define Key_XF86MailForward 0x0f1 ++#define Key_XF86Save 0x0f2 ++#define Key_XF86Documents 0x0f3 ++#define Key_XF86Battery 0x0f4 ++#define Key_XF86Bluetooth 0x0f5 ++#define Key_XF86WLAN 0x0f6 ++#define Key_XF86UWB 0x0f7 ++#define Key_XF86Next_VMode2 0x0f9 ++#define Key_XF86Prev_VMode2 0x0fa ++#define Key_XF86MonBrightnessCycle 0x0fb ++#define Key_XF86BrightnessAuto 0x0fc ++#define Key_XF86DisplayOff 0x0fd ++#define Key_XF86WWAN 0x0fe ++#define Key_XF86RFKill 0x0ff ++#define Key_XF86AudioMicMute2 0x100 ++#define Key_XF86Info 0x16e ++#define Key_XF86Favorites2 0x174 ++#define Key_XF86CycleAngle 0x17b ++#define Key_XF86FullScreen 0x17c ++#define Key_XF86Keyboard 0x17e ++#define Key_XF86AspectRatio 0x17f ++#define Key_XF86DVD 0x18d ++#define Key_XF86Audio 0x190 ++#define Key_XF86Video 0x191 ++#define Key_XF86Calendar 0x195 ++#define Key_XF86ChannelUp 0x19a ++#define Key_XF86ChannelDown 0x19b ++#define Key_XF86AudioRandomPlay 0x1a2 ++#define Key_XF86Break 0x1a3 ++#define Key_XF86VideoPhone 0x1a8 ++#define Key_XF86Game2 0x1a9 ++#define Key_XF86ZoomIn 0x1aa ++#define Key_XF86ZoomOut 0x1ab ++#define Key_XF86ZoomReset 0x1ac ++#define Key_XF86Word 0x1ad ++#define Key_XF86Editor 0x1ae ++#define Key_XF86Excel 0x1af ++#define Key_XF86GraphicsEditor 0x1b0 ++#define Key_XF86Presentation 0x1b1 ++#define Key_XF86Database 0x1b2 ++#define Key_XF86News 0x1b3 ++#define Key_XF86Voicemail 0x1b4 ++#define Key_XF86Addressbook 0x1b5 ++#define Key_XF86Messenger2 0x1b6 ++#define Key_XF86DisplayToggle 0x1b7 ++#define Key_XF86SpellCheck 0x1b8 ++#define Key_XF86LogOff 0x1b9 ++#define Key_dollar2 0x1ba ++#define Key_EuroSign 0x1bb ++#define Key_XF86FrameBack 0x1bc ++#define Key_XF86FrameForward 0x1bd ++#define Key_XF86ContextMenu 0x1be ++#define Key_XF86MediaRepeat 0x1bf ++#define Key_XF8610ChannelsUp 0x1c0 ++#define Key_XF8610ChannelsDown 0x1c1 ++#define Key_XF86Images 0x1c2 ++#define Key_XF86NotificationCenter 0x1c4 ++#define Key_XF86PickupPhone 0x1c5 ++#define Key_XF86HangupPhone 0x1c6 ++#define Key_XF86Fn 0x1d8 ++#define Key_XF86Fn_Esc 0x1d9 ++#define Key_XF86FnRightShift 0x1ed ++#define Key_braille_dot_1 0x1f9 ++#define Key_braille_dot_2 0x1fa ++#define Key_braille_dot_3 0x1fb ++#define Key_braille_dot_4 0x1fc ++#define Key_braille_dot_5 0x1fd ++#define Key_braille_dot_6 0x1fe ++#define Key_braille_dot_7 0x1ff ++#define Key_braille_dot_8 0x200 ++#define Key_braille_dot_9 0x201 ++#define Key_braille_dot_1_2 0x202 ++#define Key_XF86Numeric0 0x208 ++#define Key_XF86Numeric1 0x209 ++#define Key_XF86Numeric2 0x20a ++#define Key_XF86Numeric3 0x20b ++#define Key_XF86Numeric4 0x20c ++#define Key_XF86Numeric5 0x20d ++#define Key_XF86Numeric6 0x20e ++#define Key_XF86Numeric7 0x20f ++#define Key_XF86Numeric8 0x210 ++#define Key_XF86Numeric9 0x211 ++#define Key_XF86NumericStar 0x212 ++#define Key_XF86NumericPound 0x213 ++#define Key_XF86NumericA 0x214 ++#define Key_XF86NumericB 0x215 ++#define Key_XF86NumericC 0x216 ++#define Key_XF86NumericD 0x217 ++#define Key_XF86CameraFocus 0x218 ++#define Key_XF86WPSButton 0x219 ++#define Key_XF86TouchpadToggle2 0x21a ++#define Key_XF86TouchpadOn2 0x21b ++#define Key_XF86TouchpadOff2 0x21c ++#define Key_XF86CameraZoomIn 0x21d ++#define Key_XF86CameraZoomOut 0x21e ++#define Key_XF86CameraUp 0x21f ++#define Key_XF86CameraDown 0x220 ++#define Key_XF86CameraLeft 0x221 ++#define Key_XF86CameraRight 0x222 ++#define Key_XF86AttendantOn 0x223 ++#define Key_XF86AttendantOff 0x224 ++#define Key_XF86AttendantToggle 0x225 ++#define Key_XF86LightsToggle 0x226 ++#define Key_XF86ALSToggle 0x238 ++#define Key_XF86RotationLockToggle 0x239 ++#define Key_XF86Buttonconfig 0x248 ++#define Key_XF86Taskmanager 0x249 ++#define Key_XF86Journal 0x24a ++#define Key_XF86ControlPanel 0x24b ++#define Key_XF86AppSelect 0x24c ++#define Key_XF86Screensaver 0x24d ++#define Key_XF86VoiceCommand 0x24e ++#define Key_XF86Assistant 0x24f ++#define Key_ISO_Next_Group 0x250 ++#define Key_XF86EmojiPicker 0x251 ++#define Key_XF86Dictate 0x252 ++#define Key_XF86CameraAccessEnable 0x253 ++#define Key_XF86CameraAccessDisable 0x254 ++#define Key_XF86CameraAccessToggle 0x255 ++#define Key_XF86BrightnessMin 0x258 ++#define Key_XF86BrightnessMax 0x259 ++#define Key_XF86KbdInputAssistPrev 0x268 ++#define Key_XF86KbdInputAssistNext 0x269 ++#define Key_XF86KbdInputAssistPrevgroup 0x26a ++#define Key_XF86KbdInputAssistNextgroup 0x26b ++#define Key_XF86KbdInputAssistAccept 0x26c ++#define Key_XF86KbdInputAssistCancel 0x26d ++#define Key_XF86RightUp 0x26e ++#define Key_XF86RightDown 0x26f ++#define Key_XF86LeftUp 0x270 ++#define Key_XF86LeftDown 0x271 ++#define Key_XF86RootMenu 0x272 ++#define Key_XF86MediaTopMenu 0x273 ++#define Key_XF86Numeric11 0x274 ++#define Key_XF86Numeric12 0x275 ++#define Key_XF86AudioDesc 0x276 ++#define Key_XF863DMode 0x277 ++#define Key_XF86NextFavorite 0x278 ++#define Key_XF86StopRecord 0x279 ++#define Key_XF86PauseRecord 0x27a ++#define Key_XF86VOD 0x27b ++#define Key_XF86Unmute 0x27c ++#define Key_XF86FastReverse 0x27d ++#define Key_XF86SlowReverse 0x27e ++#define Key_XF86Data 0x27f ++#define Key_XF86OnScreenKeyboard 0x280 ++#define Key_XF86PrivacyScreenToggle 0x281 ++#define Key_XF86SelectiveScreenshot 0x282 ++#define Key_XF86NextElement 0x283 ++#define Key_XF86PreviousElement 0x284 ++#define Key_XF86AutopilotEngageToggle 0x285 ++#define Key_XF86MarkWaypoint 0x286 ++#define Key_XF86Sos 0x287 ++#define Key_XF86NavChart 0x288 ++#define Key_XF86FishingChart 0x289 ++#define Key_XF86SingleRangeRadar 0x28a ++#define Key_XF86DualRangeRadar 0x28b ++#define Key_XF86RadarOverlay 0x28c ++#define Key_XF86TraditionalSonar 0x28d ++#define Key_XF86ClearvuSonar 0x28e ++#define Key_XF86SidevuSonar 0x28f ++#define Key_XF86NavInfo 0x290 ++#define Key_XF86BrightnessAdjust 0x291 ++#define Key_XF86Macro1 0x298 ++#define Key_XF86Macro2 0x299 ++#define Key_XF86Macro3 0x29a ++#define Key_XF86Macro4 0x29b ++#define Key_XF86Macro5 0x29c ++#define Key_XF86Macro6 0x29d ++#define Key_XF86Macro7 0x29e ++#define Key_XF86Macro8 0x29f ++#define Key_XF86Macro9 0x2a0 ++#define Key_XF86Macro10 0x2a1 ++#define Key_XF86Macro11 0x2a2 ++#define Key_XF86Macro12 0x2a3 ++#define Key_XF86Macro13 0x2a4 ++#define Key_XF86Macro14 0x2a5 ++#define Key_XF86Macro15 0x2a6 ++#define Key_XF86Macro16 0x2a7 ++#define Key_XF86Macro17 0x2a8 ++#define Key_XF86Macro18 0x2a9 ++#define Key_XF86Macro19 0x2aa ++#define Key_XF86Macro20 0x2ab ++#define Key_XF86Macro21 0x2ac ++#define Key_XF86Macro22 0x2ad ++#define Key_XF86Macro23 0x2ae ++#define Key_XF86Macro24 0x2af ++#define Key_XF86Macro25 0x2b0 ++#define Key_XF86Macro26 0x2b1 ++#define Key_XF86Macro27 0x2b2 ++#define Key_XF86Macro28 0x2b3 ++#define Key_XF86Macro29 0x2b4 ++#define Key_XF86Macro30 0x2b5 ++#define Key_XF86MacroRecordStart 0x2b8 ++#define Key_XF86MacroRecordStop 0x2b9 ++#define Key_XF86MacroPresetCycle 0x2ba ++#define Key_XF86MacroPreset1 0x2bb ++#define Key_XF86MacroPreset2 0x2bc ++#define Key_XF86MacroPreset3 0x2bd ++#define Key_XF86KbdLcdMenu1 0x2c0 ++#define Key_XF86KbdLcdMenu2 0x2c1 ++#define Key_XF86KbdLcdMenu3 0x2c2 ++#define Key_XF86KbdLcdMenu4 0x2c3 ++#define Key_XF86KbdLcdMenu5 0x2c4 +-- +2.46.0 + + +From cc7d880886d91cd8d39ab31a48d03d1f745598d2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sun, 19 Mar 2023 15:50:07 -0600 +Subject: [PATCH 2/2] add program to generate keys.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + generate-keys.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + create mode 100644 generate-keys.c + +diff --git a/generate-keys.c b/generate-keys.c +new file mode 100644 +index 00000000..37655611 +--- /dev/null ++++ b/generate-keys.c +@@ -0,0 +1,95 @@ ++/****************************************************************** ++ * Copyright 2023-2024 Leonardo Hernández Hernández ++ * ++ * 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 ++ * OPEN GROUP 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. ++ * ++ ******************************************************************/ ++ ++/* cc -lxkbcommon -o generate-keys generate-keys.c */ ++ ++#define _DEFAULT_SOURCE ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++int ++main(void) ++{ ++ /* Allow generate keys with a different layout and variant. ++ * You can also use XKB_DEFAULT_* environmental variables and let this as is */ ++ struct xkb_rule_names rules = { ++ 0 ++ }; ++ struct xkb_context *context = NULL; ++ struct xkb_keymap *keymap = NULL; ++ xkb_keycode_t keycode, min_keycode, max_keycode; ++ xkb_layout_index_t layout, num_layouts; ++ xkb_level_index_t level, num_levels; ++ int i, nsyms; ++ const xkb_keysym_t *syms; ++ char keyname[64]; ++ bool ok = false; ++ FILE *file = fopen("keys.h", "w"); ++ if (!file) { ++ perror("Couldn't open keys.h"); ++ return EXIT_FAILURE; ++ } ++ ++ if (!(context = xkb_context_new(XKB_CONTEXT_NO_FLAGS))) { ++ fputs("Couldn't create xkbcommon context\n", stderr); ++ goto out; ++ } ++ ++ if (!(keymap = xkb_keymap_new_from_names(context, &rules, ++ XKB_KEYMAP_COMPILE_NO_FLAGS))) { ++ fputs("Couldn't create xkbcommon keymap\n", stderr); ++ goto out; ++ } ++ ++ min_keycode = xkb_keymap_min_keycode(keymap); ++ max_keycode = xkb_keymap_max_keycode(keymap); ++ ++ for (keycode = min_keycode; keycode <= max_keycode; keycode++) { ++ num_layouts = xkb_keymap_num_layouts_for_key(keymap, keycode); ++ for (layout = 0; layout < num_layouts; layout++) { ++ num_levels = xkb_keymap_num_levels_for_key(keymap, keycode, layout); ++ for (level = 0; level < num_levels; level++) { ++ nsyms = xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms); ++ for (i = 0; i < nsyms; i++) { ++ xkb_keysym_get_name(syms[i], keyname, sizeof(keyname) / sizeof(keyname[0])); ++ fprintf(file, "#define Key_%-27s %#05"PRIx32"\n", keyname, keycode); ++ } ++ } ++ } ++ } ++ ++ ok = true; ++ sync(); ++ ++out: ++ fclose(file); ++ xkb_keymap_unref(keymap); ++ xkb_context_unref(context); ++ return !ok; ++} +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/keycodes/keycodes.patch b/dwl/dwl-patches/patches/keycodes/keycodes.patch new file mode 100755 index 0000000..cc7e896 --- /dev/null +++ b/dwl/dwl-patches/patches/keycodes/keycodes.patch @@ -0,0 +1,883 @@ +From 308eda668e1d6496a605e44be34fd44c841a1133 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Fri, 4 Jun 2021 16:51:01 -0500 +Subject: [PATCH 1/2] allow use keycodes instead keysyms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 85 ++++----- + dwl.c | 35 ++-- + keys.h | 514 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 569 insertions(+), 65 deletions(-) + create mode 100644 keys.h + +diff --git a/config.def.h b/config.def.h +index 22d2171d..87a6e60f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -109,11 +109,11 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ + #define MODKEY WLR_MODIFIER_ALT + +-#define TAGKEYS(KEY,SKEY,TAG) \ ++#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } ++ { MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \ ++ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,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 } } +@@ -122,51 +122,52 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + static const char *termcmd[] = { "foot", NULL }; + static const char *menucmd[] = { "wmenu-run", NULL }; + ++#include "keys.h" + static const Key keys[] = { +- /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ +- /* modifier key function argument */ +- { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, +- { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, +- { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, +- { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +- { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, +- { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +- { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, +- { MODKEY, XKB_KEY_Return, zoom, {0} }, +- { MODKEY, XKB_KEY_Tab, view, {0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +- { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, +- { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, +- { MODKEY, XKB_KEY_space, setlayout, {0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, +- { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +- { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, +- { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +- { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, +- TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), +- TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), +- TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +- TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), +- TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), +- TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), +- TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), +- TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), +- TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), +- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, ++ /* modifier key function argument */ ++ { MODKEY, Key_p, spawn, {.v = menucmd} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_Return, spawn, {.v = termcmd} }, ++ { MODKEY, Key_j, focusstack, {.i = +1} }, ++ { MODKEY, Key_k, focusstack, {.i = -1} }, ++ { MODKEY, Key_i, incnmaster, {.i = +1} }, ++ { MODKEY, Key_d, incnmaster, {.i = -1} }, ++ { MODKEY, Key_h, setmfact, {.f = -0.05f} }, ++ { MODKEY, Key_l, setmfact, {.f = +0.05f} }, ++ { MODKEY, Key_Return, zoom, {0} }, ++ { MODKEY, Key_Tab, view, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_c, killclient, {0} }, ++ { MODKEY, Key_t, setlayout, {.v = &layouts[0]} }, ++ { MODKEY, Key_f, setlayout, {.v = &layouts[1]} }, ++ { MODKEY, Key_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, Key_space, setlayout, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_space, togglefloating, {0} }, ++ { MODKEY, Key_e, togglefullscreen, {0} }, ++ { MODKEY, Key_0, view, {.ui = ~0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_0, tag, {.ui = ~0} }, ++ { MODKEY, Key_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, ++ { MODKEY, Key_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_comma, tagmon, {.i = WLR_DIRECTION_LEFT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_period, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ TAGKEYS( Key_1, 0), ++ TAGKEYS( Key_2, 1), ++ TAGKEYS( Key_3, 2), ++ TAGKEYS( Key_4, 3), ++ TAGKEYS( Key_5, 4), ++ TAGKEYS( Key_6, 5), ++ TAGKEYS( Key_7, 6), ++ TAGKEYS( Key_8, 7), ++ TAGKEYS( Key_9, 8), ++ { MODKEY|WLR_MODIFIER_SHIFT, Key_q, quit, {0} }, + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ +- { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, ++ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,Key_BackSpace, quit, {0} }, ++#define CHVT(KEY,n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT, KEY, chvt, {.ui = (n)} } + /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is + * do not remove them. + */ +-#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } +- CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), +- CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), ++ CHVT(Key_F1, 1), CHVT(Key_F2, 2), CHVT(Key_F3, 3), CHVT(Key_F4, 4), ++ CHVT(Key_F5, 5), CHVT(Key_F6, 6), CHVT(Key_F7, 7), CHVT(Key_F8, 8), ++ CHVT(Key_F9, 9), CHVT(Key_F10, 10), CHVT(Key_F11, 11), CHVT(Key_F12, 12), + }; + + static const Button buttons[] = { +diff --git a/dwl.c b/dwl.c +index ad21e1ba..1c9e0ae5 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -143,7 +143,7 @@ typedef struct { + + typedef struct { + uint32_t mod; +- xkb_keysym_t keysym; ++ xkb_keycode_t keycode; + void (*func)(const Arg *); + const Arg arg; + } Key; +@@ -151,9 +151,8 @@ typedef struct { + typedef struct { + struct wlr_keyboard_group *wlr_group; + +- int nsyms; +- const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */ +- uint32_t mods; /* invalid if nsyms == 0 */ ++ xkb_keycode_t keycode; ++ uint32_t mods; /* invalid if keycode == 0 */ + struct wl_event_source *key_repeat_source; + + struct wl_listener modifiers; +@@ -291,7 +290,7 @@ static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +-static int keybinding(uint32_t mods, xkb_keysym_t sym); ++static int keybinding(uint32_t mods, xkb_keycode_t keycode); + static void keypress(struct wl_listener *listener, void *data); + static void keypressmod(struct wl_listener *listener, void *data); + static int keyrepeat(void *data); +@@ -1597,7 +1596,7 @@ inputdevice(struct wl_listener *listener, void *data) + } + + int +-keybinding(uint32_t mods, xkb_keysym_t sym) ++keybinding(uint32_t mods, xkb_keycode_t keycode) + { + /* + * Here we handle compositor keybindings. This is when the compositor is +@@ -1607,7 +1606,7 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + const Key *k; + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) +- && sym == k->keysym && k->func) { ++ && keycode == k->keycode && k->func) { + k->func(&k->arg); + return 1; + } +@@ -1618,17 +1617,12 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + void + keypress(struct wl_listener *listener, void *data) + { +- int i; + /* This event is raised when a key is pressed or released. */ + KeyboardGroup *group = wl_container_of(listener, group, key); + struct wlr_keyboard_key_event *event = data; + + /* Translate libinput keycode -> xkbcommon */ + uint32_t keycode = event->keycode + 8; +- /* Get a list of keysyms based on the keymap for this keyboard */ +- const xkb_keysym_t *syms; +- int nsyms = xkb_state_key_get_syms( +- group->wlr_group->keyboard.xkb_state, keycode, &syms); + + int handled = 0; + uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); +@@ -1637,19 +1631,16 @@ keypress(struct wl_listener *listener, void *data) + + /* On _press_ if there is no active screen locker, + * attempt to process a compositor keybinding. */ +- if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { +- for (i = 0; i < nsyms; i++) +- handled = keybinding(mods, syms[i]) || handled; +- } ++ if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) ++ handled = keybinding(mods, keycode); + + if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { + group->mods = mods; +- group->keysyms = syms; +- group->nsyms = nsyms; ++ group->keycode = keycode; + wl_event_source_timer_update(group->key_repeat_source, + group->wlr_group->keyboard.repeat_info.delay); + } else { +- group->nsyms = 0; ++ group->keycode = 0; + wl_event_source_timer_update(group->key_repeat_source, 0); + } + +@@ -1679,15 +1670,13 @@ int + keyrepeat(void *data) + { + KeyboardGroup *group = data; +- int i; +- if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0) ++ if (!group->keycode || group->wlr_group->keyboard.repeat_info.rate <= 0) + return 0; + + wl_event_source_timer_update(group->key_repeat_source, + 1000 / group->wlr_group->keyboard.repeat_info.rate); + +- for (i = 0; i < group->nsyms; i++) +- keybinding(group->mods, group->keysyms[i]); ++ keybinding(group->mods, group->keycode); + + return 0; + } +diff --git a/keys.h b/keys.h +new file mode 100644 +index 00000000..047b76b0 +--- /dev/null ++++ b/keys.h +@@ -0,0 +1,514 @@ ++/* You can use the macros within this file ++ * instead of search the keycodes yourself ++ * with wev or something like that ++ * You probably are also searching these: ++ * Key_XF86AudioMute ++ * Key_XF86AudioLowerVolume ++ * Key_XF86AudioRaiseVolume ++ * Key_XF86MonBrightnessDown ++ * Key_XF86MonBrightnessUp ++*/ ++ ++#define Key_Escape 0x009 ++#define Key_1 0x00a ++#define Key_exclam 0x00a ++#define Key_2 0x00b ++#define Key_at 0x00b ++#define Key_3 0x00c ++#define Key_numbersign 0x00c ++#define Key_4 0x00d ++#define Key_dollar 0x00d ++#define Key_5 0x00e ++#define Key_percent 0x00e ++#define Key_6 0x00f ++#define Key_asciicircum 0x00f ++#define Key_7 0x010 ++#define Key_ampersand 0x010 ++#define Key_8 0x011 ++#define Key_asterisk 0x011 ++#define Key_9 0x012 ++#define Key_parenleft 0x012 ++#define Key_0 0x013 ++#define Key_parenright 0x013 ++#define Key_minus 0x014 ++#define Key_underscore 0x014 ++#define Key_equal 0x015 ++#define Key_plus 0x015 ++#define Key_BackSpace 0x016 ++#define Key_Tab 0x017 ++#define Key_ISO_Left_Tab 0x017 ++#define Key_q 0x018 ++#define Key_Q 0x018 ++#define Key_w 0x019 ++#define Key_W 0x019 ++#define Key_e 0x01a ++#define Key_E 0x01a ++#define Key_r 0x01b ++#define Key_R 0x01b ++#define Key_t 0x01c ++#define Key_T 0x01c ++#define Key_y 0x01d ++#define Key_Y 0x01d ++#define Key_u 0x01e ++#define Key_U 0x01e ++#define Key_i 0x01f ++#define Key_I 0x01f ++#define Key_o 0x020 ++#define Key_O 0x020 ++#define Key_p 0x021 ++#define Key_P 0x021 ++#define Key_bracketleft 0x022 ++#define Key_braceleft 0x022 ++#define Key_bracketright 0x023 ++#define Key_braceright 0x023 ++#define Key_Return 0x024 ++#define Key_Control_L 0x025 ++#define Key_a 0x026 ++#define Key_A 0x026 ++#define Key_s 0x027 ++#define Key_S 0x027 ++#define Key_d 0x028 ++#define Key_D 0x028 ++#define Key_f 0x029 ++#define Key_F 0x029 ++#define Key_g 0x02a ++#define Key_G 0x02a ++#define Key_h 0x02b ++#define Key_H 0x02b ++#define Key_j 0x02c ++#define Key_J 0x02c ++#define Key_k 0x02d ++#define Key_K 0x02d ++#define Key_l 0x02e ++#define Key_L 0x02e ++#define Key_semicolon 0x02f ++#define Key_colon 0x02f ++#define Key_apostrophe 0x030 ++#define Key_quotedbl 0x030 ++#define Key_grave 0x031 ++#define Key_asciitilde 0x031 ++#define Key_Shift_L 0x032 ++#define Key_backslash 0x033 ++#define Key_bar 0x033 ++#define Key_z 0x034 ++#define Key_Z 0x034 ++#define Key_x 0x035 ++#define Key_X 0x035 ++#define Key_c 0x036 ++#define Key_C 0x036 ++#define Key_v 0x037 ++#define Key_V 0x037 ++#define Key_b 0x038 ++#define Key_B 0x038 ++#define Key_n 0x039 ++#define Key_N 0x039 ++#define Key_m 0x03a ++#define Key_M 0x03a ++#define Key_comma 0x03b ++#define Key_less 0x03b ++#define Key_period 0x03c ++#define Key_greater 0x03c ++#define Key_slash 0x03d ++#define Key_question 0x03d ++#define Key_Shift_R 0x03e ++#define Key_KP_Multiply 0x03f ++#define Key_XF86ClearGrab 0x03f ++#define Key_Alt_L 0x040 ++#define Key_Meta_L 0x040 ++#define Key_space 0x041 ++#define Key_Caps_Lock 0x042 ++#define Key_F1 0x043 ++#define Key_XF86Switch_VT_1 0x043 ++#define Key_F2 0x044 ++#define Key_XF86Switch_VT_2 0x044 ++#define Key_F3 0x045 ++#define Key_XF86Switch_VT_3 0x045 ++#define Key_F4 0x046 ++#define Key_XF86Switch_VT_4 0x046 ++#define Key_F5 0x047 ++#define Key_XF86Switch_VT_5 0x047 ++#define Key_F6 0x048 ++#define Key_XF86Switch_VT_6 0x048 ++#define Key_F7 0x049 ++#define Key_XF86Switch_VT_7 0x049 ++#define Key_F8 0x04a ++#define Key_XF86Switch_VT_8 0x04a ++#define Key_F9 0x04b ++#define Key_XF86Switch_VT_9 0x04b ++#define Key_F10 0x04c ++#define Key_XF86Switch_VT_10 0x04c ++#define Key_Num_Lock 0x04d ++#define Key_Scroll_Lock 0x04e ++#define Key_KP_Home 0x04f ++#define Key_KP_7 0x04f ++#define Key_KP_Up 0x050 ++#define Key_KP_8 0x050 ++#define Key_KP_Prior 0x051 ++#define Key_KP_9 0x051 ++#define Key_KP_Subtract 0x052 ++#define Key_XF86Prev_VMode 0x052 ++#define Key_KP_Left 0x053 ++#define Key_KP_4 0x053 ++#define Key_KP_Begin 0x054 ++#define Key_KP_5 0x054 ++#define Key_KP_Right 0x055 ++#define Key_KP_6 0x055 ++#define Key_KP_Add 0x056 ++#define Key_XF86Next_VMode 0x056 ++#define Key_KP_End 0x057 ++#define Key_KP_1 0x057 ++#define Key_KP_Down 0x058 ++#define Key_KP_2 0x058 ++#define Key_KP_Next 0x059 ++#define Key_KP_3 0x059 ++#define Key_KP_Insert 0x05a ++#define Key_KP_0 0x05a ++#define Key_KP_Delete 0x05b ++#define Key_KP_Decimal 0x05b ++#define Key_ISO_Level3_Shift 0x05c ++#define Key_less2 0x05e ++#define Key_greater2 0x05e ++#define Key_bar2 0x05e ++#define Key_brokenbar 0x05e ++#define Key_F11 0x05f ++#define Key_XF86Switch_VT_11 0x05f ++#define Key_F12 0x060 ++#define Key_XF86Switch_VT_12 0x060 ++#define Key_Katakana 0x062 ++#define Key_Hiragana 0x063 ++#define Key_Henkan_Mode 0x064 ++#define Key_Hiragana_Katakana 0x065 ++#define Key_Muhenkan 0x066 ++#define Key_KP_Enter 0x068 ++#define Key_Control_R 0x069 ++#define Key_KP_Divide 0x06a ++#define Key_XF86Ungrab 0x06a ++#define Key_Print 0x06b ++#define Key_Sys_Req 0x06b ++#define Key_Alt_R 0x06c ++#define Key_Meta_R 0x06c ++#define Key_Linefeed 0x06d ++#define Key_Home 0x06e ++#define Key_Up 0x06f ++#define Key_Prior 0x070 ++#define Key_Left 0x071 ++#define Key_Right 0x072 ++#define Key_End 0x073 ++#define Key_Down 0x074 ++#define Key_Next 0x075 ++#define Key_Insert 0x076 ++#define Key_Delete 0x077 ++#define Key_XF86AudioMute 0x079 ++#define Key_XF86AudioLowerVolume 0x07a ++#define Key_XF86AudioRaiseVolume 0x07b ++#define Key_XF86PowerOff 0x07c ++#define Key_KP_Equal 0x07d ++#define Key_plusminus 0x07e ++#define Key_Pause 0x07f ++#define Key_Break 0x07f ++#define Key_XF86LaunchA 0x080 ++#define Key_KP_Decimal2 0x081 ++#define Key_Hangul 0x082 ++#define Key_Hangul_Hanja 0x083 ++#define Key_Super_L 0x085 ++#define Key_Super_R 0x086 ++#define Key_Menu 0x087 ++#define Key_Cancel 0x088 ++#define Key_Redo 0x089 ++#define Key_SunProps 0x08a ++#define Key_Undo 0x08b ++#define Key_SunFront 0x08c ++#define Key_XF86Copy 0x08d ++#define Key_XF86Open 0x08e ++#define Key_XF86Paste 0x08f ++#define Key_Find 0x090 ++#define Key_XF86Cut 0x091 ++#define Key_Help 0x092 ++#define Key_XF86MenuKB 0x093 ++#define Key_XF86Calculator 0x094 ++#define Key_XF86Sleep 0x096 ++#define Key_XF86WakeUp 0x097 ++#define Key_XF86Explorer 0x098 ++#define Key_XF86Send 0x099 ++#define Key_XF86Xfer 0x09b ++#define Key_XF86Launch1 0x09c ++#define Key_XF86Launch2 0x09d ++#define Key_XF86WWW 0x09e ++#define Key_XF86DOS 0x09f ++#define Key_XF86ScreenSaver 0x0a0 ++#define Key_XF86RotateWindows 0x0a1 ++#define Key_XF86TaskPane 0x0a2 ++#define Key_XF86Mail 0x0a3 ++#define Key_XF86Favorites 0x0a4 ++#define Key_XF86MyComputer 0x0a5 ++#define Key_XF86Back 0x0a6 ++#define Key_XF86Forward 0x0a7 ++#define Key_XF86Eject 0x0a9 ++#define Key_XF86Eject2 0x0aa ++#define Key_XF86AudioNext 0x0ab ++#define Key_XF86AudioPlay 0x0ac ++#define Key_XF86AudioPause 0x0ac ++#define Key_XF86AudioPrev 0x0ad ++#define Key_XF86AudioStop 0x0ae ++#define Key_XF86Eject3 0x0ae ++#define Key_XF86AudioRecord 0x0af ++#define Key_XF86AudioRewind 0x0b0 ++#define Key_XF86Phone 0x0b1 ++#define Key_XF86Tools 0x0b3 ++#define Key_XF86HomePage 0x0b4 ++#define Key_XF86Reload 0x0b5 ++#define Key_XF86Close 0x0b6 ++#define Key_XF86ScrollUp 0x0b9 ++#define Key_XF86ScrollDown 0x0ba ++#define Key_parenleft2 0x0bb ++#define Key_parenright2 0x0bc ++#define Key_XF86New 0x0bd ++#define Key_Redo2 0x0be ++#define Key_XF86Tools2 0x0bf ++#define Key_XF86Launch5 0x0c0 ++#define Key_XF86Launch6 0x0c1 ++#define Key_XF86Launch7 0x0c2 ++#define Key_XF86Launch8 0x0c3 ++#define Key_XF86Launch9 0x0c4 ++#define Key_XF86AudioMicMute 0x0c6 ++#define Key_XF86TouchpadToggle 0x0c7 ++#define Key_XF86TouchpadOn 0x0c8 ++#define Key_XF86TouchpadOff 0x0c9 ++#define Key_ISO_Level5_Shift 0x0cb ++#define Key_Alt_L2 0x0cc ++#define Key_Meta_L2 0x0cd ++#define Key_Super_L2 0x0ce ++#define Key_Hyper_L 0x0cf ++#define Key_XF86AudioPlay2 0x0d0 ++#define Key_XF86AudioPause2 0x0d1 ++#define Key_XF86Launch3 0x0d2 ++#define Key_XF86Launch4 0x0d3 ++#define Key_XF86LaunchB 0x0d4 ++#define Key_XF86Suspend 0x0d5 ++#define Key_XF86Close2 0x0d6 ++#define Key_XF86AudioPlay3 0x0d7 ++#define Key_XF86AudioForward 0x0d8 ++#define Key_Print2 0x0da ++#define Key_XF86WebCam 0x0dc ++#define Key_XF86AudioPreset 0x0dd ++#define Key_XF86Mail2 0x0df ++#define Key_XF86Messenger 0x0e0 ++#define Key_XF86Search 0x0e1 ++#define Key_XF86Go 0x0e2 ++#define Key_XF86Finance 0x0e3 ++#define Key_XF86Game 0x0e4 ++#define Key_XF86Shop 0x0e5 ++#define Key_Cancel2 0x0e7 ++#define Key_XF86MonBrightnessDown 0x0e8 ++#define Key_XF86MonBrightnessUp 0x0e9 ++#define Key_XF86AudioMedia 0x0ea ++#define Key_XF86Display 0x0eb ++#define Key_XF86KbdLightOnOff 0x0ec ++#define Key_XF86KbdBrightnessDown 0x0ed ++#define Key_XF86KbdBrightnessUp 0x0ee ++#define Key_XF86Send2 0x0ef ++#define Key_XF86Reply 0x0f0 ++#define Key_XF86MailForward 0x0f1 ++#define Key_XF86Save 0x0f2 ++#define Key_XF86Documents 0x0f3 ++#define Key_XF86Battery 0x0f4 ++#define Key_XF86Bluetooth 0x0f5 ++#define Key_XF86WLAN 0x0f6 ++#define Key_XF86UWB 0x0f7 ++#define Key_XF86Next_VMode2 0x0f9 ++#define Key_XF86Prev_VMode2 0x0fa ++#define Key_XF86MonBrightnessCycle 0x0fb ++#define Key_XF86BrightnessAuto 0x0fc ++#define Key_XF86DisplayOff 0x0fd ++#define Key_XF86WWAN 0x0fe ++#define Key_XF86RFKill 0x0ff ++#define Key_XF86AudioMicMute2 0x100 ++#define Key_XF86Info 0x16e ++#define Key_XF86Favorites2 0x174 ++#define Key_XF86CycleAngle 0x17b ++#define Key_XF86FullScreen 0x17c ++#define Key_XF86Keyboard 0x17e ++#define Key_XF86AspectRatio 0x17f ++#define Key_XF86DVD 0x18d ++#define Key_XF86Audio 0x190 ++#define Key_XF86Video 0x191 ++#define Key_XF86Calendar 0x195 ++#define Key_XF86ChannelUp 0x19a ++#define Key_XF86ChannelDown 0x19b ++#define Key_XF86AudioRandomPlay 0x1a2 ++#define Key_XF86Break 0x1a3 ++#define Key_XF86VideoPhone 0x1a8 ++#define Key_XF86Game2 0x1a9 ++#define Key_XF86ZoomIn 0x1aa ++#define Key_XF86ZoomOut 0x1ab ++#define Key_XF86ZoomReset 0x1ac ++#define Key_XF86Word 0x1ad ++#define Key_XF86Editor 0x1ae ++#define Key_XF86Excel 0x1af ++#define Key_XF86GraphicsEditor 0x1b0 ++#define Key_XF86Presentation 0x1b1 ++#define Key_XF86Database 0x1b2 ++#define Key_XF86News 0x1b3 ++#define Key_XF86Voicemail 0x1b4 ++#define Key_XF86Addressbook 0x1b5 ++#define Key_XF86Messenger2 0x1b6 ++#define Key_XF86DisplayToggle 0x1b7 ++#define Key_XF86SpellCheck 0x1b8 ++#define Key_XF86LogOff 0x1b9 ++#define Key_dollar2 0x1ba ++#define Key_EuroSign 0x1bb ++#define Key_XF86FrameBack 0x1bc ++#define Key_XF86FrameForward 0x1bd ++#define Key_XF86ContextMenu 0x1be ++#define Key_XF86MediaRepeat 0x1bf ++#define Key_XF8610ChannelsUp 0x1c0 ++#define Key_XF8610ChannelsDown 0x1c1 ++#define Key_XF86Images 0x1c2 ++#define Key_XF86NotificationCenter 0x1c4 ++#define Key_XF86PickupPhone 0x1c5 ++#define Key_XF86HangupPhone 0x1c6 ++#define Key_XF86Fn 0x1d8 ++#define Key_XF86Fn_Esc 0x1d9 ++#define Key_XF86FnRightShift 0x1ed ++#define Key_braille_dot_1 0x1f9 ++#define Key_braille_dot_2 0x1fa ++#define Key_braille_dot_3 0x1fb ++#define Key_braille_dot_4 0x1fc ++#define Key_braille_dot_5 0x1fd ++#define Key_braille_dot_6 0x1fe ++#define Key_braille_dot_7 0x1ff ++#define Key_braille_dot_8 0x200 ++#define Key_braille_dot_9 0x201 ++#define Key_braille_dot_1_2 0x202 ++#define Key_XF86Numeric0 0x208 ++#define Key_XF86Numeric1 0x209 ++#define Key_XF86Numeric2 0x20a ++#define Key_XF86Numeric3 0x20b ++#define Key_XF86Numeric4 0x20c ++#define Key_XF86Numeric5 0x20d ++#define Key_XF86Numeric6 0x20e ++#define Key_XF86Numeric7 0x20f ++#define Key_XF86Numeric8 0x210 ++#define Key_XF86Numeric9 0x211 ++#define Key_XF86NumericStar 0x212 ++#define Key_XF86NumericPound 0x213 ++#define Key_XF86NumericA 0x214 ++#define Key_XF86NumericB 0x215 ++#define Key_XF86NumericC 0x216 ++#define Key_XF86NumericD 0x217 ++#define Key_XF86CameraFocus 0x218 ++#define Key_XF86WPSButton 0x219 ++#define Key_XF86TouchpadToggle2 0x21a ++#define Key_XF86TouchpadOn2 0x21b ++#define Key_XF86TouchpadOff2 0x21c ++#define Key_XF86CameraZoomIn 0x21d ++#define Key_XF86CameraZoomOut 0x21e ++#define Key_XF86CameraUp 0x21f ++#define Key_XF86CameraDown 0x220 ++#define Key_XF86CameraLeft 0x221 ++#define Key_XF86CameraRight 0x222 ++#define Key_XF86AttendantOn 0x223 ++#define Key_XF86AttendantOff 0x224 ++#define Key_XF86AttendantToggle 0x225 ++#define Key_XF86LightsToggle 0x226 ++#define Key_XF86ALSToggle 0x238 ++#define Key_XF86RotationLockToggle 0x239 ++#define Key_XF86Buttonconfig 0x248 ++#define Key_XF86Taskmanager 0x249 ++#define Key_XF86Journal 0x24a ++#define Key_XF86ControlPanel 0x24b ++#define Key_XF86AppSelect 0x24c ++#define Key_XF86Screensaver 0x24d ++#define Key_XF86VoiceCommand 0x24e ++#define Key_XF86Assistant 0x24f ++#define Key_ISO_Next_Group 0x250 ++#define Key_XF86EmojiPicker 0x251 ++#define Key_XF86Dictate 0x252 ++#define Key_XF86CameraAccessEnable 0x253 ++#define Key_XF86CameraAccessDisable 0x254 ++#define Key_XF86CameraAccessToggle 0x255 ++#define Key_XF86BrightnessMin 0x258 ++#define Key_XF86BrightnessMax 0x259 ++#define Key_XF86KbdInputAssistPrev 0x268 ++#define Key_XF86KbdInputAssistNext 0x269 ++#define Key_XF86KbdInputAssistPrevgroup 0x26a ++#define Key_XF86KbdInputAssistNextgroup 0x26b ++#define Key_XF86KbdInputAssistAccept 0x26c ++#define Key_XF86KbdInputAssistCancel 0x26d ++#define Key_XF86RightUp 0x26e ++#define Key_XF86RightDown 0x26f ++#define Key_XF86LeftUp 0x270 ++#define Key_XF86LeftDown 0x271 ++#define Key_XF86RootMenu 0x272 ++#define Key_XF86MediaTopMenu 0x273 ++#define Key_XF86Numeric11 0x274 ++#define Key_XF86Numeric12 0x275 ++#define Key_XF86AudioDesc 0x276 ++#define Key_XF863DMode 0x277 ++#define Key_XF86NextFavorite 0x278 ++#define Key_XF86StopRecord 0x279 ++#define Key_XF86PauseRecord 0x27a ++#define Key_XF86VOD 0x27b ++#define Key_XF86Unmute 0x27c ++#define Key_XF86FastReverse 0x27d ++#define Key_XF86SlowReverse 0x27e ++#define Key_XF86Data 0x27f ++#define Key_XF86OnScreenKeyboard 0x280 ++#define Key_XF86PrivacyScreenToggle 0x281 ++#define Key_XF86SelectiveScreenshot 0x282 ++#define Key_XF86NextElement 0x283 ++#define Key_XF86PreviousElement 0x284 ++#define Key_XF86AutopilotEngageToggle 0x285 ++#define Key_XF86MarkWaypoint 0x286 ++#define Key_XF86Sos 0x287 ++#define Key_XF86NavChart 0x288 ++#define Key_XF86FishingChart 0x289 ++#define Key_XF86SingleRangeRadar 0x28a ++#define Key_XF86DualRangeRadar 0x28b ++#define Key_XF86RadarOverlay 0x28c ++#define Key_XF86TraditionalSonar 0x28d ++#define Key_XF86ClearvuSonar 0x28e ++#define Key_XF86SidevuSonar 0x28f ++#define Key_XF86NavInfo 0x290 ++#define Key_XF86BrightnessAdjust 0x291 ++#define Key_XF86Macro1 0x298 ++#define Key_XF86Macro2 0x299 ++#define Key_XF86Macro3 0x29a ++#define Key_XF86Macro4 0x29b ++#define Key_XF86Macro5 0x29c ++#define Key_XF86Macro6 0x29d ++#define Key_XF86Macro7 0x29e ++#define Key_XF86Macro8 0x29f ++#define Key_XF86Macro9 0x2a0 ++#define Key_XF86Macro10 0x2a1 ++#define Key_XF86Macro11 0x2a2 ++#define Key_XF86Macro12 0x2a3 ++#define Key_XF86Macro13 0x2a4 ++#define Key_XF86Macro14 0x2a5 ++#define Key_XF86Macro15 0x2a6 ++#define Key_XF86Macro16 0x2a7 ++#define Key_XF86Macro17 0x2a8 ++#define Key_XF86Macro18 0x2a9 ++#define Key_XF86Macro19 0x2aa ++#define Key_XF86Macro20 0x2ab ++#define Key_XF86Macro21 0x2ac ++#define Key_XF86Macro22 0x2ad ++#define Key_XF86Macro23 0x2ae ++#define Key_XF86Macro24 0x2af ++#define Key_XF86Macro25 0x2b0 ++#define Key_XF86Macro26 0x2b1 ++#define Key_XF86Macro27 0x2b2 ++#define Key_XF86Macro28 0x2b3 ++#define Key_XF86Macro29 0x2b4 ++#define Key_XF86Macro30 0x2b5 ++#define Key_XF86MacroRecordStart 0x2b8 ++#define Key_XF86MacroRecordStop 0x2b9 ++#define Key_XF86MacroPresetCycle 0x2ba ++#define Key_XF86MacroPreset1 0x2bb ++#define Key_XF86MacroPreset2 0x2bc ++#define Key_XF86MacroPreset3 0x2bd ++#define Key_XF86KbdLcdMenu1 0x2c0 ++#define Key_XF86KbdLcdMenu2 0x2c1 ++#define Key_XF86KbdLcdMenu3 0x2c2 ++#define Key_XF86KbdLcdMenu4 0x2c3 ++#define Key_XF86KbdLcdMenu5 0x2c4 +-- +2.48.0 + + +From 16c0b9be41ba111bf551fd2e5e2bdaa537c6990d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sun, 19 Mar 2023 15:50:07 -0600 +Subject: [PATCH 2/2] add program to generate keys.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + generate-keys.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + create mode 100644 generate-keys.c + +diff --git a/generate-keys.c b/generate-keys.c +new file mode 100644 +index 00000000..37655611 +--- /dev/null ++++ b/generate-keys.c +@@ -0,0 +1,95 @@ ++/****************************************************************** ++ * Copyright 2023-2024 Leonardo Hernández Hernández ++ * ++ * 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 ++ * OPEN GROUP 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. ++ * ++ ******************************************************************/ ++ ++/* cc -lxkbcommon -o generate-keys generate-keys.c */ ++ ++#define _DEFAULT_SOURCE ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++int ++main(void) ++{ ++ /* Allow generate keys with a different layout and variant. ++ * You can also use XKB_DEFAULT_* environmental variables and let this as is */ ++ struct xkb_rule_names rules = { ++ 0 ++ }; ++ struct xkb_context *context = NULL; ++ struct xkb_keymap *keymap = NULL; ++ xkb_keycode_t keycode, min_keycode, max_keycode; ++ xkb_layout_index_t layout, num_layouts; ++ xkb_level_index_t level, num_levels; ++ int i, nsyms; ++ const xkb_keysym_t *syms; ++ char keyname[64]; ++ bool ok = false; ++ FILE *file = fopen("keys.h", "w"); ++ if (!file) { ++ perror("Couldn't open keys.h"); ++ return EXIT_FAILURE; ++ } ++ ++ if (!(context = xkb_context_new(XKB_CONTEXT_NO_FLAGS))) { ++ fputs("Couldn't create xkbcommon context\n", stderr); ++ goto out; ++ } ++ ++ if (!(keymap = xkb_keymap_new_from_names(context, &rules, ++ XKB_KEYMAP_COMPILE_NO_FLAGS))) { ++ fputs("Couldn't create xkbcommon keymap\n", stderr); ++ goto out; ++ } ++ ++ min_keycode = xkb_keymap_min_keycode(keymap); ++ max_keycode = xkb_keymap_max_keycode(keymap); ++ ++ for (keycode = min_keycode; keycode <= max_keycode; keycode++) { ++ num_layouts = xkb_keymap_num_layouts_for_key(keymap, keycode); ++ for (layout = 0; layout < num_layouts; layout++) { ++ num_levels = xkb_keymap_num_levels_for_key(keymap, keycode, layout); ++ for (level = 0; level < num_levels; level++) { ++ nsyms = xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms); ++ for (i = 0; i < nsyms; i++) { ++ xkb_keysym_get_name(syms[i], keyname, sizeof(keyname) / sizeof(keyname[0])); ++ fprintf(file, "#define Key_%-27s %#05"PRIx32"\n", keyname, keycode); ++ } ++ } ++ } ++ } ++ ++ ok = true; ++ sync(); ++ ++out: ++ fclose(file); ++ xkb_keymap_unref(keymap); ++ xkb_context_unref(context); ++ return !ok; ++} +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/launchtag/README.md b/dwl/dwl-patches/patches/launchtag/README.md new file mode 100755 index 0000000..86ad447 --- /dev/null +++ b/dwl/dwl-patches/patches/launchtag/README.md @@ -0,0 +1,12 @@ +### Description +Straight port of the dwm taglayouts patch, renamed because I have a hard time +finding it on the suckless site. + +This patch allows you to set the default layout for each tag. + +This is intended to be applied on top of pertag. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/launchtag/launchtag.patch) +### Authors - latest at top +- [MayOrMayNotBeACat](https://codeberg.org/MayOrMayNotBeACat) diff --git a/dwl/dwl-patches/patches/launchtag/launchtag.patch b/dwl/dwl-patches/patches/launchtag/launchtag.patch new file mode 100755 index 0000000..c298fd6 --- /dev/null +++ b/dwl/dwl-patches/patches/launchtag/launchtag.patch @@ -0,0 +1,49 @@ +From e94f4b8363f4122f9b00f774a5b541a00c49fd35 Mon Sep 17 00:00:00 2001 +From: MayOrMayNotBeACat +Date: Fri, 6 Jun 2025 22:42:16 -0400 +Subject: [PATCH] Allow initial layout to be set per tag. + +--- + config.def.h | 1 + + dwl.c | 9 ++++++++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..8f2fade 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -16,6 +16,7 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) ++static int tag_layout[TAGCOUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; /* Modify as needed to match TAGCOUNT */ + + /* logging */ + static int log_level = WLR_ERROR; +diff --git a/dwl.c b/dwl.c +index d234cd2..da46816 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1045,11 +1045,18 @@ createmon(struct wl_listener *listener, void *data) + m->pertag->nmasters[i] = m->nmaster; + m->pertag->mfacts[i] = m->mfact; + +- m->pertag->ltidxs[i][0] = m->lt[0]; ++ if (i != 0) ++ m->pertag->ltidxs[i][0] = &layouts[tag_layout[i-1]]; ++ else ++ m->pertag->ltidxs[i][0] = m->lt[0]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + } + ++ m->lt[0] = m->pertag->ltidxs[1][0]; ++ m->lt[1] = m->pertag->ltidxs[1][1]; ++ strncpy(m->ltsymbol, m->pertag->ltidxs[1][0]->symbol, LENGTH(m->ltsymbol)); ++ + /* The xdg-protocol specifies: + * + * If the fullscreened surface is not opaque, the compositor must make +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/limitnmaster/README.md b/dwl/dwl-patches/patches/limitnmaster/README.md new file mode 100755 index 0000000..e750300 --- /dev/null +++ b/dwl/dwl-patches/patches/limitnmaster/README.md @@ -0,0 +1,8 @@ +### Description +Limits nmaster to within the range of currently-opened windows (nmaster will not change past the full horizontal split layout) + +### Download +- [2024-03-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/limitnmaster/limitnmaster.patch) + +### Authors +- [dev-gm](https://codeberg.org/dev-gm) diff --git a/dwl/dwl-patches/patches/limitnmaster/limitnmaster.patch b/dwl/dwl-patches/patches/limitnmaster/limitnmaster.patch new file mode 100755 index 0000000..f4339c8 --- /dev/null +++ b/dwl/dwl-patches/patches/limitnmaster/limitnmaster.patch @@ -0,0 +1,33 @@ +From 20c948398af900564a59007fc08d15eaa0b65da3 Mon Sep 17 00:00:00 2001 +From: Gavin M +Date: Fri, 15 Mar 2024 17:33:27 -0500 +Subject: [PATCH] Added limitnmaster + +--- + dwl.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index 5867b0c..210c41d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1391,9 +1391,15 @@ handlesig(int signo) + void + incnmaster(const Arg *arg) + { ++ unsigned int n = 0; ++ Client *c; ++ + if (!arg || !selmon) + return; +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) ++ n++; ++ selmon->nmaster = MIN(MAX(selmon->nmaster + arg->i, 0), n); + arrange(selmon); + } + +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/lockedkeys/README.md b/dwl/dwl-patches/patches/lockedkeys/README.md new file mode 100755 index 0000000..50f0fd2 --- /dev/null +++ b/dwl/dwl-patches/patches/lockedkeys/README.md @@ -0,0 +1,23 @@ +### Description +This patch allows you to add keybindings to the lockscreen. + +```c +static const Key lockedkeys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ + /* modifier key function argument */ + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ + { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, +#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } + CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), + CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), +}; +``` + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/lockedkeys) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/fc4146f3068dcd46035a2a11fe9d6109a97ae6d6/lockedkeys/lockedkeys.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/2a6560c167e5c9afc5598ac5431d23d90de8846c/lockedkeys/lockedkeys.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/lockedkeys/lockedkeys.patch b/dwl/dwl-patches/patches/lockedkeys/lockedkeys.patch new file mode 100755 index 0000000..f683536 --- /dev/null +++ b/dwl/dwl-patches/patches/lockedkeys/lockedkeys.patch @@ -0,0 +1,79 @@ +From 70dc03a3817b8fd933244c2db1bb849d9626b12b Mon Sep 17 00:00:00 2001 +From: wochap +Date: Thu, 11 Apr 2024 13:16:40 -0500 +Subject: [PATCH] allow to add keybindings in lockscreen + +--- + config.def.h | 11 +++++++++++ + dwl.c | 20 ++++++++++++++++++++ + 2 files changed, 31 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 8847e58..0d4a4f8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -164,6 +164,17 @@ static const Key keys[] = { + CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), + }; + ++static const Key lockedkeys[] = { ++ /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ ++ /* modifier key function argument */ ++ ++ /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ ++ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, ++#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } ++ CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), ++ CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), ++}; ++ + static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, + { MODKEY, BTN_MIDDLE, togglefloating, {0} }, +diff --git a/dwl.c b/dwl.c +index bf763df..db4bb2b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -287,6 +287,7 @@ static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); ++static int lockedkeybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); + static void keypressmod(struct wl_listener *listener, void *data); + static int keyrepeat(void *data); +@@ -1446,6 +1447,21 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + return 0; + } + ++int ++lockedkeybinding(uint32_t mods, xkb_keysym_t sym) ++{ ++ int handled = 0; ++ const Key *k; ++ for (k = lockedkeys; k < END(lockedkeys); k++) { ++ if (CLEANMASK(mods) == CLEANMASK(k->mod) && ++ sym == k->keysym && k->func) { ++ k->func(&k->arg); ++ handled = 1; ++ } ++ } ++ return handled; ++} ++ + void + keypress(struct wl_listener *listener, void *data) + { +@@ -1473,6 +1489,10 @@ keypress(struct wl_listener *listener, void *data) + handled = keybinding(mods, syms[i]) || handled; + } + ++ if (locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) ++ for (i = 0; i < nsyms; i++) ++ handled = lockedkeybinding(mods, syms[i]) || handled; ++ + if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { + group->mods = mods; + group->keysyms = syms; +-- +2.43.2 diff --git a/dwl/dwl-patches/patches/mastercolumn/README.md b/dwl/dwl-patches/patches/mastercolumn/README.md new file mode 100755 index 0000000..14db13c --- /dev/null +++ b/dwl/dwl-patches/patches/mastercolumn/README.md @@ -0,0 +1,16 @@ +### Description +This patch adds a layout, `mastercol`, in which the windows in the master area are arranged in columns of equal size. The number of columns is always nmaster + 1, and the last column is a stack of leftover windows (as in the normal tile layout). It effectively differs from the default tile layout only in that master windows are arranged horizontally rather than vertically. + +For gaps, apply `mastercolumn-gaps.patch` on top of `mastercolumn.patch` and `gaps.patch`. + +### Download +##### `mastercolumn.patch` +- [git branch](/shivers/dwl/src/branch/mastercolumn) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/mastercolumn/mastercolumn.patch) + +##### `mastercolumn-gaps.patch` +- [git branch](/shivers/dwl/src/branch/mastercolumn-gaps) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/mastercolumn/mastercolumn-gaps.patch) + +### Authors +- [shivers](https://codeberg.org/shivers) diff --git a/dwl/dwl-patches/patches/mastercolumn/mastercolumn-gaps.patch b/dwl/dwl-patches/patches/mastercolumn/mastercolumn-gaps.patch new file mode 100755 index 0000000..943c4bd --- /dev/null +++ b/dwl/dwl-patches/patches/mastercolumn/mastercolumn-gaps.patch @@ -0,0 +1,63 @@ +From b6f2ee09778cdea8a1450d16bcf24a8a75e10b40 Mon Sep 17 00:00:00 2001 +From: moe +Date: Tue, 16 Jul 2024 13:56:24 -0400 +Subject: [PATCH 1/1] add mastercolumn gaps + +--- + dwl.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/dwl.c b/dwl.c +index b121094..be33c01 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1755,7 +1755,7 @@ unset_fullscreen: + void + mastercol(Monitor *m) + { +- unsigned int mw, mx, ty; ++ unsigned int h, w, r, e = m->gaps, mw, mx, ty; + int i, n = 0; + Client *c; + +@@ -1764,23 +1764,30 @@ mastercol(Monitor *m) + n++; + if (n == 0) + return; ++ if (smartgaps == n) ++ e = 0; + + if (n > m->nmaster) +- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; ++ mw = m->nmaster ? (int)roundf((m->w.width + gappx*e) * m->mfact) : 0; + else + mw = m->w.width; +- i = mx = ty = 0; ++ i = 0; ++ mx = ty = gappx*e; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y, +- .width = (mw - mx) / (MIN(n, m->nmaster) - i), .height = m->w.height}, 0); +- mx += c->geom.width; ++ r = MIN(n, m->nmaster) - i; ++ w = (mw - mx - gappx*e - gappx*e * (r - 1)) / r; ++ resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y + gappx*e, ++ .width = w, .height = m->w.height - 2*gappx*e}, 0); ++ mx += c->geom.width + gappx*e; + } else { ++ r = n - i; ++ h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r; + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); +- ty += c->geom.height; ++ .width = m->w.width - mw - gappx*e, .height = h}, 0); ++ ty += c->geom.height + gappx*e; + } + i++; + } +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/mastercolumn/mastercolumn.patch b/dwl/dwl-patches/patches/mastercolumn/mastercolumn.patch new file mode 100755 index 0000000..425e414 --- /dev/null +++ b/dwl/dwl-patches/patches/mastercolumn/mastercolumn.patch @@ -0,0 +1,87 @@ +From eb0c6ff53ba823f26d13f18627a084959c353627 Mon Sep 17 00:00:00 2001 +From: moe +Date: Sat, 10 Aug 2024 15:58:15 -0400 +Subject: [PATCH] add mastercolumn layout + +--- + config.def.h | 2 ++ + dwl.c | 36 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..68b27a7 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "||=", mastercol }, + }; + + /* monitors */ +@@ -139,6 +140,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index a2711f6..49f65ba 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -301,6 +301,7 @@ static int keyrepeat(void *data); + static void killclient(const Arg *arg); + static void locksession(struct wl_listener *listener, void *data); + static void mapnotify(struct wl_listener *listener, void *data); ++static void mastercol(Monitor *m); + static void maximizenotify(struct wl_listener *listener, void *data); + static void monocle(Monitor *m); + static void motionabsolute(struct wl_listener *listener, void *data); +@@ -1748,6 +1749,41 @@ unset_fullscreen: + } + } + ++void ++mastercol(Monitor *m) ++{ ++ unsigned int mw, mx, ty; ++ int i, n = 0; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ if (n == 0) ++ return; ++ ++ if (n > m->nmaster) ++ mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; ++ else ++ mw = m->w.width; ++ i = mx = ty = 0; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (i < m->nmaster) { ++ resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y, ++ .width = (mw - mx) / (MIN(n, m->nmaster) - i), .height = m->w.height}, 0); ++ mx += c->geom.width; ++ } else { ++ resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, ++ .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); ++ ty += c->geom.height; ++ } ++ i++; ++ } ++} ++ ++ + void + maximizenotify(struct wl_listener *listener, void *data) + { +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/menu/README.md b/dwl/dwl-patches/patches/menu/README.md new file mode 100755 index 0000000..ad37016 --- /dev/null +++ b/dwl/dwl-patches/patches/menu/README.md @@ -0,0 +1,18 @@ +### Description + +This patch adds `menu` command, which allows dwl to interface with dmenu-like +programs. + +By default, two menus are available: +- focusing a window by its title/appid by pressing `Alt+o` +- selecting a layout from a list by pressing `Alt+Shift+o` + +Edit `menus` array in `config.h` to add/change menus and use a different dmenu +program (`wmenu` is the default). + +### Download +- [2025-03-21 v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/menu/menu.patch) +- [2024-07-13 v0.7](https://codeberg.org/dwl/dwl-patches/raw/commit/65ea99519bbf7a52f48932aea7385f81f8b30867/patches/menu/menu.patch) + +### Authors +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) diff --git a/dwl/dwl-patches/patches/menu/menu.patch b/dwl/dwl-patches/patches/menu/menu.patch new file mode 100755 index 0000000..c1dea4d --- /dev/null +++ b/dwl/dwl-patches/patches/menu/menu.patch @@ -0,0 +1,227 @@ +From da9861cf0448ca94011470634fd61c3ef2129a25 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Fri, 21 Mar 2025 21:48:42 +0100 +Subject: [PATCH] Add menu command + +--- + config.def.h | 8 +++ + dwl.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 164 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..a5914ca 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,12 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + /* logging */ + static int log_level = WLR_ERROR; + ++static const Menu menus[] = { ++ /* command feed function action function */ ++ { "wmenu -i -l 10 -p Windows", menuwinfeed, menuwinaction }, ++ { "wmenu -i -p Layouts", menulayoutfeed, menulayoutaction }, ++}; ++ + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ +@@ -140,6 +146,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY, XKB_KEY_o, menu, {.v = &menus[0]} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, menu, {.v = &menus[1]} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, +diff --git a/dwl.c b/dwl.c +index def2562..b0e8310 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -242,6 +242,12 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++typedef struct { ++ const char *cmd; /* command to run a menu */ ++ void (*feed)(FILE *f); /* feed input to menu */ ++ void (*action)(char *line); /* do action based on menu output */ ++} Menu; ++ + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -302,6 +308,12 @@ static void killclient(const Arg *arg); + static void locksession(struct wl_listener *listener, void *data); + static void mapnotify(struct wl_listener *listener, void *data); + static void maximizenotify(struct wl_listener *listener, void *data); ++static void menu(const Arg *arg); ++static int menuread(int fd, uint32_t mask, void *data); ++static void menuwinfeed(FILE *f); ++static void menuwinaction(char *line); ++static void menulayoutfeed(FILE *f); ++static void menulayoutaction(char *line); + static void monocle(Monitor *m); + static void motionabsolute(struct wl_listener *listener, void *data); + static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, +@@ -413,6 +425,11 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static const Menu *menu_current; ++static int menu_fd; ++static pid_t menu_pid; ++static struct wl_event_source *menu_source; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -1768,6 +1785,145 @@ maximizenotify(struct wl_listener *listener, void *data) + wlr_xdg_surface_schedule_configure(c->surface.xdg); + } + ++void ++menu(const Arg *arg) ++{ ++ FILE *f; ++ int fd_right[2], fd_left[2]; ++ ++ if (menu_current != NULL) { ++ wl_event_source_remove(menu_source); ++ close(menu_fd); ++ kill(menu_pid, SIGTERM); ++ menu_current = NULL; ++ if (!arg->v) ++ return; ++ } ++ ++ if (pipe(fd_right) == -1 || pipe(fd_left) == -1) ++ return; ++ if ((menu_pid = fork()) == -1) ++ return; ++ if (menu_pid == 0) { ++ close(fd_right[1]); ++ close(fd_left[0]); ++ dup2(fd_right[0], STDIN_FILENO); ++ close(fd_right[0]); ++ dup2(fd_left[1], STDOUT_FILENO); ++ close(fd_left[1]); ++ execl("/bin/sh", "/bin/sh", "-c", ((Menu *)(arg->v))->cmd, NULL); ++ die("dwl: execl %s failed:", "/bin/sh"); ++ } ++ ++ close(fd_right[0]); ++ close(fd_left[1]); ++ menu_fd = fd_left[0]; ++ if (fd_set_nonblock(menu_fd) == -1) ++ return; ++ if (!(f = fdopen(fd_right[1], "w"))) ++ return; ++ menu_current = arg->v; ++ menu_current->feed(f); ++ fclose(f); ++ menu_source = wl_event_loop_add_fd(event_loop, ++ menu_fd, WL_EVENT_READABLE, menuread, NULL); ++} ++ ++int ++menuread(int fd, uint32_t mask, void *data) ++{ ++ char *s; ++ int n; ++ static char line[512]; ++ static int i = 0; ++ ++ if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) { ++ i = 0; ++ menu(&(const Arg){ .v = NULL }); ++ return 0; ++ } ++ if ((n = read(menu_fd, line + i, LENGTH(line) - 1 - i)) == -1) { ++ if (errno != EAGAIN) { ++ i = 0; ++ menu(&(const Arg){ .v = NULL }); ++ } ++ return 0; ++ } ++ line[i + n] = '\0'; ++ if (!(s = strchr(line + i, '\n'))) { ++ i += n; ++ return 0; ++ } ++ i = 0; ++ *s = '\0'; ++ menu_current->action(line); ++ return 0; ++} ++ ++void ++menuwinfeed(FILE *f) ++{ ++ Client *c; ++ const char *title, *appid; ++ ++ wl_list_for_each(c, &fstack, flink) { ++ if (!(title = client_get_title(c))) ++ continue; ++ fprintf(f, "%s", title); ++ if ((appid = client_get_appid(c))) ++ fprintf(f, " | %s", appid); ++ fputc('\n', f); ++ } ++} ++ ++void ++menuwinaction(char *line) ++{ ++ Client *c; ++ const char *appid, *title; ++ static char buf[512]; ++ ++ wl_list_for_each(c, &fstack, flink) { ++ if (!(title = client_get_title(c))) ++ continue; ++ appid = client_get_appid(c); ++ snprintf(buf, LENGTH(buf) - 1, "%s%s%s", ++ title, appid ? " | " : "", appid ? appid : ""); ++ if (strcmp(line, buf) == 0) ++ goto found; ++ } ++ return; ++ ++found: ++ if (!c->mon) ++ return; ++ wl_list_remove(&c->flink); ++ wl_list_insert(&fstack, &c->flink); ++ selmon = c->mon; ++ view(&(const Arg){ .ui = c->tags }); ++} ++ ++void ++menulayoutfeed(FILE *f) ++{ ++ const Layout *l; ++ for (l = layouts; l < END(layouts); l++) ++ fprintf(f, "%s\n", l->symbol); ++} ++ ++void ++menulayoutaction(char *line) ++{ ++ const Layout *l; ++ for (l = layouts; l < END(layouts); l++) ++ if (strcmp(line, l->symbol) == 0) ++ goto found; ++ return; ++ ++found: ++ setlayout(&(const Arg){ .v = l }); ++} ++ + void + monocle(Monitor *m) + { +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/menurule/README.md b/dwl/dwl-patches/patches/menurule/README.md new file mode 100755 index 0000000..8d8b757 --- /dev/null +++ b/dwl/dwl-patches/patches/menurule/README.md @@ -0,0 +1,70 @@ +### Description + +This patch adds a dmenu interface to [setrule][setrule], which allows to add or +change client rules at runtime. It must be applied on top of [setrule][setrule] +and [menu][menu] patches. + +You can invoke the menu by pressing `Alt+R`. The menu lists all the rules, plus +a shortcut to define a new one that would apply to the currently focused client +(marked with `(NEW)`). Rules that already apply to the focused client are marked +with `<`. + +![menurule in action](menurule.png) + +To edit a rule, you need to select it, press `Tab`, change what you need and +finally press `Enter`. You can remove a rule by prepending it with `-`. To add a +new rule, just put new values into `[appid|title]`. + +To add support for new rules, you need to edit `fprintf` and `sscanf` calls in +`menurulefeed` and `menuruleaction` functions respectively. + +For example, this is what I did to add support for [swallow][swallow] patch +rules. + +```diff +diff --git a/dwl.c b/dwl.c +index 34397fc..f1b31ea 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2441,10 +2441,14 @@ menurulefeed(FILE *f) + fprintf(f, "%-*s " + " tags:%-4"PRIi32 + " isfloating:%-2d" ++ " isterm:%-2d" ++ " noswallow:%-2d" + " monitor:%-2d" + "%s\n", wid, buf, + r->tags, + r->isfloating, ++ r->isterm, ++ r->noswallow, + r->monitor, + (r == &t) ? " (NEW)" : match ? " <" : ""); + } +@@ -2465,10 +2469,14 @@ menuruleaction(char *line) + sscanf(line, "[%255[^|]|%255[^]]]" + " tags:%"SCNu32 + " isfloating:%d" ++ " isterm:%d" ++ " noswallow:%d" + " monitor:%d" + "%n", appid, title, + &r.tags, + &r.isfloating, ++ &r.isterm, ++ &r.noswallow, + &r.monitor, + &end); +``` + +[setrule]: /dwl/dwl-patches/src/branch/main/patches/setrule +[menu]: /dwl/dwl-patches/src/branch/main/patches/menu +[swallow]: /dwl/dwl-patches/src/branch/main/patches/swallow + +### Download + +- [v0.7](/dwl/dwl-patches/raw/branch/main/patches/menurule/menurule.patch) + +### Authors + +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) diff --git a/dwl/dwl-patches/patches/menurule/menurule.patch b/dwl/dwl-patches/patches/menurule/menurule.patch new file mode 100755 index 0000000..b74a600 --- /dev/null +++ b/dwl/dwl-patches/patches/menurule/menurule.patch @@ -0,0 +1,167 @@ +From 7b578d9f4647d84f79a2e8a46a1c65cbacf8d90b Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Wed, 19 Mar 2025 02:28:46 +0100 +Subject: [PATCH] Add menurule to tweak rules at runtime + +--- + config.def.h | 2 + + dwl.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 118 insertions(+) + +diff --git a/config.def.h b/config.def.h +index e03a754..77b10ff 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -24,6 +24,7 @@ static const Menu menus[] = { + /* command feed function action function */ + { "wmenu -i -l 10 -p Windows", menuwinfeed, menuwinaction }, + { "wmenu -i -p Layouts", menulayoutfeed, menulayoutaction }, ++ { "wmenu -i -l 10 -p Rules", menurulefeed, menuruleaction }, + }; + + /* Max amount of dynamically added rules */ +@@ -151,6 +152,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY, XKB_KEY_o, menu, {.v = &menus[0]} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, menu, {.v = &menus[1]} }, ++ { MODKEY, XKB_KEY_r, menu, {.v = &menus[2]} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, setruleisfloating,{0} }, +diff --git a/dwl.c b/dwl.c +index be007d8..df4901f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -316,6 +316,8 @@ static void menuwinfeed(FILE *f); + static void menuwinaction(char *line); + static void menulayoutfeed(FILE *f); + static void menulayoutaction(char *line); ++static void menurulefeed(FILE *f); ++static void menuruleaction(char *line); + static void monocle(Monitor *m); + static void motionabsolute(struct wl_listener *listener, void *data); + static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, +@@ -1974,6 +1976,120 @@ found: + setlayout(&(const Arg){ .v = l }); + } + ++void ++menurulefeed(FILE *f) ++{ ++ Rule t, *p, *r; ++ const char *appid, *title; ++ static char buf[515]; ++ Client *c = focustop(selmon); ++ int n, wid = 0, match; ++ ++ t = (Rule){ 0 }; ++ t.monitor = -1; ++ if (c) { ++ t.id = client_get_appid(c); ++ t.title = client_get_title(c); ++ appid = t.id ? t.id : broken; ++ title = t.title ? t.title : broken; ++ } ++ ++ for (p = drules; p <= drules + druleslen; p++) { ++ r = (p == drules + druleslen) ? &t : p; ++ n = 0; ++ n += strlen(r->id ? r->id : "NULL"); ++ n += strlen(r->title ? r->title : "NULL"); ++ n += 3; ++ wid = MAX(wid, n); ++ } ++ wid = MIN(wid, 40); ++ ++ for (p = drules; p <= drules + druleslen; p++) { ++ match = 0; ++ /* Check if rule applies to the focused client */ ++ if (c && p < drules + druleslen) { ++ match = (!p->title || strstr(title, p->title)) ++ && (!p->id || strstr(appid, p->id)); ++ if (match && p->id) ++ t.id = NULL; ++ if (match && p->title) ++ t.title = NULL; ++ } ++ r = (p == drules + druleslen) ? &t : p; ++ if (r == &t && t.id) ++ t.title = NULL; ++ /* Do not suggest to add a new empty rule */ ++ if (r == &t && !(t.id || t.title)) ++ continue; ++ if (r->id && r->title && ++ strcmp(r->id, "removedrule") == 0 && strcmp(r->title, "removedrule") == 0) ++ continue; ++ snprintf(buf, LENGTH(buf) - 1, "[%s|%s]", ++ r->id ? r->id : "NULL", r->title ? r->title : "NULL"); ++ fprintf(f, "%-*s " ++ " tags:%-4"PRIi32 ++ " isfloating:%-2d" ++ " monitor:%-2d" ++ "%s\n", wid, buf, ++ r->tags, ++ r->isfloating, ++ r->monitor, ++ (r == &t) ? " (NEW)" : match ? " <" : ""); ++ } ++} ++ ++void ++menuruleaction(char *line) ++{ ++ Rule r, *f; ++ static char appid[256], title[256]; ++ int del = 0, end; ++ ++ if (line[0] == '-') { ++ del = 1; ++ line++; ++ } ++ end = 0; ++ sscanf(line, "[%255[^|]|%255[^]]]" ++ " tags:%"SCNu32 ++ " isfloating:%d" ++ " monitor:%d" ++ "%n", appid, title, ++ &r.tags, ++ &r.isfloating, ++ &r.monitor, ++ &end); ++ ++ /* Full line was not parsed, exit */ ++ if (!end) ++ return; ++ ++ r.id = (strcmp(appid, "NULL") != 0) ? appid : NULL; ++ r.title = (strcmp(title, "NULL") != 0) ? title : NULL; ++ ++ /* Find which rule we are trying to edit */ ++ for (f = drules; f < drules + druleslen; f++) ++ if (((!r.title && !f->title) || (r.title && f->title && !strcmp(r.title, f->title))) ++ && (((!r.id && !f->id) || (r.id && f->id && !strcmp(r.id, f->id))))) ++ goto found; ++ ++ if (druleslen >= LENGTH(rules) + RULES_MAX) ++ return; /* No free slots left */ ++ ++ f = drules + druleslen++; ++ f->id = r.id ? strdup(r.id) : NULL; ++ f->title = r.title ? strdup(r.title) : NULL; ++ ++found: ++ if (del) { ++ f->id = f->title = "removedrule"; ++ return; ++ } ++ r.id = f->id; ++ r.title = f->title; ++ *f = r; ++} ++ + void + monocle(Monitor *m) + { +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/menurule/menurule.png b/dwl/dwl-patches/patches/menurule/menurule.png new file mode 100755 index 0000000..20faac2 Binary files /dev/null and b/dwl/dwl-patches/patches/menurule/menurule.png differ diff --git a/dwl/dwl-patches/patches/meson/README.md b/dwl/dwl-patches/patches/meson/README.md new file mode 100755 index 0000000..4641bbf --- /dev/null +++ b/dwl/dwl-patches/patches/meson/README.md @@ -0,0 +1,19 @@ +### Description +Add the meson build system. + +This is useful for people who do not want to self-manage a wlroots installation. + +To enable Xwayland support, you will need to enable it in the wlroots subproject: +```sh +meson setup -Dwlroots:xwayland=enabled build +``` +It is also reccomended to see the wlroots meson project configuration logs for any +unusual checks, such as requiring `hwdata` for the DRM backend. + +### Download +- [git branch](/sewn/dwl/src/branch/meson) +- [2024-12-07](/dwl/dwl-patches/raw/branch/main/patches/meson/meson.patch) + +### Authors +- [sewn](/sewn) + diff --git a/dwl/dwl-patches/patches/meson/meson.patch b/dwl/dwl-patches/patches/meson/meson.patch new file mode 100755 index 0000000..6d78036 --- /dev/null +++ b/dwl/dwl-patches/patches/meson/meson.patch @@ -0,0 +1,135 @@ +From 136cdeb302fdfe28e5cd5c6a1693b05c3d1bfb58 Mon Sep 17 00:00:00 2001 +From: sewn +Date: Sat, 7 Dec 2024 09:59:01 +0300 +Subject: [PATCH] add meson + +--- + .gitignore | 1 + + meson.build | 93 ++++++++++++++++++++++++++++++++++++++++ + subprojects/wlroots.wrap | 5 +++ + 3 files changed, 99 insertions(+) + create mode 100644 meson.build + create mode 100644 subprojects/wlroots.wrap + +diff --git a/.gitignore b/.gitignore +index 0dde90e..9246a31 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -4,3 +4,4 @@ dwl + *-protocol.h + .ccls-cache + config.h ++subprojects/wlroots +diff --git a/meson.build b/meson.build +new file mode 100644 +index 0000000..e2219ec +--- /dev/null ++++ b/meson.build +@@ -0,0 +1,93 @@ ++project( ++ 'dwl', ++ 'c', ++ version: run_command('git', 'describe', '--tags', '--dirty', check: false).stdout().strip(), ++ license: [ 'GPL-3.0-only', 'CC0-1.0', 'MIT' ], ++ meson_version: '>=1.3', ++ default_options: [ ++ 'c_std=c99', ++ 'warning_level=2', ++ ], ++) ++ ++configure_file( ++ input: 'config.def.h', ++ output: 'config.h', ++ copy: true, ++ install_dir: '.', ++) ++ ++cc = meson.get_compiler('c') ++ ++add_project_arguments([ ++ '-DWLR_USE_UNSTABLE', ++ '-D_POSIX_C_SOURCE=200809L', ++ '-DVERSION="@0@"'.format(meson.project_version()), ++ ++ '-Wno-unused-parameter', ++], language: 'c') ++ ++wlroots = subproject('wlroots', ++ default_options: [ ++ 'backends=drm,libinput,auto', ++ 'default_library=static', ++ 'examples=false', ++ 'session=enabled', ++ ], ++) ++wlroots_has_xwlr = wlroots.get_variable('features').get('xwayland') ++ ++libinput = dependency('libinput') ++math = cc.find_library('m') ++wayland_server = dependency('wayland-server') ++xcb = dependency('xcb', required: wlroots_has_xwlr) ++xcb_icccm = dependency('xcb-icccm', required: wlroots_has_xwlr) ++xkbcommon = dependency('xkbcommon') ++ ++dwl_deps = [ ++ libinput, ++ math, ++ wayland_server, ++ wlroots.get_variable('wlroots'), ++ xkbcommon, ++] ++ ++if wlroots_has_xwlr ++ add_project_arguments('-DXWAYLAND', language: 'c') ++ dwl_deps += [ xcb, xcb_icccm ] ++endif ++ ++wayland_protos = dependency('wayland-protocols') ++wayland_scanner = dependency('wayland-scanner') ++wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir') ++wayland_scanner_prog = find_program( ++ wayland_scanner.get_variable('wayland_scanner'), ++ native: true, ++) ++ ++protocols = [ ++ wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', ++ wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', ++ 'protocols/wlr-layer-shell-unstable-v1.xml', ++ 'protocols/wlr-output-power-management-unstable-v1.xml', ++ wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', ++] ++protocols_src = [] ++ ++wayland_scanner_server = generator( ++ wayland_scanner_prog, ++ output: '@BASENAME@-protocol.h', ++ arguments: ['server-header', '@INPUT@', '@OUTPUT@'], ++) ++ ++foreach xml : protocols ++ protocols_src += wayland_scanner_server.process(xml) ++endforeach ++ ++executable( ++ 'dwl', ++ [ 'dwl.c', 'util.c', protocols_src ], ++ include_directories: [include_directories('.')], ++ dependencies: dwl_deps, ++ install: true, ++) +diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap +new file mode 100644 +index 0000000..3d9cbfa +--- /dev/null ++++ b/subprojects/wlroots.wrap +@@ -0,0 +1,5 @@ ++[wrap-git] ++url = https://gitlab.freedesktop.org/wlroots/wlroots.git ++revision = master ++depth = 1 ++clone-recursive = true +-- +2.47.1 + diff --git a/dwl/dwl-patches/patches/minimalborders/README.md b/dwl/dwl-patches/patches/minimalborders/README.md new file mode 100755 index 0000000..2a670c9 --- /dev/null +++ b/dwl/dwl-patches/patches/minimalborders/README.md @@ -0,0 +1,34 @@ +### Description +Dynamically adjusts the borders between adjacent windows to make them visually merge + +**NOTE:** to disable minimalborders after applying this patch, set `draw_minimal_borders` to `0` + +```c +static const int draw_minimal_borders = 0; /* disable minimalborders */ +``` + +
+Preview: +
+with:
+
+```c
+static const unsigned int borderpx         = 10;  /* border pixel of windows */
+```
+
+Before applying the patch
+
+
+After applying the patch
+
+
+
+ +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/minimalborders) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/minimalborders/minimalborders.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/7a5c3420822074c544fa102e030b7c30aa6b6be8/minimalborders/minimalborders.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/be3735bc6a5c64ff76c200a8679453bd179be456/minimalborders/minimalborders.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/minimalborders/minimalborders.patch b/dwl/dwl-patches/patches/minimalborders/minimalborders.patch new file mode 100755 index 0000000..cb19900 --- /dev/null +++ b/dwl/dwl-patches/patches/minimalborders/minimalborders.patch @@ -0,0 +1,161 @@ +From ce0eb92fb100801f343fbe9b76639847a9e39160 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 5 Jul 2024 11:22:57 -0500 +Subject: [PATCH] implement minimalborders + +--- + config.def.h | 1 + + dwl.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 72 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..0322dbf 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,7 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const int draw_minimal_borders = 1; /* merge adjacent borders */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); +diff --git a/dwl.c b/dwl.c +index dc0437e..198061b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -106,6 +106,7 @@ typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ + unsigned int type; /* XDGShell or X11* */ ++ int interact; + struct wlr_box geom; /* layout-relative, includes border */ + Monitor *mon; + struct wlr_scene_tree *scene; +@@ -316,7 +317,8 @@ static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); +-static void resize(Client *c, struct wlr_box geo, int interact); ++static void resizeapply(Client *c, struct wlr_box geo, int interact); ++static void resizenoapply(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); +@@ -408,6 +410,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static void (*resize)(Client *c, struct wlr_box geo, int interact) = resizeapply; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -476,6 +480,35 @@ applyrules(Client *c) + setmon(c, mon, newtags); + } + ++void ++applyminimalborders(Client *c, Monitor *m) ++{ ++ struct wlr_box geom = c->geom; ++ ++ geom.x -= borderpx; ++ geom.width += borderpx; ++ geom.y -= borderpx; ++ geom.height += borderpx; ++ ++ if (geom.x < m->w.x) { ++ geom.x += borderpx; ++ geom.width -= borderpx; ++ } ++ if (geom.x + geom.width > m->w.width - (int)borderpx) { ++ geom.width -= borderpx; ++ } ++ ++ if (geom.y < m->w.y) { ++ geom.y += borderpx; ++ geom.height -= borderpx; ++ } ++ if (geom.y + geom.height > m->w.height - (int)borderpx) { ++ geom.height -= borderpx; ++ } ++ ++ resize(c, geom, 0); ++} ++ + void + arrange(Monitor *m) + { +@@ -510,8 +543,28 @@ arrange(Monitor *m) + : c->scene->node.parent); + } + +- if (m->lt[m->sellt]->arrange) +- m->lt[m->sellt]->arrange(m); ++ if (m->lt[m->sellt]->arrange) { ++ if (draw_minimal_borders) { ++ int save_width = m->w.width; ++ int save_height = m->w.height; ++ m->w.width += borderpx; ++ m->w.height += borderpx; ++ resize = resizenoapply; ++ m->lt[m->sellt]->arrange(m); ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ if (draw_minimal_borders) ++ applyminimalborders(c, m); ++ resizeapply(c, c->geom, c->interact); ++ } ++ m->w.width = save_width; ++ m->w.height = save_height; ++ resize = resizeapply; ++ } else { ++ m->lt[m->sellt]->arrange(m); ++ } ++ } + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + } +@@ -1962,8 +2015,13 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + struct timespec now; + + if (surface != seat->pointer_state.focused_surface && +- sloppyfocus && time && c && !client_is_unmanaged(c)) +- focusclient(c, 0); ++ sloppyfocus && time && c && !client_is_unmanaged(c)) { ++ if (c->isfloating || c->isfullscreen) { ++ focusclient(c, 0); ++ } else { ++ focusclient(c, 1); ++ } ++ } + + /* If surface is NULL, clear pointer focus */ + if (!surface) { +@@ -2128,7 +2186,7 @@ requestmonstate(struct wl_listener *listener, void *data) + } + + void +-resize(Client *c, struct wlr_box geo, int interact) ++resizeapply(Client *c, struct wlr_box geo, int interact) + { + struct wlr_box *bbox; + struct wlr_box clip; +@@ -2160,6 +2218,13 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + } + ++void ++resizenoapply(Client *c, struct wlr_box geo, int interact) ++{ ++ c->geom = geo; ++ c->interact = interact; ++} ++ + void + run(char *startup_cmd) + { +-- +2.45.1 diff --git a/dwl/dwl-patches/patches/modes/README.md b/dwl/dwl-patches/patches/modes/README.md new file mode 100755 index 0000000..c855af9 --- /dev/null +++ b/dwl/dwl-patches/patches/modes/README.md @@ -0,0 +1,35 @@ +### Description +Implement modes, that way each mapping is associated with a mode and is only active while in that mode, default mode is `NORMAL` + +### Example + +In the example below, you declare a mode: `BROWSER`, which is activated when you press modkey + b. Then, you can press f to launch `Firefox` and return to the default `NORMAL` mode. + +```c +enum { + BROWSER, +}; +const char *modes_labels[] = { + "browser", +}; + +static const Key keys[] = { + // ... + { MODKEY, XKB_KEY_b, entermode, {.i = BROWSER} }, + // ... +}; + +static const Modekey modekeys[] = { + /* mode modifier key function argument */ + { BROWSER, { 0, XKB_KEY_f, spawn, SHCMD("firefox") } }, + { BROWSER, { 0, XKB_KEY_f, entermode, {.i = NORMAL} } }, + { BROWSER, { 0, XKB_KEY_Escape, entermode, {.i = NORMAL} } }, +}; +``` + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/modes) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/modes/modes.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/modes/modes.patch b/dwl/dwl-patches/patches/modes/modes.patch new file mode 100755 index 0000000..5ecf846 --- /dev/null +++ b/dwl/dwl-patches/patches/modes/modes.patch @@ -0,0 +1,165 @@ +From a32b85018ff2cea0fc9f9137789860a4aadc3b3a Mon Sep 17 00:00:00 2001 +From: wochap +Date: Wed, 6 Mar 2024 07:31:17 -0500 +Subject: [PATCH] implement modes + +like sway/river modes +--- + config.def.h | 20 ++++++++++++++++++++ + dwl.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 66 insertions(+) + +diff --git a/config.def.h b/config.def.h +index db0babc..1616136 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,6 +13,13 @@ static const float urgentcolor[] = COLOR(0xff0000ff); + /* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can also use glsl colors */ + ++enum { ++ BROWSER, ++}; ++const char *modes_labels[] = { ++ "browser", ++}; ++ + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + +@@ -152,6 +159,8 @@ static const Key keys[] = { + TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + ++ { MODKEY, XKB_KEY_b, entermode, {.i = BROWSER} }, ++ + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ + { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, + /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is +@@ -162,6 +171,17 @@ static const Key keys[] = { + CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), + }; + ++static const Modekey modekeys[] = { ++ /* mode modifier key function argument */ ++ { BROWSER, { 0, XKB_KEY_f, spawn, SHCMD("firefox") } }, ++ { BROWSER, { 0, XKB_KEY_f, entermode, {.i = NORMAL} } }, ++ { BROWSER, { 0, XKB_KEY_b, spawn, SHCMD("brave") } }, ++ { BROWSER, { 0, XKB_KEY_b, entermode, {.i = NORMAL} } }, ++ { BROWSER, { 0, XKB_KEY_g, spawn, SHCMD("google-chrome-stable") } }, ++ { BROWSER, { 0, XKB_KEY_g, entermode, {.i = NORMAL} } }, ++ { BROWSER, { 0, XKB_KEY_Escape, entermode, {.i = NORMAL} } }, ++}; ++ + static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, + { MODKEY, BTN_MIDDLE, togglefloating, {0} }, +diff --git a/dwl.c b/dwl.c +index ef27a1d..1ada006 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -139,6 +139,11 @@ typedef struct { + const Arg arg; + } Key; + ++typedef struct { ++ int mode_index; ++ Key key; ++} Modekey; ++ + typedef struct { + struct wl_list link; + struct wlr_keyboard *wlr_keyboard; +@@ -270,6 +275,7 @@ static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); ++static int modekeybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); + static void keypressmod(struct wl_listener *listener, void *data); + static int keyrepeat(void *data); +@@ -327,6 +333,7 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void entermode(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +@@ -377,6 +384,9 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static const int NORMAL = -1; ++static int active_mode_index = NORMAL; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -1372,6 +1382,11 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + */ + int handled = 0; + const Key *k; ++ ++ if (active_mode_index >= 0) { ++ return modekeybinding(mods, sym); ++ } ++ + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) && + sym == k->keysym && k->func) { +@@ -1382,6 +1397,29 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + return handled; + } + ++int ++modekeybinding(uint32_t mods, xkb_keysym_t sym) ++{ ++ int handled = 0; ++ const Modekey *mk; ++ const Key *k; ++ ++ for (mk = modekeys; mk < END(modekeys); mk++) { ++ if (active_mode_index != mk->mode_index) { ++ continue; ++ } ++ ++ k = &mk->key; ++ if (CLEANMASK(mods) == CLEANMASK(k->mod) && ++ sym == k->keysym && k->func) { ++ k->func(&k->arg); ++ handled = 1; ++ } ++ } ++ ++ return handled; ++} ++ + void + keypress(struct wl_listener *listener, void *data) + { +@@ -1851,6 +1889,7 @@ printstatus(void) + printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags], + sel, urg); + printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); ++ printf("%s mode %s\n", m->wlr_output->name, modes_labels[active_mode_index] ? modes_labels[active_mode_index] : ""); + } + fflush(stdout); + } +@@ -2746,6 +2785,13 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++void ++entermode(const Arg *arg) ++{ ++ active_mode_index = arg->i; ++ printstatus(); ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +-- +2.42.0 + diff --git a/dwl/dwl-patches/patches/monitorconfig/README.md b/dwl/dwl-patches/patches/monitorconfig/README.md new file mode 100755 index 0000000..313e5a0 --- /dev/null +++ b/dwl/dwl-patches/patches/monitorconfig/README.md @@ -0,0 +1,9 @@ +### Description +Allows more monitor configuration in config.h + +### Download +- [git branch](https://codeberg.org/Palanix/dwl/src/branch/monitorconfig) +- [2024-02-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/monitorconfig/monitorconfig.patch) + +### Authors +- [Palanix](https://codeberg.org/Palanix) diff --git a/dwl/dwl-patches/patches/monitorconfig/monitorconfig.patch b/dwl/dwl-patches/patches/monitorconfig/monitorconfig.patch new file mode 100755 index 0000000..4922f8d --- /dev/null +++ b/dwl/dwl-patches/patches/monitorconfig/monitorconfig.patch @@ -0,0 +1,95 @@ +From 73f70cd9d817a307030f360f6c8a2500046b8b76 Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Mon, 4 Apr 2022 16:08:29 +0200 +Subject: [PATCH] Updated patch now allowing setting x and y +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Co-authored-by: Leonardo Hernández Hernández +--- + config.def.h | 11 +++++++---- + dwl.c | 25 +++++++++++++++++++------ + 2 files changed, 26 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 8f498d2..4ccacd2 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -38,12 +38,15 @@ static const Layout layouts[] = { + /* monitors */ + /* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ + static const MonitorRule monrules[] = { +- /* name mfact nmaster scale layout rotate/reflect x y */ +- /* example of a HiDPI laptop monitor: +- { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ /* name mfact nmaster scale layout rotate/reflect x y resx resy rate mode adaptive*/ ++ /* example of a HiDPI laptop monitor at 120Hz: ++ { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, 0, 0, 120.000f, 1, 1}, ++ * mode let's the user decide on how dwl should implement the modes: ++ * -1 Sets a custom mode following the users choice ++ * All other number's set the mode at the index n, 0 is the standard mode; see wlr-randr + */ + /* defaults */ +- { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1, 0, 0, 0.0f, 0 ,1}, + }; + + /* keyboard */ +diff --git a/dwl.c b/dwl.c +index 52bfbc8..9609b6d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -215,6 +215,11 @@ typedef struct { + const Layout *lt; + enum wl_output_transform rr; + int x, y; ++ int resx; ++ int resy; ++ float rate; ++ int mode; ++ int adaptive; + } MonitorRule; + + typedef struct { +@@ -865,6 +870,7 @@ createmon(struct wl_listener *listener, void *data) + /* This event is raised by the backend when a new output (aka a display or + * monitor) becomes available. */ + struct wlr_output *wlr_output = data; ++ struct wlr_output_mode *mode = wl_container_of(wlr_output->modes.next, mode, link); + const MonitorRule *r; + size_t i; + struct wlr_output_state state; +@@ -893,16 +899,23 @@ createmon(struct wl_listener *listener, void *data) + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + wlr_output_state_set_scale(&state, r->scale); + wlr_output_state_set_transform(&state, r->rr); ++ ++ wlr_output_state_set_adaptive_sync_enabled(&state, r->adaptive); ++ ++ if(r->mode == -1) ++ wlr_output_state_set_custom_mode(&state, r->resx, r->resy, ++ (int) (r->rate > 0 ? r->rate * 1000 : 0)); ++ else if (!wl_list_empty(&wlr_output->modes)) { ++ for (int j = 0; j < r->mode; j++) { ++ mode = wl_container_of(mode->link.next, mode, link); ++ } ++ wlr_output_state_set_mode(&state, mode); ++ } ++ + break; + } + } + +- /* The mode is a tuple of (width, height, refresh rate), and each +- * monitor supports only a specific set of modes. We just pick the +- * monitor's preferred mode; a more sophisticated compositor would let +- * the user configure it. */ +- wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); +- + /* Set up event listeners */ + LISTEN(&wlr_output->events.frame, &m->frame, rendermon); + LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); +-- +2.45.1 + diff --git a/dwl/dwl-patches/patches/mouse-trackpad-split/README.md b/dwl/dwl-patches/patches/mouse-trackpad-split/README.md new file mode 100755 index 0000000..a3e6e44 --- /dev/null +++ b/dwl/dwl-patches/patches/mouse-trackpad-split/README.md @@ -0,0 +1,8 @@ +### Description +Separates natural scrolling and acceleration settings for trackpad and mouse. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/mouse-trackpad-split/mouse-trackpad-split-0.7.patch) + +### Authors +- [mmistika](https://codeberg.org/mmistika) diff --git a/dwl/dwl-patches/patches/mouse-trackpad-split/mouse-trackpad-split-0.7.patch b/dwl/dwl-patches/patches/mouse-trackpad-split/mouse-trackpad-split-0.7.patch new file mode 100755 index 0000000..89e33ac --- /dev/null +++ b/dwl/dwl-patches/patches/mouse-trackpad-split/mouse-trackpad-split-0.7.patch @@ -0,0 +1,96 @@ +From 211b52988756e9fecccf071fdea82832e1e17a0c Mon Sep 17 00:00:00 2001 +From: mmistika +Date: Tue, 24 Jun 2025 22:25:00 +0200 +Subject: [PATCH] Separate trackpad/mouse natural scroll and accel + +Signed-off-by: mmistika +--- + config.def.h | 12 +++++++++--- + dwl.c | 26 ++++++++++++++++++-------- + 2 files changed, 27 insertions(+), 11 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..9d05a89 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -67,10 +67,14 @@ static const int repeat_delay = 600; + static const int tap_to_click = 1; + static const int tap_and_drag = 1; + static const int drag_lock = 1; +-static const int natural_scrolling = 0; + static const int disable_while_typing = 1; + static const int left_handed = 0; + static const int middle_button_emulation = 0; ++ ++/* Natural scrolling */ ++static const int trackpad_natural_scrolling = 0; ++static const int mouse_natural_scrolling = 0; ++ + /* You can choose between: + LIBINPUT_CONFIG_SCROLL_NO_SCROLL + LIBINPUT_CONFIG_SCROLL_2FG +@@ -97,8 +101,10 @@ static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE + */ +-static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; +-static const double accel_speed = 0.0; ++static const enum libinput_config_accel_profile trackpad_accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; ++static const double trackpad_accel_speed = 0.0; ++static const enum libinput_config_accel_profile mouse_accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; ++static const double mouse_accel_speed = 0.0; + + /* You can choose between: + LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle +diff --git a/dwl.c b/dwl.c +index c717c1d..f05d6c5 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1083,14 +1083,29 @@ createpointer(struct wlr_pointer *pointer) + && (device = wlr_libinput_get_device_handle(&pointer->base))) { + + if (libinput_device_config_tap_get_finger_count(device)) { ++ /* Trackpad */ + libinput_device_config_tap_set_enabled(device, tap_to_click); + libinput_device_config_tap_set_drag_enabled(device, tap_and_drag); + libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock); + libinput_device_config_tap_set_button_map(device, button_map); +- } + +- if (libinput_device_config_scroll_has_natural_scroll(device)) +- libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling); ++ if (libinput_device_config_scroll_has_natural_scroll(device)) ++ libinput_device_config_scroll_set_natural_scroll_enabled(device, trackpad_natural_scrolling); ++ ++ if (libinput_device_config_accel_is_available(device)) { ++ libinput_device_config_accel_set_profile(device, trackpad_accel_profile); ++ libinput_device_config_accel_set_speed(device, trackpad_accel_speed); ++ } ++ } else { ++ /* Mouse */ ++ if (libinput_device_config_scroll_has_natural_scroll(device)) ++ libinput_device_config_scroll_set_natural_scroll_enabled(device, mouse_natural_scrolling); ++ ++ if (libinput_device_config_accel_is_available(device)) { ++ libinput_device_config_accel_set_profile(device, mouse_accel_profile); ++ libinput_device_config_accel_set_speed(device, mouse_accel_speed); ++ } ++ } + + if (libinput_device_config_dwt_is_available(device)) + libinput_device_config_dwt_set_enabled(device, disable_while_typing); +@@ -1109,11 +1124,6 @@ createpointer(struct wlr_pointer *pointer) + + if (libinput_device_config_send_events_get_modes(device)) + libinput_device_config_send_events_set_mode(device, send_events_mode); +- +- if (libinput_device_config_accel_is_available(device)) { +- libinput_device_config_accel_set_profile(device, accel_profile); +- libinput_device_config_accel_set_speed(device, accel_speed); +- } + } + + wlr_cursor_attach_input_device(cursor, &pointer->base); +-- +2.50.0 + diff --git a/dwl/dwl-patches/patches/movecenter/README.md b/dwl/dwl-patches/patches/movecenter/README.md new file mode 100755 index 0000000..aff8f7d --- /dev/null +++ b/dwl/dwl-patches/patches/movecenter/README.md @@ -0,0 +1,28 @@ +### Description + +> This patch is no longer being maintained by me [wochap](https://codeberg.org/wochap), since I'm now using a different patch specific to my use case: https://codeberg.org/wochap/dwl/src/branch/v0.6-c/betterfloat/betterfloat-diff.patch. + +This patch provides a keybinding to center the focused floating window. + +Press MODKEY + x to center the focused floating window. + +It does NOT center windows that are not floating. + +The variable `respect_monitor_reserved_area` allows the user to choose whether to center relative to the monitor or relative to the window area. + +
+Explanation of respect_monitor_reserved_area: +
+The "Monitor area" refers to the space enclosed by the green rectangle, while the "Window area" refers to the space enclosed by the red rectangle.
+
+
+
+ +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.6/movecenter) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/commit/b1ca929ee645cd3e175f198e250448b54624acd6/patches/movecenter/movecenter.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/187d7f511572457750fcf6e42c99cdc7befe05e7/patches/movecenter/movecenter.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) + diff --git a/dwl/dwl-patches/patches/movecenter/movecenter.patch b/dwl/dwl-patches/patches/movecenter/movecenter.patch new file mode 100755 index 0000000..f96bd36 --- /dev/null +++ b/dwl/dwl-patches/patches/movecenter/movecenter.patch @@ -0,0 +1,82 @@ +From bc5206882c71b32198dae5f1c85601a863a7c0a9 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Wed, 31 Jul 2024 07:43:10 -0500 +Subject: [PATCH] implement movecenter fn + +--- + config.def.h | 2 ++ + dwl.c | 31 +++++++++++++++++++++++++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..f5225d9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const int respect_monitor_reserved_area = 0; /* 1 to monitor center while respecting the monitor's reserved area, 0 to monitor center */ + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +@@ -142,6 +143,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_x, movecenter, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index 145fd01..791e598 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -336,6 +336,8 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void _movecenter(Client *c, int interact); ++static void movecenter(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -2683,6 +2685,35 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++_movecenter(Client *c, int interact) ++{ ++ struct wlr_box b; ++ ++ if (!c || !c->mon) { ++ return; ++ } ++ ++ if (!c->isfloating) { ++ return; ++ } ++ ++ b = respect_monitor_reserved_area ? c->mon->w : c->mon->m; ++ resize(c, (struct wlr_box){ ++ .x = (b.width - c->geom.width) / 2 + b.x, ++ .y = (b.height - c->geom.height) / 2 + b.y, ++ .width = c->geom.width, ++ .height = c->geom.height, ++ }, interact); ++} ++ ++void ++movecenter(const Arg *arg) ++{ ++ Client *c = focustop(selmon); ++ _movecenter(c, 1); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/moveresizekb/README.md b/dwl/dwl-patches/patches/moveresizekb/README.md new file mode 100755 index 0000000..0c53caf --- /dev/null +++ b/dwl/dwl-patches/patches/moveresizekb/README.md @@ -0,0 +1,20 @@ +### Description +This allows the user to change size and placement of floating windows using only the keyboard, default keybindings: + +| Keybinding | Action | +| :--- | :--- | +| MODKEY + Up | move 40px up | +| MODKEY + Down | move 40px down | +| MODKEY + Left | move 40px left | +| MODKEY + Right | move 40px right | +| MODKEY + Shift + Up | shrink height 40px | +| MODKEY + Shift + Down | grow height 40px | +| MODKEY + Shift + Left | shrink width 40px | +| MODKEY + Shift + Right | grow width 40px | + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/moveresizekb) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/moveresizekb/moveresizekb.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/moveresizekb/moveresizekb.patch b/dwl/dwl-patches/patches/moveresizekb/moveresizekb.patch new file mode 100755 index 0000000..aeb1e5e --- /dev/null +++ b/dwl/dwl-patches/patches/moveresizekb/moveresizekb.patch @@ -0,0 +1,70 @@ +From c8af428f964679089599e4ffbe7d28d08a4e875f Mon Sep 17 00:00:00 2001 +From: wochap +Date: Tue, 5 Mar 2024 23:42:55 -0500 +Subject: [PATCH] implement keybindings to move and resize focused floating + window + +--- + config.def.h | 8 ++++++++ + dwl.c | 19 +++++++++++++++++++ + 2 files changed, 27 insertions(+) + +diff --git a/config.def.h b/config.def.h +index db0babc..d0570b8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -135,6 +135,14 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 40, 0, 0 }}}, ++ { MODKEY, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, -40, 0, 0 }}}, ++ { MODKEY, XKB_KEY_Right, moveresizekb, {.v = (int []){ 40, 0, 0, 0 }}}, ++ { MODKEY, XKB_KEY_Left, moveresizekb, {.v = (int []){ -40, 0, 0, 0 }}}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 0, 0, 40 }}}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, 0, 0, -40 }}}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, moveresizekb, {.v = (int []){ 0, 0, 40, 0 }}}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, moveresizekb, {.v = (int []){ 0, 0, -40, 0 }}}, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index ef27a1d..251472b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -313,6 +313,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void moveresizekb(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -2454,6 +2455,24 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++moveresizekb(const Arg *arg) ++{ ++ Client *c = focustop(selmon); ++ Monitor *m = selmon; ++ ++ if(!(m && arg && arg->v && c && c->isfloating)) { ++ return; ++ } ++ ++ resize(c, (struct wlr_box){ ++ .x = c->geom.x + ((int *)arg->v)[0], ++ .y = c->geom.y + ((int *)arg->v)[1], ++ .width = c->geom.width + ((int *)arg->v)[2], ++ .height = c->geom.height + ((int *)arg->v)[3], ++ }, 1); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.42.0 + diff --git a/dwl/dwl-patches/patches/movestack/README.md b/dwl/dwl-patches/patches/movestack/README.md new file mode 100755 index 0000000..f50bf68 --- /dev/null +++ b/dwl/dwl-patches/patches/movestack/README.md @@ -0,0 +1,13 @@ +### Description +Allows you to move a window up and down the stack. + +### Download +- [git branch](https://codeberg.org/nikitaivanov/dwl/src/branch/movestack) +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/movestack/movestack.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [sam-barr](https://github.com/ss7m) +- [Dmitry Zakharchenko](https://github.com/dm1tz) +- [Abanoub8](https://github.com/Abanoub8) +- [Nikita Ivanov](https://github.com/NikitaIvanovV) diff --git a/dwl/dwl-patches/patches/movestack/movestack.patch b/dwl/dwl-patches/patches/movestack/movestack.patch new file mode 100755 index 0000000..2543c66 --- /dev/null +++ b/dwl/dwl-patches/patches/movestack/movestack.patch @@ -0,0 +1,87 @@ +From 08230817bd3926e29d9897657eb1852cb27d461f Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Tue, 4 Feb 2025 23:21:19 +0100 +Subject: [PATCH] Allows you to move a window up and down the stack + +--- + config.def.h | 2 ++ + dwl.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..2c129f2 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -129,6 +129,8 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, movestack, {.i = +1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, movestack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +diff --git a/dwl.c b/dwl.c +index def2562..045d6fa 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -303,6 +303,7 @@ static void locksession(struct wl_listener *listener, void *data); + static void mapnotify(struct wl_listener *listener, void *data); + static void maximizenotify(struct wl_listener *listener, void *data); + static void monocle(Monitor *m); ++static void movestack(const Arg *arg); + static void motionabsolute(struct wl_listener *listener, void *data); + static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, + double sy, double sx_unaccel, double sy_unaccel); +@@ -1786,6 +1787,48 @@ monocle(Monitor *m) + wlr_scene_node_raise_to_top(&c->scene->node); + } + ++void ++movestack(const Arg *arg) ++{ ++ Client *c, *sel = focustop(selmon); ++ ++ if (!sel) { ++ return; ++ } ++ ++ if (wl_list_length(&clients) <= 1) { ++ return; ++ } ++ ++ if (arg->i > 0) { ++ wl_list_for_each(c, &sel->link, link) { ++ if (&c->link == &clients) { ++ c = wl_container_of(&clients, c, link); ++ break; /* wrap past the sentinel node */ ++ } ++ if (VISIBLEON(c, selmon) || &c->link == &clients) { ++ break; /* found it */ ++ } ++ } ++ } else { ++ wl_list_for_each_reverse(c, &sel->link, link) { ++ if (&c->link == &clients) { ++ c = wl_container_of(&clients, c, link); ++ break; /* wrap past the sentinel node */ ++ } ++ if (VISIBLEON(c, selmon) || &c->link == &clients) { ++ break; /* found it */ ++ } ++ } ++ /* backup one client */ ++ c = wl_container_of(c->link.prev, c, link); ++ } ++ ++ wl_list_remove(&sel->link); ++ wl_list_insert(&c->link, &sel->link); ++ arrange(selmon); ++} ++ + void + motionabsolute(struct wl_listener *listener, void *data) + { +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/namedscratchpads/README.md b/dwl/dwl-patches/patches/namedscratchpads/README.md new file mode 100755 index 0000000..e436583 --- /dev/null +++ b/dwl/dwl-patches/patches/namedscratchpads/README.md @@ -0,0 +1,19 @@ +### Description +Allows for the creation of multiple scratchpad windows, each assigned to a different keybinding. In simple terms, it enables 'run or raise' functionality + +This patch adds the following functions: + +* `togglescratch`: simply toggles the scratchpad window +* `focusortogglescratch`: change the focus to the scratchpad window if it is visible and toggles it if it is already in focus +* `focusortogglematchingscratch`: similar to `focusortogglescratch` but also closes all other scratchpad windows + +If you don't assign keybindings to any of the above functions and so get a compiler warning about them not being used, just remove them from your dwl branch to stop the warning. + +### Download +- [git branch (v0.6)](https://codeberg.org/bencc/dwl/src/branch/namedscratchpads) +- [2024-07-13 (v0.6)](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/namedscratchpads/namedscratchpads.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) +- [wochap](https://codeberg.org/wochap) +- [Louis-Michel Raynauld](https://github.com/loumray) diff --git a/dwl/dwl-patches/patches/namedscratchpads/namedscratchpads.patch b/dwl/dwl-patches/patches/namedscratchpads/namedscratchpads.patch new file mode 100755 index 0000000..7a0a257 --- /dev/null +++ b/dwl/dwl-patches/patches/namedscratchpads/namedscratchpads.patch @@ -0,0 +1,278 @@ +From bd83d56b3a268112b029961ad6ff4232b2d6f00d Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Thu, 4 Jan 2024 16:35:05 +1000 +Subject: [PATCH 1/2] namedscratchpads + +--- + config.def.h | 11 ++++++++--- + dwl.c | 39 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..36a691a9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -22,10 +22,11 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating monitor scratchkey */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 1, -1, 0 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1, 0 }, /* Start on ONLY tag "9" */ ++ { NULL, "scratchpad", 0, 1, -1, 's' }, + }; + + /* layout(s) */ +@@ -122,11 +123,15 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + static const char *termcmd[] = { "foot", NULL }; + static const char *menucmd[] = { "wmenu-run", NULL }; + ++/* named scratchpads - First arg only serves to match against key in rules*/ ++static const char *scratchpadcmd[] = { "s", "alacritty", "-t", "scratchpad", NULL }; ++ + static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index dc0437e0..eb0eb775 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -139,6 +139,7 @@ typedef struct { + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; ++ char scratchkey; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -230,6 +231,7 @@ typedef struct { + uint32_t tags; + int isfloating; + int monitor; ++ const char scratchkey; + } Rule; + + typedef struct { +@@ -330,12 +332,14 @@ static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); ++static void spawnscratch(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglescratch(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -456,6 +460,7 @@ applyrules(Client *c) + Monitor *mon = selmon, *m; + + c->isfloating = client_is_float_type(c); ++ c->scratchkey = 0; + if (!(appid = client_get_appid(c))) + appid = broken; + if (!(title = client_get_title(c))) +@@ -465,6 +470,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->scratchkey = r->scratchkey; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -2603,6 +2609,16 @@ spawn(const Arg *arg) + } + } + ++void spawnscratch(const Arg *arg) ++{ ++ if (fork() == 0) { ++ dup2(STDERR_FILENO, STDOUT_FILENO); ++ setsid(); ++ execvp(((char **)arg->v)[1], ((char **)arg->v)+1); ++ die("dwl: execvp %s failed:", ((char **)arg->v)[1]); ++ } ++} ++ + void + startdrag(struct wl_listener *listener, void *data) + { +@@ -2686,6 +2702,29 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglescratch(const Arg *arg) ++{ ++ Client *c; ++ unsigned int found = 0; ++ ++ /* search for first window that matches the scratchkey */ ++ wl_list_for_each(c, &clients, link) ++ if (c->scratchkey == ((char**)arg->v)[0][0]) { ++ found = 1; ++ break; ++ } ++ ++ if (found) { ++ c->tags = VISIBLEON(c, selmon) ? 0 : selmon->tagset[selmon->seltags]; ++ ++ focusclient(c->tags == 0 ? focustop(selmon) : c, 1); ++ arrange(selmon); ++ } else{ ++ spawnscratch(arg); ++ } ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.45.2 + + +From 4963c34b4958fba9d53a23a1c9929d554a4e8b3d Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Sat, 13 Jul 2024 14:50:45 +1000 +Subject: [PATCH 2/2] namedscratchpads: focusortoggle functions + +--- + config.def.h | 2 ++ + dwl.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 89 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 36a691a9..21bb66bb 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -132,6 +132,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } }, ++ // { MODKEY, XKB_KEY_grave, focusortogglescratch, {.v = scratchpadcmd } }, ++ // { MODKEY, XKB_KEY_grave, focusortogglematchingscratch, {.v = scratchpadcmd } }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index eb0eb775..d7c5552f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -286,6 +286,8 @@ static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); ++static void focusortogglematchingscratch(const Arg *arg); ++static void focusortogglescratch(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); +@@ -1405,6 +1407,91 @@ focusmon(const Arg *arg) + focusclient(focustop(selmon), 1); + } + ++void ++focusortogglematchingscratch(const Arg *arg) ++{ ++ Client *c; ++ unsigned int found = 0; ++ unsigned int hide = 0; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->scratchkey == 0) { ++ continue; ++ } ++ if (c->scratchkey == ((char**)arg->v)[0][0]) { ++ if (VISIBLEON(c, selmon)) { ++ if (found == 1) { ++ if (hide == 1) { ++ c->tags = 0; ++ focusclient(focustop(selmon), 1); ++ } ++ continue; ++ } ++ if (focustop(selmon) == c) { ++ // hide ++ c->tags = 0; ++ focusclient(focustop(selmon), 1); ++ hide = 1; ++ } else { ++ // focus ++ focusclient(c, 1); ++ } ++ } else { ++ // show ++ c->tags = selmon->tagset[selmon->seltags]; ++ // focus ++ focusclient(c, 1); ++ } ++ found = 1; ++ continue; ++ } ++ if (VISIBLEON(c, selmon)) { ++ // hide ++ c->tags = 0; ++ } ++ } ++ ++ if (found) { ++ arrange(selmon); ++ } else { ++ spawnscratch(arg); ++ } ++} ++ ++void ++focusortogglescratch(const Arg *arg) ++{ ++ Client *c; ++ unsigned int found = 0; ++ ++ /* search for first window that matches the scratchkey */ ++ wl_list_for_each(c, &clients, link) ++ if (c->scratchkey == ((char**)arg->v)[0][0]) { ++ found = 1; ++ break; ++ } ++ ++ if (found) { ++ if (VISIBLEON(c, selmon)) { ++ if (focustop(selmon) == c) { ++ // hide ++ c->tags = 0; ++ focusclient(focustop(selmon), 1); ++ } else { ++ // focus ++ focusclient(c, 1); ++ } ++ } else { ++ // show ++ c->tags = selmon->tagset[selmon->seltags]; ++ focusclient(c, 1); ++ } ++ arrange(selmon); ++ } else{ ++ spawnscratch(arg); ++ } ++} ++ + void + focusstack(const Arg *arg) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/nextlayout/README.md b/dwl/dwl-patches/patches/nextlayout/README.md new file mode 100755 index 0000000..ea1d4a6 --- /dev/null +++ b/dwl/dwl-patches/patches/nextlayout/README.md @@ -0,0 +1,9 @@ +### Description +Change the current layout to the next available one. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/nextlayout/nextlayout.patch) + +### Authors +- [sewn](/sewn) + diff --git a/dwl/dwl-patches/patches/nextlayout/nextlayout.patch b/dwl/dwl-patches/patches/nextlayout/nextlayout.patch new file mode 100755 index 0000000..11f4dc7 --- /dev/null +++ b/dwl/dwl-patches/patches/nextlayout/nextlayout.patch @@ -0,0 +1,65 @@ +From 7d8cfa63681830a3af4512799b8260f8249bc514 Mon Sep 17 00:00:00 2001 +From: sewn +Date: Sun, 8 Sep 2024 22:49:33 +0300 +Subject: [PATCH] add feature to switch to next available layout + +ported from suckless cyclelayouts to be slightly more useful +https://dwm.suckless.org/patches/cyclelayouts/ +--- + config.def.h | 2 ++ + dwl.c | 12 ++++++++++++ + 2 files changed, 14 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..f88a615 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { NULL, NULL }, /* terminate */ + }; + + /* monitors */ +@@ -140,6 +141,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, ++ { MODKEY, XKB_KEY_n, nextlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, +diff --git a/dwl.c b/dwl.c +index a2711f6..a66d9d9 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -308,6 +308,7 @@ static void motionnotify(uint32_t time, struct wlr_input_device *device, double + double sy, double sx_unaccel, double sy_unaccel); + static void motionrelative(struct wl_listener *listener, void *data); + static void moveresize(const Arg *arg); ++static void nextlayout(const Arg *arg); + static void outputmgrapply(struct wl_listener *listener, void *data); + static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); + static void outputmgrtest(struct wl_listener *listener, void *data); +@@ -1927,6 +1928,17 @@ moveresize(const Arg *arg) + } + } + ++void ++nextlayout(const Arg *arg) ++{ ++ Layout *l; ++ for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++); ++ if(l->symbol && (l + 1)->symbol) ++ setlayout(&((Arg) { .v = (l + 1) })); ++ else ++ setlayout(&((Arg) { .v = layouts })); ++} ++ + void + outputmgrapply(struct wl_listener *listener, void *data) + { +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/numlock-capslock/README.md b/dwl/dwl-patches/patches/numlock-capslock/README.md new file mode 100755 index 0000000..54a4f34 --- /dev/null +++ b/dwl/dwl-patches/patches/numlock-capslock/README.md @@ -0,0 +1,10 @@ +### Description +Allows activating numlock or capslock at startup. + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/numlock-capslock) +- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/numlock-capslock/numlock-capslock.patch) +- [numlock-capslock.patch](/dwl/dwl-patches/raw/branch/main/patches/numlock-capslock/numlock-capslock-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) diff --git a/dwl/dwl-patches/patches/numlock-capslock/numlock-capslock-0.7.patch b/dwl/dwl-patches/patches/numlock-capslock/numlock-capslock-0.7.patch new file mode 100755 index 0000000..7b30be3 --- /dev/null +++ b/dwl/dwl-patches/patches/numlock-capslock/numlock-capslock-0.7.patch @@ -0,0 +1,84 @@ +From cbacfb5031b91bc6677b0fb7c07dbe79cc2e0177 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sun, 4 Apr 2021 19:56:09 -0500 +Subject: [PATCH] add option to enable numlock/capslock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 4 ++++ + dwl.c | 19 +++++++++++++++++++ + 2 files changed, 23 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..21dc6201 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -60,6 +60,10 @@ static const struct xkb_rule_names xkb_rules = { + .options = NULL, + }; + ++/* numlock and capslock */ ++static const int numlock = 1; ++static const int capslock = 0; ++ + static const int repeat_rate = 25; + static const int repeat_delay = 600; + +diff --git a/dwl.c b/dwl.c +index a2711f67..a11f0bcf 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -360,6 +361,7 @@ static void zoom(const Arg *arg); + static const char broken[] = "broken"; + static pid_t child_pid = -1; + static int locked; ++static uint32_t locked_mods = 0; + static void *exclusive_focus; + static struct wl_display *dpy; + static struct wl_event_loop *event_loop; +@@ -877,6 +879,8 @@ createkeyboard(struct wlr_keyboard *keyboard) + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); + ++ wlr_keyboard_notify_modifiers(keyboard, 0, 0, locked_mods, 0); ++ + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard); + } +@@ -898,6 +902,21 @@ createkeyboardgroup(void) + die("failed to compile keymap"); + + wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap); ++ if (numlock) { ++ xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM); ++ if (mod_index != XKB_MOD_INVALID) ++ locked_mods |= (uint32_t)1 << mod_index; ++ } ++ ++ if (capslock) { ++ xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); ++ if (mod_index != XKB_MOD_INVALID) ++ locked_mods |= (uint32_t)1 << mod_index; ++ } ++ ++ if (locked_mods) ++ wlr_keyboard_notify_modifiers(&group->wlr_group->keyboard, 0, 0, locked_mods, 0); ++ + xkb_keymap_unref(keymap); + xkb_context_unref(context); + +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/numlock-capslock/numlock-capslock.patch b/dwl/dwl-patches/patches/numlock-capslock/numlock-capslock.patch new file mode 100755 index 0000000..adf9f38 --- /dev/null +++ b/dwl/dwl-patches/patches/numlock-capslock/numlock-capslock.patch @@ -0,0 +1,84 @@ +From ec5dbcd9f4629549d3d14b1791305a42479a935f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Sun, 4 Apr 2021 19:56:09 -0500 +Subject: [PATCH] add option to enable numlock/capslock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 4 ++++ + dwl.c | 19 +++++++++++++++++++ + 2 files changed, 23 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..21dc6201 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -60,6 +60,10 @@ static const struct xkb_rule_names xkb_rules = { + .options = NULL, + }; + ++/* numlock and capslock */ ++static const int numlock = 1; ++static const int capslock = 0; ++ + static const int repeat_rate = 25; + static const int repeat_delay = 600; + +diff --git a/dwl.c b/dwl.c +index ad21e1ba..d0059ec8 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -355,6 +356,7 @@ static void zoom(const Arg *arg); + /* variables */ + static pid_t child_pid = -1; + static int locked; ++static uint32_t locked_mods = 0; + static void *exclusive_focus; + static struct wl_display *dpy; + static struct wl_event_loop *event_loop; +@@ -936,6 +938,8 @@ createkeyboard(struct wlr_keyboard *keyboard) + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); + ++ wlr_keyboard_notify_modifiers(keyboard, 0, 0, locked_mods, 0); ++ + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard); + } +@@ -957,6 +961,21 @@ createkeyboardgroup(void) + die("failed to compile keymap"); + + wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap); ++ if (numlock) { ++ xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM); ++ if (mod_index != XKB_MOD_INVALID) ++ locked_mods |= (uint32_t)1 << mod_index; ++ } ++ ++ if (capslock) { ++ xkb_mod_index_t mod_index = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); ++ if (mod_index != XKB_MOD_INVALID) ++ locked_mods |= (uint32_t)1 << mod_index; ++ } ++ ++ if (locked_mods) ++ wlr_keyboard_notify_modifiers(&group->wlr_group->keyboard, 0, 0, locked_mods, 0); ++ + xkb_keymap_unref(keymap); + xkb_context_unref(context); + +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/passthrough/README.md b/dwl/dwl-patches/patches/passthrough/README.md new file mode 100755 index 0000000..0380951 --- /dev/null +++ b/dwl/dwl-patches/patches/passthrough/README.md @@ -0,0 +1,13 @@ +### Description +allows pausing keybind handling + +also allows for bitcarrying-esque control of nested instances + +default keybind is Ctrl+Logo+Alt+Shift+Esc, can be customized in config.h + +### Download +- [git branch](https://codeberg.org/notchoc/dwl/src/branch/passthrough) +- [2024-06-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/passthrough/passthrough.patch) +- [2024-06-22](https://codeberg.org/dwl/dwl-patches/raw/commit/3f44fb23d8cb6c7d700f41525dc00493e392083c/patches/passthrough/passthrough.patch) +### Authors +- [notchoc](https://codeberg.org/notchoc) diff --git a/dwl/dwl-patches/patches/passthrough/passthrough.patch b/dwl/dwl-patches/patches/passthrough/passthrough.patch new file mode 100755 index 0000000..d87f00e --- /dev/null +++ b/dwl/dwl-patches/patches/passthrough/passthrough.patch @@ -0,0 +1,82 @@ +From cd67c8386b0188daa15348c1d0d99187a556e461 Mon Sep 17 00:00:00 2001 +From: choc +Date: Mon, 2 Jan 2023 13:00:29 +0800 +Subject: [PATCH] passthrough: allow pausing keybind handling + +also allows for bitcarrying-esque control of nested instances +--- + config.def.h | 4 ++++ + dwl.c | 14 ++++++++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 646a3d6..2d14e2a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,9 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + /* logging */ + static int log_level = WLR_ERROR; + ++/* passthrough */ ++static int passthrough = 0; ++ + static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ + /* examples: */ +@@ -156,6 +159,7 @@ static const Key keys[] = { + TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), + TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), + TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), ++ { WLR_MODIFIER_ALT|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT, XKB_KEY_Escape, togglepassthrough, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ +diff --git a/dwl.c b/dwl.c +index 9fb50a7..a1c65b4 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -339,6 +339,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglepassthrough(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -620,6 +621,11 @@ buttonpress(struct wl_listener *listener, void *data) + for (b = buttons; b < END(buttons); b++) { + if (CLEANMASK(mods) == CLEANMASK(b->mod) && + event->button == b->button && b->func) { ++ if (passthrough) { ++ if (b->func != togglepassthrough) continue; ++ b->func(&b->arg); ++ break; ++ } + b->func(&b->arg); + return; + } +@@ -1509,6 +1515,8 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) + && sym == k->keysym && k->func) { ++ if (passthrough && k->func != togglepassthrough) ++ continue; + k->func(&k->arg); + return 1; + } +@@ -2677,6 +2685,12 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglepassthrough(const Arg *arg) ++{ ++ passthrough = !passthrough; ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/perinputconfig/README.md b/dwl/dwl-patches/patches/perinputconfig/README.md new file mode 100755 index 0000000..ab1602c --- /dev/null +++ b/dwl/dwl-patches/patches/perinputconfig/README.md @@ -0,0 +1,12 @@ +### Description +Replace the singular keyboard and pointer input configuration with an array allowing to set different variables matching by name. + +Tip to find the names: Grep for `device_name` and add a line after it to print to stdout. Then run EX: `dwl > /tmp/print_device_names.log`, exit dwl, and should see the names. + +### Download +- [git branch](https://codeberg.org/nullsystem/dwl/src/branch/main_perinputconfig) +- [2024-06-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/perinputconfig/perinputconfig.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/perinputconfig/perinputconfig-v0.5.patch) + +### Authors +- [nullsystem](https://codeberg.org/nullsystem) diff --git a/dwl/dwl-patches/patches/perinputconfig/perinputconfig-v0.5.patch b/dwl/dwl-patches/patches/perinputconfig/perinputconfig-v0.5.patch new file mode 100755 index 0000000..25a2a92 --- /dev/null +++ b/dwl/dwl-patches/patches/perinputconfig/perinputconfig-v0.5.patch @@ -0,0 +1,173 @@ +From 9388faea3c4648aa99c01b9e4ce9287237b28b38 Mon Sep 17 00:00:00 2001 +From: nullsystem +Date: Mon, 1 Apr 2024 21:23:39 +0100 +Subject: [PATCH] Backport perinputconfig to v0.5 + +- Array replaced singular variables for configuration +- Only applies to enable-state, acceleration profile, and speed +- Like EX: Rules, requires NULL/default set at the end +- Keyboards can now also set by name +--- + config.def.h | 37 +++++++++++++++++++++++-------------- + dwl.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 69 insertions(+), 17 deletions(-) + +diff --git a/config.def.h b/config.def.h +index db0babc..861a937 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -46,12 +46,13 @@ static const MonitorRule monrules[] = { + }; + + /* keyboard */ +-static const struct xkb_rule_names xkb_rules = { +- /* can specify fields: rules, model, layout, variant, options */ ++/* NOTE: Always include a fallback rule at the end (name as NULL) */ ++static const KeyboardRule kbrules[] = { ++ /* name rules model layout variant options */ + /* example: +- .options = "ctrl:nocaps", ++ { "keyboard", NULL, NULL, "us,de", NULL, "ctrl:nocaps" }, + */ +- .options = NULL, ++ { NULL, NULL, NULL, NULL, NULL, NULL }, + }; + + static const int repeat_rate = 25; +@@ -81,23 +82,31 @@ LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER + static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + + /* You can choose between: ++LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle ++LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right ++*/ ++static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; ++ ++/* ++send_events_mode: You can choose between: + LIBINPUT_CONFIG_SEND_EVENTS_ENABLED + LIBINPUT_CONFIG_SEND_EVENTS_DISABLED + LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE +-*/ +-static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + +-/* You can choose between: ++accel_profile: You can choose between: + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE ++ ++NOTE: Always include a fallback rule at the end (name as NULL) + */ +-static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; +-static const double accel_speed = 0.0; +-/* You can choose between: +-LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle +-LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right +-*/ +-static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; ++static const InputRule inputrules[] = { ++ /* name send_events_mode accel_profile accel_speed*/ ++ /* examples: ++ { "SynPS/2 Synaptics TouchPad", LIBINPUT_CONFIG_SEND_EVENTS_DISABLED, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, 0.0 }, ++ { "TPPS/2 IBM TrackPoint", LIBINPUT_CONFIG_SEND_EVENTS_ENABLED, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, 0.0 }, ++ */ ++ { NULL, LIBINPUT_CONFIG_SEND_EVENTS_ENABLED, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, 0.0 }, ++}; + + /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ + #define MODKEY WLR_MODIFIER_ALT +diff --git a/dwl.c b/dwl.c +index ef27a1d..a35f480 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -226,6 +226,22 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++typedef struct { ++ const char *name; ++ uint32_t send_events_mode; ++ enum libinput_config_accel_profile accel_profile; ++ double accel_speed; ++} InputRule; ++ ++typedef struct { ++ const char *name; ++ const char *rules; ++ const char *model; ++ const char *layout; ++ const char *variant; ++ const char *options; ++} KeyboardRule; ++ + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -766,11 +782,31 @@ createidleinhibitor(struct wl_listener *listener, void *data) + void + createkeyboard(struct wlr_keyboard *keyboard) + { ++ struct xkb_rule_names xkb_rules; ++ struct libinput_device *libinput_device = NULL; + struct xkb_context *context; + struct xkb_keymap *keymap; ++ const KeyboardRule *krule = NULL; ++ const char *device_name = ""; + Keyboard *kb = keyboard->data = ecalloc(1, sizeof(*kb)); + kb->wlr_keyboard = keyboard; + ++ if (wlr_input_device_is_libinput(&keyboard->base) ++ && (libinput_device = wlr_libinput_get_device_handle(&keyboard->base))) { ++ device_name = libinput_device_get_name(libinput_device); ++ } ++ for (krule = kbrules; krule < END(kbrules); krule++) { ++ if (!krule->name || strstr(device_name, krule->name)) ++ break; ++ } ++ if (krule) { ++ xkb_rules.rules = krule->rules; ++ xkb_rules.model = krule->model; ++ xkb_rules.layout = krule->layout; ++ xkb_rules.variant = krule->variant; ++ xkb_rules.options = krule->options; ++ } ++ + /* Prepare an XKB keymap and assign it to the keyboard. */ + context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + keymap = xkb_keymap_new_from_names(context, &xkb_rules, +@@ -989,10 +1025,17 @@ createnotify(struct wl_listener *listener, void *data) + void + createpointer(struct wlr_pointer *pointer) + { ++ const InputRule *irule; + if (wlr_input_device_is_libinput(&pointer->base)) { + struct libinput_device *libinput_device = (struct libinput_device*) + wlr_libinput_get_device_handle(&pointer->base); + ++ const char *device_name = libinput_device_get_name(libinput_device); ++ for (irule = inputrules; irule < END(inputrules); irule++) { ++ if (!irule->name || strstr(device_name, irule->name)) ++ break; ++ } ++ + if (libinput_device_config_tap_get_finger_count(libinput_device)) { + libinput_device_config_tap_set_enabled(libinput_device, tap_to_click); + libinput_device_config_tap_set_drag_enabled(libinput_device, tap_and_drag); +@@ -1019,11 +1062,11 @@ createpointer(struct wlr_pointer *pointer) + libinput_device_config_click_set_method (libinput_device, click_method); + + if (libinput_device_config_send_events_get_modes(libinput_device)) +- libinput_device_config_send_events_set_mode(libinput_device, send_events_mode); ++ libinput_device_config_send_events_set_mode(libinput_device, irule->send_events_mode); + + if (libinput_device_config_accel_is_available(libinput_device)) { +- libinput_device_config_accel_set_profile(libinput_device, accel_profile); +- libinput_device_config_accel_set_speed(libinput_device, accel_speed); ++ libinput_device_config_accel_set_profile(libinput_device, irule->accel_profile); ++ libinput_device_config_accel_set_speed(libinput_device, irule->accel_speed); + } + } + +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/perinputconfig/perinputconfig.patch b/dwl/dwl-patches/patches/perinputconfig/perinputconfig.patch new file mode 100755 index 0000000..dae4bc8 --- /dev/null +++ b/dwl/dwl-patches/patches/perinputconfig/perinputconfig.patch @@ -0,0 +1,295 @@ +From c268707811fb5d8244115f23a0430f024e4e11a9 Mon Sep 17 00:00:00 2001 +From: nullsystem +Date: Sat, 8 Jun 2024 11:30:34 +0100 +Subject: [PATCH] perinputconfig - 2024-06-08 Update + +* Array replaced singular variables for configuration +* Only applies to enable-state, acceleration profile, and speed +* Like EX: Rules, requires NULL/default set at the end +* Keyboards can now also set by name +--- + config.def.h | 36 +++++++++++++--------- + dwl.c | 87 +++++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 95 insertions(+), 28 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a784eb4..c733137 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -49,12 +49,13 @@ static const MonitorRule monrules[] = { + }; + + /* keyboard */ +-static const struct xkb_rule_names xkb_rules = { +- /* can specify fields: rules, model, layout, variant, options */ ++/* NOTE: Always include a fallback rule at the end (name as NULL) */ ++static const KeyboardRule kbrules[] = { ++ /* name rules model layout variant options */ + /* example: +- .options = "ctrl:nocaps", ++ { "keyboard", NULL, NULL, "us,de", NULL, "ctrl:nocaps" }, + */ +- .options = NULL, ++ { NULL, NULL, NULL, NULL, NULL, NULL }, + }; + + static const int repeat_rate = 25; +@@ -84,24 +85,31 @@ LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER + static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; + + /* You can choose between: ++LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle ++LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right ++*/ ++static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; ++ ++/* ++send_events_mode: You can choose between: + LIBINPUT_CONFIG_SEND_EVENTS_ENABLED + LIBINPUT_CONFIG_SEND_EVENTS_DISABLED + LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE +-*/ +-static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + +-/* You can choose between: ++accel_profile: You can choose between: + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE +-*/ +-static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; +-static const double accel_speed = 0.0; + +-/* You can choose between: +-LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle +-LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right ++NOTE: Always include a fallback rule at the end (name as NULL) + */ +-static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; ++static const InputRule inputrules[] = { ++ /* name send_events_mode accel_profile accel_speed*/ ++ /* examples: ++ { "SynPS/2 Synaptics TouchPad", LIBINPUT_CONFIG_SEND_EVENTS_DISABLED, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, 0.0 }, ++ { "TPPS/2 IBM TrackPoint", LIBINPUT_CONFIG_SEND_EVENTS_ENABLED, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, 0.0 }, ++ */ ++ { NULL, LIBINPUT_CONFIG_SEND_EVENTS_ENABLED, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, 0.0 }, ++}; + + /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ + #define MODKEY WLR_MODIFIER_ALT +diff --git a/dwl.c b/dwl.c +index 6f041a0..0673a05 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -240,6 +240,22 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++typedef struct { ++ const char *name; ++ uint32_t send_events_mode; ++ enum libinput_config_accel_profile accel_profile; ++ double accel_speed; ++} InputRule; ++ ++typedef struct { ++ const char *name; ++ const char *rules; ++ const char *model; ++ const char *layout; ++ const char *variant; ++ const char *options; ++} KeyboardRule; ++ + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -259,7 +275,7 @@ static void commitnotify(struct wl_listener *listener, void *data); + static void createdecoration(struct wl_listener *listener, void *data); + static void createidleinhibitor(struct wl_listener *listener, void *data); + static void createkeyboard(struct wlr_keyboard *keyboard); +-static KeyboardGroup *createkeyboardgroup(void); ++static KeyboardGroup *createkeyboardgroup(struct xkb_rule_names *new_xkb_rules); + static void createlayersurface(struct wl_listener *listener, void *data); + static void createlocksurface(struct wl_listener *listener, void *data); + static void createmon(struct wl_listener *listener, void *data); +@@ -396,7 +412,7 @@ static struct wlr_session_lock_v1 *cur_lock; + static struct wl_listener lock_listener = {.notify = locksession}; + + static struct wlr_seat *seat; +-static KeyboardGroup *kb_group; ++static struct wl_list kb_groups; + static struct wlr_surface *held_grab; + static unsigned int cursor_mode; + static Client *grabc; +@@ -671,6 +687,8 @@ checkidleinhibitor(struct wlr_surface *exclude) + void + cleanup(void) + { ++ KeyboardGroup *kb_group; ++ + #ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; +@@ -683,7 +701,8 @@ cleanup(void) + wlr_xcursor_manager_destroy(cursor_mgr); + wlr_output_layout_destroy(output_layout); + +- destroykeyboardgroup(&kb_group->destroy, NULL); ++ wl_list_for_each(kb_group, &kb_groups, link) ++ destroykeyboardgroup(&kb_group->destroy, NULL); + + wl_display_destroy(dpy); + /* Destroy after the wayland display (when the monitors are already destroyed) +@@ -803,6 +822,30 @@ createidleinhibitor(struct wl_listener *listener, void *data) + void + createkeyboard(struct wlr_keyboard *keyboard) + { ++ KeyboardGroup *kb_group; ++ const char *device_name = ""; ++ const KeyboardRule *krule = NULL; ++ struct libinput_device *device = NULL; ++ ++ if (wlr_input_device_is_libinput(&keyboard->base) ++ && (device = wlr_libinput_get_device_handle(&keyboard->base))) { ++ device_name = libinput_device_get_name(device); ++ } ++ for (krule = kbrules; krule < END(kbrules); krule++) { ++ if (!krule->name || strstr(device_name, krule->name)) ++ break; ++ } ++ if (krule) { ++ struct xkb_rule_names xkb_rules; ++ xkb_rules.rules = krule->rules; ++ xkb_rules.model = krule->model; ++ xkb_rules.layout = krule->layout; ++ xkb_rules.variant = krule->variant; ++ xkb_rules.options = krule->options; ++ kb_group = createkeyboardgroup(&xkb_rules); ++ } else ++ wl_list_for_each(kb_group, &kb_groups, link); ++ + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); + +@@ -811,11 +854,16 @@ createkeyboard(struct wlr_keyboard *keyboard) + } + + KeyboardGroup * +-createkeyboardgroup(void) ++createkeyboardgroup(struct xkb_rule_names *new_xkb_rules) + { + KeyboardGroup *group = ecalloc(1, sizeof(*group)); + struct xkb_context *context; + struct xkb_keymap *keymap; ++ struct xkb_rule_names xkb_rules; ++ ++ memset(&xkb_rules, 0, sizeof(struct xkb_rule_names)); ++ if (new_xkb_rules) ++ xkb_rules = *new_xkb_rules; + + group->wlr_group = wlr_keyboard_group_create(); + group->wlr_group->data = group; +@@ -845,6 +893,9 @@ createkeyboardgroup(void) + * all of them. Set this combined wlr_keyboard as the seat keyboard. + */ + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); ++ ++ wl_list_init(&group->destroy.link); ++ wl_list_insert(&kb_groups, &group->link); + return group; + } + +@@ -1042,9 +1093,15 @@ createnotify(struct wl_listener *listener, void *data) + void + createpointer(struct wlr_pointer *pointer) + { ++ const InputRule *irule; + struct libinput_device *device; + if (wlr_input_device_is_libinput(&pointer->base) + && (device = wlr_libinput_get_device_handle(&pointer->base))) { ++ const char *device_name = libinput_device_get_name(device); ++ for (irule = inputrules; irule < END(inputrules); irule++) { ++ if (!irule->name || strstr(device_name, irule->name)) ++ break; ++ } + + if (libinput_device_config_tap_get_finger_count(device)) { + libinput_device_config_tap_set_enabled(device, tap_to_click); +@@ -1072,11 +1129,11 @@ createpointer(struct wlr_pointer *pointer) + libinput_device_config_click_set_method (device, click_method); + + if (libinput_device_config_send_events_get_modes(device)) +- libinput_device_config_send_events_set_mode(device, send_events_mode); ++ libinput_device_config_send_events_set_mode(device, irule->send_events_mode); + + if (libinput_device_config_accel_is_available(device)) { +- libinput_device_config_accel_set_profile(device, accel_profile); +- libinput_device_config_accel_set_speed(device, accel_speed); ++ libinput_device_config_accel_set_profile(device, irule->accel_profile); ++ libinput_device_config_accel_set_speed(device, irule->accel_speed); + } + } + +@@ -1277,7 +1334,6 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) + wl_list_remove(&group->key.link); + wl_list_remove(&group->modifiers.link); + wl_list_remove(&group->destroy.link); +- free(group); + } + + Monitor * +@@ -1467,6 +1523,7 @@ inputdevice(struct wl_listener *listener, void *data) + * available. */ + struct wlr_input_device *device = data; + uint32_t caps; ++ KeyboardGroup *group; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: +@@ -1485,8 +1542,11 @@ inputdevice(struct wl_listener *listener, void *data) + * there are no pointer devices, so we always include that capability. */ + /* TODO do we actually require a cursor? */ + caps = WL_SEAT_CAPABILITY_POINTER; +- if (!wl_list_empty(&kb_group->wlr_group->devices)) +- caps |= WL_SEAT_CAPABILITY_KEYBOARD; ++ wl_list_for_each(group, &kb_groups, link) ++ if (!wl_list_empty(&group->wlr_group->devices)) { ++ caps |= WL_SEAT_CAPABILITY_KEYBOARD; ++ break; ++ } + wlr_seat_set_capabilities(seat, caps); + } + +@@ -2431,6 +2491,7 @@ setup(void) + */ + wl_list_init(&clients); + wl_list_init(&fstack); ++ wl_list_init(&kb_groups); + + xdg_shell = wlr_xdg_shell_create(dpy, 6); + LISTEN_STATIC(&xdg_shell->events.new_surface, createnotify); +@@ -2514,8 +2575,7 @@ setup(void) + LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); + LISTEN_STATIC(&seat->events.start_drag, startdrag); + +- kb_group = createkeyboardgroup(); +- wl_list_init(&kb_group->destroy.link); ++ createkeyboardgroup(NULL); + + output_mgr = wlr_output_manager_v1_create(dpy); + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); +@@ -2857,10 +2917,9 @@ virtualkeyboard(struct wl_listener *listener, void *data) + { + struct wlr_virtual_keyboard_v1 *kb = data; + /* virtual keyboards shouldn't share keyboard group */ +- KeyboardGroup *group = createkeyboardgroup(); ++ KeyboardGroup *group = createkeyboardgroup(NULL); + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); +- LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup); + + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/pertag/README.md b/dwl/dwl-patches/patches/pertag/README.md new file mode 100755 index 0000000..7473da0 --- /dev/null +++ b/dwl/dwl-patches/patches/pertag/README.md @@ -0,0 +1,12 @@ +### Description +Makes layout, mwfact and nmaster individual for every tag. + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.6/pertag) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/commit/65ea99519bbf7a52f48932aea7385f81f8b30867/patches/pertag/pertag.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/bf098459219e7a473d8edb4c0435aeb6a4b82e38/pertag/pertag.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/3f9a58cde9e3aa02991b3e5a22d371b153cb1459/pertag/pertag.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [Guido Cella](https://github.com/guidocella) diff --git a/dwl/dwl-patches/patches/pertag/pertag.patch b/dwl/dwl-patches/patches/pertag/pertag.patch new file mode 100755 index 0000000..971732a --- /dev/null +++ b/dwl/dwl-patches/patches/pertag/pertag.patch @@ -0,0 +1,170 @@ +From d3b551ffe3ec85e16341962e322150b81af6722f Mon Sep 17 00:00:00 2001 +From: wochap +Date: Wed, 31 Jul 2024 08:27:26 -0500 +Subject: [PATCH] makes layout, mwfact and nmaster individual for every tag + +inspiration: https://github.com/djpohly/dwl/wiki/pertag +--- + dwl.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 70 insertions(+), 5 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 145fd01..2f364bc 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -102,6 +102,7 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct Pertag Pertag; + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -199,6 +200,7 @@ struct Monitor { + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; ++ Pertag *pertag; + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; +@@ -427,6 +429,14 @@ static xcb_atom_t netatom[NetLast]; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++struct Pertag { ++ unsigned int curtag, prevtag; /* current and previous tag */ ++ int nmasters[TAGCOUNT + 1]; /* number of windows in master area */ ++ float mfacts[TAGCOUNT + 1]; /* mfacts per tag */ ++ unsigned int sellts[TAGCOUNT + 1]; /* selected layouts */ ++ const Layout *ltidxs[TAGCOUNT + 1][2]; /* matrix of tags and layouts indexes */ ++}; ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -712,6 +722,7 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); + ++ free(m->pertag); + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); + free(m); +@@ -983,6 +994,18 @@ createmon(struct wl_listener *listener, void *data) + wl_list_insert(&mons, &m->link); + printstatus(); + ++ m->pertag = calloc(1, sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ ++ for (i = 0; i <= TAGCOUNT; i++) { ++ m->pertag->nmasters[i] = m->nmaster; ++ m->pertag->mfacts[i] = m->mfact; ++ ++ m->pertag->ltidxs[i][0] = m->lt[0]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ } ++ + /* The xdg-protocol specifies: + * + * If the fullscreened surface is not opaque, the compositor must make +@@ -1472,7 +1495,7 @@ incnmaster(const Arg *arg) + { + if (!arg || !selmon) + return; +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -2305,9 +2328,9 @@ setlayout(const Arg *arg) + if (!selmon) + return; + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; + if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); + printstatus(); +@@ -2324,7 +2347,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f; + if (f < 0.1 || f > 0.9) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); + } + +@@ -2701,9 +2724,29 @@ void + toggleview(const Arg *arg) + { + uint32_t newtagset; ++ size_t i; + if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) + return; + ++ if (newtagset == (uint32_t)~0) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = 0; ++ } ++ ++ /* test if the user did not select the same tag */ ++ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ for (i = 0; !(newtagset & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ ++ /* apply settings for this view */ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); +@@ -2892,11 +2935,33 @@ urgent(struct wl_listener *listener, void *data) + void + view(const Arg *arg) + { ++ size_t i, tmptag; ++ + if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if (arg->ui & ~0) { + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ ++ if (arg->ui == TAGMASK) ++ selmon->pertag->curtag = 0; ++ else { ++ for (i = 0; !(arg->ui & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ } else { ++ tmptag = selmon->pertag->prevtag; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = tmptag; ++ } ++ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/pointer-gestures-unstable-v1/README.md b/dwl/dwl-patches/patches/pointer-gestures-unstable-v1/README.md new file mode 100755 index 0000000..3ca5432 --- /dev/null +++ b/dwl/dwl-patches/patches/pointer-gestures-unstable-v1/README.md @@ -0,0 +1,16 @@ +### Description +Forward the following events to client: +swipe_begin, swipe_update, swipe_end, pinch_begin, pinch_update and pinch_end + +This patch allows you to pinch zoom in Chrome, for example. In combination with the following patches [gestures](https://codeberg.org/dwl/dwl-patches/wiki/gestures) and [shiftview](https://codeberg.org/dwl/dwl-patches/wiki/shiftview), it would allow you to switch workspaces by performing a 3-finger swipe on your touchpad. + + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/pointer-gestures-unstable-v1) +- [2024-07-12](https://codeberg.org/dwl/dwl-patches/raw/commit/05dbce217b676e989b0fc9e0eecf83b386ac9e07/patches/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/2322f3efeae8da44227e0acc760ffd3dea153716/patches/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/c676de59d51e613bd52ac46c77a24b1cac9a61a1/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/fc4146f3068dcd46035a2a11fe9d6109a97ae6d6/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch b/dwl/dwl-patches/patches/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch new file mode 100755 index 0000000..f76648a --- /dev/null +++ b/dwl/dwl-patches/patches/pointer-gestures-unstable-v1/pointer-gestures-unstable-v1.patch @@ -0,0 +1,186 @@ +From be7e98d28fc59aab67026e7d5efdcaeb26029713 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 12 Jul 2024 11:30:17 -0500 +Subject: [PATCH] implement pointer-gestures-unstable-v1 + +--- + dwl.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 136 insertions(+) + +diff --git a/dwl.c b/dwl.c +index dc0437e..e5805b1 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -250,6 +251,14 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); ++static void swipe_begin(struct wl_listener *listener, void *data); ++static void swipe_update(struct wl_listener *listener, void *data); ++static void swipe_end(struct wl_listener *listener, void *data); ++static void pinch_begin(struct wl_listener *listener, void *data); ++static void pinch_update(struct wl_listener *listener, void *data); ++static void pinch_end(struct wl_listener *listener, void *data); ++static void hold_begin(struct wl_listener *listener, void *data); ++static void hold_end(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); + static void cleanup(void); +@@ -383,6 +392,7 @@ static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; + static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; + static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; + static struct wlr_output_power_manager_v1 *power_mgr; ++static struct wlr_pointer_gestures_v1 *pointer_gestures; + + static struct wlr_pointer_constraints_v1 *pointer_constraints; + static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; +@@ -644,6 +654,122 @@ buttonpress(struct wl_listener *listener, void *data) + event->time_msec, event->button, event->state); + } + ++void ++swipe_begin(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_swipe_begin_event *event = data; ++ ++ // Forward swipe begin event to client ++ wlr_pointer_gestures_v1_send_swipe_begin( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->fingers ++ ); ++} ++ ++void ++swipe_update(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_swipe_update_event *event = data; ++ ++ // Forward swipe update event to client ++ wlr_pointer_gestures_v1_send_swipe_update( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->dx, ++ event->dy ++ ); ++} ++ ++void ++swipe_end(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_swipe_end_event *event = data; ++ ++ // Forward swipe end event to client ++ wlr_pointer_gestures_v1_send_swipe_end( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->cancelled ++ ); ++} ++ ++void ++pinch_begin(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_pinch_begin_event *event = data; ++ ++ // Forward pinch begin event to client ++ wlr_pointer_gestures_v1_send_pinch_begin( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->fingers ++ ); ++} ++ ++void ++pinch_update(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_pinch_update_event *event = data; ++ ++ // Forward pinch update event to client ++ wlr_pointer_gestures_v1_send_pinch_update( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->dx, ++ event->dy, ++ event->scale, ++ event->rotation ++ ); ++} ++ ++void ++pinch_end(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_pinch_end_event *event = data; ++ ++ // Forward pinch end event to client ++ wlr_pointer_gestures_v1_send_pinch_end( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->cancelled ++ ); ++} ++ ++void ++hold_begin(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_hold_begin_event *event = data; ++ ++ // Forward hold begin event to client ++ wlr_pointer_gestures_v1_send_hold_begin( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->fingers ++ ); ++} ++ ++void ++hold_end(struct wl_listener *listener, void *data) ++{ ++ struct wlr_pointer_hold_end_event *event = data; ++ ++ // Forward hold end event to client ++ wlr_pointer_gestures_v1_send_hold_end( ++ pointer_gestures, ++ seat, ++ event->time_msec, ++ event->cancelled ++ ); ++} ++ + void + chvt(const Arg *arg) + { +@@ -2556,6 +2682,16 @@ setup(void) + virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); + ++ pointer_gestures = wlr_pointer_gestures_v1_create(dpy); ++ LISTEN_STATIC(&cursor->events.swipe_begin, swipe_begin); ++ LISTEN_STATIC(&cursor->events.swipe_update, swipe_update); ++ LISTEN_STATIC(&cursor->events.swipe_end, swipe_end); ++ LISTEN_STATIC(&cursor->events.pinch_begin, pinch_begin); ++ LISTEN_STATIC(&cursor->events.pinch_update, pinch_update); ++ LISTEN_STATIC(&cursor->events.pinch_end, pinch_end); ++ LISTEN_STATIC(&cursor->events.hold_begin, hold_begin); ++ LISTEN_STATIC(&cursor->events.hold_end, hold_end); ++ + seat = wlr_seat_create(dpy, "seat0"); + LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); + LISTEN_STATIC(&seat->events.request_set_selection, setsel); +-- +2.45.1 diff --git a/dwl/dwl-patches/patches/primaryselection/README.md b/dwl/dwl-patches/patches/primaryselection/README.md new file mode 100755 index 0000000..1154452 --- /dev/null +++ b/dwl/dwl-patches/patches/primaryselection/README.md @@ -0,0 +1,10 @@ +### Description +Adds a config option to disable/enable primary selection (middle-click paste). + +### Download +- [git branch](https://codeberg.org/nullsystem/dwl/src/branch/main_primaryselection) +- [2024-04-06](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/primaryselection/primaryselection.patch) + +### Authors +- [nullsystem](https://codeberg.org/nullsystem) +- [Palanix](https://github.com/PalanixYT) - Previous Primary-Selection patch diff --git a/dwl/dwl-patches/patches/primaryselection/primaryselection.patch b/dwl/dwl-patches/patches/primaryselection/primaryselection.patch new file mode 100755 index 0000000..ab6bb64 --- /dev/null +++ b/dwl/dwl-patches/patches/primaryselection/primaryselection.patch @@ -0,0 +1,50 @@ +From 4fc77fde2f6015564544e029f9905fc1678fcb59 Mon Sep 17 00:00:00 2001 +From: nullsystem +Date: Sat, 6 Apr 2024 14:19:44 +0100 +Subject: [PATCH] primaryselection - disable/enable primary selection + +* Just simply adds a config to disable/enable primary selection +--- + config.def.h | 1 + + dwl.c | 6 ++++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 8847e58..057e1c3 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -66,6 +66,7 @@ static const int natural_scrolling = 0; + static const int disable_while_typing = 1; + static const int left_handed = 0; + static const int middle_button_emulation = 0; ++static const int enable_primary_selection = 0; + /* You can choose between: + LIBINPUT_CONFIG_SCROLL_NO_SCROLL + LIBINPUT_CONFIG_SCROLL_2FG +diff --git a/dwl.c b/dwl.c +index bf763df..7e8d8f2 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2339,7 +2339,8 @@ setup(void) + wlr_export_dmabuf_manager_v1_create(dpy); + wlr_screencopy_manager_v1_create(dpy); + wlr_data_control_manager_v1_create(dpy); +- wlr_primary_selection_v1_device_manager_create(dpy); ++ if (enable_primary_selection) ++ wlr_primary_selection_v1_device_manager_create(dpy); + wlr_viewporter_create(dpy); + wlr_single_pixel_buffer_manager_v1_create(dpy); + wlr_fractional_scale_manager_v1_create(dpy, 1); +@@ -2449,7 +2450,8 @@ setup(void) + seat = wlr_seat_create(dpy, "seat0"); + LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); + LISTEN_STATIC(&seat->events.request_set_selection, setsel); +- LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel); ++ if (enable_primary_selection) ++ LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel); + LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); + LISTEN_STATIC(&seat->events.start_drag, startdrag); + +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/push/README.md b/dwl/dwl-patches/patches/push/README.md new file mode 100755 index 0000000..5582bfd --- /dev/null +++ b/dwl/dwl-patches/patches/push/README.md @@ -0,0 +1,11 @@ +### Description +Adds functions `pushup` and `pushdown` to move windows within the tiling order. + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/push) +- [2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/push/push.patch) +- [push-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/push/push-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) +- [Devin J. Pohly](https://github.com/djpohly) diff --git a/dwl/dwl-patches/patches/push/push-0.7.patch b/dwl/dwl-patches/patches/push/push-0.7.patch new file mode 100755 index 0000000..4afad97 --- /dev/null +++ b/dwl/dwl-patches/patches/push/push-0.7.patch @@ -0,0 +1,127 @@ +From 01290daca2b01131c5c022389afd0b593b4707eb Mon Sep 17 00:00:00 2001 +From: "Devin J. Pohly" +Date: Thu, 4 Mar 2021 00:45:50 -0600 +Subject: [PATCH] port dwm "push" patch to dwl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + Makefile | 2 +- + dwl.c | 2 ++ + push.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + push.h | 4 ++++ + 4 files changed, 70 insertions(+), 1 deletion(-) + create mode 100644 push.c + create mode 100644 push.h + +diff --git a/Makefile b/Makefile +index 3358bae9..87bf3160 100644 +--- a/Makefile ++++ b/Makefile +@@ -19,7 +19,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + all: dwl + dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ +-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ ++dwl.o: dwl.c client.h config.h config.mk push.h cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h + util.o: util.c util.h +diff --git a/dwl.c b/dwl.c +index a2711f67..c3d78aa3 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -427,7 +427,9 @@ static xcb_atom_t netatom[NetLast]; + #endif + + /* configuration, allows nested code to access above variables */ ++#include "push.h" + #include "config.h" ++#include "push.c" + + /* attempt to encapsulate suck into one file */ + #include "client.h" +diff --git a/push.c b/push.c +new file mode 100644 +index 00000000..323c317e +--- /dev/null ++++ b/push.c +@@ -0,0 +1,63 @@ ++static Client * ++nexttiled(Client *sel) { ++ Client *c; ++ wl_list_for_each(c, &sel->link, link) { ++ if (&c->link == &clients) ++ break; /* don't wrap */ ++ if (!c->isfloating && VISIBLEON(c, selmon)) ++ return c; ++ } ++ return NULL; ++} ++ ++static Client * ++prevtiled(Client *sel) { ++ Client *c; ++ wl_list_for_each_reverse(c, &sel->link, link) { ++ if (&c->link == &clients) ++ break; /* don't wrap */ ++ if (!c->isfloating && VISIBLEON(c, selmon)) ++ return c; ++ } ++ return NULL; ++} ++ ++static void ++pushup(const Arg *arg) { ++ Client *sel = focustop(selmon); ++ Client *c; ++ ++ if(!sel || sel->isfloating) ++ return; ++ if((c = prevtiled(sel))) { ++ /* attach before c */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(c->link.prev, &sel->link); ++ } else { ++ /* move to the end */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(clients.prev, &sel->link); ++ } ++ focusclient(sel, 1); ++ arrange(selmon); ++} ++ ++static void ++pushdown(const Arg *arg) { ++ Client *sel = focustop(selmon); ++ Client *c; ++ ++ if(!sel || sel->isfloating) ++ return; ++ if((c = nexttiled(sel))) { ++ /* attach after c */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(&c->link, &sel->link); ++ } else { ++ /* move to the front */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(&clients, &sel->link); ++ } ++ focusclient(sel, 1); ++ arrange(selmon); ++} +diff --git a/push.h b/push.h +new file mode 100644 +index 00000000..59c0f80e +--- /dev/null ++++ b/push.h +@@ -0,0 +1,4 @@ ++static Client *nexttiled(Client *sel); ++static Client *prevtiled(Client *sel); ++static void pushdown(const Arg *arg); ++static void pushup(const Arg *arg); +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/push/push.patch b/dwl/dwl-patches/patches/push/push.patch new file mode 100755 index 0000000..5f6cba9 --- /dev/null +++ b/dwl/dwl-patches/patches/push/push.patch @@ -0,0 +1,127 @@ +From 06d86c26da60e4196ec3c5228b04c66ac042a1f8 Mon Sep 17 00:00:00 2001 +From: "Devin J. Pohly" +Date: Thu, 4 Mar 2021 00:45:50 -0600 +Subject: [PATCH] port dwm "push" patch to dwl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + Makefile | 2 +- + dwl.c | 2 ++ + push.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + push.h | 4 ++++ + 4 files changed, 70 insertions(+), 1 deletion(-) + create mode 100644 push.c + create mode 100644 push.h + +diff --git a/Makefile b/Makefile +index 578194f2..f919a61e 100644 +--- a/Makefile ++++ b/Makefile +@@ -19,7 +19,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) + all: dwl + dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ +-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ ++dwl.o: dwl.c client.h config.h config.mk push.h cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h + util.o: util.c util.h +diff --git a/dwl.c b/dwl.c +index ad21e1ba..69753921 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -450,7 +450,9 @@ static struct wlr_xwayland *xwayland; + #endif + + /* configuration, allows nested code to access above variables */ ++#include "push.h" + #include "config.h" ++#include "push.c" + + /* attempt to encapsulate suck into one file */ + #include "client.h" +diff --git a/push.c b/push.c +new file mode 100644 +index 00000000..323c317e +--- /dev/null ++++ b/push.c +@@ -0,0 +1,63 @@ ++static Client * ++nexttiled(Client *sel) { ++ Client *c; ++ wl_list_for_each(c, &sel->link, link) { ++ if (&c->link == &clients) ++ break; /* don't wrap */ ++ if (!c->isfloating && VISIBLEON(c, selmon)) ++ return c; ++ } ++ return NULL; ++} ++ ++static Client * ++prevtiled(Client *sel) { ++ Client *c; ++ wl_list_for_each_reverse(c, &sel->link, link) { ++ if (&c->link == &clients) ++ break; /* don't wrap */ ++ if (!c->isfloating && VISIBLEON(c, selmon)) ++ return c; ++ } ++ return NULL; ++} ++ ++static void ++pushup(const Arg *arg) { ++ Client *sel = focustop(selmon); ++ Client *c; ++ ++ if(!sel || sel->isfloating) ++ return; ++ if((c = prevtiled(sel))) { ++ /* attach before c */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(c->link.prev, &sel->link); ++ } else { ++ /* move to the end */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(clients.prev, &sel->link); ++ } ++ focusclient(sel, 1); ++ arrange(selmon); ++} ++ ++static void ++pushdown(const Arg *arg) { ++ Client *sel = focustop(selmon); ++ Client *c; ++ ++ if(!sel || sel->isfloating) ++ return; ++ if((c = nexttiled(sel))) { ++ /* attach after c */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(&c->link, &sel->link); ++ } else { ++ /* move to the front */ ++ wl_list_remove(&sel->link); ++ wl_list_insert(&clients, &sel->link); ++ } ++ focusclient(sel, 1); ++ arrange(selmon); ++} +diff --git a/push.h b/push.h +new file mode 100644 +index 00000000..59c0f80e +--- /dev/null ++++ b/push.h +@@ -0,0 +1,4 @@ ++static Client *nexttiled(Client *sel); ++static Client *prevtiled(Client *sel); ++static void pushdown(const Arg *arg); ++static void pushup(const Arg *arg); +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/regexrules/README.md b/dwl/dwl-patches/patches/regexrules/README.md new file mode 100755 index 0000000..8c014b2 --- /dev/null +++ b/dwl/dwl-patches/patches/regexrules/README.md @@ -0,0 +1,19 @@ +### Description +Allows the use of regular expressions for window rules "app_id" and "title" + +```c +static const Rule rules[] = { + // ... + { "kitty-htop", NULL, 1 << 8, 0, -1 }, + { "^kitty$", NULL, 0, 0, -1 }, + // ... +}; +``` + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/regexrules) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/2a6560c167e5c9afc5598ac5431d23d90de8846c/regexrules/regexrules.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/98cba933c9f4099202e54f39acbf17e05bde828a/regexrules/regexrules.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/regexrules/regexrules.patch b/dwl/dwl-patches/patches/regexrules/regexrules.patch new file mode 100755 index 0000000..f7207d3 --- /dev/null +++ b/dwl/dwl-patches/patches/regexrules/regexrules.patch @@ -0,0 +1,76 @@ +From 7fed9449575b1e4f58d519d2f87b7e66e2056125 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Thu, 11 Apr 2024 12:45:47 -0500 +Subject: [PATCH] implement regex support in rules for app_id and title Enables + the use of regular expressions for window rules "app_id" and "title" + +--- + config.def.h | 1 + + dwl.c | 19 +++++++++++++++++-- + 2 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 8847e58..89f5b60 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -25,6 +25,7 @@ static const Rule rules[] = { + /* examples: */ + { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "^kitty_EXAMPLE$", NULL, 0, 0, -1 }, + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index bf763df..fc185af 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -347,6 +348,7 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static int regex_match(const char *pattern, const char *str); + + /* variables */ + static const char broken[] = "broken"; +@@ -459,8 +461,8 @@ applyrules(Client *c) + title = broken; + + for (r = rules; r < END(rules); r++) { +- if ((!r->title || strstr(title, r->title)) +- && (!r->id || strstr(appid, r->id))) { ++ if ((!r->title || regex_match(r->title, title)) ++ && (!r->id || regex_match(r->id, appid))) { + c->isfloating = r->isfloating; + newtags |= r->tags; + i = 0; +@@ -2929,6 +2931,19 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++int ++regex_match(const char *pattern, const char *str) { ++ regex_t regex; ++ int reti; ++ if (regcomp(®ex, pattern, REG_EXTENDED) != 0) ++ return 0; ++ reti = regexec(®ex, str, (size_t)0, NULL, 0); ++ regfree(®ex); ++ if (reti == 0) ++ return 1; ++ return 0; ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +-- +2.43.2 diff --git a/dwl/dwl-patches/patches/regions/README.md b/dwl/dwl-patches/patches/regions/README.md new file mode 100755 index 0000000..8b5679a --- /dev/null +++ b/dwl/dwl-patches/patches/regions/README.md @@ -0,0 +1,11 @@ +### Description +This patch will allow for a program to be used and have the current window regions on all monitors to be passed to the program as standard input. + +example is `grim -g "$(slurp)"` + +### Download +- [git branch](https://codeberg.org/sewn/dwl/src/branch/regions) +- [2024-02-14](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/regions/regions.patch) + +### Authors +- [sewn](https://github.com/apprehensions) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/regions/regions.patch b/dwl/dwl-patches/patches/regions/regions.patch new file mode 100755 index 0000000..207c0bd --- /dev/null +++ b/dwl/dwl-patches/patches/regions/regions.patch @@ -0,0 +1,71 @@ +From 9991f8bbf2e379dfca8eb356c03d3d20085255a8 Mon Sep 17 00:00:00 2001 +From: sewn +Date: Sun, 23 Jul 2023 08:13:52 +0300 +Subject: [PATCH] pass window regions to given program as stdin + +--- + config.def.h | 1 + + dwl.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 29 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 9009517..79d0236 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -122,6 +122,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY, XKB_KEY_r, regions, SHCMD("grim -g \"$(slurp)\"") }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index fa76db2..9588e36 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -334,6 +334,7 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void regions(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +@@ -2823,6 +2824,33 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++void ++regions(const Arg *arg) ++{ ++ int pipefd[2]; ++ Client *c; ++ Monitor *m; ++ ++ if (pipe(pipefd) == -1) ++ return; ++ if (fork() == 0) { ++ close(pipefd[1]); ++ dup2(pipefd[0], STDIN_FILENO); ++ close(pipefd[0]); ++ setsid(); ++ execvp(((char **)arg->v)[0], (char **)arg->v); ++ die("dwl: execvp %s failed:", ((char **)arg->v)[0]); ++ } ++ ++ close(pipefd[0]); ++ wl_list_for_each(m, &mons, link) ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m)) ++ dprintf(pipefd[1], "%d,%d %dx%d\n", ++ c->geom.x, c->geom.y, c->geom.width, c->geom.height); ++ close(pipefd[1]); ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +-- +2.43.1 + diff --git a/dwl/dwl-patches/patches/relative-mouse-resize/README.md b/dwl/dwl-patches/patches/relative-mouse-resize/README.md new file mode 100755 index 0000000..ee462ce --- /dev/null +++ b/dwl/dwl-patches/patches/relative-mouse-resize/README.md @@ -0,0 +1,13 @@ +### Description +When resizing windows, the mouse will jump and resize the window in the quadrant that the resize starts at. + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/relative-mouse-resize) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/0bd725d0786248e1dfedbe6aa7453edfe736de43/patches/relative-mouse-resize/relative-mouse-resize.patch) +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/655fd2916c1bcaa022ce6dcdfb370051cf64df66/relative-mouse-resize/relative-mouse-resize.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/b828e21717fa584affeb3245359c3ab615759fa4/relative-mouse-resize/relative-mouse-resize.patch) +- [v0.4](https://codeberg.org/schance995/dwl/commit/c9a0c55daeb5c75cc0defa9b82f82eccd13f06c7.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [schance995](https://codeberg.org/schance995) diff --git a/dwl/dwl-patches/patches/relative-mouse-resize/relative-mouse-resize.patch b/dwl/dwl-patches/patches/relative-mouse-resize/relative-mouse-resize.patch new file mode 100755 index 0000000..e1dfc57 --- /dev/null +++ b/dwl/dwl-patches/patches/relative-mouse-resize/relative-mouse-resize.patch @@ -0,0 +1,102 @@ +From 5c75c67fe49e5ab89e4a61dfb2fe74c768477b90 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 5 Jul 2024 11:13:53 -0500 +Subject: [PATCH] implement relative-muse-resize + +--- + dwl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 59 insertions(+), 7 deletions(-) + +diff --git a/dwl.c b/dwl.c +index dc0437e..ebf9ef1 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -401,7 +401,8 @@ static struct wlr_seat *seat; + static KeyboardGroup *kb_group; + static unsigned int cursor_mode; + static Client *grabc; +-static int grabcx, grabcy; /* client-relative */ ++static Client initial_grabc; ++static int grabcx, grabcy, grabx, graby, grabcenterx, grabcentery; /* client-relative */ + + static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; +@@ -1821,8 +1822,27 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + .width = grabc->geom.width, .height = grabc->geom.height}, 1); + return; + } else if (cursor_mode == CurResize) { +- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); ++ if (grabcenterx < grabx) { ++ if (grabcentery < graby) { ++ /* bottom-right */ ++ resize(grabc, (struct wlr_box){.x = initial_grabc.geom.x, .y = initial_grabc.geom.y, ++ .width = (int)round(cursor->x) - initial_grabc.geom.x, .height = (int)round(cursor->y) - initial_grabc.geom.y}, 1); ++ } else { ++ /* top-right */ ++ resize(grabc, (struct wlr_box){.x = initial_grabc.geom.x, .y = (int)round(cursor->y), ++ .width = (int)round(cursor->x) - initial_grabc.geom.x, .height = initial_grabc.geom.y + initial_grabc.geom.height - (int)round(cursor->y)}, 1); ++ } ++ } else { ++ if (grabcentery < graby) { ++ /* bottom-left */ ++ resize(grabc, (struct wlr_box){.x = (int)round(cursor->x), .y = initial_grabc.geom.y, ++ .width = initial_grabc.geom.x + initial_grabc.geom.width - (int)round(cursor->x), .height = (int)round(cursor->y) - initial_grabc.geom.y}, 1); ++ } else { ++ /* top-left */ ++ resize(grabc, (struct wlr_box){.x = (int)round(cursor->x), .y = (int)round(cursor->y), ++ .width = initial_grabc.geom.x + initial_grabc.geom.width - (int)round(cursor->x), .height = initial_grabc.geom.y + initial_grabc.geom.height - (int)round(cursor->y)}, 1); ++ } ++ } + return; + } + +@@ -1870,10 +1890,42 @@ moveresize(const Arg *arg) + case CurResize: + /* Doesn't work for X11 output - the next absolute motion event + * returns the cursor to where it started */ +- wlr_cursor_warp_closest(cursor, NULL, +- grabc->geom.x + grabc->geom.width, +- grabc->geom.y + grabc->geom.height); +- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); ++ initial_grabc = *grabc; ++ grabx = (int)round(cursor->x); ++ graby = (int)round(cursor->y); ++ grabcx = (int)round(cursor->x) - grabc->geom.x; ++ grabcy = (int)round(cursor->y) - grabc->geom.y; ++ grabcenterx = grabc->geom.width / 2 + grabc->geom.x; ++ grabcentery = grabc->geom.height / 2 + grabc->geom.y; ++ if (grabcenterx < grabx) { ++ if (grabcentery < graby) { ++ /* bottom-right */ ++ wlr_cursor_warp_closest(cursor, NULL, ++ grabc->geom.x + grabc->geom.width, ++ grabc->geom.y + grabc->geom.height); ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); ++ } else { ++ /* top-right */ ++ wlr_cursor_warp_closest(cursor, NULL, ++ grabc->geom.x + grabc->geom.width, ++ grabc->geom.y); ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "ne-resize"); ++ } ++ } else { ++ if (grabcentery < graby) { ++ /* bottom-left */ ++ wlr_cursor_warp_closest(cursor, NULL, ++ grabc->geom.x, ++ grabc->geom.y + grabc->geom.height); ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "sw-resize"); ++ } else { ++ /* top-left */ ++ wlr_cursor_warp_closest(cursor, NULL, ++ grabc->geom.x, ++ grabc->geom.y); ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, "nw-resize"); ++ } ++ } + break; + } + } +-- +2.45.1 \ No newline at end of file diff --git a/dwl/dwl-patches/patches/restore-monitor/README.md b/dwl/dwl-patches/patches/restore-monitor/README.md new file mode 100755 index 0000000..8380967 --- /dev/null +++ b/dwl/dwl-patches/patches/restore-monitor/README.md @@ -0,0 +1,8 @@ +### Description +Moves clients to their old output when it is reattached. + +### Download +- [git branch](https://codeberg.org/eyusupov/dwl/src/branch/restore-monitor) +- [2024-04-07](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/restore-monitor/restore-monitor.patch) +### Authors +- [eyusupov](https://codeberg.org/eyusupov) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/restore-monitor/restore-monitor.patch b/dwl/dwl-patches/patches/restore-monitor/restore-monitor.patch new file mode 100755 index 0000000..0d6da98 --- /dev/null +++ b/dwl/dwl-patches/patches/restore-monitor/restore-monitor.patch @@ -0,0 +1,82 @@ +From e42ca1c539437d3098d80983cfe2ad6f938d7a08 Mon Sep 17 00:00:00 2001 +From: Eldar Yusupov +Date: Sun, 17 Mar 2024 19:12:29 +0300 +Subject: [PATCH] Restore correct montior for client when it is reattached + +--- + dwl.c | 24 ++++++++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index bf763df..d8d8139 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -107,6 +107,7 @@ typedef struct { + unsigned int type; /* XDGShell or X11* */ + struct wlr_box geom; /* layout-relative, includes border */ + Monitor *mon; ++ char *output; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; +@@ -869,6 +870,7 @@ createmon(struct wl_listener *listener, void *data) + size_t i; + struct wlr_output_state state; + Monitor *m; ++ Client *c; + + if (!wlr_output_init_render(wlr_output, alloc, drw)) + return; +@@ -938,6 +940,13 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_layout_add_auto(output_layout, wlr_output); + else + wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); ++ ++ wl_list_for_each(c, &clients, link) { ++ if (strcmp(wlr_output->name, c->output) == 0) { ++ c->mon = m; ++ } ++ } ++ updatemons(NULL, NULL); + } + + void +@@ -1186,6 +1195,7 @@ destroynotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->map.link); + wl_list_remove(&c->unmap.link); + } ++ free(c->output); + free(c); + } + +@@ -1618,6 +1628,10 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } ++ c->output = strdup(c->mon->wlr_output->name); ++ if (c->output == NULL) { ++ die("oom"); ++ } + printstatus(); + + unset_fullscreen: +@@ -2565,8 +2579,14 @@ void + tagmon(const Arg *arg) + { + Client *sel = focustop(selmon); +- if (sel) +- setmon(sel, dirtomon(arg->i), 0); ++ if (!sel) ++ return; ++ setmon(sel, dirtomon(arg->i), 0); ++ free(sel->output); ++ sel->output = strdup(sel->mon->wlr_output->name); ++ if (sel->output == NULL) { ++ die("oom"); ++ } + } + + void +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/right/README.md b/dwl/dwl-patches/patches/right/README.md new file mode 100755 index 0000000..7708ded --- /dev/null +++ b/dwl/dwl-patches/patches/right/README.md @@ -0,0 +1,8 @@ +### Description +Put newly connected monitors on the right, like X does. + +### Download +- [2024-02-11](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/right/right.patch) + +### Authors +- [Dima Krasner](https://codeberg.org/dimkr) () diff --git a/dwl/dwl-patches/patches/right/right.patch b/dwl/dwl-patches/patches/right/right.patch new file mode 100755 index 0000000..baf8eeb --- /dev/null +++ b/dwl/dwl-patches/patches/right/right.patch @@ -0,0 +1,50 @@ +From 9d4b0ebb95381525351b05aad6a98f1747ae96e2 Mon Sep 17 00:00:00 2001 +From: Dima Krasner +Date: Thu, 21 Jul 2022 21:14:14 +0300 +Subject: [PATCH] extend the display to the right + +--- + dwl.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index d48bf40..fb795e1 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -923,7 +923,8 @@ createmon(struct wl_listener *listener, void *data) + const MonitorRule *r; + size_t i; + struct wlr_output_state state; +- Monitor *m; ++ Monitor *om, *m; ++ int max_x = 0, max_x_y = 0, width, height; + + if (!wlr_output_init_render(wlr_output, alloc, drw)) + return; +@@ -967,6 +968,14 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + ++ wl_list_for_each(om, &mons, link) { ++ wlr_output_effective_resolution(om->wlr_output, &width, &height); ++ if (om->m.x + width > max_x) { ++ max_x = om->m.x + width; ++ max_x_y = om->m.y; ++ } ++ } ++ + wl_list_insert(&mons, &m->link); + printstatus(); + +@@ -990,7 +999,7 @@ createmon(struct wl_listener *listener, void *data) + */ + m->scene_output = wlr_scene_output_create(scene, wlr_output); + if (m->m.x == -1 && m->m.y == -1) +- wlr_output_layout_add_auto(output_layout, wlr_output); ++ wlr_output_layout_add(output_layout, wlr_output, max_x, max_x_y); + else + wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); + } +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/rlimit_max/README.md b/dwl/dwl-patches/patches/rlimit_max/README.md new file mode 100755 index 0000000..2bf7355 --- /dev/null +++ b/dwl/dwl-patches/patches/rlimit_max/README.md @@ -0,0 +1,11 @@ +### Description +Sets the current maximum open file descriptors to the maximum available limit. + +This patch is useful - and solves issue [#628](https://codeberg.org/dwl/dwl/issues/628) for running heavy Xwayland applications on systems that do not provide limits out of the box. + +### Download +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/rlimit_max/rlimit_max.patch) + +### Authors +- [sewn](https://codeberg.org/sewn) + diff --git a/dwl/dwl-patches/patches/rlimit_max/rlimit_max.patch b/dwl/dwl-patches/patches/rlimit_max/rlimit_max.patch new file mode 100755 index 0000000..81111b3 --- /dev/null +++ b/dwl/dwl-patches/patches/rlimit_max/rlimit_max.patch @@ -0,0 +1,91 @@ +From d25a8222651671613322677d17b2f987135e02cd Mon Sep 17 00:00:00 2001 +From: sewn +Date: Sat, 24 Aug 2024 19:26:26 +0300 +Subject: [PATCH] set max open file descriptors to available max + +--- + dwl.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/dwl.c b/dwl.c +index a2711f6..163ebdd 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -316,6 +317,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface, + static void printstatus(void); + static void powermgrsetmode(struct wl_listener *listener, void *data); + static void quit(const Arg *arg); ++static void restorerlimit(void); + static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); +@@ -358,6 +360,7 @@ static void zoom(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; ++static struct rlimit og_rlimit; + static pid_t child_pid = -1; + static int locked; + static void *exclusive_focus; +@@ -2096,6 +2099,15 @@ quit(const Arg *arg) + wl_display_terminate(dpy); + } + ++void ++restorerlimit(void) ++{ ++ if (og_rlimit.rlim_cur == 0) ++ return; ++ if (setrlimit(RLIMIT_NOFILE, &og_rlimit) < 0) ++ die("setrlimit:"); ++} ++ + void + rendermon(struct wl_listener *listener, void *data) + { +@@ -2232,6 +2244,7 @@ run(char *startup_cmd) + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { ++ restorerlimit(); + setsid(); + dup2(piperw[0], STDIN_FILENO); + close(piperw[0]); +@@ -2429,10 +2442,18 @@ setsel(struct wl_listener *listener, void *data) + void + setup(void) + { ++ struct rlimit new_rlimit; + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; + sigemptyset(&sa.sa_mask); + ++ if (getrlimit(RLIMIT_NOFILE, &og_rlimit) < 0) ++ die("getrlimit:"); ++ new_rlimit = og_rlimit; ++ new_rlimit.rlim_cur = new_rlimit.rlim_max; ++ if (setrlimit(RLIMIT_NOFILE, &new_rlimit) < 0) ++ die("setrlimit:"); ++ + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + +@@ -2649,6 +2670,7 @@ void + spawn(const Arg *arg) + { + if (fork() == 0) { ++ restorerlimit(); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/rotate-clients/README.md b/dwl/dwl-patches/patches/rotate-clients/README.md new file mode 100755 index 0000000..aaf8f67 --- /dev/null +++ b/dwl/dwl-patches/patches/rotate-clients/README.md @@ -0,0 +1,14 @@ +### Description +Rotate clients on current monitor. + +Example Configuration: +```c + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, rotate_clients, {.i = +1} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, rotate_clients, {.i = -1} }, +``` + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/rotate-clients/rotate-clients.patch) + +### Authors +- [folk](https://codeberg.org/folk) diff --git a/dwl/dwl-patches/patches/rotate-clients/rotate-clients.patch b/dwl/dwl-patches/patches/rotate-clients/rotate-clients.patch new file mode 100755 index 0000000..8f5f557 --- /dev/null +++ b/dwl/dwl-patches/patches/rotate-clients/rotate-clients.patch @@ -0,0 +1,56 @@ +diff --git a/config.def.h b/config.def.h +index 22d2171..6029666 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -129,6 +129,8 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, rotate_clients, {.i = +1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, rotate_clients, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +diff --git a/dwl.c b/dwl.c +index a2711f6..6dfd87d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -355,6 +355,7 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void rotate_clients(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +@@ -3054,6 +3055,30 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++static void rotate_clients(const Arg *arg) { ++ Monitor* m = selmon; ++ Client *c; ++ Client *first = NULL; ++ Client *last = NULL; ++ ++ if (arg->i == 0) ++ return; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) { ++ if (first == NULL) first = c; ++ last = c; ++ } ++ } ++ if (first != last) { ++ struct wl_list *append_to = (arg->i > 0) ? &last->link : first->link.prev; ++ struct wl_list *elem = (arg->i > 0) ? &first->link : &last->link; ++ wl_list_remove(elem); ++ wl_list_insert(append_to, elem); ++ arrange(selmon); ++ } ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) diff --git a/dwl/dwl-patches/patches/rotatetags/README.md b/dwl/dwl-patches/patches/rotatetags/README.md new file mode 100755 index 0000000..f981847 --- /dev/null +++ b/dwl/dwl-patches/patches/rotatetags/README.md @@ -0,0 +1,9 @@ +### Description +This patch provides the ability to rotate the tagset left / right. It implements a new function rotatetags which modifies the current tagset. Same as original dwm patch. Also adds ability to move focused client to left / right adjacent tag by specifying appropriate enum value as argument. + +### Download +- [git branch](https://codeberg.org/korei999/dwl/src/branch/rotatetags) +- [2024-01-23](https://codeberg.org/korei999/dwl-patches/raw/branch/main/rotatetags/rotatetags.patch) + +### Authors +- [korei999](https://codeberg.org/korei999) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/rotatetags/rotatetags.patch b/dwl/dwl-patches/patches/rotatetags/rotatetags.patch new file mode 100755 index 0000000..94e776f --- /dev/null +++ b/dwl/dwl-patches/patches/rotatetags/rotatetags.patch @@ -0,0 +1,91 @@ +From 308c668010bb7526ea40ad12dbaa1af62f9d7421 Mon Sep 17 00:00:00 2001 +From: korei999 +Date: Tue, 23 Jan 2024 12:01:48 +0200 +Subject: [PATCH] add rotatetags patch + +--- + config.def.h | 13 ++++++++++++- + dwl.c | 29 +++++++++++++++++++++++++++++ + 2 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 9009517..a80207a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -14,6 +14,13 @@ static const float urgentcolor[] = COLOR(0xff0000ff); + /* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ + ++enum { ++ VIEW_L = -1, ++ VIEW_R = 1, ++ SHIFT_L = -2, ++ SHIFT_R = 2, ++} RotateTags; ++ + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + +@@ -125,7 +132,11 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +- { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_i, incnmaster, {.i = -1} }, ++ { MODKEY, XKB_KEY_a, rotatetags, {.i = VIEW_L} }, ++ { MODKEY, XKB_KEY_d, rotatetags, {.i = VIEW_R} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_a, rotatetags, {.i = SHIFT_L} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_d, rotatetags, {.i = SHIFT_R} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, +diff --git a/dwl.c b/dwl.c +index bf02a6d..e737e34 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -332,6 +332,7 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void rotatetags(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +@@ -2798,6 +2799,34 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++static void ++rotatetags(const Arg *arg) ++{ ++ Arg newarg; ++ int i = arg->i; ++ int nextseltags = 0, curseltags = selmon->tagset[selmon->seltags]; ++ bool shift = false; ++ ++ switch(abs(i)) { ++ default: break; ++ case SHIFT_R: ++ shift = true; ++ break; ++ }; ++ ++ if (i > 0) ++ nextseltags = (curseltags << 1) | (curseltags >> (TAGCOUNT - 1)); ++ else ++ nextseltags = (curseltags >> 1) | (curseltags << (TAGCOUNT - 1)); ++ ++ newarg.i = nextseltags; ++ ++ if (shift) ++ tag(&newarg); ++ else ++ view(&newarg); ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/scenefx/README.md b/dwl/dwl-patches/patches/scenefx/README.md new file mode 100755 index 0000000..e1054b3 --- /dev/null +++ b/dwl/dwl-patches/patches/scenefx/README.md @@ -0,0 +1,113 @@ +### Description + +Implement https://github.com/wlrfx/scenefx + +```c +/* available options */ + +static const int opacity = 0; /* flag to enable opacity */ +static const float opacity_inactive = 0.5; +static const float opacity_active = 1.0; + +static const int shadow = 1; /* flag to enable shadow */ +static const int shadow_only_floating = 0; /* only apply shadow to floating windows */ +static const float shadow_color[4] = COLOR(0x0000FFff); +static const float shadow_color_focus[4] = COLOR(0xFF0000ff); +static const int shadow_blur_sigma = 20; +static const int shadow_blur_sigma_focus = 40; +static const char *const shadow_ignore_list[] = { NULL }; /* list of app-id to ignore */ + +static const int corner_radius = 8; /* 0 disables corner_radius */ +static const int corner_radius_inner = 8; /* 0 disables corner_radius */ +static const int corner_radius_only_floating = 0; /* only apply corner_radius and corner_radius_inner to floating windows */ + +static const int blur = 1; /* flag to enable blur */ +static const int blur_xray = 0; /* flag to make transparent fs and floating windows display your background */ +static const int blur_ignore_transparent = 1; +static const struct blur_data blur_data = { + .radius = 5, + .num_passes = 3, + .noise = (float)0.02, + .brightness = (float)0.9, + .contrast = (float)0.9, + .saturation = (float)1.1, +}; +``` + +> **NOTE:** If you are using nix with flakes, scenefx has a flake for scenefx https://github.com/wlrfx/scenefx/blob/main/flake.nix + +> **NOTE:** Blur doesn't work on windows with opacity set (opacity_active, opacity_inactive) + +> **NOTE:** In DWL's Makefile `scenefx-0.2` must be placed before `wlroots-0.18`, e.g. `PKGS = scenefx-0.2 wlroots-0.18 wayland-server ...` + +
+Preview +
+
+
+
+ +### Download + +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.8-a/scenefx-b) + +- [0.8-dev](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/scenefx/scenefx.patch) + + **NOTE:** This patch was tested with the `87c0e8b6d5c86557a800445e8e4c322f387fe19c` commit on the `main` branch of `SceneFX`. It supports rounded borders, blur, and shadows. However, it does not add rounded borders or shadows to Xwayland apps. That said, Xwayland apps can have shadows, and they might also support rounded borders, but I was never able to make it work. PRs are welcome! + + **IMPORTANT:** This patch requires you to build DWL with the following dependencies + + - **scenefx** + - libGL + +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/scenefx/scenefx.patch) + + **IMPORTANT:** This patch only works with the `2ec3505248e819191c37cb831197629f373326fb` commit on the `main` branch of `scenefx`, therefore, it does not support **blur**. + + **IMPORTANT:** This patch requires you to build DWL with the following dependencies + + - **scenefx** + - libGL + +
+ Preview +
+  
+  
+  
+
+ +- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/6e3a57ffd16dafa31900b7e89e51672bd7bcc1e8/scenefx/scenefx.patch) + + **IMPORTANT:** This patch only works with the `de4ec10e1ff9347b5833f00f8615d760d9378c99` commit on the `wlr_scene_blur` branch of `scenefx`, as it adds support for **blur**. + + **IMPORTANT:** This patch requires you to build DWL with the dependencies of WLROOTS: + + - **scenefx** + - libGL + - libcap + - libinput + - libpng + - libxkbcommon + - mesa + - pixman + - seatd + - vulkan-loader + - wayland + - wayland-protocols + - xorg.libX11 + - xorg.xcbutilerrors + - xorg.xcbutilimage + - xorg.xcbutilrenderutil + - xorg.xcbutilwm + - xwayland (optional) + - ffmpeg + - hwdata + - libliftoff + - libdisplay-info + +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/7a5c3420822074c544fa102e030b7c30aa6b6be8/scenefx/scenefx.patch) + +### Authors + +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/scenefx/scenefx.patch b/dwl/dwl-patches/patches/scenefx/scenefx.patch new file mode 100755 index 0000000..c556cb4 --- /dev/null +++ b/dwl/dwl-patches/patches/scenefx/scenefx.patch @@ -0,0 +1,700 @@ +From d209aeaee541a045de9dba2154bbbd5475bba2ec Mon Sep 17 00:00:00 2001 +From: wochap +Date: Sun, 9 Mar 2025 17:26:07 -0500 +Subject: [PATCH] implement scenefx + +--- + Makefile | 2 +- + client.h | 18 +++ + config.def.h | 30 +++- + dwl.c | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 4 files changed, 457 insertions(+), 7 deletions(-) + +diff --git a/Makefile b/Makefile +index 3358bae..8dc79bd 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) ++PKGS = scenefx-0.2 wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + +diff --git a/client.h b/client.h +index 42f225f..4e8f016 100644 +--- a/client.h ++++ b/client.h +@@ -147,6 +147,13 @@ client_get_clip(Client *c, struct wlr_box *clip) + return; + #endif + ++ *clip = (struct wlr_box){ ++ .x = c->bw, ++ .y = c->bw, ++ .width = c->geom.width - c->bw * 2, ++ .height = c->geom.height - c->bw * 2, ++ }; ++ + wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom); + clip->x = xdg_geom.x; + clip->y = xdg_geom.y; +@@ -328,6 +335,17 @@ static inline void + client_set_border_color(Client *c, const float color[static 4]) + { + int i; ++ ++#ifdef XWAYLAND ++ if (!client_is_x11(c)) { ++#endif ++ if (corner_radius > 0) { ++ return; ++ } ++#ifdef XWAYLAND ++ } ++#endif ++ + for (i = 0; i < 4; i++) + wlr_scene_rect_set_color(c->border[i], color); + } +diff --git a/config.def.h b/config.def.h +index 22d2171..8c50932 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,7 +12,35 @@ static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +-static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 0.0f}; /* You can also use glsl colors */ ++ ++static const int opacity = 0; /* flag to enable opacity */ ++static const float opacity_inactive = 0.5; ++static const float opacity_active = 1.0; ++ ++static const int shadow = 1; /* flag to enable shadow */ ++static const int shadow_only_floating = 0; /* only apply shadow to floating windows */ ++static const float shadow_color[4] = COLOR(0x0000FFff); ++static const float shadow_color_focus[4] = COLOR(0xFF0000ff); ++static const int shadow_blur_sigma = 20; ++static const int shadow_blur_sigma_focus = 40; ++static const char *const shadow_ignore_list[] = { NULL }; /* list of app-id to ignore */ ++ ++static const int corner_radius = 8; /* 0 disables corner_radius */ ++static const int corner_radius_inner = 9; /* 0 disables corner_radius */ ++static const int corner_radius_only_floating = 0; /* only apply corner_radius and corner_radius_inner to floating windows */ ++ ++static const int blur = 1; /* flag to enable blur */ ++static const int blur_xray = 0; /* flag to make transparent fs and floating windows display your background */ ++static const int blur_ignore_transparent = 1; ++static const struct blur_data blur_data = { ++ .radius = 5, ++ .num_passes = 3, ++ .noise = (float)0.02, ++ .brightness = (float)0.9, ++ .contrast = (float)0.9, ++ .saturation = (float)1.1, ++}; + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +diff --git a/dwl.c b/dwl.c +index 5bf995e..655e175 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -10,8 +10,14 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + #include + #include ++#include + #include + #include + #include +@@ -43,7 +49,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -83,7 +88,7 @@ + /* enums */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ +-enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { LyrBg, LyrBlur, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -141,6 +146,12 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ ++ float opacity; ++ int corner_radius; ++ struct wlr_scene_shadow *shadow; ++ int has_shadow_enabled; ++ struct wlr_scene_rect *round_border; + } Client; + + typedef struct { +@@ -208,6 +219,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ struct wlr_scene_optimized_blur *blur_layer; + }; + + typedef struct { +@@ -355,6 +367,18 @@ static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); ++static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); ++static void iter_xdg_scene_buffers_blur(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); ++static void iter_xdg_scene_buffers_opacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); ++static void iter_xdg_scene_buffers_corner_radius(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); ++static void output_configure_scene(struct wlr_scene_node *node, Client *c); ++static int in_shadow_ignore_list(const char *str); ++static void client_set_shadow_blur_sigma(Client *c, int blur_sigma); ++static void update_client_corner_radius(Client *c); ++static void update_client_shadow_color(Client *c); ++static void update_client_focus_decorations(Client *c, int focused, int urgent); ++static void update_client_blur(Client *c); ++static void update_buffer_corner_radius(Client *c, struct wlr_scene_buffer *buffer); + + /* variables */ + static const char broken[] = "broken"; +@@ -413,6 +437,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static float transparent[4] = {0.1f, 0.1f, 0.1f, 0.0f}; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -499,6 +525,10 @@ arrange(Monitor *m) + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, + (c = focustop(m)) && c->isfullscreen); + ++ if (blur) { ++ wlr_scene_node_set_enabled(&m->blur_layer->node, 1); ++ } ++ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + + /* We move all clients (except fullscreen and unmanaged) to LyrTile while +@@ -722,6 +752,11 @@ cleanupmon(struct wl_listener *listener, void *data) + + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); ++ ++ if (blur) { ++ wlr_scene_node_destroy(&m->blur_layer->node); ++ } ++ + free(m); + } + +@@ -785,6 +820,18 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) + } + + arrangelayers(l->mon); ++ ++ if (blur) { ++ // Rerender the optimized blur on change ++ struct wlr_layer_surface_v1 *wlr_layer_surface = l->layer_surface; ++ if (wlr_layer_surface->current.layer == ++ ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || ++ wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) { ++ if (l->mon) { ++ wlr_scene_optimized_blur_mark_dirty(l->mon->blur_layer); ++ } ++ } ++ } + } + + void +@@ -1036,6 +1083,12 @@ createmon(struct wl_listener *listener, void *data) + m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); + ++ if (blur) { ++ m->blur_layer = wlr_scene_optimized_blur_create(&scene->tree, 0, 0); ++ wlr_scene_node_reparent(&m->blur_layer->node, layers[LyrBlur]); ++ wlr_scene_node_set_enabled(&m->blur_layer->node, 0); ++ } ++ + /* Adds this to the output layout in the order it was configured. + * + * The output layout utility automatically adds a wl_output global to the +@@ -1061,6 +1114,9 @@ createnotify(struct wl_listener *listener, void *data) + c->surface.xdg = toplevel->base; + c->bw = borderpx; + ++ c->opacity = opacity; ++ c->corner_radius = corner_radius; ++ + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); + LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify); +@@ -1369,8 +1425,11 @@ focusclient(Client *c, int lift) + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +- if (!exclusive_focus && !seat->drag) ++ if (!exclusive_focus && !seat->drag) { + client_set_border_color(c, focuscolor); ++ ++ update_client_focus_decorations(c, 1, 0); ++ } + } + + /* Deactivate old client if focus is changing */ +@@ -1389,6 +1448,8 @@ focusclient(Client *c, int lift) + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, bordercolor); + ++ update_client_focus_decorations(old_c, 0, 0); ++ + client_activate_surface(old, 0); + } + } +@@ -1718,6 +1779,38 @@ mapnotify(struct wl_listener *listener, void *data) + c->border[i]->node.data = c; + } + ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers, c); ++ ++#ifdef XWAYLAND ++ if (!client_is_x11(c)) { ++#endif ++ if (corner_radius > 0) { ++ c->round_border = wlr_scene_rect_create(c->scene, 0, 0, c->isurgent ? urgentcolor : bordercolor); ++ c->round_border->node.data = c; ++ /* Lower the border below the XDG scene tree */ ++ wlr_scene_node_lower_to_bottom(&c->round_border->node); ++ ++ /* hide original border */ ++ for (i = 0; i < 4; i++) { ++ wlr_scene_rect_set_color(c->border[i], transparent); ++ } ++ } ++#ifdef XWAYLAND ++ } ++#endif ++ ++#ifdef XWAYLAND ++ if (!client_is_x11(c)) { ++#endif ++ if (shadow) { ++ c->shadow = wlr_scene_shadow_create(c->scene, 0, 0, c->corner_radius, shadow_blur_sigma, shadow_color); ++ /* Lower the shadow below the border */ ++ wlr_scene_node_lower_to_bottom(&c->shadow->node); ++ } ++#ifdef XWAYLAND ++ } ++#endif ++ + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; +@@ -1739,6 +1832,13 @@ mapnotify(struct wl_listener *listener, void *data) + } + printstatus(); + ++ /* TODO: shouldn't we call iter_xdg_scene_buffers_corner_radius? */ ++ update_client_corner_radius(c); ++ ++ update_client_shadow_color(c); ++ ++ update_client_blur(c); ++ + unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); + wl_list_for_each(w, &clients, link) { +@@ -2113,6 +2213,8 @@ rendermon(struct wl_listener *listener, void *data) + goto skip; + } + ++ output_configure_scene(&m->scene_output->scene->tree.node, NULL); ++ + /* + * HACK: The "correct" way to set the gamma is to commit it together with + * the rest of the state in one go, but to do that we would need to rewrite +@@ -2207,6 +2309,21 @@ resize(Client *c, struct wlr_box geo, int interact) + c->geom.height - 2 * c->bw); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); ++ ++ if (corner_radius > 0 && c->round_border) { ++ wlr_scene_node_set_position(&c->round_border->node, 0, 0); ++ wlr_scene_rect_set_size(c->round_border, c->geom.width, c->geom.height); ++ wlr_scene_rect_set_clipped_region(c->round_border, (struct clipped_region) { ++ .corner_radius = c->corner_radius, ++ .corners = CORNER_LOCATION_ALL, ++ .area = { c->bw, c->bw, c->geom.width - c->bw * 2, c->geom.height - c->bw * 2 } ++ }); ++ } ++ ++ if (shadow && c->shadow) { ++ /* TODO: shouldn't we call wlr_scene_shadow_set_blur_sigma? */ ++ client_set_shadow_blur_sigma(c, (int)round(c->shadow->blur_sigma)); ++ } + } + + void +@@ -2307,6 +2424,13 @@ setfloating(Client *c, int floating) + { + Client *p = client_get_parent(c); + c->isfloating = floating; ++ ++ update_client_corner_radius(c); ++ ++ update_client_shadow_color(c); ++ ++ update_client_blur(c); ++ + /* If in floating layout do not change the client's layer */ + if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange) + return; +@@ -2336,6 +2460,13 @@ setfullscreen(Client *c, int fullscreen) + * client positions are set by the user and cannot be recalculated */ + resize(c, c->prev, 0); + } ++ ++ update_client_corner_radius(c); ++ ++ update_client_shadow_color(c); ++ ++ update_client_blur(c); ++ + arrange(c->mon); + printstatus(); + } +@@ -2457,11 +2588,15 @@ setup(void) + drag_icon = wlr_scene_tree_create(&scene->tree); + wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); + ++ if (blur) { ++ wlr_scene_set_blur_data(scene, blur_data); ++ } ++ + /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user + * can also specify a renderer using the WLR_RENDERER env var. + * The renderer is responsible for defining the various pixel formats it + * supports for shared memory, this configures that for clients. */ +- if (!(drw = wlr_renderer_autocreate(backend))) ++ if (!(drw = fx_renderer_create(backend))) + die("couldn't create renderer"); + LISTEN_STATIC(&drw->events.lost, gpureset); + +@@ -2870,6 +3005,10 @@ updatemons(struct wl_listener *listener, void *data) + + wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); + wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); ++ ++ if (blur) { ++ wlr_scene_optimized_blur_set_size(m->blur_layer, m->m.width, m->m.height); ++ } + + if (m->lock_surface) { + struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; +@@ -2940,8 +3079,11 @@ urgent(struct wl_listener *listener, void *data) + c->isurgent = 1; + printstatus(); + +- if (client_surface(c)->mapped) ++ if (client_surface(c)->mapped) { + client_set_border_color(c, urgentcolor); ++ ++ update_client_focus_decorations(c, 1, 1); ++ } + } + + void +@@ -3053,6 +3195,268 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++void ++iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) ++{ ++ Client *c = user_data; ++ struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); ++ struct wlr_xdg_surface *xdg_surface; ++ ++ if (!scene_surface) { ++ return; ++ } ++ ++ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); ++ ++ if (c && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { ++ /* TODO: Be able to set whole decoration_data instead of calling */ ++ /* each individually? */ ++ if (opacity) { ++ wlr_scene_buffer_set_opacity(buffer, c->opacity); ++ } ++ ++ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { ++ update_buffer_corner_radius(c, buffer); ++ ++ if (blur) { ++ int blur_optimized = !c->isfloating || blur_xray; ++ wlr_scene_buffer_set_backdrop_blur(buffer, 1); ++ wlr_scene_buffer_set_backdrop_blur_optimized(buffer, blur_optimized); ++ wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, blur_ignore_transparent); ++ } ++ } ++ } ++} ++ ++void ++iter_xdg_scene_buffers_blur(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) ++{ ++ Client *c = user_data; ++ struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); ++ struct wlr_xdg_surface *xdg_surface; ++ ++ if (!scene_surface) { ++ return; ++ } ++ ++ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); ++ ++ if (c && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { ++ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { ++ if (blur) { ++ int blur_optimized = !c->isfloating || blur_xray; ++ wlr_scene_buffer_set_backdrop_blur_optimized(buffer, blur_optimized); ++ } ++ } ++ } ++} ++ ++void ++iter_xdg_scene_buffers_opacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) ++{ ++ Client *c = user_data; ++ struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); ++ struct wlr_xdg_surface *xdg_surface; ++ ++ if (!scene_surface) { ++ return; ++ } ++ ++ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); ++ ++ if (c && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { ++ /* TODO: Be able to set whole decoration_data instead of calling */ ++ /* each individually? */ ++ if (opacity) { ++ wlr_scene_buffer_set_opacity(buffer, c->opacity); ++ } ++ } ++} ++ ++void ++iter_xdg_scene_buffers_corner_radius(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) ++{ ++ Client *c = user_data; ++ struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); ++ struct wlr_xdg_surface *xdg_surface; ++ ++ if (!scene_surface) { ++ return; ++ } ++ ++ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); ++ ++ if (c && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { ++ /* TODO: Be able to set whole decoration_data instead of calling */ ++ /* each individually? */ ++ update_buffer_corner_radius(c, buffer); ++ } ++} ++ ++void ++output_configure_scene(struct wlr_scene_node *node, Client *c) ++{ ++ Client *_c; ++ struct wlr_xdg_surface *xdg_surface; ++ struct wlr_scene_node *_node; ++ ++ if (!node->enabled) { ++ return; ++ } ++ ++ _c = node->data; ++ if (_c) { ++ c = _c; ++ } ++ ++ if (node->type == WLR_SCENE_NODE_BUFFER) { ++ struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); ++ ++ struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(buffer); ++ if (!scene_surface) { ++ return; ++ } ++ ++ xdg_surface = wlr_xdg_surface_try_from_wlr_surface(scene_surface->surface); ++ ++ if (c && xdg_surface && xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { ++ if (opacity) { ++ wlr_scene_buffer_set_opacity(buffer, c->opacity); ++ } ++ ++ if (!wlr_subsurface_try_from_wlr_surface(xdg_surface->surface)) { ++ update_buffer_corner_radius(c, buffer); ++ } ++ } ++ } else if (node->type == WLR_SCENE_NODE_TREE) { ++ struct wlr_scene_tree *tree = wl_container_of(node, tree, node); ++ wl_list_for_each(_node, &tree->children, link) { ++ output_configure_scene(_node, c); ++ } ++ } ++} ++ ++int ++in_shadow_ignore_list(const char *str) ++{ ++ for (int i = 0; shadow_ignore_list[i] != NULL; i++) { ++ if (strcmp(shadow_ignore_list[i], str) == 0) { ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++void ++client_set_shadow_blur_sigma(Client *c, int blur_sigma) ++{ ++ wlr_scene_shadow_set_blur_sigma(c->shadow, blur_sigma); ++ wlr_scene_node_set_position(&c->shadow->node, -blur_sigma, -blur_sigma); ++ wlr_scene_shadow_set_size(c->shadow, c->geom.width + blur_sigma * 2, c->geom.height + blur_sigma * 2); ++ wlr_scene_shadow_set_clipped_region(c->shadow, (struct clipped_region) { ++ .corner_radius = c->corner_radius + c->bw, ++ .corners = CORNER_LOCATION_ALL, ++ .area = { blur_sigma, blur_sigma, c->geom.width, c->geom.height } ++ }); ++} ++ ++void ++update_client_corner_radius(Client *c) ++{ ++ if (corner_radius && c->round_border) { ++ int radius = c->corner_radius + c->bw; ++ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) { ++ radius = 0; ++ } ++ wlr_scene_rect_set_corner_radius(c->round_border, radius, CORNER_LOCATION_ALL); ++ } ++ ++#ifdef XWAYLAND ++ if (!client_is_x11(c)) { ++#endif ++ if (corner_radius_inner > 0 && c->scene) { ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_corner_radius, c); ++ } ++#ifdef XWAYLAND ++ } ++#endif ++} ++ ++void ++update_client_blur(Client *c) ++{ ++ if (!blur) { ++ return; ++ } ++ ++ if (c->scene) { ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_blur, c); ++ } ++} ++ ++void ++update_buffer_corner_radius(Client *c, struct wlr_scene_buffer *buffer) ++{ ++ int radius; ++ ++#ifdef XWAYLAND ++ if (client_is_x11(c)) { ++ return; ++ } ++#endif ++ ++ if (!corner_radius_inner) { ++ return; ++ } ++ ++ radius = corner_radius_inner; ++ if ((corner_radius_only_floating && !c->isfloating) || c->isfullscreen) { ++ radius = 0; ++ } ++ wlr_scene_buffer_set_corner_radius(buffer, radius, CORNER_LOCATION_ALL); ++} ++ ++void ++update_client_shadow_color(Client *c) ++{ ++ int has_shadow_enabled = 1; ++ const float *color; ++ ++ if (!shadow || !c->shadow) { ++ return; ++ } ++ ++ color = focustop(c->mon) == c ? shadow_color_focus : shadow_color; ++ ++ if ((shadow_only_floating && !c->isfloating) || ++ in_shadow_ignore_list(client_get_appid(c)) || ++ c->isfullscreen) { ++ color = transparent; ++ has_shadow_enabled = 0; ++ } ++ ++ wlr_scene_shadow_set_color(c->shadow, color); ++ c->has_shadow_enabled = has_shadow_enabled; ++} ++ ++void ++update_client_focus_decorations(Client *c, int focused, int urgent) ++{ ++ if (corner_radius > 0 && c->round_border) { ++ wlr_scene_rect_set_color(c->round_border, urgent ? urgentcolor : (focused ? focuscolor : bordercolor)); ++ } ++ if (shadow && c->shadow) { ++ client_set_shadow_blur_sigma(c, (int)round(focused ? shadow_blur_sigma_focus : shadow_blur_sigma)); ++ if (c->has_shadow_enabled) { ++ wlr_scene_shadow_set_color(c->shadow, focused ? shadow_color_focus : shadow_color); ++ } ++ } ++ if (opacity) { ++ c->opacity = focused ? opacity_active : opacity_inactive; ++ wlr_scene_node_for_each_buffer(&c->scene_surface->node, iter_xdg_scene_buffers_opacity, c); ++ } ++} ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +-- +2.47.2 + + diff --git a/dwl/dwl-patches/patches/setrule/README.md b/dwl/dwl-patches/patches/setrule/README.md new file mode 100755 index 0000000..bdb7408 --- /dev/null +++ b/dwl/dwl-patches/patches/setrule/README.md @@ -0,0 +1,46 @@ +### Description + +This patch adds an ability to add or change client rules at runtime. + +Sometimes it happens that some client rule I've set is not relevant in the +current circumstance and adds major disturbance and annoyance to my work +(e.g., `isfloating` is set or unset and I want the opposite). Changing the rule +is not an option because it will require recompilation and restarting dwl, which +is even worse. Having an option of always being able to change a rule solves +this issue. + +The patch only adds one keybinding (`Alt+Shift+R`) to toggle `isfloating` +option. Upon pressing it, dwl will try to find a matching rule for the focused +client and change its `isfloating` setting. If there's no such a rule, a new +rule will be added. The new rule will inherit an appid of the focused client. + +It's very easy to add support for more rule options from other patches as well. +You just need to define a new function similar to `setruleisfloating` and add a +new keybinding to `config.h`. For example, this is a function I created for my +build to toggle `noswallow` option from the [swallow][swallow] patch: + +```c +void +setrulenoswallow(const Arg *arg) +{ + Rule *r = getrule(focustop(selmon)); + if (!r) + return; + r->noswallow = !r->noswallow; +} +``` + +You can also try [menurule][menurule] patch if you want to be able to edit rules +with dmenu. + +[swallow]: /dwl/dwl-patches/src/branch/main/patches/swallow +[menurule]: /dwl/dwl-patches/src/branch/main/patches/menurule + +### Download + +- [v0.7](/dwl/dwl-patches/raw/branch/main/patches/setrule/setrule.patch) +- [2025-02-14 v0.7](https://codeberg.org/dwl/dwl-patches/raw/commit/268bee3cee239e5bd52cceed88a52bfc21143cc3/patches/setrule/setrule.patch) + +### Authors + +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) diff --git a/dwl/dwl-patches/patches/setrule/setrule.patch b/dwl/dwl-patches/patches/setrule/setrule.patch new file mode 100755 index 0000000..6f9a1a3 --- /dev/null +++ b/dwl/dwl-patches/patches/setrule/setrule.patch @@ -0,0 +1,155 @@ +From 3c78308f0d74ac6ef112804333f82c098e33bb40 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Fri, 21 Mar 2025 22:20:54 +0100 +Subject: [PATCH] setrule: add/change rules at runtime + +--- + config.def.h | 4 ++++ + dwl.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 70 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..5b05e52 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,9 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + /* logging */ + static int log_level = WLR_ERROR; + ++/* Max amount of dynamically added rules */ ++#define RULES_MAX 100 ++ + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ +@@ -142,6 +145,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, setruleisfloating,{0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index def2562..8beac1f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -290,6 +290,7 @@ static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); ++static Rule *getrule(Client *c); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); +@@ -331,6 +332,7 @@ static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); ++static void setruleisfloating(const Arg *arg); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); +@@ -413,6 +415,9 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static Rule *drules; ++static size_t druleslen; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -466,7 +471,7 @@ applyrules(Client *c) + if (!(title = client_get_title(c))) + title = broken; + +- for (r = rules; r < END(rules); r++) { ++ for (r = drules; r < drules + druleslen; r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; +@@ -1472,6 +1477,53 @@ fullscreennotify(struct wl_listener *listener, void *data) + setfullscreen(c, client_wants_fullscreen(c)); + } + ++Rule * ++getrule(Client *c) ++{ ++ Rule *r; ++ const Rule *e; ++ const char *appid, *title; ++ ++ if (!c) ++ return NULL; ++ ++ if (!(appid = client_get_appid(c))) ++ appid = broken; ++ if (!(title = client_get_title(c))) ++ title = broken; ++ ++ for (r = drules + druleslen - 1; r >= drules; r--) ++ if ((!r->title || strstr(title, r->title)) ++ && (!r->id || strstr(appid, r->id))) ++ goto found; ++ ++ if (druleslen >= LENGTH(rules) + RULES_MAX) ++ return NULL; /* No free slots left */ ++ ++ r = drules + druleslen++; ++ ++ /* Use [NULL,NULL] as the default rule if exists */ ++ for (e = rules; e < END(rules); e++) ++ if (!e->title && !e->id) { ++ *r = *e; ++ break; ++ } ++ ++ /* No default rule found, set reasoble defaults */ ++ if (e >= END(rules)) { ++ r->monitor = -1; ++ } ++ ++ /* Only set title if appid is unset */ ++ if (appid == broken) ++ r->title = strdup(title); ++ else ++ r->id = strdup(appid); ++ ++found: ++ return r; ++} ++ + void + gpureset(struct wl_listener *listener, void *data) + { +@@ -2417,6 +2469,15 @@ setpsel(struct wl_listener *listener, void *data) + wlr_seat_set_primary_selection(seat, event->source, event->serial); + } + ++void ++setruleisfloating(const Arg *arg) ++{ ++ Rule *r = getrule(focustop(selmon)); ++ if (!r) ++ return; ++ r->isfloating = !r->isfloating; ++} ++ + void + setsel(struct wl_listener *listener, void *data) + { +@@ -2645,6 +2706,10 @@ setup(void) + fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); + } + #endif ++ ++ drules = ecalloc(LENGTH(rules) + RULES_MAX, sizeof(Rule)); ++ memcpy(drules, rules, sizeof(rules)); ++ druleslen = LENGTH(rules); + } + + void +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/setupenv/README.md b/dwl/dwl-patches/patches/setupenv/README.md new file mode 100755 index 0000000..776c328 --- /dev/null +++ b/dwl/dwl-patches/patches/setupenv/README.md @@ -0,0 +1,8 @@ +### Description +Allow configuring environment variables in config.h + +### Download +- [git branch](https://codeberg.org/notchoc/dwl/src/branch/setupenv) +- [2024-03-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/setupenv/setupenv.patch) +### Authors +- [notchoc](https://codeberg.org/notchoc) diff --git a/dwl/dwl-patches/patches/setupenv/setupenv.patch b/dwl/dwl-patches/patches/setupenv/setupenv.patch new file mode 100755 index 0000000..17d2ad4 --- /dev/null +++ b/dwl/dwl-patches/patches/setupenv/setupenv.patch @@ -0,0 +1,54 @@ +From 11ee2fc23ef5728d1e132f338c08a7805c6109b2 Mon Sep 17 00:00:00 2001 +From: choc +Date: Tue, 26 Mar 2024 21:02:16 +0800 +Subject: [PATCH] implement setupenv + +--- + config.def.h | 5 +++++ + dwl.c | 7 +++++++ + 2 files changed, 12 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 9009517..b16189a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -20,6 +20,11 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + /* logging */ + static int log_level = WLR_ERROR; + ++static const Env envs[] = { ++ /* variable value */ ++ { "XDG_CURRENT_DESKTOP", "wlroots" }, ++}; ++ + static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ + /* examples: +diff --git a/dwl.c b/dwl.c +index 5867b0c..b7d522b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -230,6 +230,11 @@ typedef struct { + int monitor; + } Rule; + ++typedef struct { ++ const char *variable; ++ const char *value; ++} Env; ++ + typedef struct { + struct wlr_scene_tree *scene; + +@@ -2066,6 +2071,8 @@ run(char *startup_cmd) + if (!socket) + die("startup: display_add_socket_auto"); + setenv("WAYLAND_DISPLAY", socket, 1); ++ for (size_t i = 0; i < LENGTH(envs); i++) ++ setenv(envs[i].variable, envs[i].value, 1); + + /* Start the backend. This will enumerate outputs and inputs, become the DRM + * master, etc */ +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/shiftview/README.md b/dwl/dwl-patches/patches/shiftview/README.md new file mode 100755 index 0000000..2d25820 --- /dev/null +++ b/dwl/dwl-patches/patches/shiftview/README.md @@ -0,0 +1,9 @@ +### Description +Add keybindings to cycle through tags with visible clients. + +### Download +- [git branch](https://codeberg.org/guidocella/dwl/src/branch/shiftview) +- [2024-01-27](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/shiftview/shiftview.patch) + +### Authors +- [Guido Cella](https://codeberg.org/guidocella) diff --git a/dwl/dwl-patches/patches/shiftview/shiftview.patch b/dwl/dwl-patches/patches/shiftview/shiftview.patch new file mode 100755 index 0000000..f556916 --- /dev/null +++ b/dwl/dwl-patches/patches/shiftview/shiftview.patch @@ -0,0 +1,76 @@ +From 40f9140742277d0298988990264f4b6a738f8122 Mon Sep 17 00:00:00 2001 +From: Guido Cella +Date: Sat, 27 Jan 2024 22:43:29 +0100 +Subject: [PATCH] cycle through tags + +--- + config.def.h | 4 ++++ + shiftview.c | 34 ++++++++++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + create mode 100644 shiftview.c + +diff --git a/config.def.h b/config.def.h +index 9009517..8d77ec0 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -117,6 +117,8 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + static const char *termcmd[] = { "foot", NULL }; + static const char *menucmd[] = { "bemenu-run", NULL }; + ++#include "shiftview.c" ++ + static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ + /* modifier key function argument */ +@@ -130,6 +132,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, ++ { MODKEY, XKB_KEY_a, shiftview, { .i = -1 } }, ++ { MODKEY, XKB_KEY_semicolon, shiftview, { .i = 1 } }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, +diff --git a/shiftview.c b/shiftview.c +new file mode 100644 +index 0000000..fa53db0 +--- /dev/null ++++ b/shiftview.c +@@ -0,0 +1,34 @@ ++// "arg->i" stores the number of tags to shift right (positive value) ++// or left (negative value) ++void ++shiftview(const Arg *arg) ++{ ++ Arg a; ++ Client *c; ++ bool visible = false; ++ int i = arg->i; ++ int count = 0; ++ int nextseltags, curseltags = selmon->tagset[selmon->seltags]; ++ ++ do { ++ if (i > 0) // left circular shift ++ nextseltags = (curseltags << i) | (curseltags >> (TAGCOUNT - i)); ++ else // right circular shift ++ nextseltags = curseltags >> (-i) | (curseltags << (TAGCOUNT + i)); ++ ++ // Check if the tag is visible ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon == selmon && nextseltags & c->tags) { ++ visible = true; ++ break; ++ } ++ } ++ ++ i += arg->i; ++ } while (!visible && ++count <= TAGCOUNT); ++ ++ if (count <= TAGCOUNT) { ++ a.i = nextseltags; ++ view(&a); ++ } ++} +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/simple_scratchpad/README.md b/dwl/dwl-patches/patches/simple_scratchpad/README.md new file mode 100755 index 0000000..8076d96 --- /dev/null +++ b/dwl/dwl-patches/patches/simple_scratchpad/README.md @@ -0,0 +1,25 @@ +### Description + +# simple_scratchpad — A very simple scratchpad utility. + +Adds functions to add, toggle and remove clients to/from scratchpad client list. +![scratchpad in action](https://github.com/julmajustus/dwl-patches/blob/main/demos/simple_scratchpad_demo.gif?raw=true) + +--- + +1. **addscratchpad** + - Floats client and adds it to scratchpad clients list. + +2. **togglescratchpad** + - Shows or hides the clients in scratchpad client list. + +3. **removescratchpad** + - Removes client from scratchpad client list. + + +### Download +- [git branch](https://codeberg.org/julmajustus/dwl/src/branch/simple_scratchpad) +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/simple_scratchpad/simple_scratchpad-v0.7.patch) + +### Authors +- [julmajustus](https://codeberg.org/julmajustus) diff --git a/dwl/dwl-patches/patches/simple_scratchpad/simple_scratchpad-v0.7.patch b/dwl/dwl-patches/patches/simple_scratchpad/simple_scratchpad-v0.7.patch new file mode 100755 index 0000000..a273559 --- /dev/null +++ b/dwl/dwl-patches/patches/simple_scratchpad/simple_scratchpad-v0.7.patch @@ -0,0 +1,211 @@ +From a8d29e03f565b54a68c6c2cb2da103366c627825 Mon Sep 17 00:00:00 2001 +From: julmajustus +Date: Sat, 4 Jan 2025 13:22:12 +0200 +Subject: [PATCH] add simple_scratchpad + +--- + config.def.h | 3 ++ + dwl.c | 34 +++++++++++++++++++++-- + simple_scratchpad.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 102 insertions(+), 2 deletions(-) + create mode 100644 simple_scratchpad.c + +diff --git a/config.def.h b/config.def.h +index 22d2171..83f19b3 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -136,6 +136,9 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Z, addscratchpad, {0} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_z, togglescratchpad, {0} }, ++ { MODKEY, XKB_KEY_z, removescratchpad, {0} }, + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, +diff --git a/dwl.c b/dwl.c +index a2711f6..85f4a51 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -141,6 +141,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ struct wl_list link_temp; + } Client; + + typedef struct { +@@ -243,6 +244,7 @@ typedef struct { + } SessionLock; + + /* function declarations */ ++static void addscratchpad(const Arg *arg); + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); + static void arrange(Monitor *m); +@@ -317,6 +319,7 @@ static void printstatus(void); + static void powermgrsetmode(struct wl_listener *listener, void *data); + static void quit(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); ++static void removescratchpad(const Arg *arg); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); +@@ -340,6 +343,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglescratchpad(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -413,6 +417,9 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static struct wl_list scratchpad_clients; ++static int scratchpad_visible = 1; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -432,6 +439,8 @@ static xcb_atom_t netatom[NetLast]; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++#include "simple_scratchpad.c" ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -1259,10 +1268,20 @@ void + destroynotify(struct wl_listener *listener, void *data) + { + /* Called when the xdg_toplevel is destroyed. */ +- Client *c = wl_container_of(listener, c, destroy); ++ Client *sc, *c = wl_container_of(listener, c, destroy); + wl_list_remove(&c->destroy.link); + wl_list_remove(&c->set_title.link); + wl_list_remove(&c->fullscreen.link); ++ /* Check if destroyed client was part of scratchpad_clients ++ * and clean it from the list if so. */ ++ if (c && wl_list_length(&scratchpad_clients) > 0) { ++ wl_list_for_each(sc, &scratchpad_clients, link_temp) { ++ if (sc == c) { ++ wl_list_remove(&c->link_temp); ++ break; ++ } ++ } ++ } + #ifdef XWAYLAND + if (c->type != XDGShell) { + wl_list_remove(&c->activate.link); +@@ -2306,11 +2325,21 @@ setcursorshape(struct wl_listener *listener, void *data) + void + setfloating(Client *c, int floating) + { +- Client *p = client_get_parent(c); ++ Client *sc, *p = client_get_parent(c); + c->isfloating = floating; + /* If in floating layout do not change the client's layer */ + if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange) + return; ++ /* Check if unfloated client was part of scratchpad_clients ++ * and remove it from scratchpad_clients list if so */ ++ if (!floating && wl_list_length(&scratchpad_clients) > 0) { ++ wl_list_for_each(sc, &scratchpad_clients, link_temp) { ++ if (sc == c) { ++ wl_list_remove(&c->link_temp); ++ break; ++ } ++ } ++ } + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); +@@ -2534,6 +2563,7 @@ setup(void) + */ + wl_list_init(&clients); + wl_list_init(&fstack); ++ wl_list_init(&scratchpad_clients); + + xdg_shell = wlr_xdg_shell_create(dpy, 6); + LISTEN_STATIC(&xdg_shell->events.new_toplevel, createnotify); +diff --git a/simple_scratchpad.c b/simple_scratchpad.c +new file mode 100644 +index 0000000..381f4b5 +--- /dev/null ++++ b/simple_scratchpad.c +@@ -0,0 +1,68 @@ ++/* ************************************************************************** */ ++/* */ ++/* ::: :::::::: */ ++/* simple_scratchpad.c :+: :+: :+: */ ++/* +:+ +:+ +:+ */ ++/* By: jmakkone +#+ +:+ +#+ */ ++/* +#+#+#+#+#+ +#+ */ ++/* Created: 2024/12/19 19:35:02 by jmakkone #+# #+# */ ++/* Updated: 2025/01/04 13:35:50 by jmakkone ### ########.fr */ ++/* */ ++/* ************************************************************************** */ ++ ++void ++addscratchpad(const Arg *arg) ++{ ++ Client *cc, *c = focustop(selmon); ++ ++ if (!c) ++ return; ++ /* Check if the added client is already a scratchpad client */ ++ wl_list_for_each(cc, &scratchpad_clients, link_temp) { ++ if (cc == c) ++ return; ++ } ++ if (!c->isfloating) { ++ setfloating(c, 1); ++ } ++ wl_list_insert(&scratchpad_clients, &c->link_temp); ++} ++ ++void ++togglescratchpad(const Arg *arg) ++{ ++ Client *c; ++ Monitor *m = selmon; ++ ++ scratchpad_visible = !scratchpad_visible; ++ if (scratchpad_visible) { ++ wl_list_for_each(c, &scratchpad_clients, link_temp) { ++ c->mon = m; ++ c->tags = m->tagset[m->seltags]; ++ arrange(m); ++ focusclient(c, 1); ++ } ++ } else { ++ wl_list_for_each(c, &scratchpad_clients, link_temp) { ++ c->tags = 0; ++ focusclient(focustop(m), 1); ++ arrange(m); ++ } ++ } ++} ++ ++void ++removescratchpad(const Arg *arg) ++{ ++ Client *sc, *c = focustop(selmon); ++ ++ if (c && wl_list_length(&scratchpad_clients) > 0) { ++ /* Check if c is in scratchpad_clients */ ++ wl_list_for_each(sc, &scratchpad_clients, link_temp) { ++ if (sc == c) { ++ wl_list_remove(&c->link_temp); ++ break; ++ } ++ } ++ } ++} +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/simpleborders/README.md b/dwl/dwl-patches/patches/simpleborders/README.md new file mode 100755 index 0000000..29dcf5e --- /dev/null +++ b/dwl/dwl-patches/patches/simpleborders/README.md @@ -0,0 +1,13 @@ +### Description + +Like smartborders. Don't put borders when there is only one window on the screen. + +The patch for tag v0.7 below appears to apply cleanly to the current HEAD of +upstream/main as at 2024-10-11. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/simpleborders) +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/simpleborders/simpleborders-v0.7.patch) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/simpleborders/simpleborders-v0.6.patch) +### Authors +- [Ben Collerson](https://codeberg.org/bencc) diff --git a/dwl/dwl-patches/patches/simpleborders/simpleborders-v0.6.patch b/dwl/dwl-patches/patches/simpleborders/simpleborders-v0.6.patch new file mode 100755 index 0000000..a4797bb --- /dev/null +++ b/dwl/dwl-patches/patches/simpleborders/simpleborders-v0.6.patch @@ -0,0 +1,73 @@ +From 681e520deaeee460647de36f5312af3cb0c31f4a Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Sat, 30 Dec 2023 13:39:31 +1000 +Subject: [PATCH] simpleborders + +--- + dwl.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/dwl.c b/dwl.c +index 4d19357..900e651 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -245,6 +245,7 @@ static void cleanupmon(struct wl_listener *listener, void *data); + static void closemon(Monitor *m); + static void commitlayersurfacenotify(struct wl_listener *listener, void *data); + static void commitnotify(struct wl_listener *listener, void *data); ++static int countclients(Monitor *m); + static void createdecoration(struct wl_listener *listener, void *data); + static void createidleinhibitor(struct wl_listener *listener, void *data); + static void createkeyboard(struct wlr_keyboard *keyboard); +@@ -286,6 +287,7 @@ static void motionabsolute(struct wl_listener *listener, void *data); + static void motionnotify(uint32_t time); + static void motionrelative(struct wl_listener *listener, void *data); + static void moveresize(const Arg *arg); ++static int needsborder(Client *c); + static void outputmgrapply(struct wl_listener *listener, void *data); + static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); + static void outputmgrtest(struct wl_listener *listener, void *data); +@@ -739,6 +741,17 @@ commitnotify(struct wl_listener *listener, void *data) + c->resize = 0; + } + ++int ++countclients(Monitor *m) ++{ ++ unsigned int n = 0; ++ Client *c; ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ return n; ++} ++ + void + createdecoration(struct wl_listener *listener, void *data) + { +@@ -1697,6 +1710,14 @@ moveresize(const Arg *arg) + } + } + ++int ++needsborder(Client *c) { ++ return ((countclients(c->mon) > 1 ++ && c->mon->lt[c->mon->sellt]->arrange != monocle) ++ || c->isfloating) ++ && !c->isfullscreen; ++} ++ + void + outputmgrapply(struct wl_listener *listener, void *data) + { +@@ -1930,6 +1951,7 @@ resize(Client *c, struct wlr_box geo, int interact) + struct wlr_box clip; + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; ++ c->bw = needsborder(c) ? borderpx : 0; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/simpleborders/simpleborders-v0.7.patch b/dwl/dwl-patches/patches/simpleborders/simpleborders-v0.7.patch new file mode 100755 index 0000000..e782d84 --- /dev/null +++ b/dwl/dwl-patches/patches/simpleborders/simpleborders-v0.7.patch @@ -0,0 +1,73 @@ +From 09759c3ef75158c366e9fc63814485fbb31a3ccf Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Sat, 30 Dec 2023 13:39:31 +1000 +Subject: [PATCH] simpleborders + +--- + dwl.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/dwl.c b/dwl.c +index a2711f67..415fe1a0 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -259,6 +259,7 @@ static void closemon(Monitor *m); + static void commitlayersurfacenotify(struct wl_listener *listener, void *data); + static void commitnotify(struct wl_listener *listener, void *data); + static void commitpopup(struct wl_listener *listener, void *data); ++static int countclients(Monitor *m); + static void createdecoration(struct wl_listener *listener, void *data); + static void createidleinhibitor(struct wl_listener *listener, void *data); + static void createkeyboard(struct wlr_keyboard *keyboard); +@@ -308,6 +309,7 @@ static void motionnotify(uint32_t time, struct wlr_input_device *device, double + double sy, double sx_unaccel, double sy_unaccel); + static void motionrelative(struct wl_listener *listener, void *data); + static void moveresize(const Arg *arg); ++static int needsborder(Client *c); + static void outputmgrapply(struct wl_listener *listener, void *data); + static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); + static void outputmgrtest(struct wl_listener *listener, void *data); +@@ -849,6 +851,17 @@ commitpopup(struct wl_listener *listener, void *data) + wl_list_remove(&listener->link); + } + ++int ++countclients(Monitor *m) ++{ ++ unsigned int n = 0; ++ Client *c; ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ return n; ++} ++ + void + createdecoration(struct wl_listener *listener, void *data) + { +@@ -1927,6 +1940,14 @@ moveresize(const Arg *arg) + } + } + ++int ++needsborder(Client *c) { ++ return ((countclients(c->mon) > 1 ++ && c->mon->lt[c->mon->sellt]->arrange != monocle) ++ || c->isfloating) ++ && !c->isfullscreen; ++} ++ + void + outputmgrapply(struct wl_listener *listener, void *data) + { +@@ -2190,6 +2211,7 @@ resize(Client *c, struct wlr_box geo, int interact) + + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; ++ c->bw = needsborder(c) ? borderpx : 0; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/singlemaster/README.md b/dwl/dwl-patches/patches/singlemaster/README.md new file mode 100755 index 0000000..99cb1e6 --- /dev/null +++ b/dwl/dwl-patches/patches/singlemaster/README.md @@ -0,0 +1,9 @@ +### Description +Restricts layout to only having one client in the master area. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/singlemaster) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/singlemaster/singlemaster.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) diff --git a/dwl/dwl-patches/patches/singlemaster/singlemaster.patch b/dwl/dwl-patches/patches/singlemaster/singlemaster.patch new file mode 100755 index 0000000..ffa6045 --- /dev/null +++ b/dwl/dwl-patches/patches/singlemaster/singlemaster.patch @@ -0,0 +1,155 @@ +From 610362d2f38260ad2a06ffbd91d089ba738429e9 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Thu, 18 Jul 2024 11:03:46 +1000 +Subject: [PATCH] singlemaster + +--- + config.def.h | 8 +++----- + dwl.c | 49 ++++++++++++++++++++++--------------------------- + 2 files changed, 25 insertions(+), 32 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..0ba9ddb8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -43,12 +43,12 @@ static const Layout layouts[] = { + */ + /* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ + static const MonitorRule monrules[] = { +- /* name mfact nmaster scale layout rotate/reflect x y */ ++ /* name mfact scale layout rotate/reflect x y */ + /* example of a HiDPI laptop monitor: +- { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { "eDP-1", 0.5f, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + */ + /* defaults */ +- { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { NULL, 0.55f, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + }; + + /* keyboard */ +@@ -129,8 +129,6 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, +- { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +- { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, +diff --git a/dwl.c b/dwl.c +index 145fd018..6a3c84a7 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -70,7 +70,6 @@ + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +-#define MIN(A, B) ((A) < (B) ? (A) : (B)) + #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) +@@ -204,7 +203,6 @@ struct Monitor { + uint32_t tagset[2]; + float mfact; + int gamma_lut_changed; +- int nmaster; + char ltsymbol[16]; + int asleep; + }; +@@ -212,7 +210,6 @@ struct Monitor { + typedef struct { + const char *name; + float mfact; +- int nmaster; + float scale; + const Layout *lt; + enum wl_output_transform rr; +@@ -288,7 +285,6 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); +-static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); +@@ -955,7 +951,6 @@ createmon(struct wl_listener *listener, void *data) + m->m.x = r->x; + m->m.y = r->y; + m->mfact = r->mfact; +- m->nmaster = r->nmaster; + m->lt[0] = r->lt; + m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); +@@ -1467,15 +1462,6 @@ handlesig(int signo) + } + } + +-void +-incnmaster(const Arg *arg) +-{ +- if (!arg || !selmon) +- return; +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); +- arrange(selmon); +-} +- + void + inputdevice(struct wl_listener *listener, void *data) + { +@@ -2635,8 +2621,7 @@ tagmon(const Arg *arg) + void + tile(Monitor *m) + { +- unsigned int mw, my, ty; +- int i, n = 0; ++ unsigned int i, n = 0, mw, ty; + Client *c; + + wl_list_for_each(c, &clients, link) +@@ -2645,21 +2630,31 @@ tile(Monitor *m) + if (n == 0) + return; + +- if (n > m->nmaster) +- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; +- else +- mw = m->w.width; +- i = my = ty = 0; ++ mw = (n == 1) ? m->w.width : (int)roundf(m->w.width * m->mfact); ++ i = ty = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); +- my += c->geom.height; ++ if (i == 0) { ++ resize( ++ c, ++ (struct wlr_box){ ++ .x = m->w.x, ++ .y = m->w.y, ++ .width = mw, ++ .height = (m->w.height) ++ }, ++ 0); + } else { +- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); ++ resize( ++ c, ++ (struct wlr_box){ ++ .x = m->w.x + mw, ++ .y = m->w.y + ty, ++ .width = m->w.width - mw, ++ .height = (m->w.height - ty) / (n - i) ++ }, ++ 0); + ty += c->geom.height; + } + i++; +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/singletagset-pertag/README.md b/dwl/dwl-patches/patches/singletagset-pertag/README.md new file mode 100755 index 0000000..13ab951 --- /dev/null +++ b/dwl/dwl-patches/patches/singletagset-pertag/README.md @@ -0,0 +1,22 @@ +### Description +Pertag keeps layouts, mfact and nmaster per tag +instead of per output. + +This adapted version of pertag contains one version of +the rules per all outputs, instead of one per output. +This makes switching to tags from other monitors keep +the window layout. + +This patch expects [singletagset](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/singletagset) +patch to be already in your tree committed. It applies onto it. + +This patch is incompatible with [pertag](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/pertag). + +### Download +- [2024-07-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/singletagset-pertag/singletagset-pertag.patch) +- [git branch](https://codeberg.org/Rutherther/dwl/src/branch/v0.7/singletagset-pertag) + +### Authors +- [Rutherther](https://codeberg.org/Rutherther) +- [wochap (maintainer of pertag patch)](https://codeberg.org/wochap) +- [Guido Cella (creator of pertag patch)](https://codeberg.org/guidocella) diff --git a/dwl/dwl-patches/patches/singletagset-pertag/singletagset-pertag.patch b/dwl/dwl-patches/patches/singletagset-pertag/singletagset-pertag.patch new file mode 100755 index 0000000..5fe4f47 --- /dev/null +++ b/dwl/dwl-patches/patches/singletagset-pertag/singletagset-pertag.patch @@ -0,0 +1,261 @@ +From 4f6bdd3ea1fcc83abd962e9a2dc7737519164a6b Mon Sep 17 00:00:00 2001 +From: Rutherther +Date: Fri, 19 Jul 2024 16:25:46 +0200 +Subject: [PATCH] singletagset-pertag + +--- + config.def.h | 12 +++++-- + dwl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 90 insertions(+), 12 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..7feb04d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -43,12 +43,18 @@ static const Layout layouts[] = { + */ + /* NOTE: ALWAYS add a fallback rule, even if you are completely sure it won't be used */ + static const MonitorRule monrules[] = { +- /* name mfact nmaster scale layout rotate/reflect x y */ ++ /* name scale rotate/reflect x y */ + /* example of a HiDPI laptop monitor: +- { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { "eDP-1", 2, WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + */ + /* defaults */ +- { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { NULL, 1, WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++}; ++ ++static const TagRule tagrules[] = { ++ /* tag mfact nmaster layout */ ++ /* defaults */ ++ { 0, 0.55, 1, &layouts[0] } + }; + + /* keyboard */ +diff --git a/dwl.c b/dwl.c +index 40a6e48..465d9dd 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -104,6 +104,7 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct Pertag Pertag; + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -209,6 +210,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ unsigned int pertag[2]; /* the tag used for layout via pertag */ + }; + + typedef struct { +@@ -226,6 +228,13 @@ typedef struct { + struct wl_listener destroy; + } PointerConstraint; + ++typedef struct { ++ unsigned int tag; ++ float mfact; ++ int nmaster; ++ const Layout *lt; ++} TagRule; ++ + typedef struct { + const char *id; + const char *title; +@@ -245,6 +254,7 @@ typedef struct { + + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); ++static void applypertag(Monitor *m); + static void applyrules(Client *c); + static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, +@@ -293,6 +303,7 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); ++static unsigned int getpertagtag(unsigned int curtagset); + static size_t getunusedtag(void); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); +@@ -415,6 +426,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static Pertag pertag; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -435,6 +447,13 @@ static xcb_atom_t netatom[NetLast]; + /* attempt to encapsulate suck into one file */ + #include "client.h" + ++struct Pertag { ++ int nmasters[TAGCOUNT + 1]; /* number of windows in master area */ ++ float mfacts[TAGCOUNT + 1]; /* mfacts per tag */ ++ unsigned int sellts[TAGCOUNT + 1]; /* selected layouts */ ++ const Layout *ltidxs[TAGCOUNT + 1][2]; /* matrix of tags and layouts indexes */ ++}; ++ + /* function implementations */ + void + applybounds(Client *c, struct wlr_box *bbox) +@@ -1023,6 +1042,33 @@ createlocksurface(struct wl_listener *listener, void *data) + client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat)); + } + ++unsigned int ++getpertagtag(unsigned int curtagset) ++{ ++ size_t i; ++ ++ if (curtagset == TAGMASK) { ++ return 0; ++ } ++ ++ if ((curtagset & TAGMASK) == 0) { ++ return 0; // What to do in this case? ++ } ++ ++ for (i = 0; !(curtagset & 1 << i); i++) ; ++ return i + 1; ++} ++ ++void ++applypertag(Monitor *m) ++{ ++ m->nmaster = pertag.nmasters[m->pertag[m->seltags]]; ++ m->mfact = pertag.mfacts[m->pertag[m->seltags]]; ++ m->sellt = pertag.sellts[m->pertag[m->seltags]]; ++ m->lt[m->sellt] = pertag.ltidxs[m->pertag[m->seltags]][m->sellt]; ++ m->lt[m->sellt^1] = pertag.ltidxs[m->pertag[m->seltags]][m->sellt^1]; ++} ++ + void + createmon(struct wl_listener *listener, void *data) + { +@@ -1046,14 +1092,12 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->tagset[0] = m->tagset[1] = (1<pertag[0] = m->pertag[1] = getpertagtag(m->tagset[0]); ++ applypertag(m); + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; + m->m.y = r->y; +- m->mfact = r->mfact; +- m->nmaster = r->nmaster; +- m->lt[0] = r->lt; +- m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + wlr_output_state_set_scale(&state, r->scale); + wlr_output_state_set_transform(&state, r->rr); +@@ -1597,7 +1641,7 @@ incnmaster(const Arg *arg) + { + if (!arg || !selmon) + return; +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = pertag.nmasters[selmon->pertag[selmon->seltags]] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -2433,9 +2477,9 @@ setlayout(const Arg *arg) + if (!selmon) + return; + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ selmon->sellt = pertag.sellts[selmon->pertag[selmon->seltags]] ^= 1; + if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = pertag.ltidxs[selmon->pertag[selmon->seltags]][selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); + printstatus(); +@@ -2452,7 +2496,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f; + if (f < 0.1 || f > 0.9) + return; +- selmon->mfact = f; ++ selmon->mfact = pertag.mfacts[selmon->pertag[selmon->seltags]] = f; + arrange(selmon); + } + +@@ -2504,6 +2548,10 @@ setsel(struct wl_listener *listener, void *data) + void + setup(void) + { ++ const TagRule *r; ++ struct xkb_context *context; ++ struct xkb_keymap *keymap; ++ + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; + sigemptyset(&sa.sa_mask); +@@ -2596,6 +2644,19 @@ setup(void) + LISTEN_STATIC(&output_layout->events.change, updatemons); + wlr_xdg_output_manager_v1_create(dpy, output_layout); + ++ for (i = 0; i <= TAGCOUNT; i++) { ++ for (r = tagrules; r < END(tagrules); r++) { ++ if (!r->tag || r->tag == i) { ++ pertag.mfacts[i] = r->mfact; ++ pertag.nmasters[i] = r->nmaster; ++ pertag.sellts[i] = 0; ++ pertag.ltidxs[i][0] = r->lt; ++ pertag.ltidxs[i][1] = r->lt; ++ break; ++ } ++ } ++ } ++ + /* Configure a listener to be notified when new outputs are available on the + * backend. */ + wl_list_init(&mons); +@@ -2857,6 +2918,12 @@ toggleview(const Arg *arg) + if (m !=selmon && newtagset & m->tagset[m->seltags]) + return; + ++ // set new pertag tag only if the tag we were at was removed, or if all tags are shown. ++ if (!(newtagset & 1 << (selmon->pertag[selmon->seltags] - 1)) || newtagset == TAGMASK) { ++ selmon->pertag[selmon->seltags] = getpertagtag(newtagset); ++ } ++ ++ applypertag(selmon); + selmon->tagset[selmon->seltags] = newtagset; + attachclients(selmon); + focusclient(focustop(selmon), 1); +@@ -3072,6 +3139,8 @@ view(const Arg *arg) + } + m->seltags ^= 1; + m->tagset[m->seltags] = origm->tagset[origm->seltags]; ++ m->pertag[m->seltags] = origm->pertag[origm->seltags]; ++ applypertag(m); + attachclients(m); + /* Beware: this changes selmon */ + focusclient(focustop(m), 1); +@@ -3081,11 +3150,14 @@ view(const Arg *arg) + } + + origm->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if (arg->ui & TAGMASK) { + origm->tagset[origm->seltags] = arg->ui & TAGMASK; ++ origm->pertag[origm->seltags] = getpertagtag(arg->ui & TAGMASK); ++ } + + /* Change selmon back to orig mon */ + selmon = origm; ++ applypertag(origm); + attachclients(origm); + focusclient(focustop(origm), 1); + arrange(origm); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/singletagset-sticky/README.md b/dwl/dwl-patches/patches/singletagset-sticky/README.md new file mode 100755 index 0000000..f1f9fd3 --- /dev/null +++ b/dwl/dwl-patches/patches/singletagset-sticky/README.md @@ -0,0 +1,13 @@ +### Description +Makes sticky work as expected with singletagset. The sticky window will +stay on original output until you explicitely put it to a different monitor. + +This patch expects both [singletagset](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/singletagset) and [sticky](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/sticky) patches to be already in +your tree committed. It applies onto them. + +### Download +- [2024-07-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/singletagset-sticky/singletagset-sticky.patch) +- [git branch](https://codeberg.org/Rutherther/dwl/src/branch/v0.7/singletagset-sticky) + +### Authors +- [Rutherther](https://codeberg.org/Rutherther) diff --git a/dwl/dwl-patches/patches/singletagset-sticky/singletagset-sticky.patch b/dwl/dwl-patches/patches/singletagset-sticky/singletagset-sticky.patch new file mode 100755 index 0000000..ce6a40c --- /dev/null +++ b/dwl/dwl-patches/patches/singletagset-sticky/singletagset-sticky.patch @@ -0,0 +1,27 @@ +From a37d65c8601a7c5b03c53bb99956da8a24952628 Mon Sep 17 00:00:00 2001 +From: Rutherther +Date: Fri, 19 Jul 2024 16:51:26 +0200 +Subject: [PATCH] singletagset-sticky + +--- + dwl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 59e56bd..fbbdff9 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -73,8 +73,8 @@ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) + #define MIN(A, B) ((A) < (B) ? (A) : (B)) + #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) +-#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && (((C)->tags & (M)->tagset[(M)->seltags])) || (C)->issticky) +-#define SVISIBLEON(C, M) ((M) && (C)->mon && ((C)->tags & (M)->tagset[(M)->seltags])) ++#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((((C)->tags & (M)->tagset[(M)->seltags])) || (C)->issticky)) ++#define SVISIBLEON(C, M) ((M) && (C)->mon && (((C)->tags & (M)->tagset[(M)->seltags]) && !(C)->issticky) || ((C)->issticky && (C)->mon == (M))) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/singletagset/README.md b/dwl/dwl-patches/patches/singletagset/README.md new file mode 100755 index 0000000..920d8a4 --- /dev/null +++ b/dwl/dwl-patches/patches/singletagset/README.md @@ -0,0 +1,19 @@ +### Description +Single set of tags shared between multiple monitors. + +This patch allows all the tags to be shared between both (or more) monitors. +So a single set of tags from 1 to 9 can be viewed on any monitor, as opposed to +having separate tag sets 1 to 9 on each monitor. + +Originally based on the dwm single_tagset patch: +https://dwm.suckless.org/patches/single_tagset/ + +### Download +- [git branch (v0.7)](https://codeberg.org/Rutherther/dwl/src/branch/v0.7/singletagset) +- [git branch (v0.6)](https://codeberg.org/bencc/dwl/src/branch/singletagset) +- [2024-07-26 (v0.7)](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/singletagset/singletagset-v0.7.patch) +- [2024-05-16 (v0.6)](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/singletagset/singletagset-v0.6.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) +- [Rutherther](https://codeberg.org/Rutherther) diff --git a/dwl/dwl-patches/patches/singletagset/singletagset-v0.6.patch b/dwl/dwl-patches/patches/singletagset/singletagset-v0.6.patch new file mode 100755 index 0000000..708774b --- /dev/null +++ b/dwl/dwl-patches/patches/singletagset/singletagset-v0.6.patch @@ -0,0 +1,293 @@ +From 140fe587bf34cf43e44acaf365b16ec3e385f742 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Thu, 16 May 2024 09:56:58 +1000 +Subject: [PATCH] singletagset + +--- + dwl.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 140 insertions(+), 10 deletions(-) + +diff --git a/dwl.c b/dwl.c +index bf763dfc..5b1d594f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -72,6 +72,7 @@ + #define ROUND(X) ((int)((X < 0) ? (X - 0.5) : (X + 0.5))) + #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) ++#define SVISIBLEON(C, M) ((M) && (C)->mon && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) +@@ -246,6 +247,7 @@ static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); ++static void attachclients(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); +@@ -283,6 +285,7 @@ static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); ++static size_t getunusedtag(void); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +@@ -470,7 +473,18 @@ applyrules(Client *c) + } + } + } ++ wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]); ++ ++ wl_list_for_each(m, &mons, link) { ++ // tag with different monitor selected by rules ++ if (m->tagset[m->seltags] & newtags) { ++ mon = m; ++ break; ++ } ++ } ++ + setmon(c, mon, newtags); ++ attachclients(mon); + } + + void +@@ -558,6 +572,45 @@ arrangelayers(Monitor *m) + } + } + ++void ++attachclients(Monitor *m) ++{ ++ Monitor *tm; ++ unsigned int utags = 0; ++ Client *c; ++ int rmons = 0; ++ ++ if (m == NULL) { ++ return; ++ } ++ ++ wl_list_for_each(tm, &mons, link) { ++ if (tm != m) { ++ utags |= tm->tagset[tm->seltags]; ++ } ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (SVISIBLEON(c, m)) { ++ /* if client is also visible on other tags that are displayed on ++ * other monitors, remove these tags */ ++ if (c->tags & utags) { ++ c->tags = c->tags & m->tagset[m->seltags]; ++ rmons = 1; ++ } ++ setmon(c, m, c->tags); ++ } ++ } ++ ++ if (rmons) { ++ wl_list_for_each(tm, &mons, link) { ++ if (tm != m) { ++ arrange(tm); ++ } ++ } ++ } ++} ++ + void + axisnotify(struct wl_listener *listener, void *data) + { +@@ -881,7 +934,7 @@ createmon(struct wl_listener *listener, void *data) + + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ +- m->tagset[0] = m->tagset[1] = 1; ++ m->tagset[0] = m->tagset[1] = (1<name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; +@@ -1354,7 +1407,7 @@ focustop(Monitor *m) + { + Client *c; + wl_list_for_each(c, &fstack, flink) { +- if (VISIBLEON(c, m)) ++ if (SVISIBLEON(c, m)) + return c; + } + return NULL; +@@ -1367,6 +1420,29 @@ fullscreennotify(struct wl_listener *listener, void *data) + setfullscreen(c, client_wants_fullscreen(c)); + } + ++size_t ++getunusedtag(void) ++{ ++ size_t i = 0; ++ Monitor *m; ++ if (wl_list_empty(&mons)) { ++ return i; ++ } ++ for (i=0; i < TAGCOUNT; i++) { ++ int is_used = 0; ++ wl_list_for_each(m, &mons, link) { ++ if ((m->tagset[m->seltags] & (1<mon != m) +- continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; +@@ -2551,6 +2625,7 @@ startdrag(struct wl_listener *listener, void *data) + void + tag(const Arg *arg) + { ++ Monitor *m; + Client *sel = focustop(selmon); + if (!sel || (arg->ui & TAGMASK) == 0) + return; +@@ -2558,15 +2633,25 @@ tag(const Arg *arg) + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); ++ wl_list_for_each(m, &mons, link) { ++ attachclients(m); ++ arrange(m); ++ } + printstatus(); + } + + void + tagmon(const Arg *arg) + { ++ Monitor *m; + Client *sel = focustop(selmon); +- if (sel) ++ if (sel) { + setmon(sel, dirtomon(arg->i), 0); ++ wl_list_for_each(m, &mons, link) { ++ arrange(m); ++ } ++ focusclient(focustop(sel->mon), 1); ++ } + } + + void +@@ -2623,12 +2708,18 @@ togglefullscreen(const Arg *arg) + void + toggletag(const Arg *arg) + { ++ Monitor *m; + uint32_t newtags; + Client *sel = focustop(selmon); + if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) + return; + ++ wl_list_for_each(m, &mons, link) ++ if (m != selmon && newtags & m->tagset[m->seltags]) ++ return; ++ + sel->tags = newtags; ++ attachclients(selmon); + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); +@@ -2637,11 +2728,17 @@ toggletag(const Arg *arg) + void + toggleview(const Arg *arg) + { ++ Monitor *m; + uint32_t newtagset; + if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) + return; + ++ wl_list_for_each(m, &mons, link) ++ if (m !=selmon && newtagset & m->tagset[m->seltags]) ++ return; ++ + selmon->tagset[selmon->seltags] = newtagset; ++ attachclients(selmon); + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); +@@ -2759,6 +2856,7 @@ updatemons(struct wl_listener *listener, void *data) + wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, m->m.height); + } + ++ attachclients(m); + /* Calculate the effective monitor geometry to use for clients */ + arrangelayers(m); + /* Don't move clients to the left output when plugging monitors */ +@@ -2825,13 +2923,45 @@ urgent(struct wl_listener *listener, void *data) + void + view(const Arg *arg) + { +- if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) ++ Monitor *m, *origm = selmon; ++ unsigned int newtags; ++ ++ if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) { + return; +- selmon->seltags ^= 1; /* toggle sel tagset */ ++ } ++ ++ newtags = origm->tagset[origm->seltags ^ 1]; ++ ++ /* swap tags when trying to display a tag from another monitor */ ++ if (arg->ui & TAGMASK) { ++ newtags = arg->ui & TAGMASK; ++ } ++ wl_list_for_each(m, &mons, link) { ++ if (m != origm && newtags & m->tagset[m->seltags]) { ++ /* prevent displaying all tags (MODKEY-0) when multiple monitors ++ * are connected */ ++ if (newtags & origm->tagset[origm->seltags]) { ++ return; ++ } ++ m->seltags ^= 1; ++ m->tagset[m->seltags] = origm->tagset[origm->seltags]; ++ attachclients(m); ++ /* Beware: this changes selmon */ ++ focusclient(focustop(m), 1); ++ arrange(m); ++ break; ++ } ++ } ++ ++ origm->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) +- selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; +- focusclient(focustop(selmon), 1); +- arrange(selmon); ++ origm->tagset[origm->seltags] = arg->ui & TAGMASK; ++ ++ /* Change selmon back to orig mon */ ++ selmon = origm; ++ attachclients(origm); ++ focusclient(focustop(origm), 1); ++ arrange(origm); + printstatus(); + } + +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/singletagset/singletagset-v0.7.patch b/dwl/dwl-patches/patches/singletagset/singletagset-v0.7.patch new file mode 100755 index 0000000..9c2f98b --- /dev/null +++ b/dwl/dwl-patches/patches/singletagset/singletagset-v0.7.patch @@ -0,0 +1,312 @@ +From bd90ec504369a69dbefc34cb72265d15c7795944 Mon Sep 17 00:00:00 2001 +From: Rutherther +Date: Fri, 26 Jul 2024 12:36:41 +0200 +Subject: [PATCH] singletagset + +--- + dwl.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 145 insertions(+), 10 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 5bf995e..40a6e48 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -74,6 +74,7 @@ + #define MIN(A, B) ((A) < (B) ? (A) : (B)) + #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) ++#define SVISIBLEON(C, M) ((M) && (C)->mon && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) +@@ -249,6 +250,7 @@ static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); ++static void attachclients(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); +@@ -291,6 +293,7 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); ++static size_t getunusedtag(void); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +@@ -478,7 +481,17 @@ applyrules(Client *c) + } + } + } ++ ++ wl_list_for_each(m, &mons, link) { ++ // tag with different monitor selected by rules ++ if (m->tagset[m->seltags] & newtags) { ++ mon = m; ++ break; ++ } ++ } ++ + setmon(c, mon, newtags); ++ attachclients(mon); + } + + void +@@ -580,6 +593,45 @@ arrangelayers(Monitor *m) + } + } + ++void ++attachclients(Monitor *m) ++{ ++ Monitor *tm; ++ unsigned int utags = 0; ++ Client *c; ++ int rmons = 0; ++ ++ if (m == NULL) { ++ return; ++ } ++ ++ wl_list_for_each(tm, &mons, link) { ++ if (tm != m) { ++ utags |= tm->tagset[tm->seltags]; ++ } ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (SVISIBLEON(c, m)) { ++ /* if client is also visible on other tags that are displayed on ++ * other monitors, remove these tags */ ++ if (c->tags & utags) { ++ c->tags = c->tags & m->tagset[m->seltags]; ++ rmons = 1; ++ } ++ setmon(c, m, c->tags); ++ } ++ } ++ ++ if (rmons) { ++ wl_list_for_each(tm, &mons, link) { ++ if (tm != m) { ++ arrange(tm); ++ } ++ } ++ } ++} ++ + void + axisnotify(struct wl_listener *listener, void *data) + { +@@ -750,6 +802,9 @@ closemon(Monitor *m) + if (c->mon == m) + setmon(c, selmon, c->tags); + } ++ ++ m->tagset[0] = m->tagset[1] = 0; ++ + focusclient(focustop(selmon), 1); + printstatus(); + } +@@ -990,7 +1045,7 @@ createmon(struct wl_listener *listener, void *data) + + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ +- m->tagset[0] = m->tagset[1] = 1; ++ m->tagset[0] = m->tagset[1] = (1<name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; +@@ -1456,7 +1511,7 @@ focustop(Monitor *m) + { + Client *c; + wl_list_for_each(c, &fstack, flink) { +- if (VISIBLEON(c, m)) ++ if (SVISIBLEON(c, m)) + return c; + } + return NULL; +@@ -1469,6 +1524,29 @@ fullscreennotify(struct wl_listener *listener, void *data) + setfullscreen(c, client_wants_fullscreen(c)); + } + ++size_t ++getunusedtag(void) ++{ ++ size_t i = 0; ++ Monitor *m; ++ if (wl_list_empty(&mons)) { ++ return i; ++ } ++ for (i=0; i < TAGCOUNT; i++) { ++ int is_used = 0; ++ wl_list_for_each(m, &mons, link) { ++ if ((m->tagset[m->seltags] & (1<mon != m) +- continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; +@@ -2669,6 +2745,7 @@ startdrag(struct wl_listener *listener, void *data) + void + tag(const Arg *arg) + { ++ Monitor *m; + Client *sel = focustop(selmon); + if (!sel || (arg->ui & TAGMASK) == 0) + return; +@@ -2676,15 +2753,25 @@ tag(const Arg *arg) + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); ++ wl_list_for_each(m, &mons, link) { ++ attachclients(m); ++ arrange(m); ++ } + printstatus(); + } + + void + tagmon(const Arg *arg) + { ++ Monitor *m; + Client *sel = focustop(selmon); +- if (sel) ++ if (sel) { + setmon(sel, dirtomon(arg->i), 0); ++ wl_list_for_each(m, &mons, link) { ++ arrange(m); ++ } ++ focusclient(focustop(sel->mon), 1); ++ } + } + + void +@@ -2741,12 +2828,18 @@ togglefullscreen(const Arg *arg) + void + toggletag(const Arg *arg) + { ++ Monitor *m; + uint32_t newtags; + Client *sel = focustop(selmon); + if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) + return; + ++ wl_list_for_each(m, &mons, link) ++ if (m != selmon && newtags & m->tagset[m->seltags]) ++ return; ++ + sel->tags = newtags; ++ attachclients(selmon); + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); +@@ -2755,11 +2848,17 @@ toggletag(const Arg *arg) + void + toggleview(const Arg *arg) + { ++ Monitor *m; + uint32_t newtagset; + if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) + return; + ++ wl_list_for_each(m, &mons, link) ++ if (m !=selmon && newtagset & m->tagset[m->seltags]) ++ return; ++ + selmon->tagset[selmon->seltags] = newtagset; ++ attachclients(selmon); + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); +@@ -2863,6 +2962,9 @@ updatemons(struct wl_listener *listener, void *data) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); + ++ if ((m->tagset[0] & TAGMASK) == 0 && (m->tagset[1] & TAGMASK) == 0) ++ m->tagset[0] = m->tagset[1] = (1 << getunusedtag()) & TAGMASK; ++ + /* Get the effective monitor geometry to use for surfaces */ + wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m); + m->w = m->m; +@@ -2877,6 +2979,7 @@ updatemons(struct wl_listener *listener, void *data) + wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, m->m.height); + } + ++ attachclients(m); + /* Calculate the effective monitor geometry to use for clients */ + arrangelayers(m); + /* Don't move clients to the left output when plugging monitors */ +@@ -2947,13 +3050,45 @@ urgent(struct wl_listener *listener, void *data) + void + view(const Arg *arg) + { +- if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) ++ Monitor *m, *origm = selmon; ++ unsigned int newtags; ++ ++ if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) { + return; +- selmon->seltags ^= 1; /* toggle sel tagset */ ++ } ++ ++ newtags = origm->tagset[origm->seltags ^ 1]; ++ ++ /* swap tags when trying to display a tag from another monitor */ ++ if (arg->ui & TAGMASK) { ++ newtags = arg->ui & TAGMASK; ++ } ++ wl_list_for_each(m, &mons, link) { ++ if (m != origm && newtags & m->tagset[m->seltags]) { ++ /* prevent displaying all tags (MODKEY-0) when multiple monitors ++ * are connected */ ++ if (newtags & origm->tagset[origm->seltags]) { ++ return; ++ } ++ m->seltags ^= 1; ++ m->tagset[m->seltags] = origm->tagset[origm->seltags]; ++ attachclients(m); ++ /* Beware: this changes selmon */ ++ focusclient(focustop(m), 1); ++ arrange(m); ++ break; ++ } ++ } ++ ++ origm->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) +- selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; +- focusclient(focustop(selmon), 1); +- arrange(selmon); ++ origm->tagset[origm->seltags] = arg->ui & TAGMASK; ++ ++ /* Change selmon back to orig mon */ ++ selmon = origm; ++ attachclients(origm); ++ focusclient(focustop(origm), 1); ++ arrange(origm); + printstatus(); + } + +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/skipfocus/README.md b/dwl/dwl-patches/patches/skipfocus/README.md new file mode 100755 index 0000000..4fb6e8a --- /dev/null +++ b/dwl/dwl-patches/patches/skipfocus/README.md @@ -0,0 +1,18 @@ +### Description +Adds a rule-based ability to skip automatically focusing a window on creation. Expected use-case is for transient windows like notifications etc. The window can still be focused by mouse or keyboard movement. + +| `skipfocus` value | effect | +| ----------------- | ------------------ | +| 0 | usual | +| 1 | skipautofocus | +| 2 | skipfocus entirely | + +### Download +- [2024-09-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/skipfocus/skipfocus.patch) +- [2024-07-14](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/skipfocus/skipfocus-20240714.patch) +- [2024-01-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/skipfocus/skipfocus-20240108.patch) +- [git branch](https://codeberg.org/dhruva_sambrani/dwl/src/branch/skipfocus) + +### Authors +- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani) + diff --git a/dwl/dwl-patches/patches/skipfocus/skipfocus-20240714.patch b/dwl/dwl-patches/patches/skipfocus/skipfocus-20240714.patch new file mode 100755 index 0000000..2715fb9 --- /dev/null +++ b/dwl/dwl-patches/patches/skipfocus/skipfocus-20240714.patch @@ -0,0 +1,81 @@ +diff --git a/config.def.h b/config.def.h +index 22d2171..9f6599c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -22,10 +22,11 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating skipfocus monitor */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 1, 0, -1 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "mako_EXAMPLE", NULL, 0, 1, 1, -1 }, /* Start floating and skip focus + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index 145fd01..ec9d1af 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -138,7 +138,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, skipfocus; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -229,6 +229,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int skipfocus; + int monitor; + } Rule; + +@@ -465,6 +466,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->skipfocus = r->skipfocus; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1323,6 +1325,13 @@ focusclient(Client *c, int lift) + if (locked) + return; + ++ if (c && c->skipfocus != 0){ ++ if (c -> skipfocus == 1) { ++ c->skipfocus = 0; ++ } ++ return; ++ } ++ + /* Raise client in stacking order if requested */ + if (c && lift) + wlr_scene_node_raise_to_top(&c->scene->node); +@@ -1692,11 +1701,13 @@ mapnotify(struct wl_listener *listener, void *data) + printstatus(); + + unset_fullscreen: +- m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); +- wl_list_for_each(w, &clients, link) { +- if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags)) +- setfullscreen(w, 0); +- } ++ if (!c->skipfocus) { ++ m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); ++ wl_list_for_each(w, &clients, link) { ++ if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags)) ++ setfullscreen(w, 0); ++ } ++ } + } + + void diff --git a/dwl/dwl-patches/patches/skipfocus/skipfocus.patch b/dwl/dwl-patches/patches/skipfocus/skipfocus.patch new file mode 100755 index 0000000..ed445ec --- /dev/null +++ b/dwl/dwl-patches/patches/skipfocus/skipfocus.patch @@ -0,0 +1,81 @@ +diff --git a/config.def.h b/config.def.h +index 22d2171..9f6599c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -22,10 +22,11 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating skipfocus monitor */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 1, 0, -1 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "mako_EXAMPLE", NULL, 0, 1, 1, -1 }, /* Start floating and skip focus + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index dc0c861..b6a4cbb 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -141,7 +141,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, skipfocus; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -231,6 +231,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int skipfocus; + int monitor; + } Rule; + +@@ -466,6 +467,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->skipfocus = r->skipfocus; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1343,6 +1345,13 @@ focusclient(Client *c, int lift) + if (locked) + return; + ++ if (c && c->skipfocus != 0){ ++ if (c -> skipfocus == 1) { ++ c->skipfocus = 0; ++ } ++ return; ++ } ++ + /* Raise client in stacking order if requested */ + if (c && lift) + wlr_scene_node_raise_to_top(&c->scene->node); +@@ -1738,11 +1747,13 @@ mapnotify(struct wl_listener *listener, void *data) + printstatus(); + + unset_fullscreen: +- m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); +- wl_list_for_each(w, &clients, link) { +- if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) +- setfullscreen(w, 0); +- } ++ if (!c->skipfocus) { ++ m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); ++ wl_list_for_each(w, &clients, link) { ++ if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) ++ setfullscreen(w, 0); ++ } ++ } + } + + void diff --git a/dwl/dwl-patches/patches/skipfocus/skipfocus20240108.patch b/dwl/dwl-patches/patches/skipfocus/skipfocus20240108.patch new file mode 100755 index 0000000..10d5f4f --- /dev/null +++ b/dwl/dwl-patches/patches/skipfocus/skipfocus20240108.patch @@ -0,0 +1,62 @@ +diff --git a/config.def.h b/config.def.h +index a784eb4..5d3a4f9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -21,10 +21,11 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + static int log_level = WLR_ERROR; + + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating skipfocus monitor */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 1, 0, -1 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "mako_EXAMPLE", NULL, 0, 1, 1, -1 }, /* Start floating and skip focus + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index 6f041a0..90ac57b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -137,7 +137,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, skipfocus; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -228,6 +228,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int skipfocus; + int monitor; + } Rule; + +@@ -464,6 +465,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->skipfocus = r->skipfocus; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -1307,6 +1309,13 @@ focusclient(Client *c, int lift) + if (locked) + return; + ++ if (c && c->skipfocus != 0){ ++ if (c -> skipfocus == 1) { ++ c->skipfocus = 0; ++ } ++ return; ++ } ++ + /* Raise client in stacking order if requested */ + if (c && lift) + wlr_scene_node_raise_to_top(&c->scene->node); diff --git a/dwl/dwl-patches/patches/smartborders/README.md b/dwl/dwl-patches/patches/smartborders/README.md new file mode 100755 index 0000000..6fe0e59 --- /dev/null +++ b/dwl/dwl-patches/patches/smartborders/README.md @@ -0,0 +1,14 @@ +### Description +The borders of a window aren't drawn when the window is the only tiling window +in its tag OR if the window is in a monocle layout. + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/smartborders) +- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/smartborders/smartborders.patch) +- [smartborders-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/smartborders/smartborders-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) +- [fauxmight](https://codeberg.org/fauxmight) +- [Piotr Marendowski](https://github.com/piotr-marendowski) +- Andrey Proskurin diff --git a/dwl/dwl-patches/patches/smartborders/smartborders-0.7.patch b/dwl/dwl-patches/patches/smartborders/smartborders-0.7.patch new file mode 100755 index 0000000..732f06f --- /dev/null +++ b/dwl/dwl-patches/patches/smartborders/smartborders-0.7.patch @@ -0,0 +1,204 @@ +From b10e044d95072994d9b00b31ea70051ab02a026b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Tue, 16 Aug 2022 15:28:00 -0500 +Subject: [PATCH] don't draw borders if there is only one window +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Co-authored-by: A Frederick Christensen +Co-authored-by: Andrey Proskurin +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 1 + + dwl.c | 47 +++++++++++++++++++++++++++++++---------------- + 2 files changed, 32 insertions(+), 16 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..632f151f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,6 +6,7 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ ++static const int smartborders = 1; + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); +diff --git a/dwl.c b/dwl.c +index a2711f67..647ce38c 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -320,7 +320,7 @@ static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); +-static void resize(Client *c, struct wlr_box geo, int interact); ++static void resize(Client *c, struct wlr_box geo, int interact, int draw_borders); + static void run(char *startup_cmd); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); +@@ -746,7 +746,7 @@ closemon(Monitor *m) + wl_list_for_each(c, &clients, link) { + if (c->isfloating && c->geom.x > m->m.width) + resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y, +- .width = c->geom.width, .height = c->geom.height}, 0); ++ .width = c->geom.width, .height = c->geom.height}, 0, 1); + if (c->mon == m) + setmon(c, selmon, c->tags); + } +@@ -814,8 +814,11 @@ commitnotify(struct wl_listener *listener, void *data) + return; + } + +- if (client_surface(c)->mapped && c->mon) +- resize(c, c->geom, (c->isfloating && !c->isfullscreen)); ++ if (client_surface(c)->mapped && c->mon && c->mon->lt[c->mon->sellt]->arrange ++ && !c->isfullscreen && !c->isfloating) ++ c->mon->lt[c->mon->sellt]->arrange(c->mon); ++ else ++ resize(c, c->geom, (c->isfloating && !c->isfullscreen), (c->isfloating && !c->isfullscreen)); + + /* mark a pending resize as completed */ + if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) +@@ -1775,7 +1778,7 @@ monocle(Monitor *m) + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- resize(c, m->w, 0); ++ resize(c, m->w, 0, !smartborders); + n++; + } + if (n) +@@ -1867,11 +1870,11 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + if (cursor_mode == CurMove) { + /* Move the grabbed client to the new position. */ + resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, +- .width = grabc->geom.width, .height = grabc->geom.height}, 1); ++ .width = grabc->geom.width, .height = grabc->geom.height}, 1, 1); + return; + } else if (cursor_mode == CurResize) { + resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); ++ .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1, 1); + return; + } + +@@ -2178,7 +2181,7 @@ requestmonstate(struct wl_listener *listener, void *data) + } + + void +-resize(Client *c, struct wlr_box geo, int interact) ++resize(Client *c, struct wlr_box geo, int interact, int draw_borders) + { + struct wlr_box *bbox; + struct wlr_box clip; +@@ -2190,6 +2193,7 @@ resize(Client *c, struct wlr_box geo, int interact) + + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; ++ c->bw = draw_borders ? borderpx : 0; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ +@@ -2314,6 +2318,8 @@ setfloating(Client *c, int floating) + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); ++ if (c->isfloating && !c->bw) ++ resize(c, c->mon->m, 0, 1); + arrange(c->mon); + printstatus(); + } +@@ -2331,11 +2337,11 @@ setfullscreen(Client *c, int fullscreen) + + if (fullscreen) { + c->prev = c->geom; +- resize(c, c->mon->m, 0); ++ resize(c, c->mon->m, 0, 0); + } else { + /* restore previous size instead of arrange for floating windows since + * client positions are set by the user and cannot be recalculated */ +- resize(c, c->prev, 0); ++ resize(c, c->prev, 0, 1); + } + arrange(c->mon); + printstatus(); +@@ -2362,6 +2368,12 @@ setlayout(const Arg *arg) + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); ++ if (!selmon->lt[selmon->sellt]->arrange) { ++ /* floating layout, draw borders around all clients */ ++ Client *c; ++ wl_list_for_each(c, &clients, link) ++ resize(c, c->mon->m, 0, 1); ++ } + arrange(selmon); + printstatus(); + } +@@ -2396,7 +2408,7 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + arrange(oldmon); + if (m) { + /* Make sure window actually overlaps with the monitor */ +- resize(c, c->geom, 0); ++ resize(c, c->geom, 0, 1); + c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); +@@ -2691,7 +2703,7 @@ tagmon(const Arg *arg) + void + tile(Monitor *m) + { +- unsigned int mw, my, ty; ++ unsigned int mw, my, ty, draw_borders = 1; + int i, n = 0; + Client *c; + +@@ -2701,6 +2713,9 @@ tile(Monitor *m) + if (n == 0) + return; + ++ if (n == smartborders) ++ draw_borders = 0; ++ + if (n > m->nmaster) + mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; + else +@@ -2711,11 +2726,11 @@ tile(Monitor *m) + continue; + if (i < m->nmaster) { + resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); ++ .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0, draw_borders); + my += c->geom.height; + } else { + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); ++ .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0, draw_borders); + ty += c->geom.height; + } + i++; +@@ -2884,7 +2899,7 @@ updatemons(struct wl_listener *listener, void *data) + arrange(m); + /* make sure fullscreen clients have the right size */ + if ((c = focustop(m)) && c->isfullscreen) +- resize(c, m->m, 0); ++ resize(c, m->m, 0, 0); + + /* Try to re-set the gamma LUT when updating monitors, + * it's only really needed when enabling a disabled output, but meh. */ +@@ -3087,7 +3102,7 @@ configurex11(struct wl_listener *listener, void *data) + } + if (c->isfloating || client_is_unmanaged(c)) + resize(c, (struct wlr_box){.x = event->x, .y = event->y, +- .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0); ++ .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0, 1); + else + arrange(c->mon); + } +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/smartborders/smartborders.patch b/dwl/dwl-patches/patches/smartborders/smartborders.patch new file mode 100755 index 0000000..5eac3ee --- /dev/null +++ b/dwl/dwl-patches/patches/smartborders/smartborders.patch @@ -0,0 +1,203 @@ +From 38010bdecf63bdb8acfc584825b398838310eed1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Tue, 16 Aug 2022 15:28:00 -0500 +Subject: [PATCH] don't draw borders if there is only one window +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Co-authored-by: A Frederick Christensen +Co-authored-by: Andrey Proskurin +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 1 + + dwl.c | 46 +++++++++++++++++++++++++++++++--------------- + 2 files changed, 32 insertions(+), 15 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..632f151f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,6 +6,7 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ ++static const int smartborders = 1; + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); +diff --git a/dwl.c b/dwl.c +index ad21e1ba..0c56431a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -317,7 +317,7 @@ static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); +-static void resize(Client *c, struct wlr_box geo, int interact); ++static void resize(Client *c, struct wlr_box geo, int interact, int draw_borders); + static void run(char *startup_cmd); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); +@@ -803,7 +803,7 @@ closemon(Monitor *m) + wl_list_for_each(c, &clients, link) { + if (c->isfloating && c->geom.x > m->m.width) + resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y, +- .width = c->geom.width, .height = c->geom.height}, 0); ++ .width = c->geom.width, .height = c->geom.height}, 0, 1); + if (c->mon == m) + setmon(c, selmon, c->tags); + } +@@ -872,7 +872,11 @@ commitnotify(struct wl_listener *listener, void *data) + return; + } + +- resize(c, c->geom, (c->isfloating && !c->isfullscreen)); ++ if (client_surface(c)->mapped && c->mon && c->mon->lt[c->mon->sellt]->arrange ++ && !c->isfullscreen && !c->isfloating) ++ c->mon->lt[c->mon->sellt]->arrange(c->mon); ++ else ++ resize(c, c->geom, (c->isfloating && !c->isfullscreen), (c->isfloating && !c->isfullscreen)); + + /* mark a pending resize as completed */ + if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) +@@ -1819,7 +1823,7 @@ monocle(Monitor *m) + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- resize(c, m->w, 0); ++ resize(c, m->w, 0, !smartborders); + n++; + } + if (n) +@@ -1911,11 +1915,11 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + if (cursor_mode == CurMove) { + /* Move the grabbed client to the new position. */ + resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, +- .width = grabc->geom.width, .height = grabc->geom.height}, 1); ++ .width = grabc->geom.width, .height = grabc->geom.height}, 1, 1); + return; + } else if (cursor_mode == CurResize) { + resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); ++ .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1, 1); + return; + } + +@@ -2194,7 +2198,7 @@ requestmonstate(struct wl_listener *listener, void *data) + } + + void +-resize(Client *c, struct wlr_box geo, int interact) ++resize(Client *c, struct wlr_box geo, int interact, int draw_borders) + { + struct wlr_box *bbox; + struct wlr_box clip; +@@ -2206,6 +2210,7 @@ resize(Client *c, struct wlr_box geo, int interact) + + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; ++ c->bw = draw_borders ? borderpx : 0; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ +@@ -2330,6 +2335,8 @@ setfloating(Client *c, int floating) + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); ++ if (c->isfloating && !c->bw) ++ resize(c, c->mon->m, 0, 1); + arrange(c->mon); + printstatus(); + } +@@ -2347,11 +2354,11 @@ setfullscreen(Client *c, int fullscreen) + + if (fullscreen) { + c->prev = c->geom; +- resize(c, c->mon->m, 0); ++ resize(c, c->mon->m, 0, 0); + } else { + /* restore previous size instead of arrange for floating windows since + * client positions are set by the user and cannot be recalculated */ +- resize(c, c->prev, 0); ++ resize(c, c->prev, 0, 1); + } + arrange(c->mon); + printstatus(); +@@ -2367,6 +2374,12 @@ setlayout(const Arg *arg) + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); ++ if (!selmon->lt[selmon->sellt]->arrange) { ++ /* floating layout, draw borders around all clients */ ++ Client *c; ++ wl_list_for_each(c, &clients, link) ++ resize(c, c->mon->m, 0, 1); ++ } + arrange(selmon); + printstatus(); + } +@@ -2401,7 +2414,7 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + arrange(oldmon); + if (m) { + /* Make sure window actually overlaps with the monitor */ +- resize(c, c->geom, 0); ++ resize(c, c->geom, 0, 1); + c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); +@@ -2701,7 +2714,7 @@ tagmon(const Arg *arg) + void + tile(Monitor *m) + { +- unsigned int mw, my, ty; ++ unsigned int mw, my, ty, draw_borders = 1; + int i, n = 0; + Client *c; + +@@ -2711,6 +2724,9 @@ tile(Monitor *m) + if (n == 0) + return; + ++ if (n == smartborders) ++ draw_borders = 0; ++ + if (n > m->nmaster) + mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; + else +@@ -2721,11 +2737,11 @@ tile(Monitor *m) + continue; + if (i < m->nmaster) { + resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); ++ .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0, draw_borders); + my += c->geom.height; + } else { + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); ++ .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0, draw_borders); + ty += c->geom.height; + } + i++; +@@ -2894,7 +2910,7 @@ updatemons(struct wl_listener *listener, void *data) + arrange(m); + /* make sure fullscreen clients have the right size */ + if ((c = focustop(m)) && c->isfullscreen) +- resize(c, m->m, 0); ++ resize(c, m->m, 0, 0); + + /* Try to re-set the gamma LUT when updating monitors, + * it's only really needed when enabling a disabled output, but meh. */ +@@ -3103,7 +3119,7 @@ configurex11(struct wl_listener *listener, void *data) + if ((c->isfloating && c != grabc) || !c->mon->lt[c->mon->sellt]->arrange) { + resize(c, (struct wlr_box){.x = event->x - c->bw, + .y = event->y - c->bw, .width = event->width + c->bw * 2, +- .height = event->height + c->bw * 2}, 0); ++ .height = event->height + c->bw * 2}, 0, 1); + } else { + arrange(c->mon); + } +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/snail-gaps/README.md b/dwl/dwl-patches/patches/snail-gaps/README.md new file mode 100755 index 0000000..ba26f13 --- /dev/null +++ b/dwl/dwl-patches/patches/snail-gaps/README.md @@ -0,0 +1,15 @@ +### Description + +Adds support for the [gaps patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/gaps) +to the [snail layout patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/snail). + +Install the [gaps patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/gaps) +and the [snail patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/snail) first. + +### Download + +- [main 2024-08-08](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/snail-gaps/snail-gaps.patch) + +### Authors + +- [JoaoCostaIFG](https://codeberg.org/JoaoCostaIFG) ([joaocosta@posteo.net](mailto:joaocosta@posteo.net)) diff --git a/dwl/dwl-patches/patches/snail-gaps/snail-gaps.patch b/dwl/dwl-patches/patches/snail-gaps/snail-gaps.patch new file mode 100755 index 0000000..51d2812 --- /dev/null +++ b/dwl/dwl-patches/patches/snail-gaps/snail-gaps.patch @@ -0,0 +1,160 @@ +From 804e69ca4bf586bcec46e018630f94c1c4e0b7e7 Mon Sep 17 00:00:00 2001 +From: JoaoCostaIFG +Date: Thu, 8 Aug 2024 00:05:27 +0100 +Subject: [PATCH 2/2] Add gaps support to snail layout + +--- + dwl.c | 105 +++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 59 insertions(+), 46 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 46bdca1..a158dd6 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2659,8 +2659,8 @@ void + snail(Monitor *m) + { + int i = 0, n = 0; +- unsigned int mw = m->w.width; +- Client *c, *prev; ++ unsigned int mw = m->w.width, e = m->gaps, w = 0, h = 0, egappx = 0; ++ Client *c, *prev = NULL; + enum wlr_direction dir = WLR_DIRECTION_RIGHT; + + wl_list_for_each(c, &clients, link) +@@ -2668,9 +2668,12 @@ snail(Monitor *m) + n++; + if (n == 0) + return; ++ if (smartgaps == n) ++ e = 0; ++ egappx = e * gappx; + + if (n > m->nmaster) +- mw = m->nmaster ? ROUND(m->w.width * m->mfact) : 0; ++ mw = m->nmaster ? (unsigned int)round((m->w.width + egappx) * m->mfact) : 0; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) +@@ -2681,8 +2684,8 @@ snail(Monitor *m) + * master area with this window + */ + if (mw > 0 && i == 0) { +- c->geom = (struct wlr_box){.x = m->w.x, .y = m->w.y, +- .width = mw, .height = m->w.height}; ++ c->geom = (struct wlr_box){.x = m->w.x + egappx, .y = m->w.y + egappx, ++ .width = mw - 2*egappx, .height = m->w.height - 2*egappx}; + /* + * If the first window in the master area is wide, split it + * horizontally and put next one on its right; otherwise, split it +@@ -2694,55 +2697,65 @@ snail(Monitor *m) + * m->nmaster-th window + */ + } else if (i == m->nmaster) { +- c->geom = (struct wlr_box){.x = m->w.x + mw, .y = m->w.y, +- .width = m->w.width - mw, .height = m->w.height}; ++ c->geom = (struct wlr_box){.x = m->w.x + mw + egappx, .y = m->w.y + egappx, ++ .width = m->w.width - mw - 2*egappx, .height = m->w.height - 2*egappx}; + /* + * If the first window in the stack is wide, split it horizontally + * and put next one on its right; otherwise, split it vertically and + * put the next one below it + */ + dir = c->geom.width > m->w.height ? WLR_DIRECTION_RIGHT : WLR_DIRECTION_DOWN; +- /* +- * Split the previous horizontally and put the current window on the right +- */ +- } else if (dir == WLR_DIRECTION_RIGHT) { +- c->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; +- prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; ++ } else if (prev) { + /* +- * If it's a stack window or the first narrow window in the master +- * area, put the next one below it ++ * Split the previous horizontally and put the current window on the right + */ +- if (i >= m->nmaster || c->geom.width < m->w.height) +- dir = WLR_DIRECTION_DOWN; +- /* +- * Split the previous vertically and put the current window below it +- */ +- } else if (dir == WLR_DIRECTION_DOWN) { +- c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2, +- .width = prev->geom.width, .height = prev->geom.height / 2}; +- prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width, .height = prev->geom.height / 2}; +- dir = WLR_DIRECTION_LEFT; +- /* +- * Split the previous horizontally and put the current window on the left +- */ +- } else if (dir == WLR_DIRECTION_LEFT) { +- c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; +- prev->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y, +- .width = prev->geom.width / 2, .height = prev->geom.height}; +- dir = WLR_DIRECTION_UP; +- /* +- * Split the previous vertically and put the current window above it +- */ +- } else { +- c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, +- .width = prev->geom.width, .height = prev->geom.height / 2}; +- prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2, +- .width = prev->geom.width, .height = prev->geom.height / 2}; +- dir = WLR_DIRECTION_RIGHT; ++ if (dir == WLR_DIRECTION_RIGHT) { ++ w = prev->geom.width / 2 - egappx; ++ h = prev->geom.height; ++ c->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2 + egappx, .y = prev->geom.y, ++ .width = w, .height = h}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = w, .height = h}; ++ /* ++ * If it's a stack window or the first narrow window in the master ++ * area, put the next one below it ++ */ ++ if (i >= m->nmaster || c->geom.width < m->w.height) ++ dir = WLR_DIRECTION_DOWN; ++ /* ++ * Split the previous vertically and put the current window below it ++ */ ++ } else if (dir == WLR_DIRECTION_DOWN) { ++ w = prev->geom.width; ++ h = prev->geom.height / 2 - egappx; ++ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2 + egappx, ++ .width = w, .height = h}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = w, .height = h}; ++ dir = WLR_DIRECTION_LEFT; ++ /* ++ * Split the previous horizontally and put the current window on the left ++ */ ++ } else if (dir == WLR_DIRECTION_LEFT) { ++ w = prev->geom.width / 2 - egappx; ++ h = prev->geom.height; ++ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = w, .height = h}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2 + egappx, .y = prev->geom.y, ++ .width = w, .height = h}; ++ dir = WLR_DIRECTION_UP; ++ /* ++ * Split the previous vertically and put the current window above it ++ */ ++ } else { ++ w = prev->geom.width; ++ h = prev->geom.height / 2 - egappx; ++ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = w, .height = h}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2 + egappx, ++ .width = w, .height = h}; ++ dir = WLR_DIRECTION_RIGHT; ++ } + } + i++; + prev = c; +-- +2.46.0 + + diff --git a/dwl/dwl-patches/patches/snail/README.md b/dwl/dwl-patches/patches/snail/README.md new file mode 100755 index 0000000..0c94b79 --- /dev/null +++ b/dwl/dwl-patches/patches/snail/README.md @@ -0,0 +1,9 @@ +### Description +Adds a spiral-inspired layout for wide screens. + +### Download +- [2024-02-11](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/snail/snail.patch) + +### Authors +- [Dima Krasner](https://codeberg.org/dimkr) () +- [Nikita Ivanov](https://github.com/NikitaIvanovV) (fix for flickering) diff --git a/dwl/dwl-patches/patches/snail/snail.patch b/dwl/dwl-patches/patches/snail/snail.patch new file mode 100755 index 0000000..061030a --- /dev/null +++ b/dwl/dwl-patches/patches/snail/snail.patch @@ -0,0 +1,250 @@ +From 39b6da6082db641191699be906e485f8c8fbc4e6 Mon Sep 17 00:00:00 2001 +From: Dima Krasner +Date: Sun, 11 Feb 2024 09:09:16 +0200 +Subject: [PATCH] add the snail layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This layout is a scalable alternative to the "tile" and "spiral" layouts, optimized for wide monitors. Both the master area and the stack are "spirals", but windows in the master area are split horizontally as long as the master area has enough horizontal space, and the first window in the stack is split vertically unless the stack is wide. + +With one window in the master area and mfact = 0.5, it behaves like the spiral layout: + +┌───────────────┬────────────────┐ +│ │ │ +│ │ │ +│ │ │ +│ │ │ +│ ├───┬───┬────────┤ +│ │ │ │ │ +│ ├───┴───┤ │ +│ │ │ │ +│ │ │ │ +└───────────────┴───────┴────────┘ + +With 2 windows in the master area and 2 in the stack: + +┌───────────────┬────────────────┐ +│ │ │ +│ │ │ +│ │ │ +│ │ │ +├───────────────┼────────────────┤ +│ │ │ +│ │ │ +│ │ │ +│ │ │ +└───────────────┴────────────────┘ + +With 3 windows in the master area and 2 in the stack: + +┌───────────────┬────────────────┐ +│ │ │ +│ │ │ +│ │ │ +│ │ │ +├───────┬───────┼────────────────┤ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +└───────┴───────┴────────────────┘ + +With many windows in both areas: + +┌───────────────┬────────────────┐ +│ │ │ +│ │ │ +│ │ │ +│ │ │ +├───┬───┬───────┼───┬───┬────────┤ +│ │ │ │ │ │ │ +├───┴───┤ ├───┴───┤ │ +│ │ │ │ │ +│ │ │ │ │ +└───────┴───────┴───────┴────────┘ + +With 2 windows in the master area, many windows in the stack and high mfact: + +┌──────────┬──────────┬──────────┐ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ master ├──┬stack──┤ +│ │ │ │ │ │ +│ │ ├──┴──┤ │ +│ │ │ │ │ +│ │ │ │ │ +└──────────┴──────────┴─────┴────┘ + +With 2 windows in the master area, many windows in the stack and low mfact: + +┌──────────┬──────────┬──────────┐ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +├──master──┤ stack┬──┬────┤ +│ │ │ │ │ │ +│ │ ├──┴──┤ │ +│ │ │ │ │ +│ │ │ │ │ +└──────────┴──────────┴─────┴────┘ +--- + config.def.h | 4 +- + dwl.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 105 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..abf9644 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -34,6 +34,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "@|@", snail }, + }; + + /* monitors */ +@@ -48,7 +49,7 @@ static const MonitorRule monrules[] = { + { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + */ + /* defaults */ +- { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, ++ { NULL, 0.64f, 1, 1, &layouts[3], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, + }; + + /* keyboard */ +@@ -139,6 +140,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_s, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index 5bf995e..45ac5ad 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -333,6 +333,7 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); ++static void snail(Monitor *m); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -2644,6 +2645,107 @@ setup(void) + #endif + } + ++void ++snail(Monitor *m) ++{ ++ int i = 0, n = 0; ++ unsigned int mw = m->w.width; ++ Client *c, *prev; ++ enum wlr_direction dir = WLR_DIRECTION_RIGHT; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ if (n == 0) ++ return; ++ ++ if (n > m->nmaster) ++ mw = m->nmaster ? (int)round(m->w.width * m->mfact) : 0; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ ++ /* ++ * If the master area exists and this is the first window, fill the ++ * master area with this window ++ */ ++ if (mw > 0 && i == 0) { ++ c->geom = (struct wlr_box){.x = m->w.x, .y = m->w.y, ++ .width = mw, .height = m->w.height}; ++ /* ++ * If the first window in the master area is wide, split it ++ * horizontally and put next one on its right; otherwise, split it ++ * vertically and put the next one below it ++ */ ++ dir = c->geom.width > m->w.height ? WLR_DIRECTION_RIGHT : WLR_DIRECTION_DOWN; ++ /* ++ * If the master area is full or doesn't exist, fill the stack with the ++ * m->nmaster-th window ++ */ ++ } else if (i == m->nmaster) { ++ c->geom = (struct wlr_box){.x = m->w.x + mw, .y = m->w.y, ++ .width = m->w.width - mw, .height = m->w.height}; ++ /* ++ * If the first window in the stack is wide, split it horizontally ++ * and put next one on its right; otherwise, split it vertically and ++ * put the next one below it ++ */ ++ dir = c->geom.width > m->w.height ? WLR_DIRECTION_RIGHT : WLR_DIRECTION_DOWN; ++ /* ++ * Split the previous horizontally and put the current window on the right ++ */ ++ } else if (dir == WLR_DIRECTION_RIGHT) { ++ c->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y, ++ .width = prev->geom.width / 2, .height = prev->geom.height}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = prev->geom.width / 2, .height = prev->geom.height}; ++ /* ++ * If it's a stack window or the first narrow window in the master ++ * area, put the next one below it ++ */ ++ if (i >= m->nmaster || c->geom.width < m->w.height) ++ dir = WLR_DIRECTION_DOWN; ++ /* ++ * Split the previous vertically and put the current window below it ++ */ ++ } else if (dir == WLR_DIRECTION_DOWN) { ++ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2, ++ .width = prev->geom.width, .height = prev->geom.height / 2}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = prev->geom.width, .height = prev->geom.height / 2}; ++ dir = WLR_DIRECTION_LEFT; ++ /* ++ * Split the previous horizontally and put the current window on the left ++ */ ++ } else if (dir == WLR_DIRECTION_LEFT) { ++ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = prev->geom.width / 2, .height = prev->geom.height}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y, ++ .width = prev->geom.width / 2, .height = prev->geom.height}; ++ dir = WLR_DIRECTION_UP; ++ /* ++ * Split the previous vertically and put the current window above it ++ */ ++ } else { ++ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y, ++ .width = prev->geom.width, .height = prev->geom.height / 2}; ++ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2, ++ .width = prev->geom.width, .height = prev->geom.height / 2}; ++ dir = WLR_DIRECTION_RIGHT; ++ } ++ i++; ++ prev = c; ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ ++ resize(c, c->geom, 0); ++ } ++} ++ + void + spawn(const Arg *arg) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/spawninfo/README.md b/dwl/dwl-patches/patches/spawninfo/README.md new file mode 100755 index 0000000..5ee345d --- /dev/null +++ b/dwl/dwl-patches/patches/spawninfo/README.md @@ -0,0 +1,41 @@ +### Description + +This patch adds `spawninfo` function that is very similar to `spawn`, except it +also passes some information about the focused client via stdin. + +The info is passed in this format: + + PID + TITLE + APPID + TAGS + X,Y WIDTHxHEIGHT + +I use it for 2 things: grabbing a screenshot of a focused window and adjusting +volume of audio produced by a focused window (so much simpler than having to +open pulsemixer every time). If you want to have the same functionality, you +need to put these scripts into your PATH and make them executable: + +[screenshotwin](/dwl/dwl-patches/raw/branch/main/patches/spawninfo/screenshotwin) +for taking a screenshot (`grim` is required): + +```c + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_S, spawninfo, SHCMD("screenshotwin") }, +``` + +[pamixerc](/dwl/dwl-patches/raw/branch/main/patches/spawninfo/pamixerc) +for adjusting volume (`pactl` is required): + +```c + { MODKEY, XKB_KEY_XF86AudioRaiseVolume,spawninfo,SHCMD("pamixerc -- -i 5") }, + { MODKEY, XKB_KEY_XF86AudioLowerVolume,spawninfo,SHCMD("pamixerc -- -d 5") }, + { MODKEY, XKB_KEY_XF86AudioMute, spawninfo, SHCMD("pamixerc -- -t") }, +``` + +### Download + +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/spawninfo/spawninfo.patch) + +### Authors + +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) diff --git a/dwl/dwl-patches/patches/spawninfo/pamixerc b/dwl/dwl-patches/patches/spawninfo/pamixerc new file mode 100755 index 0000000..91a41c4 --- /dev/null +++ b/dwl/dwl-patches/patches/spawninfo/pamixerc @@ -0,0 +1,134 @@ +#!/usr/bin/awk -f + +function get_parent(pid, cmd, ppid, arr) { + cmd = sprintf("/proc/%d/stat", pid) + ppid = "" + if ((getline line < cmd) > 0) { + split(line, arr) + ppid = arr[4] + } + close(cmd) + return ppid +} + +function proc_clients(line, arr) { + if (match(line, /^Client #(.*)/, arr)) { + store_client() + client_index = arr[1] + return + } + else if (match(line, /^\s*application\.process\.id = "(.*)"/, arr)) { + process_id = arr[1] + return + } + else if (match(line, /^\s*application\.name = "(.*)"/, arr)) { + application_name = arr[1] + return + } +} + +function store_client() { + if (client_index == "") + return + + clients[client_index] = 1 + clients[client_index, "pid"] = process_id + clients[client_index, "parent_pid"] = get_parent(process_id) + clients[client_index, "name"] = application_name + client_index = "" + process_id = "" +} + +function proc_sink_inputs(line, arr) { + if (match(line, /^Sink Input #(.*)/, arr)) { + apply_sink_input() + sink_index = arr[1] + return + } + else if (match(line, /^\s*application\.process\.id = "(.*)"/, arr)) { + process_id = arr[1] + return + } + else if (match(line, /^\s*Client: (.*)/, arr)) { + client_index = arr[1] + return + } + else if (match(line, /^\s*Mute: (.*)/, arr)) { + muted = (arr[1] == "yes") + return + } + else if (match(line, /^\s*Volume:.* ([0-9]+)%/, arr)) { + volume = strtonum(arr[1]) + return + } +} + +function apply_sink_input( cmd, header, msg, inc) { + if (sink_index == "") + return + + # Do stuff if PID matches + if (PID == clients[client_index, "pid"] || PID == clients[client_index, "parent_pid"]) { + switch (ACTION) { + case "-i": + case "-d": + inc = strtonum(ARG) + if (ACTION == "-i") + volume += inc + else + volume -= inc + volume = volume > 100 ? 100 : volume + volume = volume < 0 ? 0 : volume + cmd = sprintf("pactl set-sink-input-volume '%d' '%d'%", sink_index, volume) + system(cmd) + print cmd + break + case "-t": + muted = !muted + cmd = sprintf("pactl set-sink-input-mute '%d' '%s'", sink_index, muted ? "true" : "false") + system(cmd) + print cmd + break + } + # Display a "popup" with new volume + header = sprintf("Client Volume: %d%%%s", volume, muted ? " MUTED" : "") + msg = clients[client_index, "name"] + system(sprintf("notify-send -r 101 -u low -h 'int:value:%d' '%s' '%s'", volume, header, msg)) + } + + sink_index = "" +} + +BEGIN { + # Get arguments + # ACTION: -d, -i or -t (like pamixer) + # ARG: num arg for -d or -i + ACTION = ARGV[1] + ARG = ARGV[2] + for (i = 1; i < ARGC; i++) + delete ARGV[i] + + # Get client info + getline PID + getline TITLE # Not used + getline APPID # Not used + getline TAGS # Not used + getline GEOMETRY # Not used + + if (PID == "") + exit 1 + + # Process PulseAudio clients list and store PIDs for each + cmd = "pactl list clients" + while ((cmd | getline line) > 0) + proc_clients(line) + close(cmd) + store_client() + + # Process PulseAudio sink inputs list and run apply_sink_input() for each + cmd = "pactl list sink-inputs" + while ((cmd | getline line) > 0) + proc_sink_inputs(line) + close(cmd) + apply_sink_input() +} diff --git a/dwl/dwl-patches/patches/spawninfo/screenshotwin b/dwl/dwl-patches/patches/spawninfo/screenshotwin new file mode 100755 index 0000000..c8a3ebf --- /dev/null +++ b/dwl/dwl-patches/patches/spawninfo/screenshotwin @@ -0,0 +1,21 @@ +#!/bin/sh + +# Get client info +read -r PID +read -r TITLE +read -r APPID +read -r TAGS +read -r GEOMETRY + +[ -n "$GEOMETRY" ] || exit 1 + +tempdir="/tmp/screenshots" +mkdir -p "$tempdir" +file="$(mktemp -p "$tempdir" "XXXXXX.png")" + +# Grab the screenshot! Very conviniently, GEOMETRY format matches the one +# expected by grim +grim -g "$GEOMETRY" "$file" || exit + +wl-copy -t image/png < "$file" +notify-send -i "$file" "Screenshot taken!" "Image copied to clipboard and saved to $file" diff --git a/dwl/dwl-patches/patches/spawninfo/spawninfo.patch b/dwl/dwl-patches/patches/spawninfo/spawninfo.patch new file mode 100755 index 0000000..e452a4e --- /dev/null +++ b/dwl/dwl-patches/patches/spawninfo/spawninfo.patch @@ -0,0 +1,110 @@ +From 83b8dc03f5ea40f472e90d452671f8e55faf2c4c Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Sun, 9 Feb 2025 23:27:48 +0100 +Subject: [PATCH] spawninfo: spawn but pass client info via stdin + +--- + client.h | 12 ++++++++++++ + dwl.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 54 insertions(+) + +diff --git a/client.h b/client.h +index 42f225f..bc9cad2 100644 +--- a/client.h ++++ b/client.h +@@ -131,6 +131,18 @@ client_get_appid(Client *c) + return c->surface.xdg->toplevel->app_id; + } + ++static inline int ++client_get_pid(Client *c) ++{ ++ pid_t pid; ++#ifdef XWAYLAND ++ if (client_is_x11(c)) ++ return c->surface.xwayland->pid; ++#endif ++ wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); ++ return pid; ++} ++ + static inline void + client_get_clip(Client *c, struct wlr_box *clip) + { +diff --git a/dwl.c b/dwl.c +index def2562..859514c 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -141,6 +141,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ pid_t pid; + } Client; + + typedef struct { +@@ -334,6 +335,7 @@ static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); ++static void spawninfo(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -466,6 +468,8 @@ applyrules(Client *c) + if (!(title = client_get_title(c))) + title = broken; + ++ c->pid = client_get_pid(c); ++ + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { +@@ -2658,6 +2662,44 @@ spawn(const Arg *arg) + } + } + ++void ++spawninfo(const Arg *arg) ++{ ++ int fd[2]; ++ pid_t pid; ++ const char *title, *appid; ++ Client *c = focustop(selmon); ++ ++ if (pipe(fd) == -1) ++ return; ++ if ((pid = fork()) == -1) ++ return; ++ if (pid == 0) { ++ dup2(fd[0], STDIN_FILENO); ++ close(fd[0]); ++ close(fd[1]); ++ dup2(STDERR_FILENO, STDOUT_FILENO); ++ setsid(); ++ execvp(((char **)arg->v)[0], (char **)arg->v); ++ die("dwl: execvp %s failed:", ((char **)arg->v)[0]); ++ } ++ ++ close(fd[0]); ++ ++ if (c) { ++ if (!(title = client_get_title(c))) ++ title = ""; ++ if (!(appid = client_get_appid(c))) ++ appid = ""; ++ dprintf(fd[1], "%d\n%s\n%s\n%"PRIu32"\n%d,%d %dx%d\n", c->pid, ++ title, appid, c->tags, ++ c->geom.x + c->bw, c->geom.y + c->bw, ++ c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); ++ } ++ ++ close(fd[1]); ++} ++ + void + startdrag(struct wl_listener *listener, void *data) + { +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/stacker/README.md b/dwl/dwl-patches/patches/stacker/README.md new file mode 100755 index 0000000..c7778a0 --- /dev/null +++ b/dwl/dwl-patches/patches/stacker/README.md @@ -0,0 +1,28 @@ +### Description +Stacker is a patch that allows moving around the stack more freely. With only +one keybinding, quickly move, swap and jump around the window stack. + +1. Focus any window of the stack with a single key binding. +2. Swap the currently focused windows with any other window in the stack. +3. Move the selected window in the stack with `relativeswap`. + +This patch is heavily inspired by the original [stacker](https://dwm.suckless.org/patches/stacker/) dwm patch. + +### Keybinding + +- `MODKEY` + {`q`, `w`, `e`, `r`}: jump to the first, second, third and last + window of the stack +- `MODKEY` + `SHIFT` + {`Q`, `W`, `E`, `R`}: swap the selected with the first, second, third and last + window of the stack +- `MODKEY` + `SHIFT` + {`J`, `K`}: move the selected window up & down the stack + +### Missing feature + +Jumping to the last selected window is not yet implemented. + +### Download +- [git branch](https://codeberg.org/jeromecst/dwl/src/branch/stacker) +- [2024-05-17](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/stacker/stacker.patch) + +### Authors +- [jeromecst](https://codeberg.org/jeromecst) diff --git a/dwl/dwl-patches/patches/stacker/stacker.patch b/dwl/dwl-patches/patches/stacker/stacker.patch new file mode 100755 index 0000000..dba1cb0 --- /dev/null +++ b/dwl/dwl-patches/patches/stacker/stacker.patch @@ -0,0 +1,212 @@ +From b8f39c0710eb3cfdf4c619f532222d356ec58140 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A9r=C3=B4me?= +Date: Fri, 17 May 2024 23:06:19 +0200 +Subject: [PATCH] stacker + +--- + config.def.h | 10 +++++ + dwl.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 114 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 8f498d2..44cbcd8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -120,10 +120,20 @@ static const char *menucmd[] = { "wmenu-run", NULL }; + static const Key keys[] = { + /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ + /* modifier key function argument */ ++ { MODKEY, XKB_KEY_q, focusto, {.i = 0} }, ++ { MODKEY, XKB_KEY_w, focusto, {.i = 1} }, ++ { MODKEY, XKB_KEY_e, focusto, {.i = 2} }, ++ { MODKEY, XKB_KEY_r, focusto, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, swapstack, {.i = 0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_W, swapstack, {.i = 1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_E, swapstack, {.i = 2} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, swapstack, {.i = -1} }, + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, relativeswap, {.i = +1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, relativeswap, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +diff --git a/dwl.c b/dwl.c +index bf763df..be88c6d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -279,6 +279,7 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); ++static void focusto(const Arg *arg); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); +@@ -308,6 +309,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); + static void printstatus(void); + static void quit(const Arg *arg); ++static void relativeswap(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); +@@ -327,6 +329,8 @@ static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); ++static void swapstack(const Arg *arg); ++static void relativeswap(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); +@@ -343,9 +347,11 @@ static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); + static void virtualkeyboard(struct wl_listener *listener, void *data); + static void virtualpointer(struct wl_listener *listener, void *data); ++static Client *nextvisible(int i, struct wl_list *from, Monitor *m); + static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); ++static void wl_list_swap(struct wl_list *a, struct wl_list *b); + static void zoom(const Arg *arg); + + /* variables */ +@@ -1308,6 +1314,21 @@ focusclient(Client *c, int lift) + client_activate_surface(client_surface(c), 1); + } + ++void ++focusto(const Arg *arg) ++{ ++ Client *c, *sel = focustop(selmon); ++ int i; ++ if (!sel || (sel->isfullscreen && !client_has_children(sel))) ++ return; ++ ++ i = arg->i > -1 ? arg->i + 1 : arg->i; ++ ++ c = nextvisible(i, &clients, selmon); ++ if (c) ++ focusclient(c , 1); ++} ++ + void + focusmon(const Arg *arg) + { +@@ -1951,6 +1972,24 @@ quit(const Arg *arg) + wl_display_terminate(dpy); + } + ++void ++relativeswap(const Arg *arg) ++{ ++ Client *trgt, *sel = focustop(selmon); ++ ++ if (!sel || !selmon) ++ return; ++ ++ trgt = nextvisible(arg->i, &sel->link, selmon); ++ if (!trgt || trgt == sel) ++ return; ++ ++ wl_list_swap(&sel->link, &trgt->link); ++ ++ focusclient(sel, 1); ++ arrange(selmon); ++} ++ + void + rendermon(struct wl_listener *listener, void *data) + { +@@ -2548,6 +2587,26 @@ startdrag(struct wl_listener *listener, void *data) + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); + } + ++void ++swapstack(const Arg *arg) ++{ ++ Client *trgt, *sel = focustop(selmon); ++ int i; ++ ++ if (!sel || !selmon) ++ return; ++ ++ i = arg->i > -1 ? arg->i + 1 : arg->i; ++ trgt = nextvisible(i, &clients, selmon); ++ if (!trgt || trgt == sel) ++ return; ++ ++ wl_list_swap(&sel->link, &trgt->link); ++ ++ focusclient(sel, 1); ++ arrange(selmon); ++} ++ + void + tag(const Arg *arg) + { +@@ -2858,6 +2917,28 @@ virtualpointer(struct wl_listener *listener, void *data) + wlr_cursor_map_input_to_output(cursor, &pointer.base, event->suggested_output); + } + ++Client * ++nextvisible(int i, struct wl_list *from, Monitor *m) ++{ ++ Client *c; ++ if (i >= 0){ ++ wl_list_for_each(c, from, link) { ++ // if (VISIBLEON(c , m) && &c->link != from && i--) ++ if (VISIBLEON(c , m)) { ++ if (--i == 0) ++ return c; ++ } ++ } ++ } else if (i < 0) { ++ wl_list_for_each_reverse(c, from, link) { ++ if (VISIBLEON(c , m)) ++ if (++i == 0) ++ return c; ++ } ++ } ++ return NULL; ++} ++ + Monitor * + xytomon(double x, double y) + { +@@ -2865,6 +2946,29 @@ xytomon(double x, double y) + return o ? o->data : NULL; + } + ++void ++wl_list_swap(struct wl_list *a, struct wl_list *b) ++{ ++ struct wl_list *prev_a = a->prev; ++ struct wl_list *prev_b = b->prev; ++ ++ if (prev_b == a) { ++ wl_list_remove(a); ++ wl_list_insert(b, a); ++ return; ++ } ++ if (prev_a == b) { ++ wl_list_remove(b); ++ wl_list_insert(a, b); ++ return; ++ } ++ wl_list_remove(a); ++ wl_list_insert(prev_b, a); ++ ++ wl_list_remove(b); ++ wl_list_insert(prev_a, b); ++} ++ + void + xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny) +-- +2.45.1 + diff --git a/dwl/dwl-patches/patches/stairs/README.md b/dwl/dwl-patches/patches/stairs/README.md new file mode 100755 index 0000000..403a276 --- /dev/null +++ b/dwl/dwl-patches/patches/stairs/README.md @@ -0,0 +1,42 @@ +### Description +Port of the [stairs](https://dwm.suckless.org/patches/stairs/) patch from dwm. + +The remaining text is from the description on the dwm site: + +This layout can be modified using the 3 variables provided in config.h: stairpx, stairdirection and stairsamesize. + +``` ++-------------+--------+----------------+ +| | | | +| | +--| S1 | +| | |S2| | +| | +--| | | +| | |S3| | | +| M |--| | +----------------+ +| |S4| | | | +| | | +-----------------+ | +| | | | | +| | +------------------+ | +| | | | ++-------------+-------------------+-----+ + stairsamesize = 1 + ++-------------+--------+----------------+ +| | | | +| | +--| S1 | +| | |S2| | +| | +--| | | +| | |S3| | | +| M |--| | | | +| |S4| | | | +| | | | | | +| | | | | | +| | | | | | +| | | | | | ++-------------+--+--+--+----------------+ + stairsamesize = 0 +``` +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/stairs/stairs.patch) +### Authors +- [MayOrMayNotBeACat](https://codeberg.org/MayOrMayNotBeACat) diff --git a/dwl/dwl-patches/patches/stairs/stairs.patch b/dwl/dwl-patches/patches/stairs/stairs.patch new file mode 100755 index 0000000..d39932e --- /dev/null +++ b/dwl/dwl-patches/patches/stairs/stairs.patch @@ -0,0 +1,136 @@ +From d5bbe6d54d044fa11c76e2e20b96a44897319424 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Tue, 4 Feb 2025 20:51:06 +0100 +Subject: [PATCH 1/2] Fix crash disabling monitor with locked surface + +(cherry picked from commit d1880b44223701c91b51b319fc69a0f63044f861) +--- + dwl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dwl.c b/dwl.c +index cf3ef70..c717c1d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -716,6 +716,8 @@ cleanupmon(struct wl_listener *listener, void *data) + wl_list_remove(&m->frame.link); + wl_list_remove(&m->link); + wl_list_remove(&m->request_state.link); ++ if (m->lock_surface) ++ destroylocksurface(&m->destroy_lock_surface, NULL); + m->wlr_output->data = NULL; + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); +-- +2.50.1 + + +From b6e96ab6281eddacdda26c39e6446b72ce05de39 Mon Sep 17 00:00:00 2001 +From: JustinWayland +Date: Fri, 6 Jun 2025 22:14:31 -0400 +Subject: [PATCH 2/2] Add stairs layout. + +--- + config.def.h | 5 +++++ + dwl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 53 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..e81568c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,9 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int stairpx = 20; /* depth of the stairs layout */ ++static const int stairdirection = 1; /* 0: left-aligned, 1: right-aligned */ ++static const int stairsamesize = 1; /* 1 means shrink all the staired windows to the same size */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); +@@ -34,6 +37,7 @@ static const Layout layouts[] = { + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "[S]", stairs }, + }; + + /* monitors */ +@@ -139,6 +143,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XKB_KEY_s, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, +diff --git a/dwl.c b/dwl.c +index cf3ef70..4debf15 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -334,6 +334,7 @@ static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); ++static void stairs(Monitor* m); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -2657,6 +2658,53 @@ spawn(const Arg *arg) + } + } + ++void ++stairs(Monitor *m) ++{ ++ int i, n, h, mw, my; ++ int ox, oy, ow, oh; ++ Client *c; ++ ++ n = 0; ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ if (n == 0) ++ return; ++ ++ if (n > m->nmaster) ++ mw = m->nmaster ? ROUND(m->w.width * m->mfact) : 0; ++ else ++ mw = m->w.width; ++ ++ i = my = 0; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c,m) || c->isfloating || c->fullscreen) ++ continue; ++ if (i < m->nmaster) { ++ h = (m->w.height - my) / (MIN(n, m->nmaster) - i); ++ resize(c, (struct wlr_box){ ++ .x=m->w.x,.y=m->w.y + my,.width=mw,.height=h ++ }, 0); ++ my += c->geom.height; ++ } else { ++ oy = i - m->nmaster; ++ ox = stairdirection ? n - i - 1 : (stairsamesize ? i - m->nmaster: 0); ++ ow = stairsamesize ? n - m->nmaster - 1 : n - i - 1; ++ oh = stairsamesize ? ow : i - m->nmaster; ++ resize(c, (struct wlr_box){ ++ .x=m->w.x + mw + (ox * stairpx), ++ .y=m->w.y + (oy * stairpx), ++ .width=m->w.width - mw - (ow * stairpx), ++ .height=m->w.height - (oh * stairpx) ++ }, 0); ++ if (c == focustop(selmon)) ++ wlr_scene_node_raise_to_top(&c->scene->node); ++ } ++ i++; ++ } ++} ++ + void + startdrag(struct wl_listener *listener, void *data) + { +-- +2.50.1 + diff --git a/dwl/dwl-patches/patches/startargv/README.md b/dwl/dwl-patches/patches/startargv/README.md new file mode 100755 index 0000000..bc15225 --- /dev/null +++ b/dwl/dwl-patches/patches/startargv/README.md @@ -0,0 +1,13 @@ +### Description +allow passing startup command on argv + +e.g. `dwl -s foot -s` launches `foot -s` + +put `sh -c` right after `dwl -s` to emulate normal behaviour + +### Download +- [git branch](https://codeberg.org/notchoc/dwl/src/branch/startargv) +- [2024-07-03](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/startargv/startargv.patch) + +### Authors +- [notchoc](https://codeberg.org/notchoc) diff --git a/dwl/dwl-patches/patches/startargv/startargv.patch b/dwl/dwl-patches/patches/startargv/startargv.patch new file mode 100755 index 0000000..5697b9c --- /dev/null +++ b/dwl/dwl-patches/patches/startargv/startargv.patch @@ -0,0 +1,58 @@ +From a823f7923f8d2006eedc013ca1c1ba7a496543d5 Mon Sep 17 00:00:00 2001 +From: choc +Date: Wed, 3 Jul 2024 11:21:33 +0800 +Subject: [PATCH] startargv: allow passing startup command on argv + +--- + dwl.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 9fb50a7..43b1ac1 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -320,7 +320,7 @@ static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); +-static void run(char *startup_cmd); ++static void run(char **startup_cmd); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -2158,7 +2158,7 @@ resize(Client *c, struct wlr_box geo, int interact) + } + + void +-run(char *startup_cmd) ++run(char **startup_cmd) + { + /* Add a Unix socket to the Wayland display. */ + const char *socket = wl_display_add_socket_auto(dpy); +@@ -2183,7 +2183,7 @@ run(char *startup_cmd) + dup2(piperw[0], STDIN_FILENO); + close(piperw[0]); + close(piperw[1]); +- execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); ++ execvp(startup_cmd[0], startup_cmd); + die("startup: execl:"); + } + dup2(piperw[1], STDOUT_FILENO); +@@ -3124,12 +3124,12 @@ xwaylandready(struct wl_listener *listener, void *data) + int + main(int argc, char *argv[]) + { +- char *startup_cmd = NULL; ++ char **startup_cmd = NULL; + int c; + + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') +- startup_cmd = optarg; ++ *(startup_cmd = &argv[optind-1]) = optarg, argc = 0; + else if (c == 'd') + log_level = WLR_DEBUG; + else if (c == 'v') +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/sticky/README.md b/dwl/dwl-patches/patches/sticky/README.md new file mode 100755 index 0000000..af0e81f --- /dev/null +++ b/dwl/dwl-patches/patches/sticky/README.md @@ -0,0 +1,13 @@ +### Description +Adds a toggleable function that makes a sticky client that is visible on all tags. + +Originally based on [dwm sticky patch](https://dwm.suckless.org/patches/sticky). + +### Download +- [2024-07-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/sticky/sticky.patch) +- [v0.4](https://github.com/djpohly/dwl/compare/main...dm1tz:04-sticky.patch) +- [git branch](https://codeberg.org/Rutherther/dwl/src/branch/v0.7/sticky) + +### Authors +- [Rutherther](https://codeberg.org/Rutherther) +- [Dmitry Zakharchenko](https://github.com/dm1tz) diff --git a/dwl/dwl-patches/patches/sticky/sticky.patch b/dwl/dwl-patches/patches/sticky/sticky.patch new file mode 100755 index 0000000..ece8308 --- /dev/null +++ b/dwl/dwl-patches/patches/sticky/sticky.patch @@ -0,0 +1,85 @@ +From f113cdc0b4cecceaaf28679489852ae61a1aa3f5 Mon Sep 17 00:00:00 2001 +From: Rutherther +Date: Fri, 19 Jul 2024 16:29:43 +0200 +Subject: [PATCH] sticky + +--- + dwl.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 5bf995e..820f4af 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -73,7 +73,7 @@ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) + #define MIN(A, B) ((A) < (B) ? (A) : (B)) + #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) +-#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) ++#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && (((C)->tags & (M)->tagset[(M)->seltags]) || C->issticky)) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) +@@ -139,7 +139,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, issticky; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -326,6 +326,7 @@ static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); + static void setfullscreen(Client *c, int fullscreen); ++static void setsticky(Client *c, int sticky); + static void setgamma(struct wl_listener *listener, void *data); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); +@@ -339,6 +340,7 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); ++static void togglesticky(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +@@ -2351,6 +2353,17 @@ setgamma(struct wl_listener *listener, void *data) + wlr_output_schedule_frame(m->wlr_output); + } + ++void ++setsticky(Client *c, int sticky) ++{ ++ if(sticky && !c->issticky) { ++ c->issticky = 1; ++ } else if(!sticky && c->issticky) { ++ c->issticky = 0; ++ arrange(c->mon); ++ } ++} ++ + void + setlayout(const Arg *arg) + { +@@ -2738,6 +2751,16 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglesticky(const Arg *arg) ++{ ++ Client *c = focustop(selmon); ++ if(!c) ++ return; ++ ++ setsticky(c, !c->issticky); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/swallow/README.md b/dwl/dwl-patches/patches/swallow/README.md new file mode 100755 index 0000000..6c16162 --- /dev/null +++ b/dwl/dwl-patches/patches/swallow/README.md @@ -0,0 +1,53 @@ +### Description + +This patch adds "window swallowing" to dwl. + +If a user runs a graphical program from the terminal (e.g., `mpv`), the terminal +will be hidden and only a window of the newly spawned graphical program will +be visible. The terminal stays hidden until the graphical program is closed. +This patch helps users spawning a lot of graphical programs from their command +line by avoiding cluttering the screen with many unusable terminals. + +`foot` is the terminal by default, you can change it in client rules in config.h. + +In `2025-03-03 v0.7` version and above, the patch had been rewritten from +scratch to make it more robust and add a few more features: + +- "dynamically swallow" windows by pressing `Alt+a` (a focused window will + swallow/unswallow the previously focused one) +- toggle automatic swallowing by `Alt+Shift+a` +- if a window has swallowed another, it get thicker borders + +### Download + +#### swallow.patch + +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/swallow/swallow.patch) +- [2025-03-03 v0.7](https://codeberg.org/dwl/dwl-patches/raw/commit/2e5748edfe1129f95c7bb1bf9dd590a897f55f57/patches/swallow/swallow.patch) (added "dynamic swallowing" support) +- [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/commit/f1ed83eaeba46108f4ee8164094cb431d64a3e68/patches/swallow/swallow.patch) +- [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/commit/f64d701bab2f9f52d3637edd091684f920407d87/patches/swallow/swallow.patch) +- [2024-05-02](https://codeberg.org/dwl/dwl-patches/raw/commit/9c5d5d85f3ac780e7a14d5d0535e3349ce8b8f53/patches/swallow/swallow.patch) +- [2024-04-03](https://codeberg.org/dwl/dwl-patches/raw/commit/3c9a8e3232a8531871924484cef1ef0938730e15/swallow/swallow.patch) +- [2024-01-01](https://codeberg.org/dwl/dwl-patches/raw/commit/8a352a1b27a64821ba9fbfda52fe82463ac84c66/swallow/swallow.patch) +- [2023-10-26](https://github.com/djpohly/dwl/compare/main...youbitchoc:swallow.patch) +- [2023-08-16](https://github.com/djpohly/dwl/compare/main...mewkl:swallowx.patch) (added XWayland support) +- [2023-07-15](https://github.com/djpohly/dwl/compare/main...NikitaIvanovV:swallow.patch) +- [v0.4](https://github.com/djpohly/dwl/compare/main...dm1tz:04-swallow.patch) +- [2021-12-03](https://github.com/djpohly/dwl/compare/main...dm1tz:swallow.patch) + +#### swallow-freebsd.patch + +Apply this patch on top of the swallow.patch if you use FreeBSD. + +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/swallow/swallow-freebsd.patch) +- [2025-03-03 v0.7](https://codeberg.org/dwl/dwl-patches/raw/commit/2e5748edfe1129f95c7bb1bf9dd590a897f55f57/patches/swallow/swallow-freebsd.patch) (added "dynamic swallowing" support) +- [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/commit/f1ed83eaeba46108f4ee8164094cb431d64a3e68/patches/swallow/swallow-freebsd.patch) + +### Authors + +- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV)) +- [Dmitry Zakharchenko](https://github.com/dm1tz) +- [Palanix](https://codeberg.org/Palanix) +- [Connor Worrell](https://github.com/ConnorWorrell) +- [Mewkl](https://github.com/mewkl) +- [Choc](https://codeberg.org/notchoc) diff --git a/dwl/dwl-patches/patches/swallow/swallow-freebsd.patch b/dwl/dwl-patches/patches/swallow/swallow-freebsd.patch new file mode 100755 index 0000000..795a5e1 --- /dev/null +++ b/dwl/dwl-patches/patches/swallow/swallow-freebsd.patch @@ -0,0 +1,54 @@ +From 301e1b368d92a32a7bdcd4bd1f0ede0295977e3e Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Mon, 3 Mar 2025 19:49:07 +0100 +Subject: [PATCH] swallow: add FreeBSD support + +--- + dwl.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/dwl.c b/dwl.c +index 71d500a..52fdd9c 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -67,6 +67,14 @@ + #include + #endif + ++#ifdef __FreeBSD__ ++#define __BSD_VISIBLE ++#include ++#include ++#include ++#include ++#endif ++ + #include "util.h" + + /* macros */ +@@ -2032,6 +2040,7 @@ outputmgrtest(struct wl_listener *listener, void *data) + pid_t + parentpid(pid_t pid) + { ++#ifdef __linux__ + unsigned int v = 0; + FILE *f; + char buf[256]; +@@ -2041,6 +2050,14 @@ parentpid(pid_t pid) + fscanf(f, "%*u %*s %*c %u", &v); + fclose(f); + return (pid_t)v; ++#elif defined(__FreeBSD__) ++ struct kinfo_proc kip; ++ size_t len = sizeof(struct kinfo_proc); ++ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, p }; ++ if (sysctl(mib, 4, &kip, &len, NULL, 0) < 0 || len == 0) ++ return 0; ++ return kip.ki_ppid; ++#endif + } + + void +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/swallow/swallow.patch b/dwl/dwl-patches/patches/swallow/swallow.patch new file mode 100755 index 0000000..ee1a1c1 --- /dev/null +++ b/dwl/dwl-patches/patches/swallow/swallow.patch @@ -0,0 +1,351 @@ +From a220e1ed4b04a66c837dfc8e3363d3e696cbf541 Mon Sep 17 00:00:00 2001 +From: Nikita Ivanov +Date: Wed, 5 Feb 2025 02:34:39 +0100 +Subject: [PATCH] Swallow: hide the terminal when it spawns a client + +--- + client.h | 12 ++++ + config.def.h | 11 +++- + dwl.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 168 insertions(+), 7 deletions(-) + +diff --git a/client.h b/client.h +index 42f225f..bc9cad2 100644 +--- a/client.h ++++ b/client.h +@@ -131,6 +131,18 @@ client_get_appid(Client *c) + return c->surface.xdg->toplevel->app_id; + } + ++static inline int ++client_get_pid(Client *c) ++{ ++ pid_t pid; ++#ifdef XWAYLAND ++ if (client_is_x11(c)) ++ return c->surface.xwayland->pid; ++#endif ++ wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); ++ return pid; ++} ++ + static inline void + client_get_clip(Client *c, struct wlr_box *clip) + { +diff --git a/config.def.h b/config.def.h +index 22d2171..42342f1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,6 +13,8 @@ static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ ++static int enableautoswallow = 1; /* enables autoswallowing newly spawned clients */ ++static float swallowborder = 1.0f; /* add this multiplied by borderpx to border when a client is swallowed */ + + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) +@@ -22,10 +24,11 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating isterm noswallow monitor */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "foot", NULL, 0, 0, 1, 1, -1 }, ++ { "Gimp_EXAMPLE", NULL, 0, 1, 0, 0, -1 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, 0, -1 }, /* Start on ONLY tag "9" */ + }; + + /* layout(s) */ +@@ -142,6 +145,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, ++ { MODKEY, XKB_KEY_a, toggleswallow, {0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_A, toggleautoswallow,{0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, +diff --git a/dwl.c b/dwl.c +index def2562..71d500a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -73,12 +73,13 @@ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) + #define MIN(A, B) ((A) < (B) ? (A) : (B)) + #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) +-#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) ++#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]) && !(C)->swallowedby) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) + #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) ++#define BORDERPX(C) (borderpx + ((C)->swallowing ? (int)ceilf(swallowborder * (C)->swallowing->bw) : 0)) + + /* enums */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ +@@ -104,7 +105,8 @@ typedef struct { + } Button; + + typedef struct Monitor Monitor; +-typedef struct { ++typedef struct Client Client; ++struct Client { + /* Must keep these three elements in this order */ + unsigned int type; /* XDGShell or X11* */ + struct wlr_box geom; /* layout-relative, includes border */ +@@ -140,8 +142,12 @@ typedef struct { + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; ++ int isterm, noswallow; + uint32_t resize; /* configure serial of a pending resize */ +-} Client; ++ pid_t pid; ++ Client *swallowing; /* client being hidden */ ++ Client *swallowedby; ++}; + + typedef struct { + uint32_t mod; +@@ -230,6 +236,8 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int isterm; ++ int noswallow; + int monitor; + } Rule; + +@@ -311,6 +319,7 @@ static void moveresize(const Arg *arg); + static void outputmgrapply(struct wl_listener *listener, void *data); + static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); + static void outputmgrtest(struct wl_listener *listener, void *data); ++static pid_t parentpid(pid_t pid); + static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); + static void printstatus(void); +@@ -335,11 +344,15 @@ static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); ++static void swallow(Client *c, Client *toswallow); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static Client *termforwin(Client *c); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void toggleswallow(const Arg *arg); ++static void toggleautoswallow(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -466,11 +479,15 @@ applyrules(Client *c) + if (!(title = client_get_title(c))) + title = broken; + ++ c->pid = client_get_pid(c); ++ + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; + newtags |= r->tags; ++ c->isterm = r->isterm; ++ c->noswallow = r->noswallow; + i = 0; + wl_list_for_each(m, &mons, link) { + if (r->monitor == i++) +@@ -478,6 +495,12 @@ applyrules(Client *c) + } + } + } ++ if (enableautoswallow && !c->noswallow && !c->isfloating && ++ !c->surface.xdg->initial_commit) { ++ Client *p = termforwin(c); ++ if (p) ++ swallow(c, p); ++ } + setmon(c, mon, newtags); + } + +@@ -2006,6 +2029,20 @@ outputmgrtest(struct wl_listener *listener, void *data) + outputmgrapplyortest(config, 1); + } + ++pid_t ++parentpid(pid_t pid) ++{ ++ unsigned int v = 0; ++ FILE *f; ++ char buf[256]; ++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)pid); ++ if (!(f = fopen(buf, "r"))) ++ return 0; ++ fscanf(f, "%*u %*s %*c %u", &v); ++ fclose(f); ++ return (pid_t)v; ++} ++ + void + pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + uint32_t time) +@@ -2326,7 +2363,7 @@ setfullscreen(Client *c, int fullscreen) + c->isfullscreen = fullscreen; + if (!c->mon || !client_surface(c)->mapped) + return; +- c->bw = fullscreen ? 0 : borderpx; ++ c->bw = fullscreen ? 0 : BORDERPX(c); + client_set_fullscreen(c, fullscreen); + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen + ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); +@@ -2404,6 +2441,9 @@ setmon(Client *c, Monitor *m, uint32_t newtags) + setfloating(c, c->isfloating); + } + focusclient(focustop(selmon), 1); ++ ++ if (c->swallowing) ++ setmon(c->swallowing, m, newtags); + } + + void +@@ -2669,6 +2709,44 @@ startdrag(struct wl_listener *listener, void *data) + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); + } + ++void ++swallow(Client *c, Client *toswallow) ++{ ++ /* Do not allow a client to swallow itself */ ++ if (c == toswallow) ++ return; ++ ++ /* Swallow */ ++ if (toswallow && !c->swallowing) { ++ c->swallowing = toswallow; ++ toswallow->swallowedby = c; ++ toswallow->mon = c->mon; ++ toswallow->mon = c->mon; ++ wl_list_remove(&c->link); ++ wl_list_insert(&c->swallowing->link, &c->link); ++ wl_list_remove(&c->flink); ++ wl_list_insert(&c->swallowing->flink, &c->flink); ++ c->bw = BORDERPX(c); ++ c->tags = toswallow->tags; ++ c->isfloating = toswallow->isfloating; ++ c->geom = toswallow->geom; ++ setfullscreen(toswallow, 0); ++ } ++ ++ /* Unswallow */ ++ else if (c->swallowing) { ++ wl_list_remove(&c->swallowing->link); ++ wl_list_insert(&c->link, &c->swallowing->link); ++ wl_list_remove(&c->swallowing->flink); ++ wl_list_insert(&c->flink, &c->swallowing->flink); ++ c->swallowing->tags = c->tags; ++ c->swallowing->swallowedby = NULL; ++ c->swallowing = NULL; ++ c->bw = BORDERPX(c); ++ setfullscreen(c, 0); ++ } ++} ++ + void + tag(const Arg *arg) + { +@@ -2690,6 +2768,40 @@ tagmon(const Arg *arg) + setmon(sel, dirtomon(arg->i), 0); + } + ++Client * ++termforwin(Client *c) ++{ ++ Client *p; ++ pid_t pid; ++ pid_t pids[32]; ++ size_t i, pids_len; ++ ++ if (!c->pid || c->isterm) ++ return NULL; ++ ++ /* Get all parent pids */ ++ pids_len = 0; ++ pid = c->pid; ++ while (pids_len < LENGTH(pids)) { ++ pid = parentpid(pid); ++ if (!pid) ++ break; ++ pids[pids_len++] = pid; ++ } ++ ++ /* Find closest parent */ ++ for (i = 0; i < pids_len; i++) { ++ wl_list_for_each(p, &clients, link) { ++ if (!p->pid || !p->isterm || p->swallowedby) ++ continue; ++ if (pids[i] == p->pid) ++ return p; ++ } ++ } ++ ++ return NULL; ++} ++ + void + tile(Monitor *m) + { +@@ -2741,6 +2853,32 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++toggleswallow(const Arg *arg) ++{ ++ Client *c, *sel = focustop(selmon); ++ if (!sel) ++ return; ++ ++ if (sel->swallowing) { ++ swallow(sel, NULL); ++ } else { ++ wl_list_for_each(c, &sel->flink, flink) { ++ if (&c->flink == &fstack) ++ continue; /* wrap past the sentinel node */ ++ if (VISIBLEON(c, selmon)) ++ break; /* found it */ ++ } ++ swallow(sel, c); ++ } ++} ++ ++void ++toggleautoswallow(const Arg *arg) ++{ ++ enableautoswallow = !enableautoswallow; ++} ++ + void + toggletag(const Arg *arg) + { +@@ -2801,6 +2939,12 @@ unmapnotify(struct wl_listener *listener, void *data) + grabc = NULL; + } + ++ if (c->swallowing) { ++ swallow(c, NULL); ++ } else if (c->swallowedby) { ++ swallow(c->swallowedby, NULL); ++ } ++ + if (client_is_unmanaged(c)) { + if (c == exclusive_focus) { + exclusive_focus = NULL; +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/swapandfocusdir/README.md b/dwl/dwl-patches/patches/swapandfocusdir/README.md new file mode 100755 index 0000000..2861a07 --- /dev/null +++ b/dwl/dwl-patches/patches/swapandfocusdir/README.md @@ -0,0 +1,14 @@ +### Description +Focus the window (floating or no) to the left, right, above, or below the current focused window. + +Swap the focused window with the window (no floating) to the left, right, above, or below. + +**NOTE:** this patch uses the same algorithm that River uses to select the window in the given direction. + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/swapandfocusdir) +- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/swapandfocusdir/swapandfocusdir.patch) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/swapandfocusdir/swapandfocusdir.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) diff --git a/dwl/dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch b/dwl/dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch new file mode 100755 index 0000000..3636387 --- /dev/null +++ b/dwl/dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch @@ -0,0 +1,221 @@ +From 285470897406b653e77d732a77356aaf9a70b799 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Fri, 5 Jul 2024 12:37:39 -0500 +Subject: [PATCH] implement swapandfocusdir + +--- + config.def.h | 8 +++ + dwl.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 172 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..724e15e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -129,6 +129,14 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, focusdir, {.ui = 0} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, focusdir, {.ui = 1} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, focusdir, {.ui = 2} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, focusdir, {.ui = 3} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapdir, {.ui = 0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapdir, {.ui = 1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapdir, {.ui = 2} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapdir, {.ui = 3} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +diff --git a/dwl.c b/dwl.c +index dc0437e..844c1f5 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -241,6 +241,11 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++typedef struct { ++ int x; ++ int y; ++} Vector; ++ + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -285,6 +290,8 @@ static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); ++static void focusdir(const Arg *arg); ++static void swapdir(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); +@@ -1425,6 +1432,163 @@ focusstack(const Arg *arg) + focusclient(c, 1); + } + ++Vector ++position_of_box(const struct wlr_box *box) ++{ ++ return (Vector){ ++ .x = box->x + box->width / 2, ++ .y = box->y + box->height / 2, ++ }; ++} ++ ++Vector ++diff_of_vectors(Vector *a, Vector *b) ++{ ++ return (Vector){ ++ .x = b->x - a->x, ++ .y = b->y - a->y, ++ }; ++} ++ ++const char * ++direction_of_vector(Vector *vector) ++{ ++ // A zero length vector has no direction ++ if (vector->x == 0 && vector->y == 0) return ""; ++ ++ if (abs(vector->y) > abs(vector->x)) { ++ // Careful: We are operating in a Y-inverted coordinate system. ++ return (vector->y > 0) ? "bottom" : "top"; ++ } else { ++ return (vector->x > 0) ? "right" : "left"; ++ } ++} ++ ++uint32_t ++vector_length(Vector *vector) ++{ ++ // Euclidean distance formula ++ return (uint32_t)sqrt(vector->x * vector->x + vector->y * vector->y); ++} ++ ++// Spatial direction, based on focused client position. ++Client * ++client_in_direction(const char *direction, const int *skipfloat) ++{ ++ Client *cfocused = focustop(selmon); ++ Vector cfocusedposition; ++ Client *ctarget = NULL; ++ double targetdistance = INFINITY; ++ Client *c; ++ ++ if (!cfocused || cfocused->isfullscreen || (skipfloat && cfocused->isfloating)) ++ return NULL; ++ ++ cfocusedposition = position_of_box(&cfocused->geom); ++ ++ wl_list_for_each(c, &clients, link) { ++ Vector cposition; ++ Vector positiondiff; ++ uint32_t distance; ++ ++ if (c == cfocused) ++ continue; ++ ++ if (skipfloat && c->isfloating) ++ continue; ++ ++ if (!VISIBLEON(c, selmon)) ++ continue; ++ ++ cposition = position_of_box(&c->geom); ++ positiondiff = diff_of_vectors(&cfocusedposition, &cposition); ++ ++ if (strcmp(direction, direction_of_vector(&positiondiff)) != 0) ++ continue; ++ ++ distance = vector_length(&positiondiff); ++ ++ if (distance < targetdistance) { ++ ctarget = c; ++ targetdistance = distance; ++ } ++ } ++ ++ return ctarget; ++} ++ ++void ++focusdir(const Arg *arg) ++{ ++ Client *c = NULL; ++ ++ if (arg->ui == 0) ++ c = client_in_direction("left", (int *)0); ++ if (arg->ui == 1) ++ c = client_in_direction("right", (int *)0); ++ if (arg->ui == 2) ++ c = client_in_direction("top", (int *)0); ++ if (arg->ui == 3) ++ c = client_in_direction("bottom", (int *)0); ++ ++ if (c != NULL) ++ focusclient(c, 1); ++} ++ ++void ++wl_list_swap(struct wl_list *list1, struct wl_list *list2) ++{ ++ struct wl_list *prev1, *next1, *prev2, *next2; ++ struct wl_list temp; ++ ++ if (list1 == list2) { ++ // No need to swap the same list ++ return; ++ } ++ ++ // Get the lists before and after list1 ++ prev1 = list1->prev; ++ next1 = list1->next; ++ ++ // Get the lists before and after list2 ++ prev2 = list2->prev; ++ next2 = list2->next; ++ ++ // Update the next and previous pointers of adjacent lists ++ prev1->next = list2; ++ next1->prev = list2; ++ prev2->next = list1; ++ next2->prev = list1; ++ ++ // Swap the next and previous pointers of the lists to actually swap them ++ temp = *list1; ++ *list1 = *list2; ++ *list2 = temp; ++} ++ ++void ++swapdir(const Arg *arg) ++{ ++ Client *c = NULL; ++ Client *cfocused; ++ ++ if (arg->ui == 0) ++ c = client_in_direction("left", (int *)1); ++ if (arg->ui == 1) ++ c = client_in_direction("right", (int *)1); ++ if (arg->ui == 2) ++ c = client_in_direction("top", (int *)1); ++ if (arg->ui == 3) ++ c = client_in_direction("bottom", (int *)1); ++ ++ if (c == NULL) ++ return; ++ ++ cfocused = focustop(selmon); ++ wl_list_swap(&cfocused->link, &c->link); ++ arrange(selmon); ++} ++ + /* We probably should change the name of this, it sounds like + * will focus the topmost client of this mon, when actually will + * only return that client */ +-- +2.45.1 + diff --git a/dwl/dwl-patches/patches/switchtotag/README.md b/dwl/dwl-patches/patches/switchtotag/README.md new file mode 100755 index 0000000..55175d1 --- /dev/null +++ b/dwl/dwl-patches/patches/switchtotag/README.md @@ -0,0 +1,9 @@ +### Description +Add a rule option to switch to the configured tag when a window opens, then switch back when it closes. + +### Download +- [git branch](https://codeberg.org/guidocella/dwl/src/branch/switchtotag) +- [2024-09-30](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/switchtotag/switchtotag.patch) + +### Authors +- [Guido Cella](https://codeberg.org/guidocella) diff --git a/dwl/dwl-patches/patches/switchtotag/switchtotag.patch b/dwl/dwl-patches/patches/switchtotag/switchtotag.patch new file mode 100755 index 0000000..bbe1638 --- /dev/null +++ b/dwl/dwl-patches/patches/switchtotag/switchtotag.patch @@ -0,0 +1,116 @@ +From 08cfc2eceb34316cfd7eaf591a8a631e3d58ff3a Mon Sep 17 00:00:00 2001 +From: Guido Cella +Date: Mon, 30 Sep 2024 08:40:25 +0200 +Subject: [PATCH] allow switching to the configured tag when a window opens + +Add a rule option to switch to the configured tag when a window opens, +then switch back when it closes. +--- + config.def.h | 6 +++--- + dwl.c | 23 +++++++++++++++++++---- + 2 files changed, 22 insertions(+), 7 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..52ea128 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -22,10 +22,10 @@ static int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask switchtotag isfloating monitor */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 1, 0, -1 }, /* Start on ONLY tag "9" */ + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index dc0c861..621b614 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -142,6 +142,7 @@ typedef struct { + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; ++ int switchtotag; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -230,6 +231,7 @@ typedef struct { + const char *id; + const char *title; + uint32_t tags; ++ bool switchtotag; + int isfloating; + int monitor; + } Rule; +@@ -245,7 +247,7 @@ typedef struct { + + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); +-static void applyrules(Client *c); ++static void applyrules(Client *c, bool map); + static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); +@@ -449,7 +451,7 @@ applybounds(Client *c, struct wlr_box *bbox) + } + + void +-applyrules(Client *c) ++applyrules(Client *c, bool map) + { + /* rule matching */ + const char *appid, *title; +@@ -472,6 +474,11 @@ applyrules(Client *c) + if (r->monitor == i++) + mon = m; + } ++ if (r->switchtotag && map) { ++ c->switchtotag = selmon->tagset[selmon->seltags]; ++ mon->seltags ^= 1; ++ mon->tagset[selmon->seltags] = r->tags & TAGMASK; ++ } + } + } + setmon(c, mon, newtags); +@@ -795,7 +802,7 @@ commitnotify(struct wl_listener *listener, void *data) + * a different monitor based on its title this will likely select + * a wrong monitor. + */ +- applyrules(c); ++ applyrules(c, false); + if (c->mon) { + client_set_scale(client_surface(c), c->mon->wlr_output->scale); + } +@@ -1733,7 +1740,7 @@ mapnotify(struct wl_listener *listener, void *data) + c->isfloating = 1; + setmon(c, p->mon, p->tags); + } else { +- applyrules(c); ++ applyrules(c, true); + } + printstatus(); + +@@ -2769,6 +2776,14 @@ unmapnotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->flink); + } + ++ if (c->switchtotag) { ++ Arg a = { .ui = c->switchtotag }; ++ // Call view() -> arrange() -> checkidleinhibitor() before ++ // wlr_scene_node_destroy() to prevent a rare use after free of ++ // tree->node. ++ view(&a); ++ } ++ + wlr_scene_node_destroy(&c->scene->node); + printstatus(); + motionnotify(0, NULL, 0, 0, 0, 0); +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/systemd/README.md b/dwl/dwl-patches/patches/systemd/README.md new file mode 100755 index 0000000..a861b5e --- /dev/null +++ b/dwl/dwl-patches/patches/systemd/README.md @@ -0,0 +1,33 @@ +### Description +This is a simple patch that runs `systemctl --user import-environment WAYLAND_DISPLAY DISPLAY`, and `systemctl --user start dwl-session.target` after Dwl initializes, and then `systemctl --user stop dwl-session.target` when Dwl quits. This allows you to handle graceful startup and shutdown of your graphical systemd services, with the proper environment variables set. This is similar to [uwsm](https://github.com/Vladimir-csp/uwsm?tab=readme-ov-file), but it integrates natively with your existing systemd user services, and doesn't have uwsm's runtime overhead. + +You must have a `dwl-session.target` created that binds to `graphical-session.target`. You can then set the WantedBy of your systemd services to either `graphical-session.target`, or `dwl-session.target`, depending on whether you want them to start for just Dwl, or for every graphical session. + +Below is the Nix home-manager configuration I use to generate `dwl-session.target`, and its resulting output. +``` +systemd.user.targets.dwl-session.Unit = { + Description = "dwl compositor session"; + Documentation = [ "man:systemd.special(7)" ]; + BindsTo = [ "graphical-session.target" ]; + Wants = [ "graphical-session-pre.target" ]; + After = [ "graphical-session-pre.target" ]; +}; +``` + +``` +[Unit] +After=graphical-session-pre.target +BindsTo=graphical-session.target +Description=dwl compositor session +Documentation=man:systemd.special(7) +Wants=graphical-session-pre.target +``` + +### Download +- [git branch](https://github.com/Shringe/dwl/tree/systemd) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/systemd/systemd-0.7.patch) + +### Authors +- [Shringe](https://codeberg.org/Shringe) +- shringe_ at [dwl Discord](https://discord.gg/jJxZnrGPWN) + diff --git a/dwl/dwl-patches/patches/systemd/systemd-0.7.patch b/dwl/dwl-patches/patches/systemd/systemd-0.7.patch new file mode 100755 index 0000000..f911997 --- /dev/null +++ b/dwl/dwl-patches/patches/systemd/systemd-0.7.patch @@ -0,0 +1,64 @@ +From 43b3026b0744d54287eada71c84ea8be174950c3 Mon Sep 17 00:00:00 2001 +From: Shringe +Date: Sat, 12 Jul 2025 01:00:46 -0500 +Subject: [PATCH] basic implementation + +--- + dwl.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/dwl.c b/dwl.c +index c717c1d..4ba134d 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -680,6 +680,15 @@ cleanup(void) + wlr_xwayland_destroy(xwayland); + xwayland = NULL; + #endif ++ /* Stop systemd target */ ++ if (fork() == 0) { ++ setsid(); ++ execvp("systemctl", (char *const[]) { ++ "systemctl", "--user", "stop", "dwl-session.target", NULL ++ }); ++ exit(1); ++ } ++ + wl_display_destroy_clients(dpy); + if (child_pid > 0) { + kill(-child_pid, SIGTERM); +@@ -2222,6 +2231,31 @@ run(char *startup_cmd) + die("startup: display_add_socket_auto"); + setenv("WAYLAND_DISPLAY", socket, 1); + ++ /* Import environment variables then start systemd target */ ++ if (fork() == 0) { ++ setsid(); ++ ++ /* First: import environment variables */ ++ pid_t import_pid = fork(); ++ if (import_pid == 0) { ++ execvp("systemctl", (char *const[]) { ++ "systemctl", "--user", "import-environment", ++ "DISPLAY", "WAYLAND_DISPLAY", NULL ++ }); ++ exit(1); ++ } ++ ++ /* Wait for import to complete */ ++ waitpid(import_pid, NULL, 0); ++ ++ /* Second: start target */ ++ execvp("systemctl", (char *const[]) { ++ "systemctl", "--user", "start", "dwl-session.target", NULL ++ }); ++ ++ exit(1); ++ } ++ + /* Start the backend. This will enumerate outputs and inputs, become the DRM + * master, etc */ + if (!wlr_backend_start(backend)) +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/tab/README.md b/dwl/dwl-patches/patches/tab/README.md new file mode 100755 index 0000000..9f08765 --- /dev/null +++ b/dwl/dwl-patches/patches/tab/README.md @@ -0,0 +1,24 @@ +### Description +Add tabs or a title bar to the top or bottom of windows. + +Much of the code was taken from the [bar patch](/dwl/dwl-patches/src/branch/main/patches/bar). + +**This is the new version using `drwl`. The [old version](/dwl/dwl-patches/src/branch/main/_STALE_PATCHES/tab-pango) is deprecated.** + +### Dependencies +- tllist (build dependency, required & pulled automatically by fcft) +- fcft +- pixman + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/tab/tab-0.7.patch) +- [0.7 + bar](/dwl/dwl-patches/raw/branch/main/patches/tab/tab-0.7-bar.patch) +- [main 2024-11-15](/dwl/dwl-patches/raw/branch/main/patches/tab/tab.patch) + +### Authors +- [dev-gm](https://codeberg.org/dev-gm) + +### Credits +- [sewn](https://codeberg.org/sewn) +- [MadcowOG](https://codeberg.org/MadcowOG) +- [kolumni](https://codeberg.org/kolumni) diff --git a/dwl/dwl-patches/patches/tab/tab-0.7-bar.patch b/dwl/dwl-patches/patches/tab/tab-0.7-bar.patch new file mode 100755 index 0000000..4a79bbc --- /dev/null +++ b/dwl/dwl-patches/patches/tab/tab-0.7-bar.patch @@ -0,0 +1,767 @@ +From 3944cc81d0683700405cd106edf965293abbb87c Mon Sep 17 00:00:00 2001 +From: dev-gm +Date: Sat, 16 Nov 2024 23:27:19 -0500 +Subject: [PATCH] Add tab support + +--- + config.def.h | 25 +++- + dwl.c | 392 +++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 386 insertions(+), 31 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 5d1dc2b..52fcfee 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,6 +10,13 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + 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 *tbar_fonts[] = {"monospace:size=10"}; ++static const int tbar_top = 0; ++static const int tbar_height = -1; ++static const int tbar_borderpx = 1; ++static const int tbar_padding = 10; ++static const float tbar_scale = -1; /* -1 means use monitor scale */ ++static const int tbar_float_sel_sep = 0; /* should tbar be highlighted only on the currently selected window or on both the last selected floating window and the laste selected tiling window */ + static const float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +@@ -20,6 +27,13 @@ static uint32_t colors[][3] = { + [SchemeUrg] = { 0, 0, 0x770000ff }, + }; + ++static uint32_t tbar_colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x555555ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x555555ff }, ++ [SchemeUrg] = { 0xc7c7c7ff, 0x222222ff, 0x770000ff }, ++}; ++ + /* tagging - TAGCOUNT must be no greater than 31 */ + static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +@@ -34,12 +48,15 @@ static const Rule rules[] = { + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ + }; + ++static const unsigned int floating_tbar_type = TBarLabel; ++static const int floating_tbar_only_top = 0; ++ + /* layout(s) */ + static const Layout layouts[] = { +- /* symbol arrange function */ +- { "[]=", tile }, +- { "><>", NULL }, /* no layout function means floating behavior */ +- { "[M]", monocle }, ++ /* symbol tbar type tbar only on top arrange function */ ++ { "[]=", TBarLabel, 0, tile }, ++ { "><>", TBarLabel, 0, NULL }, /* no layout function means floating behavior */ ++ { "[M]", TBarMultiple, 1, monocle }, + }; + + /* monitors */ +diff --git a/dwl.c b/dwl.c +index 1e199f3..e7754d3 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -90,6 +91,7 @@ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ + enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ ++enum { TBarNone, TBarLabel, TBarMultiple, TBarAlways }; /* tbar types */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -110,6 +112,14 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct { ++ struct wlr_buffer base; ++ struct wl_listener release; ++ bool busy; ++ Img *image; ++ uint32_t data[]; ++} Buffer; ++ + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -119,6 +129,11 @@ typedef struct { + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; ++ struct wlr_scene_buffer *tbar_buffer; ++ Drwl *drw; ++ Buffer *pool[2]; ++ int tbar_height, tbar_real_height; ++ float tbar_scale; + struct wl_list link; + struct wl_list flink; + union { +@@ -146,7 +161,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, tbar_enabled, resize_tbar_enabled; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -190,17 +205,11 @@ typedef struct { + + typedef struct { + const char *symbol; ++ unsigned int tbar_type; /* type of tbar */ ++ int tbar_only_top; + void (*arrange)(Monitor *); + } Layout; + +-typedef struct { +- struct wlr_buffer base; +- struct wl_listener release; +- bool busy; +- Img *image; +- uint32_t data[]; +-} Buffer; +- + struct Monitor { + struct wl_list link; + struct wlr_output *wlr_output; +@@ -275,10 +284,11 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); + static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy); +-static void bufdestroy(struct wlr_buffer *buffer); +-static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags, ++static Buffer *bufclient(Client *c); ++static void bufdestroy(struct wlr_buffer *wlr_buffer); ++static bool bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, + void **data, uint32_t *format, size_t *stride); +-static void bufdataend(struct wlr_buffer *buffer); ++static void bufdataend(struct wlr_buffer *wlr_buffer); + static Buffer *bufmon(Monitor *m); + static void bufrelease(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); +@@ -316,12 +326,15 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawtbars(Monitor *m, int floating, int clients_changed); ++static void drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout); + static void drawbar(Monitor *m); + static void drawbars(void); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); ++static Client *focustop_onlytiled(Monitor *m, int onlytiled); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); +@@ -529,14 +542,16 @@ void + arrange(Monitor *m) + { + Client *c; ++ int enabled; + + if (!m->wlr_output->enabled) + return; + + wl_list_for_each(c, &clients, link) { + if (c->mon == m) { +- wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m)); +- client_set_suspended(c, !VISIBLEON(c, m)); ++ enabled = VISIBLEON(c, m); ++ wlr_scene_node_set_enabled(&c->scene->node, enabled); ++ client_set_suspended(c, !enabled); + } + } + +@@ -561,6 +576,7 @@ arrange(Monitor *m) + + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); ++ + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + } +@@ -650,6 +666,36 @@ baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy) + return true; + } + ++Buffer * ++bufclient(Client *c) ++{ ++ size_t i; ++ Buffer *buf = NULL; ++ ++ for (i = 0; i < LENGTH(c->pool); i++) { ++ if (c->pool[i]) { ++ if (c->pool[i]->busy) ++ continue; ++ buf = c->pool[i]; ++ break; ++ } ++ ++ buf = ecalloc(1, sizeof(Buffer) + (int)(c->geom.width * c->tbar_scale * 4 * (c->tbar_height + 2*tbar_borderpx))); ++ buf->image = drwl_image_create(NULL, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx, buf->data); ++ wlr_buffer_init(&buf->base, &buffer_impl, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx); ++ c->pool[i] = buf; ++ break; ++ } ++ if (!buf) ++ return NULL; ++ ++ buf->busy = true; ++ LISTEN(&buf->base.events.release, &buf->release, bufrelease); ++ wlr_buffer_lock(&buf->base); ++ drwl_setimage(c->drw, buf->image); ++ return buf; ++} ++ + void + bufdestroy(struct wlr_buffer *wlr_buffer) + { +@@ -827,6 +873,21 @@ checkidleinhibitor(struct wlr_surface *exclude) + void + cleanup(void) + { ++ Client *c; ++ unsigned int i; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!c->tbar_enabled) ++ continue; ++ ++ for (i = 0; i < LENGTH(c->pool); i++) ++ wlr_buffer_drop(&c->pool[i]->base); ++ ++ drwl_setimage(c->drw, NULL); ++ drwl_destroy(c->drw); ++ ++ wlr_scene_node_destroy(&c->tbar_buffer->node); ++ } + #ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; +@@ -1230,6 +1291,10 @@ createnotify(struct wl_listener *listener, void *data) + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; ++ c->tbar_enabled = 0; ++ c->resize_tbar_enabled = 0; ++ c->tbar_height = 0; ++ c->tbar_buffer = NULL; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); +@@ -1579,6 +1644,166 @@ drawbars(void) + drawbar(m); + } + ++void ++drawtbars(Monitor *m, int floating, int clients_changed) ++{ ++ unsigned int tbar_type, tbar_only_top, len = 0; ++ int nodraw = 0, ismonocle; ++ Client *c, *sel = NULL, *sel_in_layout = NULL; ++ ++ if (!m) ++ return; ++ ++ tbar_type = floating ? floating_tbar_type : m->lt[m->sellt]->tbar_type; ++ tbar_only_top = floating ? floating_tbar_only_top : m->lt[m->sellt]->tbar_only_top; ++ ismonocle = m->lt[m->sellt]->arrange == monocle; ++ ++ if (!clients_changed && !floating && ismonocle && (sel = focustop_onlytiled(m, 1))) { ++ wlr_scene_node_raise_to_top(&sel->scene->node); ++ if (sel->tbar_buffer) ++ wlr_scene_node_raise_to_top(&sel->tbar_buffer->node); ++ return; ++ } ++ ++ if (tbar_type == TBarNone) ++ nodraw = 2; ++ ++ if (!nodraw) { ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m)) ++ continue; ++ if (!sel && (!tbar_float_sel_sep || c->isfloating == floating)) ++ sel = c; ++ if (!sel_in_layout && c->isfloating == floating) ++ sel_in_layout = c; ++ if (c->isfloating == floating && !c->isfullscreen) ++ len++; ++ } ++ ++ if (len == 0) ++ return; ++ } ++ ++ if (tbar_type == TBarMultiple && len <= 1) ++ nodraw = 2; ++ ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m) || c->isfloating != floating) ++ continue; ++ if (c->tbar_buffer && c->tbar_enabled && (nodraw == 2 || c->isfullscreen)) { ++ wlr_scene_node_set_enabled(&c->tbar_buffer->node, 0); ++ c->tbar_enabled = 0; ++ if (m->lt[m->sellt]->arrange != tile) ++ resize(c, c->geom, 0); ++ } ++ if (!nodraw && !c->isfullscreen) { ++ drawtbar(c, tbar_type, len, ismonocle ? c : sel_in_layout, sel_in_layout); ++ if (!ismonocle && tbar_only_top) ++ nodraw = 1; ++ } ++ if (c == sel_in_layout) { ++ wlr_scene_node_raise_to_top(&sel_in_layout->scene->node); ++ if (sel_in_layout->tbar_buffer) ++ wlr_scene_node_raise_to_top(&sel_in_layout->tbar_buffer->node); ++ } ++ } ++ ++ if (m->lt[m->sellt]->arrange == tile) ++ m->lt[m->sellt]->arrange(m); ++} ++ ++void ++drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout) ++{ ++ Buffer *buf; ++ float width = c->geom.width * c->tbar_scale; ++ unsigned int i, scheme; ++ Client *l; ++ uint32_t tbar_border_colors[][3] = { ++ [SchemeNorm] = { [ColBg] = tbar_colors[SchemeNorm][2] }, ++ [SchemeSel] = { [ColBg] = tbar_colors[SchemeSel][2] }, ++ [SchemeUrg] = { [ColBg] = tbar_colors[SchemeUrg][2] } ++ }; ++ ++ if (!c->tbar_buffer) ++ c->tbar_buffer = wlr_scene_buffer_create(c->scene, NULL); ++ ++ for (i = 0; i < LENGTH(c->pool); i++) { ++ if (c->pool[i]) { ++ wlr_buffer_drop(&c->pool[i]->base); ++ c->pool[i] = NULL; ++ } ++ } ++ drwl_setimage(c->drw, NULL); ++ ++ if (!(buf = bufclient(c))) ++ return; ++ ++ switch (tbar_type) { ++ case TBarLabel: ++ scheme = c->isurgent ? SchemeUrg : (c == sel ? SchemeSel : SchemeNorm); ++ ++ if (tbar_borderpx) { ++ drwl_setscheme(c->drw, tbar_border_colors[scheme]); ++ drwl_rect(c->drw, 0, 0, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, 0, c->tbar_height + tbar_borderpx, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, 0, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ drwl_rect(c->drw, (unsigned int)width - tbar_borderpx, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ } ++ ++ drwl_setscheme(c->drw, tbar_colors[scheme]); ++ drwl_text(c->drw, tbar_borderpx, tbar_borderpx, ++ (unsigned int)width - 2*tbar_borderpx, c->tbar_height, ++ tbar_padding, client_get_title(c), 0); ++ ++ break; ++ ++ case TBarMultiple: ++ case TBarAlways: ++ width /= len; ++ i = 0; ++ ++ wl_list_for_each(l, &clients, link) { ++ if (!VISIBLEON(l, c->mon) || l->isfullscreen || l->isfloating != c->isfloating) ++ continue; ++ ++ scheme = l->isurgent ? SchemeUrg : (l == sel ? SchemeSel : SchemeNorm); ++ ++ if (tbar_borderpx) { ++ drwl_setscheme(c->drw, tbar_border_colors[scheme]); ++ drwl_rect(c->drw, (unsigned int)(width*i), 0, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, (unsigned int)(width*i), c->tbar_height + tbar_borderpx, ++ (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, (unsigned int)(width*i), tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ if (i == len-1) ++ drwl_rect(c->drw, (unsigned int)(width*(i+1)) - tbar_borderpx, tbar_borderpx, ++ tbar_borderpx, c->tbar_height + 2*tbar_borderpx, 1, 1); ++ } ++ ++ drwl_setscheme(c->drw, tbar_colors[scheme]); ++ drwl_text(c->drw, (unsigned int)(width*i) + tbar_borderpx, tbar_borderpx, ++ (unsigned int)width - (i == len-1 ? 2*tbar_borderpx : tbar_borderpx), ++ c->tbar_height, tbar_padding, client_get_title(l), 0); ++ ++ i += 1; ++ } ++ ++ break; ++ } ++ ++ c->tbar_enabled = 1; ++ if (!c->resize_tbar_enabled) ++ resize(c, c->geom, 0); ++ ++ wlr_scene_buffer_set_dest_size(c->tbar_buffer, c->geom.width, ++ c->tbar_real_height + 2*tbar_borderpx); ++ wlr_scene_node_set_position(&c->tbar_buffer->node, 0, tbar_top ? 0 ++ : (c->geom.height - c->tbar_real_height - 2*tbar_borderpx)); ++ wlr_scene_buffer_set_buffer(c->tbar_buffer, &buf->base); ++ wlr_scene_node_set_enabled(&c->tbar_buffer->node, 1); ++ wlr_buffer_unlock(&buf->base); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1635,6 +1860,12 @@ focusclient(Client *c, int lift) + client_activate_surface(old, 0); + } + } ++ ++ if (c && c->mon) ++ drawtbars(c->mon, c->isfloating, 0); ++ if (c && old_c && old_c->mon && (old_c->mon != c->mon || old_c->isfloating != c->isfloating)) ++ drawtbars(old_c->mon, old_c->isfloating, 0); ++ + drawbars(); + + if (!c) { +@@ -1705,6 +1936,20 @@ focustop(Monitor *m) + return NULL; + } + ++Client * ++focustop_onlytiled(Monitor *m, int onlytiled) ++{ ++ Client *c; ++ wl_list_for_each(c, &fstack, flink) { ++ if (VISIBLEON(c, m)) { ++ if ((onlytiled == 1 && c->isfloating) || (onlytiled == 2 && !c->isfloating && m->lt[m->sellt]->arrange)) ++ continue; ++ return c; ++ } ++ } ++ return NULL; ++} ++ + void + fullscreennotify(struct wl_listener *listener, void *data) + { +@@ -1764,6 +2009,7 @@ incnmaster(const Arg *arg) + return; + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + void +@@ -1932,6 +2178,7 @@ mapnotify(struct wl_listener *listener, void *data) + Client *w, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; ++ char fontattrs[12]; + + /* Create scene tree for this client and its border */ + c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); +@@ -1988,6 +2235,20 @@ unset_fullscreen: + if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) + setfullscreen(w, 0); + } ++ ++ if (!(c->drw = drwl_create())) ++ die("failed to create drwl context"); ++ c->tbar_scale = tbar_scale > 0 ? tbar_scale : m->wlr_output->scale; ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale); ++ if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs))) ++ die("Could not load font"); ++ if (!c->tbar_height) { ++ c->tbar_height = c->drw->font->height; ++ if (tbar_height > c->tbar_height) ++ c->tbar_height = tbar_height; ++ c->tbar_real_height = (int)((float)c->tbar_height / c->tbar_scale); ++ } ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -2012,18 +2273,28 @@ void + monocle(Monitor *m) + { + Client *c; +- int n = 0; ++ int n = 0, old_tbar_enabled; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- resize(c, m->w, 0); ++ if (!n) ++ wlr_scene_node_raise_to_top(&c->scene->node); + n++; ++ if (n > 1) ++ break; ++ } ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ old_tbar_enabled = c->tbar_enabled; ++ c->tbar_enabled = m->lt[m->sellt]->tbar_type != TBarNone ++ && m->lt[m->sellt]->tbar_type == TBarMultiple ? n > 1 : 1; ++ resize(c, m->w, 0); ++ c->tbar_enabled = old_tbar_enabled; + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); +- if ((c = focustop(m))) +- wlr_scene_node_raise_to_top(&c->scene->node); + } + + void +@@ -2384,32 +2655,37 @@ resize(Client *c, struct wlr_box geo, int interact) + { + struct wlr_box *bbox; + struct wlr_box clip; ++ unsigned int th; + + if (!c->mon || !client_surface(c)->mapped) + return; + + bbox = interact ? &sgeom : &c->mon->w; + ++ th = c->tbar_enabled ? (unsigned int)(c->tbar_real_height + 2*tbar_borderpx) : c->bw; ++ + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); +- wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); +- wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); +- wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); ++ wlr_scene_node_set_position(&c->scene_surface->node, c->bw, tbar_top ? th : c->bw); ++ wlr_scene_rect_set_size(c->border[0], c->geom.width, (c->tbar_enabled && tbar_top) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[1], c->geom.width, (c->tbar_enabled && !tbar_top) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - th - c->bw); ++ wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - th - c->bw); + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); +- wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); +- wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_node_set_position(&c->border[2]->node, 0, tbar_top ? th : c->bw); ++ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, tbar_top ? th : c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +- c->geom.height - 2 * c->bw); ++ c->geom.height - th - c->bw); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); ++ ++ c->resize_tbar_enabled = c->tbar_enabled; + } + + void +@@ -2505,6 +2781,8 @@ setfloating(Client *c, int floating) + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); + drawbars(); ++ drawtbars(c->mon, 0, 1); ++ drawtbars(c->mon, 1, 1); + } + + void +@@ -2528,6 +2806,7 @@ setfullscreen(Client *c, int fullscreen) + } + arrange(c->mon); + drawbars(); ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -2553,6 +2832,7 @@ setlayout(const Arg *arg) + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); + drawbar(selmon); ++ drawtbars(selmon, 0, 1); + } + + /* arg > 1.0 will set mfact absolutely */ +@@ -2568,6 +2848,7 @@ setmfact(const Arg *arg) + return; + selmon->mfact = f; + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + void +@@ -2898,14 +3179,22 @@ tag(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void + tagmon(const Arg *arg) + { + Client *sel = focustop(selmon); +- if (sel) ++ Monitor *old_mon = selmon; ++ if (sel) { + setmon(sel, dirtomon(arg->i), 0); ++ if (selmon) ++ drawtbars(selmon, sel->isfloating, 1); ++ if (old_mon && selmon != old_mon) ++ drawtbars(old_mon, sel->isfloating, 1); ++ } + } + + void +@@ -2979,6 +3268,8 @@ toggletag(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void +@@ -2992,6 +3283,8 @@ toggleview(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void +@@ -3022,6 +3315,9 @@ unmapnotify(struct wl_listener *listener, void *data) + { + /* Called when the surface is unmapped, and should no longer be shown. */ + Client *c = wl_container_of(listener, c, unmap); ++ Monitor *m = c->mon; ++ unsigned int i; ++ + if (c == grabc) { + cursor_mode = CurNormal; + grabc = NULL; +@@ -3038,6 +3334,20 @@ unmapnotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->flink); + } + ++ if (m && !c->isfloating && m->lt[m->sellt]->arrange == monocle) ++ drawtbars(m, c->isfloating, 1); ++ ++ if (c->tbar_enabled) { ++ for (i = 0; i < LENGTH(c->pool); i++) ++ if (c->pool[i]) ++ wlr_buffer_drop(&c->pool[i]->base); ++ ++ drwl_setimage(c->drw, NULL); ++ drwl_destroy(c->drw); ++ ++ wlr_scene_node_destroy(&c->tbar_buffer->node); ++ } ++ + wlr_scene_node_destroy(&c->scene->node); + drawbars(); + motionnotify(0, NULL, 0, 0, 0, 0); +@@ -3058,9 +3368,12 @@ updatemons(struct wl_listener *listener, void *data) + Client *c; + struct wlr_output_configuration_head_v1 *config_head; + Monitor *m; ++ char fontattrs[12]; + + /* First remove from the layout the disabled monitors */ + wl_list_for_each(m, &mons, link) { ++ if (m->asleep) ++ continue; + if (m->wlr_output->enabled || m->asleep) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); +@@ -3124,6 +3437,23 @@ updatemons(struct wl_listener *listener, void *data) + if (!selmon) { + selmon = m; + } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || (c->drw && (tbar_scale > 0 || c->tbar_scale == m->wlr_output->scale))) ++ continue; ++ if (!c->drw && !(c->drw = drwl_create())) ++ die("failed to create drwl context"); ++ drwl_font_destroy(c->drw->font); ++ c->tbar_scale = m->wlr_output->scale; ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale); ++ if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs))) ++ die("Could not load font"); ++ if (!c->tbar_height) { ++ c->tbar_height = c->drw->font->height; ++ if (tbar_height > c->tbar_height) ++ c->tbar_height = tbar_height; ++ } ++ } + } + + if (selmon && selmon->wlr_output->enabled) { +@@ -3195,6 +3525,7 @@ updatetitle(struct wl_listener *listener, void *data) + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) + drawbars(); ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -3208,6 +3539,7 @@ urgent(struct wl_listener *listener, void *data) + + c->isurgent = 1; + drawbars(); ++ drawtbars(c->mon, 1, 1); + + if (client_surface(c)->mapped) + client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); +@@ -3322,8 +3654,10 @@ zoom(const Arg *arg) + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); + ++ drawtbars(selmon, 0, 1); + focusclient(sel, 1); + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + #ifdef XWAYLAND +@@ -3375,6 +3709,10 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; ++ c->tbar_enabled = 0; ++ c->resize_tbar_enabled = 0; ++ c->tbar_height = 0; ++ c->tbar_buffer = NULL; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +-- +2.47.0 + diff --git a/dwl/dwl-patches/patches/tab/tab-0.7.patch b/dwl/dwl-patches/patches/tab/tab-0.7.patch new file mode 100755 index 0000000..b7edd4f --- /dev/null +++ b/dwl/dwl-patches/patches/tab/tab-0.7.patch @@ -0,0 +1,1252 @@ +From 419fa4d6212806d9e4a3439568f8a103a57de912 Mon Sep 17 00:00:00 2001 +From: dev-gm +Date: Sat, 16 Nov 2024 23:19:42 -0500 +Subject: [PATCH] Add tab support + +--- + Makefile | 2 +- + config.def.h | 37 ++++- + drwl.h | 320 ++++++++++++++++++++++++++++++++++++ + dwl.c | 449 ++++++++++++++++++++++++++++++++++++++++++++++++--- + 4 files changed, 777 insertions(+), 31 deletions(-) + create mode 100644 drwl.h + +diff --git a/Makefile b/Makefile +index 3358bae..9bc67db 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) ++PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 22d2171..9d33d89 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,13 +7,31 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); +-static const float bordercolor[] = COLOR(0x444444ff); +-static const float focuscolor[] = COLOR(0x005577ff); +-static const float urgentcolor[] = COLOR(0xff0000ff); ++static const char *tbar_fonts[] = {"monospace:size=10"}; ++static const int tbar_top = 0; ++static const int tbar_height = -1; ++static const int tbar_borderpx = 1; ++static const int tbar_padding = 10; ++static const float tbar_scale = -1; /* -1 means use monitor scale */ ++static const int tbar_float_sel_sep = 0; /* should tbar be highlighted only on the currently selected window or on both the last selected floating window and the laste selected tiling window */ ++static const float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ + ++static uint32_t colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, ++ [SchemeUrg] = { 0, 0, 0x770000ff }, ++}; ++ ++static uint32_t tbar_colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x555555ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x555555ff }, ++ [SchemeUrg] = { 0xc7c7c7ff, 0x222222ff, 0x770000ff }, ++}; ++ + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + +@@ -28,12 +46,15 @@ static const Rule rules[] = { + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ + }; + ++static const unsigned int floating_tbar_type = TBarLabel; ++static const int floating_tbar_only_top = 0; ++ + /* layout(s) */ + static const Layout layouts[] = { +- /* symbol arrange function */ +- { "[]=", tile }, +- { "><>", NULL }, /* no layout function means floating behavior */ +- { "[M]", monocle }, ++ /* symbol tbar type tbar only on top arrange function */ ++ { "[]=", TBarLabel, 0, tile }, ++ { "><>", TBarLabel, 0, NULL }, /* no layout function means floating behavior */ ++ { "[M]", TBarMultiple, 1, monocle }, + }; + + /* monitors */ +diff --git a/drwl.h b/drwl.h +new file mode 100644 +index 0000000..02eb8e9 +--- /dev/null ++++ b/drwl.h +@@ -0,0 +1,320 @@ ++/* ++ * drwl - https://codeberg.org/sewn/drwl ++ * ++ * Copyright (c) 2023-2024 sewn ++ * Copyright (c) 2024 notchoc ++ * ++ * 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. ++ * ++ * The UTF-8 Decoder included is from Bjoern Hoehrmann: ++ * Copyright (c) 2008-2010 Bjoern Hoehrmann ++ * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. ++ */ ++#pragma once ++ ++#include ++#include ++#include ++ ++enum { ColFg, ColBg, ColBorder }; /* colorscheme index */ ++ ++typedef struct fcft_font Fnt; ++typedef pixman_image_t Img; ++ ++typedef struct { ++ Img *image; ++ Fnt *font; ++ uint32_t *scheme; ++} Drwl; ++ ++#define UTF8_ACCEPT 0 ++#define UTF8_REJECT 12 ++#define UTF8_INVALID 0xFFFD ++ ++static const uint8_t utf8d[] = { ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, ++ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, ++ ++ 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, ++ 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, ++ 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, ++ 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, ++ 12,36,12,12,12,12,12,12,12,12,12,12, ++}; ++ ++static inline uint32_t ++utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) ++{ ++ uint32_t type = utf8d[byte]; ++ ++ *codep = (*state != UTF8_ACCEPT) ? ++ (byte & 0x3fu) | (*codep << 6) : ++ (0xff >> type) & (byte); ++ ++ *state = utf8d[256 + *state + type]; ++ return *state; ++} ++ ++static int ++drwl_init(void) ++{ ++ fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); ++ return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR); ++} ++ ++static Drwl * ++drwl_create(void) ++{ ++ Drwl *drwl; ++ ++ if (!(drwl = calloc(1, sizeof(Drwl)))) ++ return NULL; ++ ++ return drwl; ++} ++ ++static void ++drwl_setfont(Drwl *drwl, Fnt *font) ++{ ++ if (drwl) ++ drwl->font = font; ++} ++ ++static void ++drwl_setimage(Drwl *drwl, Img *image) ++{ ++ if (drwl) ++ drwl->image = image; ++} ++ ++static Fnt * ++drwl_font_create(Drwl *drwl, size_t count, ++ const char *names[static count], const char *attributes) ++{ ++ Fnt *font = fcft_from_name(count, names, attributes); ++ if (drwl) ++ drwl_setfont(drwl, font); ++ return font; ++} ++ ++static void ++drwl_font_destroy(Fnt *font) ++{ ++ fcft_destroy(font); ++} ++ ++static inline pixman_color_t ++convert_color(uint32_t clr) ++{ ++ return (pixman_color_t){ ++ ((clr >> 24) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 16) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 8) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ (clr & 0xFF) * 0x101 ++ }; ++} ++ ++static void ++drwl_setscheme(Drwl *drwl, uint32_t *scm) ++{ ++ if (drwl) ++ drwl->scheme = scm; ++} ++ ++static Img * ++drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits) ++{ ++ Img *image; ++ pixman_region32_t clip; ++ ++ image = pixman_image_create_bits_no_clear( ++ PIXMAN_a8r8g8b8, w, h, bits, w * 4); ++ if (!image) ++ return NULL; ++ pixman_region32_init_rect(&clip, 0, 0, w, h); ++ pixman_image_set_clip_region32(image, &clip); ++ pixman_region32_fini(&clip); ++ ++ if (drwl) ++ drwl_setimage(drwl, image); ++ return image; ++} ++ ++static void ++drwl_rect(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ int filled, int invert) ++{ ++ pixman_color_t clr; ++ if (!drwl || !drwl->scheme || !drwl->image) ++ return; ++ ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ if (filled) ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1, ++ &(pixman_rectangle16_t){x, y, w, h}); ++ else ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4, ++ (pixman_rectangle16_t[4]){ ++ { x, y, w, 1 }, ++ { x, y + h - 1, w, 1 }, ++ { x, y, 1, h }, ++ { x + w - 1, y, 1, h }}); ++} ++ ++static int ++drwl_text(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ unsigned int lpad, const char *text, int invert) ++{ ++ int ty; ++ int render = x || y || w || h; ++ long x_kern; ++ uint32_t cp = 0, last_cp = 0, state; ++ pixman_color_t clr; ++ pixman_image_t *fg_pix = NULL; ++ int noellipsis = 0; ++ const struct fcft_glyph *glyph, *eg = NULL; ++ int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; ++ ++ if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font) ++ return 0; ++ ++ if (!render) { ++ w = invert ? invert : ~invert; ++ } else { ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ fg_pix = pixman_image_create_solid_fill(&clr); ++ ++ drwl_rect(drwl, x, y, w, h, 1, !invert); ++ ++ x += lpad; ++ w -= lpad; ++ } ++ ++ if (render && (drwl->scheme[ColBg] & 0xFF) != 0xFF) ++ fcft_subpixel_mode = FCFT_SUBPIXEL_NONE; ++ ++ if (render) ++ eg = fcft_rasterize_char_utf32(drwl->font, 0x2026 /* … */, fcft_subpixel_mode); ++ ++ for (const char *p = text, *pp; pp = p, *p; p++) { ++ for (state = UTF8_ACCEPT; *p && ++ utf8decode(&state, &cp, *p) > UTF8_REJECT; p++) ++ ; ++ if (!*p || state == UTF8_REJECT) { ++ cp = UTF8_INVALID; ++ if (p > pp) ++ p--; ++ } ++ ++ glyph = fcft_rasterize_char_utf32(drwl->font, cp, fcft_subpixel_mode); ++ if (!glyph) ++ continue; ++ ++ x_kern = 0; ++ if (last_cp) ++ fcft_kerning(drwl->font, last_cp, cp, &x_kern, NULL); ++ last_cp = cp; ++ ++ ty = y + (h - drwl->font->height) / 2 + drwl->font->ascent; ++ ++ if (render && !noellipsis && x_kern + glyph->advance.x + eg->advance.x > w && ++ *(p + 1) != '\0') { ++ /* cannot fit ellipsis after current codepoint */ ++ if (drwl_text(drwl, 0, 0, 0, 0, 0, pp, 0) + x_kern <= w) { ++ noellipsis = 1; ++ } else { ++ w -= eg->advance.x; ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0, ++ x + eg->x, ty - eg->y, eg->width, eg->height); ++ } ++ } ++ ++ if ((x_kern + glyph->advance.x) > w) ++ break; ++ ++ x += x_kern; ++ ++ if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) ++ /* pre-rendered glyphs (eg. emoji) */ ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ else if (render) ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ ++ x += glyph->advance.x; ++ w -= glyph->advance.x; ++ } ++ ++ if (render) ++ pixman_image_unref(fg_pix); ++ ++ return x + (render ? w : 0); ++} ++ ++static unsigned int ++drwl_font_getwidth(Drwl *drwl, const char *text) ++{ ++ if (!drwl || !drwl->font || !text) ++ return 0; ++ return drwl_text(drwl, 0, 0, 0, 0, 0, text, 0); ++} ++ ++static unsigned int ++drwl_font_getwidth_clamp(Drwl *drwl, const char *text, unsigned int n) ++{ ++ unsigned int tmp = 0; ++ if (drwl && drwl->font && text && n) ++ tmp = drwl_text(drwl, 0, 0, 0, 0, 0, text, n); ++ return tmp < n ? tmp : n; ++} ++ ++static void ++drwl_image_destroy(Img *image) ++{ ++ pixman_image_unref(image); ++} ++ ++static void ++drwl_destroy(Drwl *drwl) ++{ ++ if (drwl->font) ++ drwl_font_destroy(drwl->font); ++ if (drwl->image) ++ drwl_image_destroy(drwl->image); ++ free(drwl); ++} ++ ++static void ++drwl_fini(void) ++{ ++ fcft_fini(); ++} +diff --git a/dwl.c b/dwl.c +index def2562..893b1f1 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -12,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -58,6 +60,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -68,6 +71,7 @@ + #endif + + #include "util.h" ++#include "drwl.h" + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +@@ -81,9 +85,11 @@ + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) + + /* enums */ ++enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { TBarNone, TBarLabel, TBarMultiple, TBarAlways }; /* tbar types */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -103,6 +109,14 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct { ++ struct wlr_buffer base; ++ struct wl_listener release; ++ bool busy; ++ Img *image; ++ uint32_t data[]; ++} Buffer; ++ + typedef struct Monitor Monitor; + typedef struct { + /* Must keep these three elements in this order */ +@@ -112,6 +126,11 @@ typedef struct { + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; ++ struct wlr_scene_buffer *tbar_buffer; ++ Drwl *drw; ++ Buffer *pool[2]; ++ int tbar_height, tbar_real_height; ++ float tbar_scale; + struct wl_list link; + struct wl_list flink; + union { +@@ -139,7 +158,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, tbar_enabled, resize_tbar_enabled; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -183,6 +202,8 @@ typedef struct { + + typedef struct { + const char *symbol; ++ unsigned int tbar_type; /* type of tbar */ ++ int tbar_only_top; + void (*arrange)(Monitor *); + } Layout; + +@@ -250,6 +271,12 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static Buffer *bufclient(Client *c); ++static void bufdestroy(struct wlr_buffer *wlr_buffer); ++static bool bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride); ++static void bufdataend(struct wlr_buffer *wlr_buffer); ++static void bufrelease(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -285,10 +312,13 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawtbars(Monitor *m, int floating, int clients_changed); ++static void drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); ++static Client *focustop_onlytiled(Monitor *m, int onlytiled); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); +@@ -413,6 +443,12 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static const struct wlr_buffer_impl buffer_impl = { ++ .destroy = bufdestroy, ++ .begin_data_ptr_access = bufdatabegin, ++ .end_data_ptr_access = bufdataend, ++}; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -485,14 +521,16 @@ void + arrange(Monitor *m) + { + Client *c; ++ int enabled; + + if (!m->wlr_output->enabled) + return; + + wl_list_for_each(c, &clients, link) { + if (c->mon == m) { +- wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m)); +- client_set_suspended(c, !VISIBLEON(c, m)); ++ enabled = VISIBLEON(c, m); ++ wlr_scene_node_set_enabled(&c->scene->node, enabled); ++ client_set_suspended(c, !enabled); + } + } + +@@ -517,6 +555,7 @@ arrange(Monitor *m) + + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); ++ + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + } +@@ -595,6 +634,74 @@ axisnotify(struct wl_listener *listener, void *data) + event->delta_discrete, event->source, event->relative_direction); + } + ++Buffer * ++bufclient(Client *c) ++{ ++ size_t i; ++ Buffer *buf = NULL; ++ ++ for (i = 0; i < LENGTH(c->pool); i++) { ++ if (c->pool[i]) { ++ if (c->pool[i]->busy) ++ continue; ++ buf = c->pool[i]; ++ break; ++ } ++ ++ buf = ecalloc(1, sizeof(Buffer) + (int)(c->geom.width * c->tbar_scale * 4 * (c->tbar_height + 2*tbar_borderpx))); ++ buf->image = drwl_image_create(NULL, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx, buf->data); ++ wlr_buffer_init(&buf->base, &buffer_impl, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx); ++ c->pool[i] = buf; ++ break; ++ } ++ if (!buf) ++ return NULL; ++ ++ buf->busy = true; ++ LISTEN(&buf->base.events.release, &buf->release, bufrelease); ++ wlr_buffer_lock(&buf->base); ++ drwl_setimage(c->drw, buf->image); ++ return buf; ++} ++ ++void ++bufdestroy(struct wlr_buffer *wlr_buffer) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ if (buf->busy) ++ wl_list_remove(&buf->release.link); ++ drwl_image_destroy(buf->image); ++ free(buf); ++} ++ ++bool ++bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ ++ if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; ++ ++ *data = buf->data; ++ *stride = wlr_buffer->width * 4; ++ *format = DRM_FORMAT_ARGB8888; ++ ++ return true; ++} ++ ++void ++bufdataend(struct wlr_buffer *wlr_buffer) ++{ ++} ++ ++void ++bufrelease(struct wl_listener *listener, void *data) ++{ ++ Buffer *buf = wl_container_of(listener, buf, release); ++ buf->busy = false; ++ wl_list_remove(&buf->release.link); ++} ++ + void + buttonpress(struct wl_listener *listener, void *data) + { +@@ -676,6 +783,21 @@ checkidleinhibitor(struct wlr_surface *exclude) + void + cleanup(void) + { ++ Client *c; ++ unsigned int i; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!c->tbar_enabled) ++ continue; ++ ++ for (i = 0; i < LENGTH(c->pool); i++) ++ wlr_buffer_drop(&c->pool[i]->base); ++ ++ drwl_setimage(c->drw, NULL); ++ drwl_destroy(c->drw); ++ ++ wlr_scene_node_destroy(&c->tbar_buffer->node); ++ } + #ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; +@@ -697,6 +819,8 @@ cleanup(void) + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); ++ ++ drwl_fini(); + } + + void +@@ -1063,6 +1187,10 @@ createnotify(struct wl_listener *listener, void *data) + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; ++ c->tbar_enabled = 0; ++ c->resize_tbar_enabled = 0; ++ c->tbar_height = 0; ++ c->tbar_buffer = NULL; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); +@@ -1338,6 +1466,166 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++void ++drawtbars(Monitor *m, int floating, int clients_changed) ++{ ++ unsigned int tbar_type, tbar_only_top, len = 0; ++ int nodraw = 0, ismonocle; ++ Client *c, *sel = NULL, *sel_in_layout = NULL; ++ ++ if (!m) ++ return; ++ ++ tbar_type = floating ? floating_tbar_type : m->lt[m->sellt]->tbar_type; ++ tbar_only_top = floating ? floating_tbar_only_top : m->lt[m->sellt]->tbar_only_top; ++ ismonocle = m->lt[m->sellt]->arrange == monocle; ++ ++ if (!clients_changed && !floating && ismonocle && (sel = focustop_onlytiled(m, 1))) { ++ wlr_scene_node_raise_to_top(&sel->scene->node); ++ if (sel->tbar_buffer) ++ wlr_scene_node_raise_to_top(&sel->tbar_buffer->node); ++ return; ++ } ++ ++ if (tbar_type == TBarNone) ++ nodraw = 2; ++ ++ if (!nodraw) { ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m)) ++ continue; ++ if (!sel && (!tbar_float_sel_sep || c->isfloating == floating)) ++ sel = c; ++ if (!sel_in_layout && c->isfloating == floating) ++ sel_in_layout = c; ++ if (c->isfloating == floating && !c->isfullscreen) ++ len++; ++ } ++ ++ if (len == 0) ++ return; ++ } ++ ++ if (tbar_type == TBarMultiple && len <= 1) ++ nodraw = 2; ++ ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m) || c->isfloating != floating) ++ continue; ++ if (c->tbar_buffer && c->tbar_enabled && (nodraw == 2 || c->isfullscreen)) { ++ wlr_scene_node_set_enabled(&c->tbar_buffer->node, 0); ++ c->tbar_enabled = 0; ++ if (m->lt[m->sellt]->arrange != tile) ++ resize(c, c->geom, 0); ++ } ++ if (!nodraw && !c->isfullscreen) { ++ drawtbar(c, tbar_type, len, ismonocle ? c : sel_in_layout, sel_in_layout); ++ if (!ismonocle && tbar_only_top) ++ nodraw = 1; ++ } ++ if (c == sel_in_layout) { ++ wlr_scene_node_raise_to_top(&sel_in_layout->scene->node); ++ if (sel_in_layout->tbar_buffer) ++ wlr_scene_node_raise_to_top(&sel_in_layout->tbar_buffer->node); ++ } ++ } ++ ++ if (m->lt[m->sellt]->arrange == tile) ++ m->lt[m->sellt]->arrange(m); ++} ++ ++void ++drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout) ++{ ++ Buffer *buf; ++ float width = c->geom.width * c->tbar_scale; ++ unsigned int i, scheme; ++ Client *l; ++ uint32_t tbar_border_colors[][3] = { ++ [SchemeNorm] = { [ColBg] = tbar_colors[SchemeNorm][2] }, ++ [SchemeSel] = { [ColBg] = tbar_colors[SchemeSel][2] }, ++ [SchemeUrg] = { [ColBg] = tbar_colors[SchemeUrg][2] } ++ }; ++ ++ if (!c->tbar_buffer) ++ c->tbar_buffer = wlr_scene_buffer_create(c->scene, NULL); ++ ++ for (i = 0; i < LENGTH(c->pool); i++) { ++ if (c->pool[i]) { ++ wlr_buffer_drop(&c->pool[i]->base); ++ c->pool[i] = NULL; ++ } ++ } ++ drwl_setimage(c->drw, NULL); ++ ++ if (!(buf = bufclient(c))) ++ return; ++ ++ switch (tbar_type) { ++ case TBarLabel: ++ scheme = c->isurgent ? SchemeUrg : (c == sel ? SchemeSel : SchemeNorm); ++ ++ if (tbar_borderpx) { ++ drwl_setscheme(c->drw, tbar_border_colors[scheme]); ++ drwl_rect(c->drw, 0, 0, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, 0, c->tbar_height + tbar_borderpx, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, 0, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ drwl_rect(c->drw, (unsigned int)width - tbar_borderpx, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ } ++ ++ drwl_setscheme(c->drw, tbar_colors[scheme]); ++ drwl_text(c->drw, tbar_borderpx, tbar_borderpx, ++ (unsigned int)width - 2*tbar_borderpx, c->tbar_height, ++ tbar_padding, client_get_title(c), 0); ++ ++ break; ++ ++ case TBarMultiple: ++ case TBarAlways: ++ width /= len; ++ i = 0; ++ ++ wl_list_for_each(l, &clients, link) { ++ if (!VISIBLEON(l, c->mon) || l->isfullscreen || l->isfloating != c->isfloating) ++ continue; ++ ++ scheme = l->isurgent ? SchemeUrg : (l == sel ? SchemeSel : SchemeNorm); ++ ++ if (tbar_borderpx) { ++ drwl_setscheme(c->drw, tbar_border_colors[scheme]); ++ drwl_rect(c->drw, (unsigned int)(width*i), 0, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, (unsigned int)(width*i), c->tbar_height + tbar_borderpx, ++ (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, (unsigned int)(width*i), tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ if (i == len-1) ++ drwl_rect(c->drw, (unsigned int)(width*(i+1)) - tbar_borderpx, tbar_borderpx, ++ tbar_borderpx, c->tbar_height + 2*tbar_borderpx, 1, 1); ++ } ++ ++ drwl_setscheme(c->drw, tbar_colors[scheme]); ++ drwl_text(c->drw, (unsigned int)(width*i) + tbar_borderpx, tbar_borderpx, ++ (unsigned int)width - (i == len-1 ? 2*tbar_borderpx : tbar_borderpx), ++ c->tbar_height, tbar_padding, client_get_title(l), 0); ++ ++ i += 1; ++ } ++ ++ break; ++ } ++ ++ c->tbar_enabled = 1; ++ if (!c->resize_tbar_enabled) ++ resize(c, c->geom, 0); ++ ++ wlr_scene_buffer_set_dest_size(c->tbar_buffer, c->geom.width, ++ c->tbar_real_height + 2*tbar_borderpx); ++ wlr_scene_node_set_position(&c->tbar_buffer->node, 0, tbar_top ? 0 ++ : (c->geom.height - c->tbar_real_height - 2*tbar_borderpx)); ++ wlr_scene_buffer_set_buffer(c->tbar_buffer, &buf->base); ++ wlr_scene_node_set_enabled(&c->tbar_buffer->node, 1); ++ wlr_buffer_unlock(&buf->base); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1373,13 +1661,13 @@ focusclient(Client *c, int lift) + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) +- client_set_border_color(c, focuscolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder])); + } + + /* Deactivate old client if focus is changing */ + if (old && (!c || client_surface(c) != old)) { + /* If an overlay is focused, don't focus or activate the client, +- * but only update its position in fstack to render its border with focuscolor ++ * but only update its position in fstack to render its border with its color + * and focus it after the overlay is closed. */ + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) +@@ -1390,11 +1678,18 @@ focusclient(Client *c, int lift) + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { +- client_set_border_color(old_c, bordercolor); ++ client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder])); + + client_activate_surface(old, 0); + } + } ++ ++ if (c && c->mon) ++ drawtbars(c->mon, c->isfloating, 0); ++ if (c && old_c && old_c->mon && (old_c->mon != c->mon || old_c->isfloating != c->isfloating)) ++ drawtbars(old_c->mon, old_c->isfloating, 0); ++ ++ + printstatus(); + + if (!c) { +@@ -1465,6 +1760,20 @@ focustop(Monitor *m) + return NULL; + } + ++Client * ++focustop_onlytiled(Monitor *m, int onlytiled) ++{ ++ Client *c; ++ wl_list_for_each(c, &fstack, flink) { ++ if (VISIBLEON(c, m)) { ++ if ((onlytiled == 1 && c->isfloating) || (onlytiled == 2 && !c->isfloating && m->lt[m->sellt]->arrange)) ++ continue; ++ return c; ++ } ++ } ++ return NULL; ++} ++ + void + fullscreennotify(struct wl_listener *listener, void *data) + { +@@ -1524,6 +1833,7 @@ incnmaster(const Arg *arg) + return; + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + void +@@ -1692,6 +2002,7 @@ mapnotify(struct wl_listener *listener, void *data) + Client *w, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; ++ char fontattrs[12]; + + /* Create scene tree for this client and its border */ + c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); +@@ -1717,7 +2028,7 @@ mapnotify(struct wl_listener *listener, void *data) + + for (i = 0; i < 4; i++) { + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, +- c->isurgent ? urgentcolor : bordercolor); ++ (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder])); + c->border[i]->node.data = c; + } + +@@ -1740,6 +2051,7 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } ++ + printstatus(); + + unset_fullscreen: +@@ -1748,6 +2060,20 @@ unset_fullscreen: + if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) + setfullscreen(w, 0); + } ++ ++ if (!(c->drw = drwl_create())) ++ die("failed to create drwl context"); ++ c->tbar_scale = tbar_scale > 0 ? tbar_scale : m->wlr_output->scale; ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale); ++ if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs))) ++ die("Could not load font"); ++ if (!c->tbar_height) { ++ c->tbar_height = c->drw->font->height; ++ if (tbar_height > c->tbar_height) ++ c->tbar_height = tbar_height; ++ c->tbar_real_height = (int)((float)c->tbar_height / c->tbar_scale); ++ } ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -1772,18 +2098,28 @@ void + monocle(Monitor *m) + { + Client *c; +- int n = 0; ++ int n = 0, old_tbar_enabled; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- resize(c, m->w, 0); ++ if (!n) ++ wlr_scene_node_raise_to_top(&c->scene->node); + n++; ++ if (n > 1) ++ break; ++ } ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ old_tbar_enabled = c->tbar_enabled; ++ c->tbar_enabled = m->lt[m->sellt]->tbar_type != TBarNone ++ && m->lt[m->sellt]->tbar_type == TBarMultiple ? n > 1 : 1; ++ resize(c, m->w, 0); ++ c->tbar_enabled = old_tbar_enabled; + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); +- if ((c = focustop(m))) +- wlr_scene_node_raise_to_top(&c->scene->node); + } + + void +@@ -2184,32 +2520,37 @@ resize(Client *c, struct wlr_box geo, int interact) + { + struct wlr_box *bbox; + struct wlr_box clip; ++ unsigned int th; + + if (!c->mon || !client_surface(c)->mapped) + return; + + bbox = interact ? &sgeom : &c->mon->w; + ++ th = c->tbar_enabled ? (unsigned int)(c->tbar_real_height + 2*tbar_borderpx) : c->bw; ++ + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); +- wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); +- wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); +- wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); ++ wlr_scene_node_set_position(&c->scene_surface->node, c->bw, tbar_top ? th : c->bw); ++ wlr_scene_rect_set_size(c->border[0], c->geom.width, (c->tbar_enabled && tbar_top) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[1], c->geom.width, (c->tbar_enabled && !tbar_top) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - th - c->bw); ++ wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - th - c->bw); + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); +- wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); +- wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_node_set_position(&c->border[2]->node, 0, tbar_top ? th : c->bw); ++ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, tbar_top ? th : c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +- c->geom.height - 2 * c->bw); ++ c->geom.height - th - c->bw); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); ++ ++ c->resize_tbar_enabled = c->tbar_enabled; + } + + void +@@ -2318,6 +2659,8 @@ setfloating(Client *c, int floating) + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); + printstatus(); ++ drawtbars(c->mon, 0, 1); ++ drawtbars(c->mon, 1, 1); + } + + void +@@ -2341,6 +2684,7 @@ setfullscreen(Client *c, int fullscreen) + } + arrange(c->mon); + printstatus(); ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -2366,6 +2710,7 @@ setlayout(const Arg *arg) + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); + } + + /* arg > 1.0 will set mfact absolutely */ +@@ -2381,6 +2726,7 @@ setmfact(const Arg *arg) + return; + selmon->mfact = f; + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + void +@@ -2627,6 +2973,8 @@ setup(void) + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); + LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); + ++ drwl_init(); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2680,14 +3028,22 @@ tag(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void + tagmon(const Arg *arg) + { + Client *sel = focustop(selmon); +- if (sel) ++ Monitor *old_mon = selmon; ++ if (sel) { + setmon(sel, dirtomon(arg->i), 0); ++ if (selmon) ++ drawtbars(selmon, sel->isfloating, 1); ++ if (old_mon && selmon != old_mon) ++ drawtbars(old_mon, sel->isfloating, 1); ++ } + } + + void +@@ -2753,6 +3109,8 @@ toggletag(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void +@@ -2766,6 +3124,8 @@ toggleview(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void +@@ -2796,6 +3156,9 @@ unmapnotify(struct wl_listener *listener, void *data) + { + /* Called when the surface is unmapped, and should no longer be shown. */ + Client *c = wl_container_of(listener, c, unmap); ++ Monitor *m = c->mon; ++ unsigned int i; ++ + if (c == grabc) { + cursor_mode = CurNormal; + grabc = NULL; +@@ -2812,6 +3175,20 @@ unmapnotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->flink); + } + ++ if (m && !c->isfloating && m->lt[m->sellt]->arrange == monocle) ++ drawtbars(m, c->isfloating, 1); ++ ++ if (c->tbar_enabled) { ++ for (i = 0; i < LENGTH(c->pool); i++) ++ if (c->pool[i]) ++ wlr_buffer_drop(&c->pool[i]->base); ++ ++ drwl_setimage(c->drw, NULL); ++ drwl_destroy(c->drw); ++ ++ wlr_scene_node_destroy(&c->tbar_buffer->node); ++ } ++ + wlr_scene_node_destroy(&c->scene->node); + printstatus(); + motionnotify(0, NULL, 0, 0, 0, 0); +@@ -2832,9 +3209,12 @@ updatemons(struct wl_listener *listener, void *data) + Client *c; + struct wlr_output_configuration_head_v1 *config_head; + Monitor *m; ++ char fontattrs[12]; + + /* First remove from the layout the disabled monitors */ + wl_list_for_each(m, &mons, link) { ++ if (m->asleep) ++ continue; + if (m->wlr_output->enabled || m->asleep) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); +@@ -2898,6 +3278,23 @@ updatemons(struct wl_listener *listener, void *data) + if (!selmon) { + selmon = m; + } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || (c->drw && (tbar_scale > 0 || c->tbar_scale == m->wlr_output->scale))) ++ continue; ++ if (!c->drw && !(c->drw = drwl_create())) ++ die("failed to create drwl context"); ++ drwl_font_destroy(c->drw->font); ++ c->tbar_scale = m->wlr_output->scale; ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale); ++ if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs))) ++ die("Could not load font"); ++ if (!c->tbar_height) { ++ c->tbar_height = c->drw->font->height; ++ if (tbar_height > c->tbar_height) ++ c->tbar_height = tbar_height; ++ } ++ } + } + + if (selmon && selmon->wlr_output->enabled) { +@@ -2929,6 +3326,7 @@ updatetitle(struct wl_listener *listener, void *data) + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) + printstatus(); ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -2942,9 +3340,10 @@ urgent(struct wl_listener *listener, void *data) + + c->isurgent = 1; + printstatus(); ++ drawtbars(c->mon, 1, 1); + + if (client_surface(c)->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +@@ -3052,8 +3451,10 @@ zoom(const Arg *arg) + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); + ++ drawtbars(selmon, 0, 1); + focusclient(sel, 1); + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + #ifdef XWAYLAND +@@ -3105,6 +3506,10 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; ++ c->tbar_enabled = 0; ++ c->resize_tbar_enabled = 0; ++ c->tbar_height = 0; ++ c->tbar_buffer = NULL; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +@@ -3150,7 +3555,7 @@ sethints(struct wl_listener *listener, void *data) + printstatus(); + + if (c->isurgent && surface && surface->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +-- +2.47.0 + diff --git a/dwl/dwl-patches/patches/tab/tab.patch b/dwl/dwl-patches/patches/tab/tab.patch new file mode 100755 index 0000000..49276ad --- /dev/null +++ b/dwl/dwl-patches/patches/tab/tab.patch @@ -0,0 +1,1252 @@ +From d722eef53d488c9e9ed04991112376035e8c9b25 Mon Sep 17 00:00:00 2001 +From: dev-gm +Date: Sat, 16 Nov 2024 23:22:14 -0500 +Subject: [PATCH] Add tab support + +--- + Makefile | 2 +- + config.def.h | 37 ++++- + drwl.h | 320 ++++++++++++++++++++++++++++++++++++ + dwl.c | 449 ++++++++++++++++++++++++++++++++++++++++++++++++--- + 4 files changed, 777 insertions(+), 31 deletions(-) + create mode 100644 drwl.h + +diff --git a/Makefile b/Makefile +index 578194f..279b1c0 100644 +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wayland-server xkbcommon libinput $(XLIBS) ++PKGS = wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 22d2171..9d33d89 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,13 +7,31 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); +-static const float bordercolor[] = COLOR(0x444444ff); +-static const float focuscolor[] = COLOR(0x005577ff); +-static const float urgentcolor[] = COLOR(0xff0000ff); ++static const char *tbar_fonts[] = {"monospace:size=10"}; ++static const int tbar_top = 0; ++static const int tbar_height = -1; ++static const int tbar_borderpx = 1; ++static const int tbar_padding = 10; ++static const float tbar_scale = -1; /* -1 means use monitor scale */ ++static const int tbar_float_sel_sep = 0; /* should tbar be highlighted only on the currently selected window or on both the last selected floating window and the laste selected tiling window */ ++static const float rootcolor[] = COLOR(0x000000ff); + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ + ++static uint32_t colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff }, ++ [SchemeUrg] = { 0, 0, 0x770000ff }, ++}; ++ ++static uint32_t tbar_colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x555555ff }, ++ [SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x555555ff }, ++ [SchemeUrg] = { 0xc7c7c7ff, 0x222222ff, 0x770000ff }, ++}; ++ + /* tagging - TAGCOUNT must be no greater than 31 */ + #define TAGCOUNT (9) + +@@ -28,12 +46,15 @@ static const Rule rules[] = { + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ + }; + ++static const unsigned int floating_tbar_type = TBarLabel; ++static const int floating_tbar_only_top = 0; ++ + /* layout(s) */ + static const Layout layouts[] = { +- /* symbol arrange function */ +- { "[]=", tile }, +- { "><>", NULL }, /* no layout function means floating behavior */ +- { "[M]", monocle }, ++ /* symbol tbar type tbar only on top arrange function */ ++ { "[]=", TBarLabel, 0, tile }, ++ { "><>", TBarLabel, 0, NULL }, /* no layout function means floating behavior */ ++ { "[M]", TBarMultiple, 1, monocle }, + }; + + /* monitors */ +diff --git a/drwl.h b/drwl.h +new file mode 100644 +index 0000000..02eb8e9 +--- /dev/null ++++ b/drwl.h +@@ -0,0 +1,320 @@ ++/* ++ * drwl - https://codeberg.org/sewn/drwl ++ * ++ * Copyright (c) 2023-2024 sewn ++ * Copyright (c) 2024 notchoc ++ * ++ * 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. ++ * ++ * The UTF-8 Decoder included is from Bjoern Hoehrmann: ++ * Copyright (c) 2008-2010 Bjoern Hoehrmann ++ * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. ++ */ ++#pragma once ++ ++#include ++#include ++#include ++ ++enum { ColFg, ColBg, ColBorder }; /* colorscheme index */ ++ ++typedef struct fcft_font Fnt; ++typedef pixman_image_t Img; ++ ++typedef struct { ++ Img *image; ++ Fnt *font; ++ uint32_t *scheme; ++} Drwl; ++ ++#define UTF8_ACCEPT 0 ++#define UTF8_REJECT 12 ++#define UTF8_INVALID 0xFFFD ++ ++static const uint8_t utf8d[] = { ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ++ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, ++ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, ++ ++ 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, ++ 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, ++ 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, ++ 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, ++ 12,36,12,12,12,12,12,12,12,12,12,12, ++}; ++ ++static inline uint32_t ++utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) ++{ ++ uint32_t type = utf8d[byte]; ++ ++ *codep = (*state != UTF8_ACCEPT) ? ++ (byte & 0x3fu) | (*codep << 6) : ++ (0xff >> type) & (byte); ++ ++ *state = utf8d[256 + *state + type]; ++ return *state; ++} ++ ++static int ++drwl_init(void) ++{ ++ fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); ++ return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR); ++} ++ ++static Drwl * ++drwl_create(void) ++{ ++ Drwl *drwl; ++ ++ if (!(drwl = calloc(1, sizeof(Drwl)))) ++ return NULL; ++ ++ return drwl; ++} ++ ++static void ++drwl_setfont(Drwl *drwl, Fnt *font) ++{ ++ if (drwl) ++ drwl->font = font; ++} ++ ++static void ++drwl_setimage(Drwl *drwl, Img *image) ++{ ++ if (drwl) ++ drwl->image = image; ++} ++ ++static Fnt * ++drwl_font_create(Drwl *drwl, size_t count, ++ const char *names[static count], const char *attributes) ++{ ++ Fnt *font = fcft_from_name(count, names, attributes); ++ if (drwl) ++ drwl_setfont(drwl, font); ++ return font; ++} ++ ++static void ++drwl_font_destroy(Fnt *font) ++{ ++ fcft_destroy(font); ++} ++ ++static inline pixman_color_t ++convert_color(uint32_t clr) ++{ ++ return (pixman_color_t){ ++ ((clr >> 24) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 16) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ ((clr >> 8) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF, ++ (clr & 0xFF) * 0x101 ++ }; ++} ++ ++static void ++drwl_setscheme(Drwl *drwl, uint32_t *scm) ++{ ++ if (drwl) ++ drwl->scheme = scm; ++} ++ ++static Img * ++drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits) ++{ ++ Img *image; ++ pixman_region32_t clip; ++ ++ image = pixman_image_create_bits_no_clear( ++ PIXMAN_a8r8g8b8, w, h, bits, w * 4); ++ if (!image) ++ return NULL; ++ pixman_region32_init_rect(&clip, 0, 0, w, h); ++ pixman_image_set_clip_region32(image, &clip); ++ pixman_region32_fini(&clip); ++ ++ if (drwl) ++ drwl_setimage(drwl, image); ++ return image; ++} ++ ++static void ++drwl_rect(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ int filled, int invert) ++{ ++ pixman_color_t clr; ++ if (!drwl || !drwl->scheme || !drwl->image) ++ return; ++ ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ if (filled) ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1, ++ &(pixman_rectangle16_t){x, y, w, h}); ++ else ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4, ++ (pixman_rectangle16_t[4]){ ++ { x, y, w, 1 }, ++ { x, y + h - 1, w, 1 }, ++ { x, y, 1, h }, ++ { x + w - 1, y, 1, h }}); ++} ++ ++static int ++drwl_text(Drwl *drwl, ++ int x, int y, unsigned int w, unsigned int h, ++ unsigned int lpad, const char *text, int invert) ++{ ++ int ty; ++ int render = x || y || w || h; ++ long x_kern; ++ uint32_t cp = 0, last_cp = 0, state; ++ pixman_color_t clr; ++ pixman_image_t *fg_pix = NULL; ++ int noellipsis = 0; ++ const struct fcft_glyph *glyph, *eg = NULL; ++ int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT; ++ ++ if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font) ++ return 0; ++ ++ if (!render) { ++ w = invert ? invert : ~invert; ++ } else { ++ clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]); ++ fg_pix = pixman_image_create_solid_fill(&clr); ++ ++ drwl_rect(drwl, x, y, w, h, 1, !invert); ++ ++ x += lpad; ++ w -= lpad; ++ } ++ ++ if (render && (drwl->scheme[ColBg] & 0xFF) != 0xFF) ++ fcft_subpixel_mode = FCFT_SUBPIXEL_NONE; ++ ++ if (render) ++ eg = fcft_rasterize_char_utf32(drwl->font, 0x2026 /* … */, fcft_subpixel_mode); ++ ++ for (const char *p = text, *pp; pp = p, *p; p++) { ++ for (state = UTF8_ACCEPT; *p && ++ utf8decode(&state, &cp, *p) > UTF8_REJECT; p++) ++ ; ++ if (!*p || state == UTF8_REJECT) { ++ cp = UTF8_INVALID; ++ if (p > pp) ++ p--; ++ } ++ ++ glyph = fcft_rasterize_char_utf32(drwl->font, cp, fcft_subpixel_mode); ++ if (!glyph) ++ continue; ++ ++ x_kern = 0; ++ if (last_cp) ++ fcft_kerning(drwl->font, last_cp, cp, &x_kern, NULL); ++ last_cp = cp; ++ ++ ty = y + (h - drwl->font->height) / 2 + drwl->font->ascent; ++ ++ if (render && !noellipsis && x_kern + glyph->advance.x + eg->advance.x > w && ++ *(p + 1) != '\0') { ++ /* cannot fit ellipsis after current codepoint */ ++ if (drwl_text(drwl, 0, 0, 0, 0, 0, pp, 0) + x_kern <= w) { ++ noellipsis = 1; ++ } else { ++ w -= eg->advance.x; ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0, ++ x + eg->x, ty - eg->y, eg->width, eg->height); ++ } ++ } ++ ++ if ((x_kern + glyph->advance.x) > w) ++ break; ++ ++ x += x_kern; ++ ++ if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) ++ /* pre-rendered glyphs (eg. emoji) */ ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ else if (render) ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ ++ x += glyph->advance.x; ++ w -= glyph->advance.x; ++ } ++ ++ if (render) ++ pixman_image_unref(fg_pix); ++ ++ return x + (render ? w : 0); ++} ++ ++static unsigned int ++drwl_font_getwidth(Drwl *drwl, const char *text) ++{ ++ if (!drwl || !drwl->font || !text) ++ return 0; ++ return drwl_text(drwl, 0, 0, 0, 0, 0, text, 0); ++} ++ ++static unsigned int ++drwl_font_getwidth_clamp(Drwl *drwl, const char *text, unsigned int n) ++{ ++ unsigned int tmp = 0; ++ if (drwl && drwl->font && text && n) ++ tmp = drwl_text(drwl, 0, 0, 0, 0, 0, text, n); ++ return tmp < n ? tmp : n; ++} ++ ++static void ++drwl_image_destroy(Img *image) ++{ ++ pixman_image_unref(image); ++} ++ ++static void ++drwl_destroy(Drwl *drwl) ++{ ++ if (drwl->font) ++ drwl_font_destroy(drwl->font); ++ if (drwl->image) ++ drwl_image_destroy(drwl->image); ++ free(drwl); ++} ++ ++static void ++drwl_fini(void) ++{ ++ fcft_fini(); ++} +diff --git a/dwl.c b/dwl.c +index 9acb898..bde4009 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -12,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -59,6 +61,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -69,6 +72,7 @@ + #endif + + #include "util.h" ++#include "drwl.h" + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +@@ -82,9 +86,11 @@ + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) + + /* enums */ ++enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { TBarNone, TBarLabel, TBarMultiple, TBarAlways }; /* tbar types */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -104,6 +110,14 @@ typedef struct { + const Arg arg; + } Button; + ++typedef struct { ++ struct wlr_buffer base; ++ struct wl_listener release; ++ bool busy; ++ Img *image; ++ uint32_t data[]; ++} Buffer; ++ + typedef struct Monitor Monitor; + typedef struct { + /* Must keep this field first */ +@@ -113,6 +127,11 @@ typedef struct { + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; ++ struct wlr_scene_buffer *tbar_buffer; ++ Drwl *drw; ++ Buffer *pool[2]; ++ int tbar_height, tbar_real_height; ++ float tbar_scale; + struct wl_list link; + struct wl_list flink; + struct wlr_box geom; /* layout-relative, includes border */ +@@ -141,7 +160,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, tbar_enabled, resize_tbar_enabled; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -184,6 +203,8 @@ typedef struct { + + typedef struct { + const char *symbol; ++ unsigned int tbar_type; /* type of tbar */ ++ int tbar_only_top; + void (*arrange)(Monitor *); + } Layout; + +@@ -251,6 +272,12 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static Buffer *bufclient(Client *c); ++static void bufdestroy(struct wlr_buffer *wlr_buffer); ++static bool bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride); ++static void bufdataend(struct wlr_buffer *wlr_buffer); ++static void bufrelease(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -286,10 +313,13 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawtbars(Monitor *m, int floating, int clients_changed); ++static void drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); ++static Client *focustop_onlytiled(Monitor *m, int onlytiled); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); +@@ -411,6 +441,12 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static const struct wlr_buffer_impl buffer_impl = { ++ .destroy = bufdestroy, ++ .begin_data_ptr_access = bufdatabegin, ++ .end_data_ptr_access = bufdataend, ++}; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -481,14 +517,16 @@ void + arrange(Monitor *m) + { + Client *c; ++ int enabled; + + if (!m->wlr_output->enabled) + return; + + wl_list_for_each(c, &clients, link) { + if (c->mon == m) { +- wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m)); +- client_set_suspended(c, !VISIBLEON(c, m)); ++ enabled = VISIBLEON(c, m); ++ wlr_scene_node_set_enabled(&c->scene->node, enabled); ++ client_set_suspended(c, !enabled); + } + } + +@@ -513,6 +551,7 @@ arrange(Monitor *m) + + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); ++ + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + } +@@ -589,6 +628,74 @@ axisnotify(struct wl_listener *listener, void *data) + event->delta_discrete, event->source, event->relative_direction); + } + ++Buffer * ++bufclient(Client *c) ++{ ++ size_t i; ++ Buffer *buf = NULL; ++ ++ for (i = 0; i < LENGTH(c->pool); i++) { ++ if (c->pool[i]) { ++ if (c->pool[i]->busy) ++ continue; ++ buf = c->pool[i]; ++ break; ++ } ++ ++ buf = ecalloc(1, sizeof(Buffer) + (int)(c->geom.width * c->tbar_scale * 4 * (c->tbar_height + 2*tbar_borderpx))); ++ buf->image = drwl_image_create(NULL, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx, buf->data); ++ wlr_buffer_init(&buf->base, &buffer_impl, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx); ++ c->pool[i] = buf; ++ break; ++ } ++ if (!buf) ++ return NULL; ++ ++ buf->busy = true; ++ LISTEN(&buf->base.events.release, &buf->release, bufrelease); ++ wlr_buffer_lock(&buf->base); ++ drwl_setimage(c->drw, buf->image); ++ return buf; ++} ++ ++void ++bufdestroy(struct wlr_buffer *wlr_buffer) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ if (buf->busy) ++ wl_list_remove(&buf->release.link); ++ drwl_image_destroy(buf->image); ++ free(buf); ++} ++ ++bool ++bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride) ++{ ++ Buffer *buf = wl_container_of(wlr_buffer, buf, base); ++ ++ if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; ++ ++ *data = buf->data; ++ *stride = wlr_buffer->width * 4; ++ *format = DRM_FORMAT_ARGB8888; ++ ++ return true; ++} ++ ++void ++bufdataend(struct wlr_buffer *wlr_buffer) ++{ ++} ++ ++void ++bufrelease(struct wl_listener *listener, void *data) ++{ ++ Buffer *buf = wl_container_of(listener, buf, release); ++ buf->busy = false; ++ wl_list_remove(&buf->release.link); ++} ++ + void + buttonpress(struct wl_listener *listener, void *data) + { +@@ -670,6 +777,21 @@ checkidleinhibitor(struct wlr_surface *exclude) + void + cleanup(void) + { ++ Client *c; ++ unsigned int i; ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!c->tbar_enabled) ++ continue; ++ ++ for (i = 0; i < LENGTH(c->pool); i++) ++ wlr_buffer_drop(&c->pool[i]->base); ++ ++ drwl_setimage(c->drw, NULL); ++ drwl_destroy(c->drw); ++ ++ wlr_scene_node_destroy(&c->tbar_buffer->node); ++ } + #ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; +@@ -691,6 +813,8 @@ cleanup(void) + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); ++ ++ drwl_fini(); + } + + void +@@ -1057,6 +1181,10 @@ createnotify(struct wl_listener *listener, void *data) + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; ++ c->tbar_enabled = 0; ++ c->resize_tbar_enabled = 0; ++ c->tbar_height = 0; ++ c->tbar_buffer = NULL; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); +@@ -1332,6 +1460,166 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++void ++drawtbars(Monitor *m, int floating, int clients_changed) ++{ ++ unsigned int tbar_type, tbar_only_top, len = 0; ++ int nodraw = 0, ismonocle; ++ Client *c, *sel = NULL, *sel_in_layout = NULL; ++ ++ if (!m) ++ return; ++ ++ tbar_type = floating ? floating_tbar_type : m->lt[m->sellt]->tbar_type; ++ tbar_only_top = floating ? floating_tbar_only_top : m->lt[m->sellt]->tbar_only_top; ++ ismonocle = m->lt[m->sellt]->arrange == monocle; ++ ++ if (!clients_changed && !floating && ismonocle && (sel = focustop_onlytiled(m, 1))) { ++ wlr_scene_node_raise_to_top(&sel->scene->node); ++ if (sel->tbar_buffer) ++ wlr_scene_node_raise_to_top(&sel->tbar_buffer->node); ++ return; ++ } ++ ++ if (tbar_type == TBarNone) ++ nodraw = 2; ++ ++ if (!nodraw) { ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m)) ++ continue; ++ if (!sel && (!tbar_float_sel_sep || c->isfloating == floating)) ++ sel = c; ++ if (!sel_in_layout && c->isfloating == floating) ++ sel_in_layout = c; ++ if (c->isfloating == floating && !c->isfullscreen) ++ len++; ++ } ++ ++ if (len == 0) ++ return; ++ } ++ ++ if (tbar_type == TBarMultiple && len <= 1) ++ nodraw = 2; ++ ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m) || c->isfloating != floating) ++ continue; ++ if (c->tbar_buffer && c->tbar_enabled && (nodraw == 2 || c->isfullscreen)) { ++ wlr_scene_node_set_enabled(&c->tbar_buffer->node, 0); ++ c->tbar_enabled = 0; ++ if (m->lt[m->sellt]->arrange != tile) ++ resize(c, c->geom, 0); ++ } ++ if (!nodraw && !c->isfullscreen) { ++ drawtbar(c, tbar_type, len, ismonocle ? c : sel_in_layout, sel_in_layout); ++ if (!ismonocle && tbar_only_top) ++ nodraw = 1; ++ } ++ if (c == sel_in_layout) { ++ wlr_scene_node_raise_to_top(&sel_in_layout->scene->node); ++ if (sel_in_layout->tbar_buffer) ++ wlr_scene_node_raise_to_top(&sel_in_layout->tbar_buffer->node); ++ } ++ } ++ ++ if (m->lt[m->sellt]->arrange == tile) ++ m->lt[m->sellt]->arrange(m); ++} ++ ++void ++drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout) ++{ ++ Buffer *buf; ++ float width = c->geom.width * c->tbar_scale; ++ unsigned int i, scheme; ++ Client *l; ++ uint32_t tbar_border_colors[][3] = { ++ [SchemeNorm] = { [ColBg] = tbar_colors[SchemeNorm][2] }, ++ [SchemeSel] = { [ColBg] = tbar_colors[SchemeSel][2] }, ++ [SchemeUrg] = { [ColBg] = tbar_colors[SchemeUrg][2] } ++ }; ++ ++ if (!c->tbar_buffer) ++ c->tbar_buffer = wlr_scene_buffer_create(c->scene, NULL); ++ ++ for (i = 0; i < LENGTH(c->pool); i++) { ++ if (c->pool[i]) { ++ wlr_buffer_drop(&c->pool[i]->base); ++ c->pool[i] = NULL; ++ } ++ } ++ drwl_setimage(c->drw, NULL); ++ ++ if (!(buf = bufclient(c))) ++ return; ++ ++ switch (tbar_type) { ++ case TBarLabel: ++ scheme = c->isurgent ? SchemeUrg : (c == sel ? SchemeSel : SchemeNorm); ++ ++ if (tbar_borderpx) { ++ drwl_setscheme(c->drw, tbar_border_colors[scheme]); ++ drwl_rect(c->drw, 0, 0, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, 0, c->tbar_height + tbar_borderpx, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, 0, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ drwl_rect(c->drw, (unsigned int)width - tbar_borderpx, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ } ++ ++ drwl_setscheme(c->drw, tbar_colors[scheme]); ++ drwl_text(c->drw, tbar_borderpx, tbar_borderpx, ++ (unsigned int)width - 2*tbar_borderpx, c->tbar_height, ++ tbar_padding, client_get_title(c), 0); ++ ++ break; ++ ++ case TBarMultiple: ++ case TBarAlways: ++ width /= len; ++ i = 0; ++ ++ wl_list_for_each(l, &clients, link) { ++ if (!VISIBLEON(l, c->mon) || l->isfullscreen || l->isfloating != c->isfloating) ++ continue; ++ ++ scheme = l->isurgent ? SchemeUrg : (l == sel ? SchemeSel : SchemeNorm); ++ ++ if (tbar_borderpx) { ++ drwl_setscheme(c->drw, tbar_border_colors[scheme]); ++ drwl_rect(c->drw, (unsigned int)(width*i), 0, (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, (unsigned int)(width*i), c->tbar_height + tbar_borderpx, ++ (unsigned int)width, tbar_borderpx, 1, 1); ++ drwl_rect(c->drw, (unsigned int)(width*i), tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1); ++ if (i == len-1) ++ drwl_rect(c->drw, (unsigned int)(width*(i+1)) - tbar_borderpx, tbar_borderpx, ++ tbar_borderpx, c->tbar_height + 2*tbar_borderpx, 1, 1); ++ } ++ ++ drwl_setscheme(c->drw, tbar_colors[scheme]); ++ drwl_text(c->drw, (unsigned int)(width*i) + tbar_borderpx, tbar_borderpx, ++ (unsigned int)width - (i == len-1 ? 2*tbar_borderpx : tbar_borderpx), ++ c->tbar_height, tbar_padding, client_get_title(l), 0); ++ ++ i += 1; ++ } ++ ++ break; ++ } ++ ++ c->tbar_enabled = 1; ++ if (!c->resize_tbar_enabled) ++ resize(c, c->geom, 0); ++ ++ wlr_scene_buffer_set_dest_size(c->tbar_buffer, c->geom.width, ++ c->tbar_real_height + 2*tbar_borderpx); ++ wlr_scene_node_set_position(&c->tbar_buffer->node, 0, tbar_top ? 0 ++ : (c->geom.height - c->tbar_real_height - 2*tbar_borderpx)); ++ wlr_scene_buffer_set_buffer(c->tbar_buffer, &buf->base); ++ wlr_scene_node_set_enabled(&c->tbar_buffer->node, 1); ++ wlr_buffer_unlock(&buf->base); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1366,13 +1654,13 @@ focusclient(Client *c, int lift) + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) +- client_set_border_color(c, focuscolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder])); + } + + /* Deactivate old client if focus is changing */ + if (old && (!c || client_surface(c) != old)) { + /* If an overlay is focused, don't focus or activate the client, +- * but only update its position in fstack to render its border with focuscolor ++ * but only update its position in fstack to render its border with its color + * and focus it after the overlay is closed. */ + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) +@@ -1383,11 +1671,18 @@ focusclient(Client *c, int lift) + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { +- client_set_border_color(old_c, bordercolor); ++ client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder])); + + client_activate_surface(old, 0); + } + } ++ ++ if (c && c->mon) ++ drawtbars(c->mon, c->isfloating, 0); ++ if (c && old_c && old_c->mon && (old_c->mon != c->mon || old_c->isfloating != c->isfloating)) ++ drawtbars(old_c->mon, old_c->isfloating, 0); ++ ++ + printstatus(); + + if (!c) { +@@ -1458,6 +1753,20 @@ focustop(Monitor *m) + return NULL; + } + ++Client * ++focustop_onlytiled(Monitor *m, int onlytiled) ++{ ++ Client *c; ++ wl_list_for_each(c, &fstack, flink) { ++ if (VISIBLEON(c, m)) { ++ if ((onlytiled == 1 && c->isfloating) || (onlytiled == 2 && !c->isfloating && m->lt[m->sellt]->arrange)) ++ continue; ++ return c; ++ } ++ } ++ return NULL; ++} ++ + void + fullscreennotify(struct wl_listener *listener, void *data) + { +@@ -1517,6 +1826,7 @@ incnmaster(const Arg *arg) + return; + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + void +@@ -1685,6 +1995,7 @@ mapnotify(struct wl_listener *listener, void *data) + Client *w, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; ++ char fontattrs[12]; + + /* Create scene tree for this client and its border */ + c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); +@@ -1712,7 +2023,7 @@ mapnotify(struct wl_listener *listener, void *data) + + for (i = 0; i < 4; i++) { + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, +- c->isurgent ? urgentcolor : bordercolor); ++ (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder])); + c->border[i]->node.data = c; + } + +@@ -1735,6 +2046,7 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } ++ + printstatus(); + + unset_fullscreen: +@@ -1743,6 +2055,20 @@ unset_fullscreen: + if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) + setfullscreen(w, 0); + } ++ ++ if (!(c->drw = drwl_create())) ++ die("failed to create drwl context"); ++ c->tbar_scale = tbar_scale > 0 ? tbar_scale : m->wlr_output->scale; ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale); ++ if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs))) ++ die("Could not load font"); ++ if (!c->tbar_height) { ++ c->tbar_height = c->drw->font->height; ++ if (tbar_height > c->tbar_height) ++ c->tbar_height = tbar_height; ++ c->tbar_real_height = (int)((float)c->tbar_height / c->tbar_scale); ++ } ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -1767,18 +2093,28 @@ void + monocle(Monitor *m) + { + Client *c; +- int n = 0; ++ int n = 0, old_tbar_enabled; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- resize(c, m->w, 0); ++ if (!n) ++ wlr_scene_node_raise_to_top(&c->scene->node); + n++; ++ if (n > 1) ++ break; ++ } ++ wl_list_for_each(c, &fstack, flink) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) ++ continue; ++ old_tbar_enabled = c->tbar_enabled; ++ c->tbar_enabled = m->lt[m->sellt]->tbar_type != TBarNone ++ && m->lt[m->sellt]->tbar_type == TBarMultiple ? n > 1 : 1; ++ resize(c, m->w, 0); ++ c->tbar_enabled = old_tbar_enabled; + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); +- if ((c = focustop(m))) +- wlr_scene_node_raise_to_top(&c->scene->node); + } + + void +@@ -2150,32 +2486,37 @@ resize(Client *c, struct wlr_box geo, int interact) + { + struct wlr_box *bbox; + struct wlr_box clip; ++ unsigned int th; + + if (!c->mon || !client_surface(c)->mapped) + return; + + bbox = interact ? &sgeom : &c->mon->w; + ++ th = c->tbar_enabled ? (unsigned int)(c->tbar_real_height + 2*tbar_borderpx) : c->bw; ++ + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); +- wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); +- wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); +- wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); ++ wlr_scene_node_set_position(&c->scene_surface->node, c->bw, tbar_top ? th : c->bw); ++ wlr_scene_rect_set_size(c->border[0], c->geom.width, (c->tbar_enabled && tbar_top) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[1], c->geom.width, (c->tbar_enabled && !tbar_top) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - th - c->bw); ++ wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - th - c->bw); + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); +- wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); +- wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_node_set_position(&c->border[2]->node, 0, tbar_top ? th : c->bw); ++ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, tbar_top ? th : c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +- c->geom.height - 2 * c->bw); ++ c->geom.height - th - c->bw); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); ++ ++ c->resize_tbar_enabled = c->tbar_enabled; + } + + void +@@ -2284,6 +2625,8 @@ setfloating(Client *c, int floating) + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); + printstatus(); ++ drawtbars(c->mon, 0, 1); ++ drawtbars(c->mon, 1, 1); + } + + void +@@ -2307,6 +2650,7 @@ setfullscreen(Client *c, int fullscreen) + } + arrange(c->mon); + printstatus(); ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -2321,6 +2665,7 @@ setlayout(const Arg *arg) + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); + } + + /* arg > 1.0 will set mfact absolutely */ +@@ -2336,6 +2681,7 @@ setmfact(const Arg *arg) + return; + selmon->mfact = f; + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + void +@@ -2585,6 +2931,8 @@ setup(void) + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); + LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); + ++ drwl_init(); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2638,14 +2986,22 @@ tag(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void + tagmon(const Arg *arg) + { + Client *sel = focustop(selmon); +- if (sel) ++ Monitor *old_mon = selmon; ++ if (sel) { + setmon(sel, dirtomon(arg->i), 0); ++ if (selmon) ++ drawtbars(selmon, sel->isfloating, 1); ++ if (old_mon && selmon != old_mon) ++ drawtbars(old_mon, sel->isfloating, 1); ++ } + } + + void +@@ -2711,6 +3067,8 @@ toggletag(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void +@@ -2724,6 +3082,8 @@ toggleview(const Arg *arg) + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); ++ drawtbars(selmon, 0, 1); ++ drawtbars(selmon, 1, 1); + } + + void +@@ -2754,6 +3114,9 @@ unmapnotify(struct wl_listener *listener, void *data) + { + /* Called when the surface is unmapped, and should no longer be shown. */ + Client *c = wl_container_of(listener, c, unmap); ++ Monitor *m = c->mon; ++ unsigned int i; ++ + if (c == grabc) { + cursor_mode = CurNormal; + grabc = NULL; +@@ -2770,6 +3133,20 @@ unmapnotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->flink); + } + ++ if (m && !c->isfloating && m->lt[m->sellt]->arrange == monocle) ++ drawtbars(m, c->isfloating, 1); ++ ++ if (c->tbar_enabled) { ++ for (i = 0; i < LENGTH(c->pool); i++) ++ if (c->pool[i]) ++ wlr_buffer_drop(&c->pool[i]->base); ++ ++ drwl_setimage(c->drw, NULL); ++ drwl_destroy(c->drw); ++ ++ wlr_scene_node_destroy(&c->tbar_buffer->node); ++ } ++ + wlr_scene_node_destroy(&c->scene->node); + printstatus(); + motionnotify(0, NULL, 0, 0, 0, 0); +@@ -2790,9 +3167,12 @@ updatemons(struct wl_listener *listener, void *data) + Client *c; + struct wlr_output_configuration_head_v1 *config_head; + Monitor *m; ++ char fontattrs[12]; + + /* First remove from the layout the disabled monitors */ + wl_list_for_each(m, &mons, link) { ++ if (m->asleep) ++ continue; + if (m->wlr_output->enabled || m->asleep) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); +@@ -2856,6 +3236,23 @@ updatemons(struct wl_listener *listener, void *data) + if (!selmon) { + selmon = m; + } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || (c->drw && (tbar_scale > 0 || c->tbar_scale == m->wlr_output->scale))) ++ continue; ++ if (!c->drw && !(c->drw = drwl_create())) ++ die("failed to create drwl context"); ++ drwl_font_destroy(c->drw->font); ++ c->tbar_scale = m->wlr_output->scale; ++ snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale); ++ if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs))) ++ die("Could not load font"); ++ if (!c->tbar_height) { ++ c->tbar_height = c->drw->font->height; ++ if (tbar_height > c->tbar_height) ++ c->tbar_height = tbar_height; ++ } ++ } + } + + if (selmon && selmon->wlr_output->enabled) { +@@ -2887,6 +3284,7 @@ updatetitle(struct wl_listener *listener, void *data) + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) + printstatus(); ++ drawtbars(c->mon, c->isfloating, 1); + } + + void +@@ -2900,9 +3298,10 @@ urgent(struct wl_listener *listener, void *data) + + c->isurgent = 1; + printstatus(); ++ drawtbars(c->mon, 1, 1); + + if (client_surface(c)->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +@@ -3010,8 +3409,10 @@ zoom(const Arg *arg) + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); + ++ drawtbars(selmon, 0, 1); + focusclient(sel, 1); + arrange(selmon); ++ drawtbars(selmon, 0, 0); + } + + #ifdef XWAYLAND +@@ -3070,6 +3471,10 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; ++ c->tbar_enabled = 0; ++ c->resize_tbar_enabled = 0; ++ c->tbar_height = 0; ++ c->tbar_buffer = NULL; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +@@ -3115,7 +3520,7 @@ sethints(struct wl_listener *listener, void *data) + printstatus(); + + if (c->isurgent && surface && surface->mapped) +- client_set_border_color(c, urgentcolor); ++ client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); + } + + void +-- +2.47.0 + diff --git a/dwl/dwl-patches/patches/tablet-input/README.md b/dwl/dwl-patches/patches/tablet-input/README.md new file mode 100755 index 0000000..3b3be09 --- /dev/null +++ b/dwl/dwl-patches/patches/tablet-input/README.md @@ -0,0 +1,25 @@ +### Description +implements wlr-tablet-v2 for drawing tablets and supports cursor emulation + +inspired by @guyuming76's [branch](https://codeberg.org/guyuming76/dwl/commits/branch/graphic_tablet), with coding help from @Palanix and testing by @Thanatos + +**Please note:** wlroots modified the order of arguments to the function `wlr_surface_accepts_tablet_v2` +In versions less than or equal to 0.18.1 (against which, dwl 0.7 is typically built), the order is `tablet, surface`. +In the master branch and (anticipated) in versions later than 0.18.1, the order is `surface, tablet`. +The git branch for this patch uses the `surface, tablet` order. + +If you are attempting to use this codebase to make your own modifications to the patch, there is only one call to the `wlr_surface_accepts_tablet_v2` function, but you will need to make the argument order change if you expect to build against wlroots 0.18.1 or earlier. + +The `0.7` patch linked here accounts for the change and uses the `tablet, surface` order, but the patch is orphaned from a codebase. + +There was discussion of this matter in [Issue #141](https://codeberg.org/dwl/dwl-patches/issues/141). + +### Download +- [git branch](https://codeberg.org/fauxmight/dwl/src/branch/tablet-input) +- [main 2025-05-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input.patch) +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tablet-input/tablet-input-0.7.patch) + +### Authors +- [fauxmight](https://codeberg.org/fauxmight) +- [notchoc](https://codeberg.org/notchoc) +- [Palanix](https://codeberg.org/Palanix) diff --git a/dwl/dwl-patches/patches/tablet-input/tablet-input-0.7.patch b/dwl/dwl-patches/patches/tablet-input/tablet-input-0.7.patch new file mode 100755 index 0000000..37fdf8a --- /dev/null +++ b/dwl/dwl-patches/patches/tablet-input/tablet-input-0.7.patch @@ -0,0 +1,355 @@ +From e504dc0fccfc3994962f03dc824d8907c6afc64f Mon Sep 17 00:00:00 2001 +From: choc +Date: Sat, 4 May 2024 01:16:12 +0800 +Subject: [PATCH] implement wlr-tablet-v2 + +--- + Makefile | 6 +- + config.def.h | 1 + + dwl.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 230 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index f955e7b..ce1b556 100644 +--- a/Makefile ++++ b/Makefile +@@ -21,7 +21,8 @@ dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ + dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ +- wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ ++ tablet-v2-protocol.h + util.o: util.c util.h + + # wayland-scanner is a tool which generates C headers and rigging for Wayland +@@ -45,6 +46,9 @@ wlr-output-power-management-unstable-v1-protocol.h: + xdg-shell-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ ++tablet-v2-protocol.h: ++ $(WAYLAND_SCANNER) server-header \ ++ $(WAYLAND_PROTOCOLS)/unstable/tablet/tablet-unstable-v2.xml $@ + + config.h: + cp config.def.h $@ +diff --git a/config.def.h b/config.def.h +index 22d2171..3ad98ef 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -4,6 +4,7 @@ + ((hex >> 8) & 0xFF) / 255.0f, \ + (hex & 0xFF) / 255.0f } + /* appearance */ ++static const int tabletmaptosurface = 0; /* map tablet input to surface(1) or monitor(0) */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +diff --git a/dwl.c b/dwl.c +index ac9c36b..b8d129f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -50,6 +50,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -270,6 +273,7 @@ static void createnotify(struct wl_listener *listener, void *data); + static void createpointer(struct wlr_pointer *pointer); + static void createpointerconstraint(struct wl_listener *listener, void *data); + static void createpopup(struct wl_listener *listener, void *data); ++static void createtablet(struct wlr_input_device *device); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); +@@ -284,6 +288,9 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data); + static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); ++static void destroytablet(struct wl_listener *listener, void *data); ++static void destroytabletsurfacenotify(struct wl_listener *listener, void *data); ++static void destroytablettool(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); +@@ -337,6 +344,11 @@ static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy); ++static void tablettoolproximity(struct wl_listener *listener, void *data); ++static void tablettoolaxis(struct wl_listener *listener, void *data); ++static void tablettoolbutton(struct wl_listener *listener, void *data); ++static void tablettooltip(struct wl_listener *listener, void *data); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); +@@ -396,6 +408,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint; + static struct wlr_cursor *cursor; + static struct wlr_xcursor_manager *cursor_mgr; + ++static struct wlr_tablet_manager_v2 *tablet_mgr; ++static struct wlr_tablet_v2_tablet *tablet = NULL; ++static struct wlr_tablet_v2_tablet_tool *tablet_tool = NULL; ++static struct wlr_tablet_v2_tablet_pad *tablet_pad = NULL; ++static struct wlr_surface *tablet_curr_surface = NULL; ++static struct wl_listener destroy_tablet_surface_listener = {.notify = destroytabletsurfacenotify}; ++ + static struct wlr_scene_rect *root_bg; + static struct wlr_session_lock_manager_v1 *session_lock_mgr; + static struct wlr_scene_rect *locked_bg; +@@ -1133,6 +1152,28 @@ createpopup(struct wl_listener *listener, void *data) + LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); + } + ++void ++createtablet(struct wlr_input_device *device) ++{ ++ if (!tablet) { ++ struct libinput_device *device_handle = NULL; ++ if (!wlr_input_device_is_libinput(device) || ++ !(device_handle = wlr_libinput_get_device_handle(device))) ++ return; ++ ++ tablet = wlr_tablet_create(tablet_mgr, seat, device); ++ LISTEN_STATIC(&tablet->wlr_device->events.destroy, destroytablet); ++ if (libinput_device_config_send_events_get_modes(device_handle)) { ++ libinput_device_config_send_events_set_mode(device_handle, send_events_mode); ++ wlr_cursor_attach_input_device(cursor, device); ++ } ++ } else if (device == tablet->wlr_device) { ++ wlr_log(WLR_ERROR, "createtablet: duplicate device"); ++ } else { ++ wlr_log(WLR_ERROR, "createtablet: already have one tablet"); ++ } ++} ++ + void + cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) + { +@@ -1321,6 +1362,27 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) + free(group); + } + ++void ++destroytablet(struct wl_listener *listener, void *data) ++{ ++ tablet = NULL; ++} ++ ++void ++destroytabletsurfacenotify(struct wl_listener *listener, void *data) ++{ ++ if (tablet_curr_surface) ++ wl_list_remove(&destroy_tablet_surface_listener.link); ++ tablet_curr_surface = NULL; ++} ++ ++void ++destroytablettool(struct wl_listener *listener, void *data) ++{ ++ destroytabletsurfacenotify(NULL, NULL); ++ tablet_tool = NULL; ++} ++ + Monitor * + dirtomon(enum wlr_direction dir) + { +@@ -1540,6 +1602,12 @@ inputdevice(struct wl_listener *listener, void *data) + case WLR_INPUT_DEVICE_POINTER: + createpointer(wlr_pointer_from_input_device(device)); + break; ++ case WLR_INPUT_DEVICE_TABLET: ++ createtablet(device); ++ break; ++ case WLR_INPUT_DEVICE_TABLET_PAD: ++ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device); ++ break; + default: + /* TODO handle other input device types */ + break; +@@ -2567,6 +2635,8 @@ setup(void) + + relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); + ++ tablet_mgr = wlr_tablet_v2_create(dpy); ++ + /* + * Creates a cursor, which is a wlroots utility for tracking the cursor + * image shown on screen. +@@ -2596,6 +2666,10 @@ setup(void) + LISTEN_STATIC(&cursor->events.button, buttonpress); + LISTEN_STATIC(&cursor->events.axis, axisnotify); + LISTEN_STATIC(&cursor->events.frame, cursorframe); ++ LISTEN_STATIC(&cursor->events.tablet_tool_proximity, tablettoolproximity); ++ LISTEN_STATIC(&cursor->events.tablet_tool_axis, tablettoolaxis); ++ LISTEN_STATIC(&cursor->events.tablet_tool_button, tablettoolbutton); ++ LISTEN_STATIC(&cursor->events.tablet_tool_tip, tablettooltip); + + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape); +@@ -2689,6 +2763,156 @@ tagmon(const Arg *arg) + setmon(sel, dirtomon(arg->i), 0); + } + ++void ++tabletapplymap(double x, double y, struct wlr_input_device *dev) ++{ ++ Client *p; ++ struct wlr_box geom = {0}; ++ if (tabletmaptosurface && tablet_curr_surface) { ++ toplevel_from_wlr_surface(tablet_curr_surface, &p, NULL); ++ if (p) { ++ for (; client_get_parent(p); p = client_get_parent(p)); ++ geom.x = p->geom.x + p->bw; ++ geom.y = p->geom.y + p->bw; ++ geom.width = p->geom.width - 2 * p->bw; ++ geom.height = p->geom.height - 2 * p->bw; ++ } ++ } ++ wlr_cursor_map_input_to_region(cursor, dev, &geom); ++ wlr_cursor_map_input_to_output(cursor, dev, selmon->wlr_output); ++} ++ ++void ++tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, ++ double x, double y, double dx, double dy) ++{ ++ struct wlr_surface *surface = NULL; ++ double sx, sy; ++ ++ if (!change_x && !change_y) ++ return; ++ ++ tabletapplymap(x, y, tablet->wlr_device); ++ ++ // TODO: apply constraints ++ switch (tablet_tool->wlr_tool->type) { ++ case WLR_TABLET_TOOL_TYPE_LENS: ++ case WLR_TABLET_TOOL_TYPE_MOUSE: ++ wlr_cursor_move(cursor, tablet->wlr_device, dx, dy); ++ break; ++ default: ++ wlr_cursor_warp_absolute(cursor, tablet->wlr_device, change_x ? x : NAN, change_y ? y : NAN); ++ break; ++ } ++ ++ motionnotify(0, NULL, 0, 0, 0, 0); ++ ++ xytonode(cursor->x, cursor->y, &surface, NULL, NULL, &sx, &sy); ++ if (surface && !wlr_surface_accepts_tablet_v2(tablet, surface)) ++ surface = NULL; ++ ++ if (surface != tablet_curr_surface) { ++ if (tablet_curr_surface) { ++ // TODO: wait until all buttons released before leaving ++ if (tablet_tool) ++ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); ++ if (tablet_pad) ++ wlr_tablet_v2_tablet_pad_notify_leave(tablet_pad, tablet_curr_surface); ++ wl_list_remove(&destroy_tablet_surface_listener.link); ++ } ++ if (surface) { ++ if (tablet_pad) ++ wlr_tablet_v2_tablet_pad_notify_enter(tablet_pad, tablet, surface); ++ if (tablet_tool) ++ wlr_tablet_v2_tablet_tool_notify_proximity_in(tablet_tool, tablet, surface); ++ wl_signal_add(&surface->events.destroy, &destroy_tablet_surface_listener); ++ } ++ tablet_curr_surface = surface; ++ } ++ ++ if (surface) ++ wlr_tablet_v2_tablet_tool_notify_motion(tablet_tool, sx, sy); ++} ++ ++void ++tablettoolproximity(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_proximity_event *event = data; ++ struct wlr_tablet_tool *tool = event->tool; ++ ++ if (!tablet_tool) { ++ tablet_tool = wlr_tablet_tool_create(tablet_mgr, seat, tool); ++ LISTEN_STATIC(&tablet_tool->wlr_tool->events.destroy, destroytablettool); ++ LISTEN_STATIC(&tablet_tool->events.set_cursor, setcursor); ++ } ++ ++ switch (event->state) { ++ case WLR_TABLET_TOOL_PROXIMITY_OUT: ++ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); ++ destroytabletsurfacenotify(NULL, NULL); ++ break; ++ case WLR_TABLET_TOOL_PROXIMITY_IN: ++ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0); ++ break; ++ } ++} ++ ++void ++tablettoolaxis(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_axis_event *event = data; ++ ++ tablettoolmotion(tablet_tool, ++ event->updated_axes & WLR_TABLET_TOOL_AXIS_X, ++ event->updated_axes & WLR_TABLET_TOOL_AXIS_Y, ++ event->x, event->y, event->dx, event->dy); ++ ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE) ++ wlr_tablet_v2_tablet_tool_notify_pressure(tablet_tool, event->pressure); ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE) ++ wlr_tablet_v2_tablet_tool_notify_distance(tablet_tool, event->distance); ++ if (event->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y)) ++ wlr_tablet_v2_tablet_tool_notify_tilt(tablet_tool, event->tilt_x, event->tilt_y); ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_ROTATION) ++ wlr_tablet_v2_tablet_tool_notify_rotation(tablet_tool, event->rotation); ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER) ++ wlr_tablet_v2_tablet_tool_notify_slider(tablet_tool, event->slider); ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL) ++ wlr_tablet_v2_tablet_tool_notify_wheel(tablet_tool, event->wheel_delta, 0); ++} ++ ++void ++tablettoolbutton(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_button_event *event = data; ++ wlr_tablet_v2_tablet_tool_notify_button(tablet_tool, event->button, ++ (enum zwp_tablet_pad_v2_button_state)event->state); ++} ++ ++void ++tablettooltip(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_tip_event *event = data; ++ ++ if (!tablet_curr_surface) { ++ struct wlr_pointer_button_event fakeptrbtnevent = { ++ .button = BTN_LEFT, ++ .state = event->state == WLR_TABLET_TOOL_TIP_UP ? ++ WL_POINTER_BUTTON_STATE_RELEASED : WL_POINTER_BUTTON_STATE_PRESSED, ++ .time_msec = event->time_msec, ++ }; ++ buttonpress(NULL, (void *)&fakeptrbtnevent); ++ } ++ ++ if (event->state == WLR_TABLET_TOOL_TIP_UP) { ++ wlr_tablet_v2_tablet_tool_notify_up(tablet_tool); ++ return; ++ } ++ ++ wlr_tablet_v2_tablet_tool_notify_down(tablet_tool); ++ wlr_tablet_tool_v2_start_implicit_grab(tablet_tool); ++} ++ + void + tile(Monitor *m) + { +-- +2.43.0 + diff --git a/dwl/dwl-patches/patches/tablet-input/tablet-input.patch b/dwl/dwl-patches/patches/tablet-input/tablet-input.patch new file mode 100755 index 0000000..e7d1211 --- /dev/null +++ b/dwl/dwl-patches/patches/tablet-input/tablet-input.patch @@ -0,0 +1,372 @@ +From 0659663b7eb9cafbd4f86779084765aa838e29cd Mon Sep 17 00:00:00 2001 +From: A Frederick Christensen +Date: Sat, 17 May 2025 23:26:15 -0500 +Subject: [PATCH] Add tablet input + +--- + Makefile | 6 +- + config.def.h | 1 + + dwl.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 237 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 578194f..e0d1835 100644 +--- a/Makefile ++++ b/Makefile +@@ -21,7 +21,8 @@ dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ + dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ +- wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ ++ tablet-v2-protocol.h + util.o: util.c util.h + + # wayland-scanner is a tool which generates C headers and rigging for Wayland +@@ -45,6 +46,9 @@ wlr-output-power-management-unstable-v1-protocol.h: + xdg-shell-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ ++tablet-v2-protocol.h: ++ $(WAYLAND_SCANNER) server-header \ ++ $(WAYLAND_PROTOCOLS)/unstable/tablet/tablet-unstable-v2.xml $@ + + config.h: + cp config.def.h $@ +diff --git a/config.def.h b/config.def.h +index 22d2171..3ad98ef 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -4,6 +4,7 @@ + ((hex >> 8) & 0xFF) / 255.0f, \ + (hex & 0xFF) / 255.0f } + /* appearance */ ++static const int tabletmaptosurface = 0; /* map tablet input to surface(1) or monitor(0) */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +diff --git a/dwl.c b/dwl.c +index 4816159..e8d36ac 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -51,6 +51,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -268,6 +271,7 @@ static void createnotify(struct wl_listener *listener, void *data); + static void createpointer(struct wlr_pointer *pointer); + static void createpointerconstraint(struct wl_listener *listener, void *data); + static void createpopup(struct wl_listener *listener, void *data); ++static void createtablet(struct wlr_input_device *device); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); +@@ -281,6 +285,9 @@ static void destroynotify(struct wl_listener *listener, void *data); + static void destroypointerconstraint(struct wl_listener *listener, void *data); + static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); ++static void destroytablet(struct wl_listener *listener, void *data); ++static void destroytabletsurfacenotify(struct wl_listener *listener, void *data); ++static void destroytablettool(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); +@@ -333,6 +340,11 @@ static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static void tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, double x, double y, double dx, double dy); ++static void tablettoolproximity(struct wl_listener *listener, void *data); ++static void tablettoolaxis(struct wl_listener *listener, void *data); ++static void tablettoolbutton(struct wl_listener *listener, void *data); ++static void tablettooltip(struct wl_listener *listener, void *data); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); +@@ -390,6 +402,13 @@ static struct wlr_pointer_constraint_v1 *active_constraint; + static struct wlr_cursor *cursor; + static struct wlr_xcursor_manager *cursor_mgr; + ++static struct wlr_tablet_manager_v2 *tablet_mgr; ++static struct wlr_tablet_v2_tablet *tablet = NULL; ++static struct wlr_tablet_v2_tablet_tool *tablet_tool = NULL; ++static struct wlr_tablet_v2_tablet_pad *tablet_pad = NULL; ++static struct wlr_surface *tablet_curr_surface = NULL; ++static struct wl_listener destroy_tablet_surface_listener = {.notify = destroytabletsurfacenotify}; ++ + static struct wlr_scene_rect *root_bg; + static struct wlr_session_lock_manager_v1 *session_lock_mgr; + static struct wlr_scene_rect *locked_bg; +@@ -412,6 +431,12 @@ static struct wl_listener cursor_button = {.notify = buttonpress}; + static struct wl_listener cursor_frame = {.notify = cursorframe}; + static struct wl_listener cursor_motion = {.notify = motionrelative}; + static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute}; ++static struct wl_listener tablet_device_destroy = {.notify = destroytablet}; ++static struct wl_listener tablet_tool_axis = {.notify = tablettoolaxis}; ++static struct wl_listener tablet_tool_button = {.notify = tablettoolbutton}; ++static struct wl_listener tablet_tool_destroy = {.notify = destroytablettool}; ++static struct wl_listener tablet_tool_proximity = {.notify = tablettoolproximity}; ++static struct wl_listener tablet_tool_tip = {.notify = tablettooltip}; + static struct wl_listener gpu_reset = {.notify = gpureset}; + static struct wl_listener layout_change = {.notify = updatemons}; + static struct wl_listener new_idle_inhibitor = {.notify = createidleinhibitor}; +@@ -1196,6 +1221,28 @@ createpopup(struct wl_listener *listener, void *data) + LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); + } + ++void ++createtablet(struct wlr_input_device *device) ++{ ++ if (!tablet) { ++ struct libinput_device *device_handle = NULL; ++ if (!wlr_input_device_is_libinput(device) || ++ !(device_handle = wlr_libinput_get_device_handle(device))) ++ return; ++ ++ tablet = wlr_tablet_create(tablet_mgr, seat, device); ++ wl_signal_add(&tablet->wlr_device->events.destroy, &tablet_device_destroy); ++ if (libinput_device_config_send_events_get_modes(device_handle)) { ++ libinput_device_config_send_events_set_mode(device_handle, send_events_mode); ++ wlr_cursor_attach_input_device(cursor, device); ++ } ++ } else if (device == tablet->wlr_device) { ++ wlr_log(WLR_ERROR, "createtablet: duplicate device"); ++ } else { ++ wlr_log(WLR_ERROR, "createtablet: already have one tablet"); ++ } ++} ++ + void + cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) + { +@@ -1380,6 +1427,27 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) + free(group); + } + ++void ++destroytablet(struct wl_listener *listener, void *data) ++{ ++ tablet = NULL; ++} ++ ++void ++destroytabletsurfacenotify(struct wl_listener *listener, void *data) ++{ ++ if (tablet_curr_surface) ++ wl_list_remove(&destroy_tablet_surface_listener.link); ++ tablet_curr_surface = NULL; ++} ++ ++void ++destroytablettool(struct wl_listener *listener, void *data) ++{ ++ destroytabletsurfacenotify(NULL, NULL); ++ tablet_tool = NULL; ++} ++ + Monitor * + dirtomon(enum wlr_direction dir) + { +@@ -1587,6 +1655,12 @@ inputdevice(struct wl_listener *listener, void *data) + case WLR_INPUT_DEVICE_POINTER: + createpointer(wlr_pointer_from_input_device(device)); + break; ++ case WLR_INPUT_DEVICE_TABLET: ++ createtablet(device); ++ break; ++ case WLR_INPUT_DEVICE_TABLET_PAD: ++ tablet_pad = wlr_tablet_pad_create(tablet_mgr, seat, device); ++ break; + default: + /* TODO handle other input device types */ + break; +@@ -2580,6 +2654,8 @@ setup(void) + + relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); + ++ tablet_mgr = wlr_tablet_v2_create(dpy); ++ + /* + * Creates a cursor, which is a wlroots utility for tracking the cursor + * image shown on screen. +@@ -2609,6 +2685,11 @@ setup(void) + wl_signal_add(&cursor->events.button, &cursor_button); + wl_signal_add(&cursor->events.axis, &cursor_axis); + wl_signal_add(&cursor->events.frame, &cursor_frame); ++ wl_signal_add(&cursor->events.tablet_tool_proximity, &tablet_tool_proximity); ++ wl_signal_add(&cursor->events.tablet_tool_axis, &tablet_tool_axis); ++ wl_signal_add(&cursor->events.tablet_tool_button, &tablet_tool_button); ++ wl_signal_add(&cursor->events.tablet_tool_tip, &tablet_tool_tip); ++ + + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape); +@@ -2704,6 +2785,159 @@ tagmon(const Arg *arg) + setmon(sel, dirtomon(arg->i), 0); + } + ++void ++tabletapplymap(double x, double y, struct wlr_input_device *dev) ++{ ++ Client *p; ++ struct wlr_box geom = {0}; ++ if (tabletmaptosurface && tablet_curr_surface) { ++ toplevel_from_wlr_surface(tablet_curr_surface, &p, NULL); ++ if (p) { ++ for (; client_get_parent(p); p = client_get_parent(p)); ++ geom.x = p->geom.x + p->bw; ++ geom.y = p->geom.y + p->bw; ++ geom.width = p->geom.width - 2 * p->bw; ++ geom.height = p->geom.height - 2 * p->bw; ++ } ++ } ++ wlr_cursor_map_input_to_region(cursor, dev, &geom); ++ wlr_cursor_map_input_to_output(cursor, dev, selmon->wlr_output); ++} ++ ++void ++tablettoolmotion(struct wlr_tablet_v2_tablet_tool *tool, bool change_x, bool change_y, ++ double x, double y, double dx, double dy) ++{ ++ struct wlr_surface *surface = NULL; ++ double sx, sy; ++ ++ if (!change_x && !change_y) ++ return; ++ ++ tabletapplymap(x, y, tablet->wlr_device); ++ ++ // TODO: apply constraints ++ switch (tablet_tool->wlr_tool->type) { ++ case WLR_TABLET_TOOL_TYPE_LENS: ++ case WLR_TABLET_TOOL_TYPE_MOUSE: ++ wlr_cursor_move(cursor, tablet->wlr_device, dx, dy); ++ break; ++ default: ++ wlr_cursor_warp_absolute(cursor, tablet->wlr_device, change_x ? x : NAN, change_y ? y : NAN); ++ break; ++ } ++ ++ motionnotify(0, NULL, 0, 0, 0, 0); ++ ++ xytonode(cursor->x, cursor->y, &surface, NULL, NULL, &sx, &sy); ++ if (surface && !wlr_surface_accepts_tablet_v2(surface, tablet)) ++ surface = NULL; ++ ++ if (surface != tablet_curr_surface) { ++ if (tablet_curr_surface) { ++ // TODO: wait until all buttons released before leaving ++ if (tablet_tool) ++ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); ++ if (tablet_pad) ++ wlr_tablet_v2_tablet_pad_notify_leave(tablet_pad, tablet_curr_surface); ++ wl_list_remove(&destroy_tablet_surface_listener.link); ++ } ++ if (surface) { ++ if (tablet_pad) ++ wlr_tablet_v2_tablet_pad_notify_enter(tablet_pad, tablet, surface); ++ if (tablet_tool) ++ wlr_tablet_v2_tablet_tool_notify_proximity_in(tablet_tool, tablet, surface); ++ wl_signal_add(&surface->events.destroy, &destroy_tablet_surface_listener); ++ } ++ tablet_curr_surface = surface; ++ } ++ ++ if (surface) ++ wlr_tablet_v2_tablet_tool_notify_motion(tablet_tool, sx, sy); ++} ++ ++void ++tablettoolproximity(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_proximity_event *event = data; ++ struct wlr_tablet_tool *tool = event->tool; ++ ++ if (!tablet_tool) { ++ tablet_tool = wlr_tablet_tool_create(tablet_mgr, seat, tool); ++ wl_signal_add(&tablet_tool->wlr_tool->events.destroy, &tablet_tool_destroy); ++ wl_signal_add(&tablet_tool->events.set_cursor, &request_cursor); ++ } ++ ++ switch (event->state) { ++ case WLR_TABLET_TOOL_PROXIMITY_OUT: ++ wlr_tablet_v2_tablet_tool_notify_proximity_out(tablet_tool); ++ destroytabletsurfacenotify(NULL, NULL); ++ break; ++ case WLR_TABLET_TOOL_PROXIMITY_IN: ++ tablettoolmotion(tablet_tool, true, true, event->x, event->y, 0, 0); ++ break; ++ } ++} ++ ++void ++tablettoolaxis(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_axis_event *event = data; ++ ++ tablettoolmotion(tablet_tool, ++ event->updated_axes & WLR_TABLET_TOOL_AXIS_X, ++ event->updated_axes & WLR_TABLET_TOOL_AXIS_Y, ++ event->x, event->y, event->dx, event->dy); ++ ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE) ++ wlr_tablet_v2_tablet_tool_notify_pressure(tablet_tool, event->pressure); ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE) ++ wlr_tablet_v2_tablet_tool_notify_distance(tablet_tool, event->distance); ++ if (event->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y)) ++ { ++ printf("DEBUGGING: In axis event handling\n"); ++ wlr_tablet_v2_tablet_tool_notify_tilt(tablet_tool, event->tilt_x, event->tilt_y); ++ } ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_ROTATION) ++ wlr_tablet_v2_tablet_tool_notify_rotation(tablet_tool, event->rotation); ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER) ++ wlr_tablet_v2_tablet_tool_notify_slider(tablet_tool, event->slider); ++ if (event->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL) ++ wlr_tablet_v2_tablet_tool_notify_wheel(tablet_tool, event->wheel_delta, 0); ++} ++ ++void ++tablettoolbutton(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_button_event *event = data; ++ wlr_tablet_v2_tablet_tool_notify_button(tablet_tool, event->button, ++ (enum zwp_tablet_pad_v2_button_state)event->state); ++} ++ ++void ++tablettooltip(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tablet_tool_tip_event *event = data; ++ ++ if (!tablet_curr_surface) { ++ struct wlr_pointer_button_event fakeptrbtnevent = { ++ .button = BTN_LEFT, ++ .state = event->state == WLR_TABLET_TOOL_TIP_UP ? ++ WL_POINTER_BUTTON_STATE_RELEASED : WL_POINTER_BUTTON_STATE_PRESSED, ++ .time_msec = event->time_msec, ++ }; ++ buttonpress(NULL, (void *)&fakeptrbtnevent); ++ } ++ ++ if (event->state == WLR_TABLET_TOOL_TIP_UP) { ++ wlr_tablet_v2_tablet_tool_notify_up(tablet_tool); ++ return; ++ } ++ ++ wlr_tablet_v2_tablet_tool_notify_down(tablet_tool); ++ wlr_tablet_tool_v2_start_implicit_grab(tablet_tool); ++} ++ + void + tile(Monitor *m) + { +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/tagshift/README.md b/dwl/dwl-patches/patches/tagshift/README.md new file mode 100755 index 0000000..e3d7a03 --- /dev/null +++ b/dwl/dwl-patches/patches/tagshift/README.md @@ -0,0 +1,10 @@ +### Description +Port of the [tagshift](https://dwm.suckless.org/patches/tagshift/) patch into dwl. + +Allows a user to change his view and/or focused client into the next or previous tag. + +### Download +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/tagshift/tagshift.patch) +### Authors +- [h3nc4](https://codeberg.org/h3nc4) + me@h3nc4.com diff --git a/dwl/dwl-patches/patches/tagshift/tagshift.patch b/dwl/dwl-patches/patches/tagshift/tagshift.patch new file mode 100755 index 0000000..fac6033 --- /dev/null +++ b/dwl/dwl-patches/patches/tagshift/tagshift.patch @@ -0,0 +1,83 @@ +From 938c63ad0a8a706fba0b4db1c66397e9defdcb92 Mon Sep 17 00:00:00 2001 +From: h3nc4 +Date: Mon, 17 Mar 2025 17:38:22 -0300 +Subject: [PATCH] port the tagshift patch from dwm + +--- + config.def.h | 4 ++++ + dwl.c | 37 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 41 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..72dbaa1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -131,6 +131,10 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, ++ { MODKEY, XKB_KEY_Left, shiftview, {.i = -1 } }, ++ { MODKEY, XKB_KEY_Right, shiftview, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, shifttag, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, shifttag, {.i = +1 } }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, +diff --git a/dwl.c b/dwl.c +index cf3ef70..be1e89e 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -333,6 +333,8 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); ++static void shiftview(const Arg *arg); ++static void shifttag(const Arg *arg); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -2646,6 +2648,41 @@ setup(void) + #endif + } + ++void ++shiftview(const Arg *arg) ++{ ++ Arg a; ++ int nextseltags, curseltags = selmon->tagset[selmon->seltags]; ++ if (arg->i > 0) // left circular shift ++ nextseltags = (curseltags << arg->i) | (curseltags >> (TAGCOUNT - arg->i)); ++ else // right circular shift ++ nextseltags = curseltags >> (-arg->i) | (curseltags << (TAGCOUNT + arg->i)); ++ ++ a.i = nextseltags; // Change view to the new tag ++ view(&a); ++} ++ ++void ++shifttag(const Arg *arg) ++{ ++ Arg a; ++ int nextseltags, curseltags = selmon->tagset[selmon->seltags]; ++ Client *sel = focustop(selmon); ++ if (!sel) ++ return; ++ if (arg->i > 0) // left circular shift ++ nextseltags = (curseltags << arg->i) | (curseltags >> (TAGCOUNT - arg->i)); ++ else // right circular shift ++ nextseltags = curseltags >> (-arg->i) | (curseltags << (TAGCOUNT + arg->i)); ++ ++ sel->tags = nextseltags & TAGMASK;// Apply new tag to the client ++ a.i = nextseltags; // Change view to the new tag ++ view(&a); ++ ++ arrange(selmon); ++ printstatus(); // change to 'drawbars();' if using "bars" patch ++} ++ + void + spawn(const Arg *arg) + { +-- +2.47.2 + diff --git a/dwl/dwl-patches/patches/tearing/README.md b/dwl/dwl-patches/patches/tearing/README.md new file mode 100755 index 0000000..45efbf9 --- /dev/null +++ b/dwl/dwl-patches/patches/tearing/README.md @@ -0,0 +1,17 @@ +### Description +This patch adds support for tearing protocol. To get it working `export WLR_DRM_NO_ATOMIC=1` is probably required. +Some apps would send ASYNC hint and tearing will "just work", otherwise it's possible to force specified clients to tear with a rule. + +Set rules in the config.h (exact string match): +``` +static const ForceTearingRule force_tearing[] = { + {.title = "", .appid = "hl_linux"}, + {.title = "Warcraft III", .appid = ""}, + {.title = "", .appid = "gamescope"}, +}; +``` +### Download +- [git branch](https://codeberg.org/korei999/dwl/src/branch/tearing) +- [2025-04-22](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tearing/tearing.patch) +### Authors +- [korei999](https://codeberg.org/korei999) diff --git a/dwl/dwl-patches/patches/tearing/tearing.patch b/dwl/dwl-patches/patches/tearing/tearing.patch new file mode 100755 index 0000000..feea1fd --- /dev/null +++ b/dwl/dwl-patches/patches/tearing/tearing.patch @@ -0,0 +1,362 @@ +From c5216442cfb22eed7c2d4196f46c9ad8db3a5425 Mon Sep 17 00:00:00 2001 +From: korei999 +Date: Sun, 2 Feb 2025 13:44:41 +0200 +Subject: [PATCH] implement tearing protocol + +--- + Makefile | 5 +- + config.def.h | 8 +++ + dwl.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++---- + 3 files changed, 174 insertions(+), 15 deletions(-) + +diff --git a/Makefile b/Makefile +index 578194f..7d24970 100644 +--- a/Makefile ++++ b/Makefile +@@ -21,7 +21,7 @@ dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ + dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ +- wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h tearing-control-v1-protocol.h + util.o: util.c util.h + + # wayland-scanner is a tool which generates C headers and rigging for Wayland +@@ -45,6 +45,9 @@ wlr-output-power-management-unstable-v1-protocol.h: + xdg-shell-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ ++tearing-control-v1-protocol.h: ++ $(WAYLAND_SCANNER) server-header \ ++ $(WAYLAND_PROTOCOLS)/staging/tearing-control/tearing-control-v1.xml $@ + + config.h: + cp config.def.h $@ +diff --git a/config.def.h b/config.def.h +index 22d2171..52d38d3 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -28,6 +28,14 @@ static const Rule rules[] = { + { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ + }; + ++/* tearing */ ++static int tearing_allowed = 1; ++static const ForceTearingRule force_tearing[] = { ++ {.title = "", .appid = "hl_linux"}, ++ {.title = "Warcraft III", .appid = ""}, ++ {.title = "", .appid = "gamescope"}, ++}; ++ + /* layout(s) */ + static const Layout layouts[] = { + /* symbol arrange function */ +diff --git a/dwl.c b/dwl.c +index 4816159..747e16f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -86,6 +87,11 @@ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ + ++typedef struct ForceTearingRule { ++ const char* title; ++ const char* appid; ++} ForceTearingRule; ++ + typedef union { + int i; + uint32_t ui; +@@ -139,6 +145,7 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ enum wp_tearing_control_v1_presentation_hint tearing_hint; + } Client; + + typedef struct { +@@ -239,6 +246,17 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++typedef struct TearingController { ++ struct wlr_tearing_control_v1 *tearing_control; ++ struct wl_listener set_hint; ++ struct wl_listener destroy; ++} TearingController; ++ ++typedef struct SendFrameDoneData { ++ struct timespec when; ++ struct Monitor *mon; ++} SendFrameDoneData; ++ + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -305,6 +323,7 @@ static void motionnotify(uint32_t time, struct wlr_input_device *device, double + double sy, double sx_unaccel, double sy_unaccel); + static void motionrelative(struct wl_listener *listener, void *data); + static void moveresize(const Arg *arg); ++static int moncantear(Monitor* m); + static void outputmgrapply(struct wl_listener *listener, void *data); + static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); + static void outputmgrtest(struct wl_listener *listener, void *data); +@@ -319,6 +338,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void sendframedoneiterator(struct wlr_scene_buffer *buffer, int x, int y, void *user_data); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -333,6 +353,9 @@ static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static void tearingcontrollersethint(struct wl_listener *listener, void *data); ++static void tearingcontrollerdestroy(struct wl_listener *listener, void *data); ++static void tearingnewhint(struct wl_listener *listener, void *data); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); +@@ -395,6 +418,8 @@ static struct wlr_session_lock_manager_v1 *session_lock_mgr; + static struct wlr_scene_rect *locked_bg; + static struct wlr_session_lock_v1 *cur_lock; + ++static struct wlr_tearing_control_manager_v1 *tearing_control_v1; ++ + static struct wlr_seat *seat; + static KeyboardGroup *kb_group; + static unsigned int cursor_mode; +@@ -435,6 +460,7 @@ static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape}; + static struct wl_listener request_start_drag = {.notify = requeststartdrag}; + static struct wl_listener start_drag = {.notify = startdrag}; + static struct wl_listener new_session_lock = {.notify = locksession}; ++static struct wl_listener tearing_control_new_object = {.notify = tearingnewhint}; + + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); +@@ -779,6 +805,7 @@ cleanuplisteners(void) + wl_list_remove(&request_start_drag.link); + wl_list_remove(&start_drag.link); + wl_list_remove(&new_session_lock.link); ++ wl_list_remove(&tearing_control_new_object.link); + #ifdef XWAYLAND + wl_list_remove(&new_xwayland_surface.link); + wl_list_remove(&xwayland_ready.link); +@@ -1563,6 +1590,63 @@ handlesig(int signo) + quit(NULL); + } + ++void ++tearingcontrollersethint(struct wl_listener *listener, void *data) ++{ ++ Client *c = NULL, *i = NULL; ++ TearingController *controller = wl_container_of(listener, controller, set_hint); ++ ++ struct wlr_xdg_surface *surface = wlr_xdg_surface_try_from_wlr_surface(controller->tearing_control->surface); ++#ifdef XWAYLAND ++ struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_try_from_wlr_surface(controller->tearing_control->surface); ++#endif ++ ++ wl_list_for_each(i, &fstack, flink) { ++ if (i->surface.xdg == surface ++#ifdef XWAYLAND ++ || i->surface.xwayland == xsurface ++#endif ++ ) { ++ c = i; ++ break; ++ } ++ } ++ ++ if (c) { ++ enum wp_tearing_control_v1_presentation_hint hint = controller->tearing_control->current; ++ fprintf( ++ stderr, "TEARING: found surface: %p(appid: '%s', title: '%s'), hint: %d(%s)\n", ++ (void*)c, client_get_appid(c), client_get_title(c), hint, hint ? "ASYNC" : "VSYNC" ++ ); ++ c->tearing_hint = controller->tearing_control->current; ++ } ++} ++ ++void ++tearingcontrollerdestroy(struct wl_listener *listener, void *data) ++{ ++ TearingController *controller = wl_container_of(listener, controller, destroy); ++ ++ wl_list_remove(&controller->set_hint.link); ++ wl_list_remove(&controller->destroy.link); ++ free(controller); ++} ++ ++void ++tearingnewhint(struct wl_listener *listener, void *data) ++{ ++ struct wlr_tearing_control_v1 *tearing_control = data; ++ TearingController *controller = ecalloc(1, sizeof(*controller)); ++ ++ controller->tearing_control = tearing_control; ++ ++ controller->set_hint.notify = tearingcontrollersethint; ++ wl_signal_add(&tearing_control->events.set_hint, &controller->set_hint); ++ ++ controller->destroy.notify = tearingcontrollerdestroy; ++ wl_signal_add(&tearing_control->events.destroy, &controller->destroy); ++} ++ + void + incnmaster(const Arg *arg) + { +@@ -1730,6 +1814,35 @@ locksession(struct wl_listener *listener, void *data) + wlr_session_lock_v1_send_locked(session_lock); + } + ++static inline void ++forcetearingrule(Client *c) ++{ ++ int success = 0; ++ const char* appid = client_get_appid(c); ++ const char* title = client_get_title(c); ++ ++ for (unsigned i = 0; i < LENGTH(force_tearing); ++i) { ++ if (appid) { ++ if (strcmp(force_tearing[i].appid, appid) == 0) { ++ success = 1; ++ break; ++ } ++ } ++ ++ if (title) { ++ if (strcmp(force_tearing[i].title, title) == 0) { ++ success = 1; ++ break; ++ } ++ } ++ } ++ ++ if (success) { ++ c->tearing_hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC; ++ fprintf(stderr, "Forcing tearing for appid: '%s', title: '%s'\n", appid, title); ++ } ++} ++ + void + mapnotify(struct wl_listener *listener, void *data) + { +@@ -1739,6 +1852,8 @@ mapnotify(struct wl_listener *listener, void *data) + Monitor *m; + int i; + ++ forcetearingrule(c); ++ + /* Create scene tree for this client and its border */ + c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); + /* Enabled later by a call to arrange() */ +@@ -1977,6 +2092,13 @@ moveresize(const Arg *arg) + } + } + ++int ++moncantear(Monitor* m) ++{ ++ Client *c = focustop(m); ++ return (c && c->isfullscreen && c->tearing_hint); /* 1 == ASYNC */ ++} ++ + void + outputmgrapply(struct wl_listener *listener, void *data) + { +@@ -2147,27 +2269,40 @@ quit(const Arg *arg) + void + rendermon(struct wl_listener *listener, void *data) + { +- /* This function is called every time an output is ready to display a frame, +- * generally at the output's refresh rate (e.g. 60Hz). */ + Monitor *m = wl_container_of(listener, m, frame); +- Client *c; ++ struct wlr_scene_output *scene_output = m->scene_output; + struct wlr_output_state pending = {0}; +- struct timespec now; ++ SendFrameDoneData frame_done_data = {0}; + +- /* Render if no XDG clients have an outstanding resize and are visible on +- * this monitor. */ +- wl_list_for_each(c, &clients, link) { +- if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) +- goto skip; ++ m->wlr_output->frame_pending = false; ++ ++ if (!wlr_scene_output_needs_frame(scene_output)) { ++ goto skip; + } + +- wlr_scene_output_commit(m->scene_output, NULL); ++ wlr_output_state_init(&pending); ++ if (!wlr_scene_output_build_state(m->scene_output, &pending, NULL)) { ++ goto skip; ++ } ++ ++ if (tearing_allowed && moncantear(m)) { ++ pending.tearing_page_flip = true; ++ ++ if (!wlr_output_test_state(m->wlr_output, &pending)) { ++ fprintf(stderr, "Output test failed on '%s', retrying without tearing page-flip\n", m->wlr_output->name); ++ pending.tearing_page_flip = false; ++ } ++ } ++ ++ if (!wlr_output_commit_state(m->wlr_output, &pending)) ++ fprintf(stderr, "Page-flip failed on output %s", m->wlr_output->name); + +-skip: +- /* Let clients know a frame has been rendered */ +- clock_gettime(CLOCK_MONOTONIC, &now); +- wlr_scene_output_send_frame_done(m->scene_output, &now); + wlr_output_state_finish(&pending); ++ ++skip: ++ clock_gettime(CLOCK_MONOTONIC, &frame_done_data.when); ++ frame_done_data.mon = m; ++ wlr_scene_output_for_each_buffer(m->scene_output, sendframedoneiterator, &frame_done_data); + } + + void +@@ -2291,6 +2426,16 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++void ++sendframedoneiterator(struct wlr_scene_buffer *buffer, int x, int y, void *user_data) ++{ ++ SendFrameDoneData *data = user_data; ++ if (buffer->primary_output != data->mon->scene_output) ++ return; ++ ++ wlr_scene_buffer_send_frame_done(buffer, &data->when); ++} ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2641,6 +2786,9 @@ setup(void) + wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); + wl_signal_add(&output_mgr->events.test, &output_mgr_test); + ++ tearing_control_v1 = wlr_tearing_control_manager_v1_create(dpy, 1); ++ wl_signal_add(&tearing_control_v1->events.new_object, &tearing_control_new_object); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/titleurgent/README.md b/dwl/dwl-patches/patches/titleurgent/README.md new file mode 100755 index 0000000..aa4c99d --- /dev/null +++ b/dwl/dwl-patches/patches/titleurgent/README.md @@ -0,0 +1,11 @@ +### Description +Whenever a client title changes set the client's urgent flag. + +Hacky solution I use to deal with qutebrowser not setting urgent flag when a new tab is opened. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/titleurgent) +- [2024-01-02](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/titleurgent/titleurgent.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/titleurgent/titleurgent.patch b/dwl/dwl-patches/patches/titleurgent/titleurgent.patch new file mode 100755 index 0000000..9a73f66 --- /dev/null +++ b/dwl/dwl-patches/patches/titleurgent/titleurgent.patch @@ -0,0 +1,80 @@ +From ab002204c8bb7c8c36828aeb89ef3cf9b0447ea6 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Fri, 29 Dec 2023 19:02:11 +1000 +Subject: [PATCH] titleurgent + +--- + config.def.h | 8 +++++--- + dwl.c | 8 ++++++++ + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a784eb4f..a5000901 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -21,10 +21,12 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + static int log_level = WLR_ERROR; + + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating titleurgent monitor */ + /* examples: */ +- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ +- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "Gimp_EXAMPLE", NULL, 0, 1, 0, -1 }, /* Start on currently visible tags floating, not tiled */ ++ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, -1 }, /* Start on ONLY tag "9" */ ++ { "org.qutebrowser.qutebrowser_EXAMPLE", ++ NULL, 0, 0, 1, -1 }, + }; + + /* layout(s) */ +diff --git a/dwl.c b/dwl.c +index 6f041a0d..9486c435 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -138,6 +138,7 @@ typedef struct { + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; ++ int titleurgent; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -228,6 +229,7 @@ typedef struct { + const char *title; + uint32_t tags; + int isfloating; ++ int titleurgent; + int monitor; + } Rule; + +@@ -455,6 +457,7 @@ applyrules(Client *c) + Monitor *mon = selmon, *m; + + c->isfloating = client_is_float_type(c); ++ c->titleurgent = 0; + if (!(appid = client_get_appid(c))) + appid = broken; + if (!(title = client_get_title(c))) +@@ -464,6 +467,7 @@ applyrules(Client *c) + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; ++ c->titleurgent = r->titleurgent; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { +@@ -2821,6 +2825,10 @@ updatetitle(struct wl_listener *listener, void *data) + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) + printstatus(); ++ else if (c->titleurgent) { ++ c->isurgent = 1; ++ printstatus(); ++ } + } + + void +-- +2.45.1 + diff --git a/dwl/dwl-patches/patches/tmux-borders/README.md b/dwl/dwl-patches/patches/tmux-borders/README.md new file mode 100755 index 0000000..e203e76 --- /dev/null +++ b/dwl/dwl-patches/patches/tmux-borders/README.md @@ -0,0 +1,15 @@ +### Description +This patch replaces the window borders of tiled windows with borders that are similar to those found in tmux. The result is that there are no more unnecessary borders along the monitor edges in tiled mode. Borders of floating windows are not affected. + +### Preview +![two clients](screenshot1.png) + +![three clients](screenshot2.png) + +### Download +- [git branch](/kerberoge/dwl/src/branch/tmux-borders) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/tmux-borders/tmux-borders-0.7.patch) + +### Authors +- [kerberoge](https://codeberg.org/kerberoge)\ + kerberoge at [dwl Discord](https://discord.gg/jJxZnrGPWN) diff --git a/dwl/dwl-patches/patches/tmux-borders/screenshot1.png b/dwl/dwl-patches/patches/tmux-borders/screenshot1.png new file mode 100755 index 0000000..ed12cc5 Binary files /dev/null and b/dwl/dwl-patches/patches/tmux-borders/screenshot1.png differ diff --git a/dwl/dwl-patches/patches/tmux-borders/screenshot2.png b/dwl/dwl-patches/patches/tmux-borders/screenshot2.png new file mode 100755 index 0000000..83ae2e2 Binary files /dev/null and b/dwl/dwl-patches/patches/tmux-borders/screenshot2.png differ diff --git a/dwl/dwl-patches/patches/tmux-borders/tmux-borders-0.7.patch b/dwl/dwl-patches/patches/tmux-borders/tmux-borders-0.7.patch new file mode 100755 index 0000000..f6839a8 --- /dev/null +++ b/dwl/dwl-patches/patches/tmux-borders/tmux-borders-0.7.patch @@ -0,0 +1,489 @@ +From 464259603cb3b7346670cc33fd9afa0f8fe0cd49 Mon Sep 17 00:00:00 2001 +From: kerberoge +Date: Sun, 1 Jun 2025 17:03:09 +0200 +Subject: [PATCH 1/1] Created tmux-borders patch for stock dwl + +--- + client.h | 6 ++ + dwl.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 280 insertions(+), 24 deletions(-) + +diff --git a/client.h b/client.h +index 42f225f..007ab7d 100644 +--- a/client.h ++++ b/client.h +@@ -291,6 +291,12 @@ client_is_unmanaged(Client *c) + return 0; + } + ++static inline int ++client_needs_borders(Client *c) ++{ ++ return c->isfloating || !c->mon->lt[c->mon->sellt]->arrange; ++} ++ + static inline void + client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb) + { +diff --git a/dwl.c b/dwl.c +index a2711f6..c092c0e 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -191,6 +191,7 @@ struct Monitor { + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ ++ struct wlr_scene_tree *borders, *fborders, *uborders; + struct wl_listener frame; + struct wl_listener destroy; + struct wl_listener request_state; +@@ -255,10 +256,12 @@ static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); + static void cleanup(void); + static void cleanupmon(struct wl_listener *listener, void *data); ++static int clientindex(Monitor *m, Client *c); + static void closemon(Monitor *m); + static void commitlayersurfacenotify(struct wl_listener *listener, void *data); + static void commitnotify(struct wl_listener *listener, void *data); + static void commitpopup(struct wl_listener *listener, void *data); ++static int countclients(Monitor *m); + static void createdecoration(struct wl_listener *listener, void *data); + static void createidleinhibitor(struct wl_listener *listener, void *data); + static void createkeyboard(struct wlr_keyboard *keyboard); +@@ -273,6 +276,7 @@ static void createpopup(struct wl_listener *listener, void *data); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); ++static void destroyborders(struct wlr_scene_tree *t); + static void destroydecoration(struct wl_listener *listener, void *data); + static void destroydragicon(struct wl_listener *listener, void *data); + static void destroyidleinhibitor(struct wl_listener *listener, void *data); +@@ -285,6 +289,13 @@ static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static void destroykeyboardgroup(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawclientborders(struct wlr_scene_tree *t, Client *c, ++ int cidx, int n, const float color[static 4]); ++static void drawrect(struct wlr_scene_tree *t, ++ int x, int y, int w, int h, const float color[static 4]); ++static void drawborders(Monitor *m); ++static void drawfborders(Monitor *m); ++static void drawuborders(Monitor *m); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -517,6 +528,11 @@ arrange(Monitor *m) + + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); ++ ++ drawborders(m); ++ drawuborders(m); ++ drawfborders(m); ++ + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + } +@@ -721,10 +737,34 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_scene_output_destroy(m->scene_output); + + closemon(m); ++ wlr_scene_node_destroy(&m->borders->node); ++ wlr_scene_node_destroy(&m->fborders->node); ++ wlr_scene_node_destroy(&m->uborders->node); + wlr_scene_node_destroy(&m->fullscreen_bg->node); + free(m); + } + ++int ++clientindex(Monitor *m, Client *c) ++{ ++ unsigned int i = 0; ++ Client *ci; ++ ++ if (!c || m->lt[m->sellt]->arrange != tile) ++ return -1; ++ ++ wl_list_for_each(ci, &clients, link) { ++ if (VISIBLEON(ci, m) && !ci->isfloating && !ci->isfullscreen) { ++ if (ci == c) ++ return i; ++ else ++ i++; ++ } ++ } ++ ++ return -1; ++} ++ + void + closemon(Monitor *m) + { +@@ -743,6 +783,10 @@ closemon(Monitor *m) + selmon = NULL; + } + ++ destroyborders(m->borders); ++ destroyborders(m->fborders); ++ destroyborders(m->uborders); ++ + wl_list_for_each(c, &clients, link) { + if (c->isfloating && c->geom.x > m->m.width) + resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y, +@@ -849,6 +893,19 @@ commitpopup(struct wl_listener *listener, void *data) + wl_list_remove(&listener->link); + } + ++int ++countclients(Monitor *m) ++{ ++ unsigned int n = 0; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) ++ n++; ++ ++ return n; ++} ++ + void + createdecoration(struct wl_listener *listener, void *data) + { +@@ -985,6 +1042,9 @@ createmon(struct wl_listener *listener, void *data) + + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; ++ m->borders = wlr_scene_tree_create(layers[LyrTile]); ++ m->fborders = wlr_scene_tree_create(layers[LyrTile]); ++ m->uborders = wlr_scene_tree_create(layers[LyrTile]); + + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); +@@ -1171,6 +1231,15 @@ cursorwarptohint(void) + } + } + ++void ++destroyborders(struct wlr_scene_tree *t) ++{ ++ struct wlr_scene_node *node, *tmp; ++ ++ wl_list_for_each_safe(node, tmp, &t->children, link) ++ wlr_scene_node_destroy(node); ++} ++ + void + destroydecoration(struct wl_listener *listener, void *data) + { +@@ -1336,6 +1405,154 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++void ++drawclientborders(struct wlr_scene_tree *t, Client *c, int cidx, int n, const float color[static 4]) ++{ ++ Monitor *m; ++ int mw, x, y, w, h; ++ ++ m = c->mon; ++ mw = (int)round(m->w.width * m->mfact - 0.5 * borderpx); ++ ++ if (m->nmaster == 1 && n == 2) { ++ /* Half vertical center line */ ++ y = m->w.y + (cidx == 1 ? m->w.height / 2 : 0); ++ h = (int)round(0.5 * m->w.height); ++ drawrect(t, m->w.x + mw, y, borderpx, h, color); ++ } else if (m->nmaster != 1 && n == 2) { ++ /* Half horizontal center line */ ++ x = m->w.x + (cidx == 1 ? m->w.width / 2 : 0); ++ y = m->w.y + (int)round(0.5 * m->w.height - 0.5 * borderpx); ++ w = (int)round(0.5 * m->w.width); ++ drawrect(t, x, y, w, borderpx, color); ++ } else { ++ if (m->nmaster && n > m->nmaster) ++ /* Vertical line next to client */ ++ drawrect(t, m->w.x + mw, c->geom.y, borderpx, c->geom.height, color); ++ ++ if (n > m->nmaster && cidx < m->nmaster) { ++ /* Left half */ ++ x = m->w.x; ++ w = mw + borderpx; ++ } else if (m->nmaster && cidx >= m->nmaster) { ++ /* Right half */ ++ x = m->w.x + mw; ++ w = m->w.width - mw; ++ } else { ++ /* Full width */ ++ x = m->w.x; ++ w = m->w.width; ++ } ++ ++ if ((cidx > 0 && cidx < m->nmaster) || (cidx > m->nmaster)) ++ /* Line above client */ ++ drawrect(t, x, c->geom.y - borderpx, w, borderpx, color); ++ ++ if ((cidx < m->nmaster - 1) || (cidx >= m->nmaster && cidx < n - 1)) ++ /* Line below client */ ++ drawrect(t, x, c->geom.y + c->geom.height, w, borderpx, color); ++ } ++} ++ ++void ++drawrect(struct wlr_scene_tree *t, int x, int y, int w, int h, const float color[static 4]) ++{ ++ struct wlr_scene_rect *r; ++ ++ r = wlr_scene_rect_create(t, w, h, color); ++ wlr_scene_node_set_position(&r->node, x, y); ++} ++ ++void ++drawborders(Monitor *m) ++{ ++ int n, i; ++ int mw, tw, my = 0, ty = 0; ++ ++ if (!m) ++ return; ++ ++ destroyborders(m->borders); ++ n = countclients(m); ++ ++ if (n <= 1 || m->lt[m->sellt]->arrange != tile) ++ return; ++ ++ if (m->nmaster > 0 && n > m->nmaster) ++ mw = (int)round(m->w.width * m->mfact - 0.5 * borderpx); ++ else if (n <= m->nmaster) ++ mw = m->w.width; ++ else ++ mw = 0; ++ ++ if (mw > 0) ++ tw = m->w.width - mw - borderpx; ++ else ++ tw = m->w.width; ++ ++ /* Vertical center line */ ++ if (mw > 0 && mw < m->w.width) ++ drawrect(m->borders, m->w.x + mw, m->w.y, borderpx, m->w.height, bordercolor); ++ ++ /* Lines between master clients */ ++ for (i = 0; i < MIN(n, m->nmaster) - 1; i++) { ++ my += (m->w.height - my - borderpx * (MIN(n, m->nmaster) - i - 1)) ++ / (MIN(n, m->nmaster) - i); ++ drawrect(m->borders, m->w.x, m->w.y + my, mw, borderpx, bordercolor); ++ my += borderpx; ++ } ++ ++ /* Lines between clients on the stack */ ++ for (i = m->nmaster; i < n - 1; i++) { ++ ty += (m->w.height - ty - borderpx * (n - i - 1)) / (n - i); ++ drawrect(m->borders, m->m.x + (mw ? mw + borderpx : 0), m->w.y + ty, ++ tw, borderpx, bordercolor); ++ ty += borderpx; ++ } ++} ++ ++void ++drawfborders(Monitor *m) ++{ ++ Client *fc; ++ int n, cidx; ++ ++ if (!m) ++ return; ++ ++ destroyborders(m->fborders); ++ n = countclients(m); ++ fc = focustop(m); ++ cidx = clientindex(m, fc); ++ ++ if (n <= 1 || cidx == -1) ++ return; ++ ++ drawclientborders(m->fborders, fc, cidx, n, focuscolor); ++} ++ ++void ++drawuborders(Monitor *m) ++{ ++ Client *c; ++ int n, cidx; ++ ++ if (!m) ++ return; ++ ++ destroyborders(m->uborders); ++ n = countclients(m); ++ ++ if (n <= 1) ++ return; ++ ++ wl_list_for_each(c, &clients, link) { ++ cidx = clientindex(m, c); ++ if (cidx != -1 && c->isurgent) ++ drawclientborders(m->uborders, c, cidx, n, urgentcolor); ++ } ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1366,12 +1583,15 @@ focusclient(Client *c, int lift) + wl_list_insert(&fstack, &c->flink); + selmon = c->mon; + c->isurgent = 0; ++ drawuborders(c->mon); + client_restack_surface(c); + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ +- if (!exclusive_focus && !seat->drag) ++ if (!exclusive_focus && !seat->drag) { + client_set_border_color(c, focuscolor); ++ drawfborders(c->mon); ++ } + } + + /* Deactivate old client if focus is changing */ +@@ -1389,7 +1609,8 @@ focusclient(Client *c, int lift) + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, bordercolor); +- ++ if (old_c->mon && (!c || c->mon != old_c->mon)) ++ destroyborders(old_c->mon->fborders); + client_activate_surface(old, 0); + } + } +@@ -2193,15 +2414,20 @@ resize(Client *c, struct wlr_box geo, int interact) + applybounds(c, bbox); + + /* Update scene-graph, including borders */ ++ c->bw = client_needs_borders(c) ? borderpx : 0; + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); +- wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); +- wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); +- wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); +- wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); +- wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ for (int i = 0; i < 4; i++) ++ wlr_scene_node_set_enabled(&c->border[i]->node, c->bw); ++ if (c->bw) { ++ wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); ++ wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); ++ wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); ++ wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); ++ wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); ++ wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); ++ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ } + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +@@ -2359,8 +2585,13 @@ setlayout(const Arg *arg) + return; + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; ++ else ++ return; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ if (selmon->lt[selmon->sellt ^ 1]->arrange == tile && !selmon->lt[selmon->sellt]->arrange) ++ /* Tiled -> floating, remove monitor borders and enable client borders */ ++ tile(selmon); + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); + printstatus(); +@@ -2692,31 +2923,46 @@ void + tile(Monitor *m) + { + unsigned int mw, my, ty; +- int i, n = 0; ++ int i, n; + Client *c; ++ struct wlr_box wb; ++ int borders = m->lt[m->sellt]->arrange == tile ? 1 : 0; + +- wl_list_for_each(c, &clients, link) +- if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) +- n++; ++ n = countclients(m); + if (n == 0) + return; + +- if (n > m->nmaster) +- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; +- else ++ if (n > m->nmaster && m->nmaster) { ++ mw = (int)round(m->w.width * m->mfact - (borders ? 0.5 * borderpx : 0)); ++ } else if (m->nmaster) + mw = m->w.width; ++ else ++ mw = 0; + i = my = ty = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); +- my += c->geom.height; ++ wb.x = m->w.x; ++ wb.y = m->w.y + my; ++ wb.width = mw; ++ if (borders) ++ wb.height = (m->w.height - my - borderpx * (MIN(n, m->nmaster) - i - 1)) ++ / (MIN(n, m->nmaster) - i); ++ else ++ wb.height = (m->w.height - my) / (MIN(n, m->nmaster) - i); ++ resize(c, wb, 0); ++ my += wb.height + (borders ? borderpx : 0); + } else { +- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); +- ty += c->geom.height; ++ wb.x = m->w.x + mw + (mw && borders ? borderpx : 0); ++ wb.y = m->w.y + ty; ++ wb.width = m->w.width - mw - (mw && borders ? borderpx : 0); ++ if (borders) ++ wb.height = (m->w.height - ty - borderpx * (n - i - 1)) / (n - i); ++ else ++ wb.height = (m->w.height - ty) / (n - i); ++ resize(c, wb, 0); ++ ty += wb.height + (borders ? borderpx : 0); + } + i++; + } +@@ -2941,8 +3187,10 @@ urgent(struct wl_listener *listener, void *data) + c->isurgent = 1; + printstatus(); + +- if (client_surface(c)->mapped) ++ if (client_surface(c)->mapped) { + client_set_border_color(c, urgentcolor); ++ drawuborders(c->mon); ++ } + } + + void +@@ -3147,8 +3395,10 @@ sethints(struct wl_listener *listener, void *data) + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); + printstatus(); + +- if (c->isurgent && surface && surface->mapped) ++ if (c->isurgent && surface && surface->mapped) { + client_set_border_color(c, urgentcolor); ++ drawuborders(c->mon); ++ } + } + + void +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/toggle_constraints/README.md b/dwl/dwl-patches/patches/toggle_constraints/README.md new file mode 100755 index 0000000..7f2be77 --- /dev/null +++ b/dwl/dwl-patches/patches/toggle_constraints/README.md @@ -0,0 +1,17 @@ +### Description +Adds a function called togglepointerconstraints to turn pointer constraint enforcement on and off with a keybind. + +### Usage +Add a binding for the togglepointerconstraints function in the keys[] array of config.h. The function does not take any argument. Pointer constraints default to enabled, and can be toggled on and off with the function from there. + +Example: +``` +{ MODKEY, XKB_KEY_c, togglepointerconstraints, {0}}, +``` + +### Download +- [Git branch](https://codeberg.org/thanatos/dwl/src/branch/toggle_constraints) +- [2024-03-26](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/toggle_constraints/toggle_constraints) + +### Authors +- [thanatos](https://codeberg.org/thanatos) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/toggle_constraints/toggle_constraints.patch b/dwl/dwl-patches/patches/toggle_constraints/toggle_constraints.patch new file mode 100755 index 0000000..e823377 --- /dev/null +++ b/dwl/dwl-patches/patches/toggle_constraints/toggle_constraints.patch @@ -0,0 +1,86 @@ +From 13bb9d86a0da2ebc82c20ee721b3eeb28592b0a0 Mon Sep 17 00:00:00 2001 +From: David Donahue +Date: Tue, 26 Mar 2024 17:45:26 -0600 +Subject: [PATCH] Added function to toggle pointer constraints via a keybind + +--- + dwl.c | 41 ++++++++++++++++++++++++++--------------- + 1 file changed, 26 insertions(+), 15 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 5867b0c..04d377b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -332,6 +332,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglepointerconstraints(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -400,6 +401,8 @@ static unsigned int cursor_mode; + static Client *grabc; + static int grabcx, grabcy; /* client-relative */ + ++static int enable_constraints = 1; ++ + static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; +@@ -1700,22 +1703,24 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + relative_pointer_mgr, seat, (uint64_t)time * 1000, + dx, dy, dx_unaccel, dy_unaccel); + +- wl_list_for_each(constraint, &pointer_constraints->constraints, link) +- cursorconstrain(constraint); +- +- if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) { +- toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); +- if (c && active_constraint->surface == seat->pointer_state.focused_surface) { +- sx = cursor->x - c->geom.x - c->bw; +- sy = cursor->y - c->geom.y - c->bw; +- if (wlr_region_confine(&active_constraint->region, sx, sy, +- sx + dx, sy + dy, &sx_confined, &sy_confined)) { +- dx = sx_confined - sx; +- dy = sy_confined - sy; ++ if (enable_constraints){ ++ wl_list_for_each(constraint, &pointer_constraints->constraints, link) ++ cursorconstrain(constraint); ++ ++ if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) { ++ toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); ++ if (c && active_constraint->surface == seat->pointer_state.focused_surface) { ++ sx = cursor->x - c->geom.x - c->bw; ++ sy = cursor->y - c->geom.y - c->bw; ++ if (wlr_region_confine(&active_constraint->region, sx, sy, ++ sx + dx, sy + dy, &sx_confined, &sy_confined)) { ++ dx = sx_confined - sx; ++ dy = sy_confined - sy; ++ } ++ ++ if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) ++ return; + } +- +- if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) +- return; + } + } + +@@ -2620,6 +2625,12 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglepointerconstraints(const Arg *arg) ++{ ++ enable_constraints = !enable_constraints; ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.43.2 + diff --git a/dwl/dwl-patches/patches/togglekblayoutandoptions/README.md b/dwl/dwl-patches/patches/togglekblayoutandoptions/README.md new file mode 100755 index 0000000..883dd6d --- /dev/null +++ b/dwl/dwl-patches/patches/togglekblayoutandoptions/README.md @@ -0,0 +1,9 @@ +### Description +Switch between multiple keyboard layouts, variants, and options at runtime. + +### Download +- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/togglekblayoutandoptions/togglekblayoutandoptions.patch) + +### Authors +- [LaKato](https://codeberg.org/LaKato) +- [dev-gm](https://codeberg.org/dev-gm) diff --git a/dwl/dwl-patches/patches/togglekblayoutandoptions/togglekblayoutandoptions.patch b/dwl/dwl-patches/patches/togglekblayoutandoptions/togglekblayoutandoptions.patch new file mode 100755 index 0000000..dc7fd81 --- /dev/null +++ b/dwl/dwl-patches/patches/togglekblayoutandoptions/togglekblayoutandoptions.patch @@ -0,0 +1,160 @@ +From 9ee76adc7c6567650e7b34273f953fed03191c05 Mon Sep 17 00:00:00 2001 +From: LaKato +Date: Sat, 8 Mar 2025 12:14:41 -0500 +Subject: [PATCH] Update for v0.7 + +Additional changes: +- incxkbrules now uses its argument +- A new setxkbrules function has been added +- Keyboard groups are no longer looped over because only one is created +--- + config.def.h | 17 +++++++++++------ + dwl.c | 44 +++++++++++++++++++++++++++++++++----------- + 2 files changed, 44 insertions(+), 17 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..b3b4699 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -52,12 +52,15 @@ static const MonitorRule monrules[] = { + }; + + /* keyboard */ +-static const struct xkb_rule_names xkb_rules = { +- /* can specify fields: rules, model, layout, variant, options */ +- /* example: +- .options = "ctrl:nocaps", +- */ +- .options = NULL, ++static const struct xkb_rule_names xkb_rules[] = { ++ { ++ .layout = "us", ++ }, ++ /*{ ++ .layout = "us", ++ .variant = "dvp", ++ .options = "compose:102,numpad:shift3,kpdl:semi,keypad:atm,caps:super" ++ }*/ + }; + + static const int repeat_rate = 25; +@@ -148,6 +151,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_A, incxkbrules, {.i = +1} }, ++ /*{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_E, setxkbrules, {.i = +1} },*/ + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +diff --git a/dwl.c b/dwl.c +index a2711f6..a2413e9 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -249,6 +249,7 @@ static void arrange(Monitor *m); + static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); ++static void assignkeymap(struct wlr_keyboard *keyboard); + static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); +@@ -293,6 +294,7 @@ static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); ++static void incxkbrules(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); +@@ -333,6 +335,7 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); + static void setup(void); ++static void setxkbrules(const Arg *arg); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -404,6 +407,7 @@ static struct wl_listener lock_listener = {.notify = locksession}; + + static struct wlr_seat *seat; + static KeyboardGroup *kb_group; ++static unsigned int kblayout = 0; + static unsigned int cursor_mode; + static Client *grabc; + static int grabcx, grabcy; /* client-relative */ +@@ -580,6 +584,20 @@ arrangelayers(Monitor *m) + } + } + ++void ++assignkeymap(struct wlr_keyboard *keyboard) { ++ struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); ++ struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &xkb_rules[kblayout], ++ XKB_KEYMAP_COMPILE_NO_FLAGS); ++ ++ if (!keymap) ++ die("failed to compile keymap"); ++ ++ wlr_keyboard_set_keymap(keyboard, keymap); ++ xkb_keymap_unref(keymap); ++ xkb_context_unref(context); ++} ++ + void + axisnotify(struct wl_listener *listener, void *data) + { +@@ -885,21 +903,11 @@ KeyboardGroup * + createkeyboardgroup(void) + { + KeyboardGroup *group = ecalloc(1, sizeof(*group)); +- struct xkb_context *context; +- struct xkb_keymap *keymap; + + group->wlr_group = wlr_keyboard_group_create(); + group->wlr_group->data = group; + +- /* Prepare an XKB keymap and assign it to the keyboard group. */ +- context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); +- if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules, +- XKB_KEYMAP_COMPILE_NO_FLAGS))) +- die("failed to compile keymap"); +- +- wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap); +- xkb_keymap_unref(keymap); +- xkb_context_unref(context); ++ assignkeymap(&group->wlr_group->keyboard); + + wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay); + +@@ -1524,6 +1532,13 @@ incnmaster(const Arg *arg) + arrange(selmon); + } + ++void ++incxkbrules(const Arg *arg) ++{ ++ kblayout = (kblayout + arg->i) % LENGTH(xkb_rules); ++ assignkeymap(&kb_group->wlr_group->keyboard); ++} ++ + void + inputdevice(struct wl_listener *listener, void *data) + { +@@ -2645,6 +2660,13 @@ setup(void) + #endif + } + ++void ++setxkbrules(const Arg *arg) ++{ ++ kblayout = arg->i; ++ assignkeymap(&kb_group->wlr_group->keyboard); ++} ++ + void + spawn(const Arg *arg) + { +-- +2.48.1 + diff --git a/dwl/dwl-patches/patches/touch-input/README.md b/dwl/dwl-patches/patches/touch-input/README.md new file mode 100755 index 0000000..3d37fc2 --- /dev/null +++ b/dwl/dwl-patches/patches/touch-input/README.md @@ -0,0 +1,20 @@ +### Description +Adds touchscreen functionality. + +KNOWN BUGS: +- Sometimes, the pointer moves to where the screen is pressed, but the button press doesn't occur until the screen is touched AGAIN. This means that if you touch to click button 'Q' on the screen (for instance), nothing happens; then you touch elsewhere on the screen and THEN button 'Q' registers a click. This is annoying, doesn't always happen, and I don't yet know how to fix it. + +### Download +- [git branch](https://codeberg.org/fauxmight/dwl/src/branch/touch-input) +- [2025-05-17](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/touch-input/touch-input.patch) + +### Authors +- [fauxmight](https://codeberg.org/fauxmight) +- [minego](https://codeberg.org/minego) +- [Unprex](https://github.com/Unprex) + +### Changelog +- 2025-01-01 @fauxmight took over maintenance. Previous maintainer @minego notes [lack of available time](https://codeberg.org/dwl/dwl-patches/pulls/102#issuecomment-2557944) +- 2024-02-11 Corrected issue where motion events where not sending notifications for unfocused clients such as an on screen keyboard +- 2024-03-26 Rebased, and removed #ifdef's for the pointer constraints patch which has been merged into upstream +- 2024-03-28 Removed debug diff --git a/dwl/dwl-patches/patches/touch-input/touch-input.patch b/dwl/dwl-patches/patches/touch-input/touch-input.patch new file mode 100755 index 0000000..bfd33e7 --- /dev/null +++ b/dwl/dwl-patches/patches/touch-input/touch-input.patch @@ -0,0 +1,260 @@ +From f133af7120e28f3d8bda4d4e14b3bfd477b46426 Mon Sep 17 00:00:00 2001 +From: A Frederick Christensen +Date: Sat, 17 May 2025 21:59:37 -0500 +Subject: [PATCH] Add support for touchscreen input devices + +and send the appropriate events to clients +--- + dwl.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 158 insertions(+) + +diff --git a/dwl.c b/dwl.c +index 4816159..3a378f9 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -161,6 +162,12 @@ typedef struct { + struct wl_listener destroy; + } KeyboardGroup; + ++typedef struct TouchGroup { ++ struct wl_list link; ++ struct wlr_touch *touch; ++ Monitor *m; ++} TouchGroup; ++ + typedef struct { + /* Must keep this field first */ + unsigned int type; /* LayerShell */ +@@ -268,7 +275,9 @@ static void createnotify(struct wl_listener *listener, void *data); + static void createpointer(struct wlr_pointer *pointer); + static void createpointerconstraint(struct wl_listener *listener, void *data); + static void createpopup(struct wl_listener *listener, void *data); ++static void createtouch(struct wlr_touch *touch); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); ++static void createtouch(struct wlr_touch *touch); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); + static void destroydecoration(struct wl_listener *listener, void *data); +@@ -338,6 +347,10 @@ static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); ++static void touchdown(struct wl_listener *listener, void *data); ++static void touchup(struct wl_listener *listener, void *data); ++static void touchframe(struct wl_listener *listener, void *data); ++static void touchmotion(struct wl_listener *listener, void *data); + static void unlocksession(struct wl_listener *listener, void *data); + static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); + static void unmapnotify(struct wl_listener *listener, void *data); +@@ -405,6 +418,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static struct wl_list touches; + + /* global event handlers */ + static struct wl_listener cursor_axis = {.notify = axisnotify}; +@@ -434,6 +448,10 @@ static struct wl_listener request_set_sel = {.notify = setsel}; + static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape}; + static struct wl_listener request_start_drag = {.notify = requeststartdrag}; + static struct wl_listener start_drag = {.notify = startdrag}; ++static struct wl_listener touch_down = {.notify = touchdown}; ++static struct wl_listener touch_frame = {.notify = touchframe}; ++static struct wl_listener touch_motion = {.notify = touchmotion}; ++static struct wl_listener touch_up = {.notify = touchup}; + static struct wl_listener new_session_lock = {.notify = locksession}; + + #ifdef XWAYLAND +@@ -778,6 +796,10 @@ cleanuplisteners(void) + wl_list_remove(&request_set_cursor_shape.link); + wl_list_remove(&request_start_drag.link); + wl_list_remove(&start_drag.link); ++ wl_list_remove(&touch_down.link); ++ wl_list_remove(&touch_frame.link); ++ wl_list_remove(&touch_motion.link); ++ wl_list_remove(&touch_up.link); + wl_list_remove(&new_session_lock.link); + #ifdef XWAYLAND + wl_list_remove(&new_xwayland_surface.link); +@@ -1196,6 +1218,16 @@ createpopup(struct wl_listener *listener, void *data) + LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); + } + ++void ++createtouch(struct wlr_touch *wlr_touch) ++{ ++ TouchGroup *touch = ecalloc(1, sizeof(TouchGroup)); ++ ++ touch->touch = wlr_touch; ++ wl_list_insert(&touches, &touch->link); ++ wlr_cursor_attach_input_device(cursor, &wlr_touch->base); ++} ++ + void + cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) + { +@@ -1587,6 +1619,9 @@ inputdevice(struct wl_listener *listener, void *data) + case WLR_INPUT_DEVICE_POINTER: + createpointer(wlr_pointer_from_input_device(device)); + break; ++ case WLR_INPUT_DEVICE_TOUCH: ++ createtouch(wlr_touch_from_input_device(device)); ++ break; + default: + /* TODO handle other input device types */ + break; +@@ -1599,6 +1634,8 @@ inputdevice(struct wl_listener *listener, void *data) + caps = WL_SEAT_CAPABILITY_POINTER; + if (!wl_list_empty(&kb_group->wlr_group->devices)) + caps |= WL_SEAT_CAPABILITY_KEYBOARD; ++ if (!wl_list_empty(&touches)) ++ caps |= WL_SEAT_CAPABILITY_TOUCH; + wlr_seat_set_capabilities(seat, caps); + } + +@@ -2610,6 +2647,13 @@ setup(void) + wl_signal_add(&cursor->events.axis, &cursor_axis); + wl_signal_add(&cursor->events.frame, &cursor_frame); + ++ wl_list_init(&touches); ++ ++ wl_signal_add(&cursor->events.touch_down, &touch_down); ++ wl_signal_add(&cursor->events.touch_frame, &touch_frame); ++ wl_signal_add(&cursor->events.touch_motion, &touch_motion); ++ wl_signal_add(&cursor->events.touch_up, &touch_up); ++ + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape); + +@@ -2782,6 +2826,120 @@ toggleview(const Arg *arg) + printstatus(); + } + ++void ++touchdown(struct wl_listener *listener, void *data) ++{ ++ struct wlr_touch_down_event *event = data; ++ double lx, ly; ++ double sx, sy; ++ struct wlr_surface *surface; ++ Client *c = NULL; ++ uint32_t serial = 0; ++ Monitor *m; ++ ++ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); ++ ++ // Map the input to the appropriate output, to ensure that rotation is ++ // handled. ++ wl_list_for_each(m, &mons, link) { ++ if (m == NULL || m->wlr_output == NULL) { ++ continue; ++ } ++ if (event->touch->output_name != NULL && 0 != strcmp(event->touch->output_name, m->wlr_output->name)) { ++ continue; ++ } ++ ++ wlr_cursor_map_input_to_output(cursor, &event->touch->base, m->wlr_output); ++ } ++ ++ wlr_cursor_absolute_to_layout_coords(cursor, &event->touch->base, event->x, event->y, &lx, &ly); ++ ++ /* Find the client under the pointer and send the event along. */ ++ xytonode(lx, ly, &surface, &c, NULL, &sx, &sy); ++ if (sloppyfocus) ++ focusclient(c, 0); ++ ++ if (surface != NULL) { ++ serial = wlr_seat_touch_notify_down(seat, surface, event->time_msec, event->touch_id, sx, sy); ++ } ++ ++ if (serial && wlr_seat_touch_num_points(seat) == 1) { ++ /* Emulate a mouse click if the touch event wasn't handled */ ++ struct wlr_pointer_button_event *button_event = data; ++ struct wlr_pointer_motion_absolute_event *motion_event = data; ++ double dx, dy; ++ ++ wlr_cursor_absolute_to_layout_coords(cursor, &motion_event->pointer->base, motion_event->x, motion_event->y, &lx, &ly); ++ wlr_cursor_warp_closest(cursor, &motion_event->pointer->base, lx, ly); ++ dx = lx - cursor->x; ++ dy = ly - cursor->y; ++ motionnotify(motion_event->time_msec, &motion_event->pointer->base, dx, dy, dx, dy); ++ ++ button_event->button = BTN_LEFT; ++ button_event->state = WL_POINTER_BUTTON_STATE_PRESSED; ++ buttonpress(listener, button_event); ++ } ++} ++ ++void ++touchup(struct wl_listener *listener, void *data) ++{ ++ struct wlr_touch_up_event *event = data; ++ ++ if (!wlr_seat_touch_get_point(seat, event->touch_id)) { ++ return; ++ } ++ ++ if (wlr_seat_touch_num_points(seat) == 1) { ++ struct wlr_pointer_button_event *button_event = data; ++ ++ button_event->button = BTN_LEFT; ++ button_event->state = WL_POINTER_BUTTON_STATE_RELEASED; ++ buttonpress(listener, button_event); ++ } ++ ++ wlr_seat_touch_notify_up(seat, event->time_msec, event->touch_id); ++ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); ++} ++ ++void ++touchframe(struct wl_listener *listener, void *data) ++{ ++ wlr_seat_touch_notify_frame(seat); ++ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); ++} ++ ++void ++touchmotion(struct wl_listener *listener, void *data) ++{ ++ struct wlr_touch_motion_event *event = data; ++ double lx, ly; ++ double sx, sy; ++ struct wlr_surface *surface; ++ Client *c = NULL; ++ ++ if (!wlr_seat_touch_get_point(seat, event->touch_id)) { ++ return; ++ } ++ ++ wlr_cursor_absolute_to_layout_coords(cursor, &event->touch->base, event->x, event->y, &lx, &ly); ++ xytonode(lx, ly, &surface, &c, NULL, &sx, &sy); ++ ++ if (c != NULL && surface != NULL) { ++ if (sloppyfocus) ++ focusclient(c, 0); ++ wlr_seat_touch_point_focus(seat, surface, event->time_msec, event->touch_id, sx, sy); ++ } else { ++ if (sloppyfocus) ++ focusclient(NULL, 0); ++ wlr_seat_touch_point_clear_focus(seat, event->time_msec, event->touch_id); ++ } ++ wlr_seat_touch_notify_motion(seat, event->time_msec, event->touch_id, sx, sy); ++ ++ wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); ++} ++ ++ + void + unlocksession(struct wl_listener *listener, void *data) + { +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/unclutter/README.md b/dwl/dwl-patches/patches/unclutter/README.md new file mode 100755 index 0000000..48bf85a --- /dev/null +++ b/dwl/dwl-patches/patches/unclutter/README.md @@ -0,0 +1,11 @@ +### Description +Hide the mouse cursor if it isn't being used for a certain period of time. + +### Download +- [git branch](https://codeberg.org/guidocella/dwl/src/branch/unclutter) +- [2025-06-09](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/unclutter/unclutter.patch) + +### Authors +- [Guido Cella](https://github.com/guidocella) +- [dm1tz](https://github.com/dm1tz) +- [Ben Collerson](https://codeberg.org/bencc) diff --git a/dwl/dwl-patches/patches/unclutter/unclutter.patch b/dwl/dwl-patches/patches/unclutter/unclutter.patch new file mode 100755 index 0000000..4c9aede --- /dev/null +++ b/dwl/dwl-patches/patches/unclutter/unclutter.patch @@ -0,0 +1,192 @@ +From 68914f40359ebccc7b684a1f74d82419b1796cdf Mon Sep 17 00:00:00 2001 +From: Guido Cella +Date: Thu, 25 Jul 2024 17:59:05 +0200 +Subject: [PATCH] =?UTF-8?q?hide=20the=20mouse=20cursor=20if=20it=20isn?= + =?UTF-8?q?=E2=80=99t=20being=20used?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + config.def.h | 2 ++ + dwl.c | 74 +++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 67 insertions(+), 9 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171..790c73d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -106,6 +106,8 @@ LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right + */ + static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; + ++static const int cursor_timeout = 5; ++ + /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ + #define MODKEY WLR_MODIFIER_ALT + +diff --git a/dwl.c b/dwl.c +index 775dadf..621779e 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -288,6 +288,8 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); ++static void handlecursoractivity(void); ++static int hidecursor(void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +@@ -389,6 +391,14 @@ static struct wlr_pointer_constraint_v1 *active_constraint; + + static struct wlr_cursor *cursor; + static struct wlr_xcursor_manager *cursor_mgr; ++static struct wl_event_source *hide_source; ++static bool cursor_hidden = false; ++static struct { ++ enum wp_cursor_shape_device_v1_shape shape; ++ struct wlr_surface *surface; ++ int hotspot_x; ++ int hotspot_y; ++} last_cursor; + + static struct wlr_scene_rect *root_bg; + static struct wlr_session_lock_manager_v1 *session_lock_mgr; +@@ -609,8 +619,9 @@ axisnotify(struct wl_listener *listener, void *data) + * for example when you move the scroll wheel. */ + struct wlr_pointer_axis_event *event = data; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); +- /* TODO: allow usage of scroll wheel for mousebindings, it can be implemented +- * by checking the event's orientation and the delta of the event */ ++ handlecursoractivity(); ++ /* TODO: allow usage of scroll whell for mousebindings, it can be implemented ++ * checking the event's orientation and the delta of the event */ + /* Notify the client with pointer focus of the axis event. */ + wlr_seat_pointer_notify_axis(seat, + event->time_msec, event->orientation, event->delta, +@@ -627,6 +638,7 @@ buttonpress(struct wl_listener *listener, void *data) + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); ++ handlecursoractivity(); + + switch (event->state) { + case WL_POINTER_BUTTON_STATE_PRESSED: +@@ -1563,6 +1575,32 @@ handlesig(int signo) + quit(NULL); + } + ++void ++handlecursoractivity(void) ++{ ++ wl_event_source_timer_update(hide_source, cursor_timeout * 1000); ++ ++ if (!cursor_hidden) ++ return; ++ ++ cursor_hidden = false; ++ ++ if (last_cursor.shape) ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, ++ wlr_cursor_shape_v1_name(last_cursor.shape)); ++ else ++ wlr_cursor_set_surface(cursor, last_cursor.surface, ++ last_cursor.hotspot_x, last_cursor.hotspot_y); ++} ++ ++int ++hidecursor(void *data) ++{ ++ wlr_cursor_unset_image(cursor); ++ cursor_hidden = true; ++ return 1; ++} ++ + void + incnmaster(const Arg *arg) + { +@@ -1903,6 +1941,7 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + + wlr_cursor_move(cursor, device, dx, dy); + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); ++ handlecursoractivity(); + + /* Update selmon (even while dragging a window) */ + if (sloppyfocus) +@@ -1927,7 +1966,7 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d + /* If there's no client surface under the cursor, set the cursor image to a + * default. This is what makes the cursor image appear when you move it + * off of a client or over its border. */ +- if (!surface && !seat->drag) ++ if (!surface && !seat->drag && !cursor_hidden) + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + + pointerfocus(c, surface, sx, sy, time); +@@ -2284,6 +2323,7 @@ run(char *startup_cmd) + * monitor when displayed here */ + wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); ++ handlecursoractivity(); + + /* Run the Wayland event loop. This does not return until you exit the + * compositor. Starting the backend rigged up all of the necessary event +@@ -2307,9 +2347,16 @@ setcursor(struct wl_listener *listener, void *data) + * use the provided surface as the cursor image. It will set the + * hardware cursor on the output that it's currently on and continue to + * do so as the cursor moves between outputs. */ +- if (event->seat_client == seat->pointer_state.focused_client) +- wlr_cursor_set_surface(cursor, event->surface, +- event->hotspot_x, event->hotspot_y); ++ if (event->seat_client == seat->pointer_state.focused_client) { ++ last_cursor.shape = 0; ++ last_cursor.surface = event->surface; ++ last_cursor.hotspot_x = event->hotspot_x; ++ last_cursor.hotspot_y = event->hotspot_y; ++ ++ if (!cursor_hidden) ++ wlr_cursor_set_surface(cursor, event->surface, ++ event->hotspot_x, event->hotspot_y); ++ } + } + + void +@@ -2321,9 +2368,14 @@ setcursorshape(struct wl_listener *listener, void *data) + /* This can be sent by any client, so we check to make sure this one + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided cursor shape. */ +- if (event->seat_client == seat->pointer_state.focused_client) +- wlr_cursor_set_xcursor(cursor, cursor_mgr, +- wlr_cursor_shape_v1_name(event->shape)); ++ if (event->seat_client == seat->pointer_state.focused_client) { ++ last_cursor.shape = event->shape; ++ last_cursor.surface = NULL; ++ ++ if (!cursor_hidden) ++ wlr_cursor_set_xcursor(cursor, cursor_mgr, ++ wlr_cursor_shape_v1_name(event->shape)); ++ } + } + + void +@@ -2614,6 +2666,9 @@ setup(void) + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + wl_signal_add(&cursor_shape_mgr->events.request_set_shape, &request_set_cursor_shape); + ++ hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy), ++ hidecursor, cursor); ++ + /* + * Configures a seat, which is a single "seat" at which a user sits and + * operates the computer. This conceptually includes up to one keyboard, +@@ -2998,6 +3053,7 @@ virtualpointer(struct wl_listener *listener, void *data) + wlr_cursor_attach_input_device(cursor, device); + if (event->suggested_output) + wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); ++ handlecursoractivity(); + } + + Monitor * +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/ungroup-keyboards/README.md b/dwl/dwl-patches/patches/ungroup-keyboards/README.md new file mode 100755 index 0000000..e56f94b --- /dev/null +++ b/dwl/dwl-patches/patches/ungroup-keyboards/README.md @@ -0,0 +1,15 @@ +### Description +Ungroup keyboard input devices based on device name. + +I wrote this patch was because keyboard device grouping breaks the behaviour of +the ydotool virtual device. This patch fixes my issue #558 in the codeberg +issue tracker. + +See the inputdevicerules patch for a more generalised version of this idea. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/ungroup-keyboards) +- [2024-06-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/ungroup-keyboards/ungroup-keyboards.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) diff --git a/dwl/dwl-patches/patches/ungroup-keyboards/ungroup-keyboards.patch b/dwl/dwl-patches/patches/ungroup-keyboards/ungroup-keyboards.patch new file mode 100755 index 0000000..b3249b6 --- /dev/null +++ b/dwl/dwl-patches/patches/ungroup-keyboards/ungroup-keyboards.patch @@ -0,0 +1,97 @@ +From d9b9797680ae58bdb910e3bc1f71408f6b67c0d5 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Sat, 15 Jun 2024 12:34:01 +1000 +Subject: [PATCH] ungroup-keyboards + +Ungroup keyboards based on device name. My use case is keeping the +ydotool virtual keyboard from from being grouped with other keyboards. +--- + config.def.h | 7 +++++++ + dwl.c | 29 ++++++++++++++++++++++++++++- + 2 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index a784eb4f..9ad1c256 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -57,6 +57,13 @@ static const struct xkb_rule_names xkb_rules = { + .options = NULL, + }; + ++/* keyboard input devices - used to ungroup named keyboard devices */ ++static const KBInputRule kbinputrules[] = { ++ /* name kbcreate */ ++ { "ydotoold virtual device", createungroupedkeyboard }, ++ { NULL, createkeyboard }, ++}; ++ + static const int repeat_rate = 25; + static const int repeat_delay = 600; + +diff --git a/dwl.c b/dwl.c +index 5a31aeef..41db830b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -141,6 +141,11 @@ typedef struct { + uint32_t resize; /* configure serial of a pending resize */ + } Client; + ++typedef struct { ++ const char *name; ++ void (*kbcreate)(struct wlr_keyboard *); ++} KBInputRule; ++ + typedef struct { + uint32_t mod; + xkb_keysym_t keysym; +@@ -266,6 +271,7 @@ static void createmon(struct wl_listener *listener, void *data); + static void createnotify(struct wl_listener *listener, void *data); + static void createpointer(struct wlr_pointer *pointer); + static void createpointerconstraint(struct wl_listener *listener, void *data); ++static void createungroupedkeyboard(struct wlr_keyboard *keyboard); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); +@@ -1089,6 +1095,20 @@ createpointerconstraint(struct wl_listener *listener, void *data) + &pointer_constraint->destroy, destroypointerconstraint); + } + ++void ++createungroupedkeyboard(struct wlr_keyboard *keyboard) ++{ ++ /* for keyboards that need their own keyboard group */ ++ KeyboardGroup *group = createkeyboardgroup(); ++ ++ /* Set the keymap to match the group keymap */ ++ wlr_keyboard_set_keymap(keyboard, group->wlr_group->keyboard.keymap); ++ LISTEN(&keyboard->base.events.destroy, &group->destroy, destroykeyboardgroup); ++ ++ /* Add the new keyboard to the group */ ++ wlr_keyboard_group_add_keyboard(group->wlr_group, keyboard); ++} ++ + void + cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) + { +@@ -1464,10 +1484,17 @@ inputdevice(struct wl_listener *listener, void *data) + * available. */ + struct wlr_input_device *device = data; + uint32_t caps; ++ const KBInputRule *r; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: +- createkeyboard(wlr_keyboard_from_input_device(device)); ++ for (r = kbinputrules; r < END(kbinputrules); r++) { ++ if (!r->name || strstr(device->name, r->name)) { ++ r->kbcreate(wlr_keyboard_from_input_device(device)); ++ break; ++ } ++ } ++ + break; + case WLR_INPUT_DEVICE_POINTER: + createpointer(wlr_pointer_from_input_device(device)); +-- +2.45.1 + diff --git a/dwl/dwl-patches/patches/vanitygaps/README.md b/dwl/dwl-patches/patches/vanitygaps/README.md new file mode 100755 index 0000000..cbdf6b4 --- /dev/null +++ b/dwl/dwl-patches/patches/vanitygaps/README.md @@ -0,0 +1,12 @@ +### Description +Adds (inner) gaps between client windows and (outer) gaps between windows and +the screen edge in a flexible manner. + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/vanitygaps) +- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/vanitygaps/vanitygaps.patch) +- [vanitygaps-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/vanitygaps/vanitygaps-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) +- [Bonicgamer](https://github.com/Bonicgamer) diff --git a/dwl/dwl-patches/patches/vanitygaps/vanitygaps-0.7.patch b/dwl/dwl-patches/patches/vanitygaps/vanitygaps-0.7.patch new file mode 100755 index 0000000..622b444 --- /dev/null +++ b/dwl/dwl-patches/patches/vanitygaps/vanitygaps-0.7.patch @@ -0,0 +1,358 @@ +From 3c95b58bc2b87ebd9b8481b3b16e49d99883f0a7 Mon Sep 17 00:00:00 2001 +From: Bonicgamer <44382222+Bonicgamer@users.noreply.github.com> +Date: Mon, 17 Aug 2020 14:48:24 -0400 +Subject: [PATCH 1/2] Implement vanitygaps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 21 ++++++++ + dwl.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 161 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..39e528b1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,7 +6,12 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ ++static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappih = 10; /* horiz inner gap between windows */ ++static const unsigned int gappiv = 10; /* vert inner gap between windows */ ++static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ ++static const unsigned int gappov = 10; /* vert outer gap between windows and screen edge */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); +@@ -133,6 +138,22 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_h, incgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_l, incgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_H, incogaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_L, incogaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_h, incigaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_l, incigaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_0, togglegaps, {0} }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_parenright,defaultgaps, {0} }, ++ { MODKEY, XKB_KEY_y, incihgaps, {.i = +1 } }, ++ { MODKEY, XKB_KEY_o, incihgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_y, incivgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_o, incivgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_y, incohgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_o, incohgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Y, incovgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, incovgaps, {.i = -1 } }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index a2711f67..d749728a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -200,6 +200,10 @@ struct Monitor { + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; ++ int gappih; /* horizontal gap between windows */ ++ int gappiv; /* vertical gap between windows */ ++ int gappoh; /* horizontal outer gaps */ ++ int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; +@@ -273,6 +277,7 @@ static void createpopup(struct wl_listener *listener, void *data); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); ++static void defaultgaps(const Arg *arg); + static void destroydecoration(struct wl_listener *listener, void *data); + static void destroydragicon(struct wl_listener *listener, void *data); + static void destroyidleinhibitor(struct wl_listener *listener, void *data); +@@ -293,6 +298,13 @@ static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); ++static void incgaps(const Arg *arg); ++static void incigaps(const Arg *arg); ++static void incihgaps(const Arg *arg); ++static void incivgaps(const Arg *arg); ++static void incogaps(const Arg *arg); ++static void incohgaps(const Arg *arg); ++static void incovgaps(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); +@@ -327,6 +339,7 @@ static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); + static void setfullscreen(Client *c, int fullscreen); + static void setgamma(struct wl_listener *listener, void *data); ++static void setgaps(int oh, int ov, int ih, int iv); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); +@@ -340,6 +353,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglegaps(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -413,6 +427,8 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static int enablegaps = 1; /* enables gaps, used by togglegaps */ ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -989,6 +1005,11 @@ createmon(struct wl_listener *listener, void *data) + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); + ++ m->gappih = gappih; ++ m->gappiv = gappiv; ++ m->gappoh = gappoh; ++ m->gappov = gappov; ++ + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->tagset[0] = m->tagset[1] = 1; +@@ -1171,6 +1192,12 @@ cursorwarptohint(void) + } + } + ++void ++defaultgaps(const Arg *arg) ++{ ++ setgaps(gappoh, gappov, gappih, gappiv); ++} ++ + void + destroydecoration(struct wl_listener *listener, void *data) + { +@@ -1524,6 +1551,83 @@ incnmaster(const Arg *arg) + arrange(selmon); + } + ++void ++incgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incigaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incihgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv ++ ); ++} ++ ++void ++incivgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incogaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incohgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incovgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ + void + inputdevice(struct wl_listener *listener, void *data) + { +@@ -2352,6 +2456,16 @@ setgamma(struct wl_listener *listener, void *data) + wlr_output_schedule_frame(m->wlr_output); + } + ++void ++setgaps(int oh, int ov, int ih, int iv) ++{ ++ selmon->gappoh = MAX(oh, 0); ++ selmon->gappov = MAX(ov, 0); ++ selmon->gappih = MAX(ih, 0); ++ selmon->gappiv = MAX(iv, 0); ++ arrange(selmon); ++} ++ + void + setlayout(const Arg *arg) + { +@@ -2691,7 +2805,7 @@ tagmon(const Arg *arg) + void + tile(Monitor *m) + { +- unsigned int mw, my, ty; ++ unsigned int mw, my, ty, h, r, oe = enablegaps, ie = enablegaps; + int i, n = 0; + Client *c; + +@@ -2701,22 +2815,31 @@ tile(Monitor *m) + if (n == 0) + return; + ++ if (smartgaps == n) { ++ oe = 0; // outer gaps disabled ++ } ++ + if (n > m->nmaster) +- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; ++ mw = m->nmaster ? (int)roundf((m->w.width + m->gappiv*ie) * m->mfact) : 0; + else +- mw = m->w.width; +- i = my = ty = 0; ++ mw = m->w.width - 2*m->gappov*oe + m->gappiv*ie; ++ i = 0; ++ my = ty = m->gappoh*oe; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); +- my += c->geom.height; ++ r = MIN(n, m->nmaster) - i; ++ h = (m->w.height - my - m->gappoh*oe - m->gappih*ie * (r - 1)) / r; ++ resize(c, (struct wlr_box){.x = m->w.x + m->gappov*oe, .y = m->w.y + my, ++ .width = mw - m->gappiv*ie, .height = h}, 0); ++ my += c->geom.height + m->gappih*ie; + } else { +- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); +- ty += c->geom.height; ++ r = n - i; ++ h = (m->w.height - ty - m->gappoh*oe - m->gappih*ie * (r - 1)) / r; ++ resize(c, (struct wlr_box){.x = m->w.x + mw + m->gappov*oe, .y = m->w.y + ty, ++ .width = m->w.width - mw - 2*m->gappov*oe, .height = h}, 0); ++ ty += c->geom.height + m->gappih*ie; + } + i++; + } +@@ -2739,6 +2862,13 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglegaps(const Arg *arg) ++{ ++ enablegaps = !enablegaps; ++ arrange(selmon); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.46.0 + + +From 8b9db986eddeade22d92fb15a8c836912869be29 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Wed, 20 Jul 2022 00:15:32 -0500 +Subject: [PATCH 2/2] allow gaps in monocle layout if requested +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 1 + + dwl.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 39e528b1..f4d4095d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,7 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ ++static const int monoclegaps = 0; /* 1 means outer gaps in monocle layout */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int gappih = 10; /* horiz inner gap between windows */ + static const unsigned int gappiv = 10; /* vert inner gap between windows */ +diff --git a/dwl.c b/dwl.c +index d749728a..dbc66ef8 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1879,8 +1879,12 @@ monocle(Monitor *m) + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- resize(c, m->w, 0); + n++; ++ if (!monoclegaps) ++ resize(c, m->w, 0); ++ else ++ resize(c, (struct wlr_box){.x = m->w.x + gappoh, .y = m->w.y + gappov, ++ .width = m->w.width - 2 * gappoh, .height = m->w.height - 2 * gappov}, 0); + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); +-- +2.46.0 + diff --git a/dwl/dwl-patches/patches/vanitygaps/vanitygaps.patch b/dwl/dwl-patches/patches/vanitygaps/vanitygaps.patch new file mode 100755 index 0000000..db1ddf4 --- /dev/null +++ b/dwl/dwl-patches/patches/vanitygaps/vanitygaps.patch @@ -0,0 +1,357 @@ +From 8d29d5cace06c97917fbc26c673fd37731ac4984 Mon Sep 17 00:00:00 2001 +From: Bonicgamer <44382222+Bonicgamer@users.noreply.github.com> +Date: Mon, 17 Aug 2020 14:48:24 -0400 +Subject: [PATCH 1/2] Implement vanitygaps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 21 ++++++++ + dwl.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 160 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 22d2171d..39e528b1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,7 +6,12 @@ + /* appearance */ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ ++static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappih = 10; /* horiz inner gap between windows */ ++static const unsigned int gappiv = 10; /* vert inner gap between windows */ ++static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ ++static const unsigned int gappov = 10; /* vert outer gap between windows and screen edge */ + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); +@@ -133,6 +138,22 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_h, incgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_l, incgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_H, incogaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_L, incogaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_h, incigaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_CTRL, XKB_KEY_l, incigaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_0, togglegaps, {0} }, ++ { MODKEY|WLR_MODIFIER_LOGO|WLR_MODIFIER_SHIFT, XKB_KEY_parenright,defaultgaps, {0} }, ++ { MODKEY, XKB_KEY_y, incihgaps, {.i = +1 } }, ++ { MODKEY, XKB_KEY_o, incihgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_y, incivgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_o, incivgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_y, incohgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_LOGO, XKB_KEY_o, incohgaps, {.i = -1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Y, incovgaps, {.i = +1 } }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, incovgaps, {.i = -1 } }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index ad21e1ba..fa823957 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -197,6 +197,10 @@ struct Monitor { + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; ++ int gappih; /* horizontal gap between windows */ ++ int gappiv; /* vertical gap between windows */ ++ int gappoh; /* horizontal outer gaps */ ++ int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; +@@ -271,6 +275,7 @@ static void createpopup(struct wl_listener *listener, void *data); + static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); + static void cursorframe(struct wl_listener *listener, void *data); + static void cursorwarptohint(void); ++static void defaultgaps(const Arg *arg); + static void destroydecoration(struct wl_listener *listener, void *data); + static void destroydragicon(struct wl_listener *listener, void *data); + static void destroyidleinhibitor(struct wl_listener *listener, void *data); +@@ -290,6 +295,13 @@ static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); ++static void incgaps(const Arg *arg); ++static void incigaps(const Arg *arg); ++static void incihgaps(const Arg *arg); ++static void incivgaps(const Arg *arg); ++static void incogaps(const Arg *arg); ++static void incohgaps(const Arg *arg); ++static void incovgaps(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); + static void keypress(struct wl_listener *listener, void *data); +@@ -323,6 +335,7 @@ static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); + static void setfullscreen(Client *c, int fullscreen); ++static void setgaps(int oh, int ov, int ih, int iv); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); +@@ -336,6 +349,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); + static void togglefullscreen(const Arg *arg); ++static void togglegaps(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); +@@ -405,6 +419,7 @@ static struct wlr_output_layout *output_layout; + static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; ++static int enablegaps = 1; /* enables gaps, used by togglegaps */ + + /* global event handlers */ + static struct wl_listener cursor_axis = {.notify = axisnotify}; +@@ -1048,6 +1063,11 @@ createmon(struct wl_listener *listener, void *data) + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); + ++ m->gappih = gappih; ++ m->gappiv = gappiv; ++ m->gappoh = gappoh; ++ m->gappov = gappov; ++ + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->tagset[0] = m->tagset[1] = 1; +@@ -1230,6 +1250,12 @@ cursorwarptohint(void) + } + } + ++void ++defaultgaps(const Arg *arg) ++{ ++ setgaps(gappoh, gappov, gappih, gappiv); ++} ++ + void + destroydecoration(struct wl_listener *listener, void *data) + { +@@ -1566,6 +1592,83 @@ incnmaster(const Arg *arg) + arrange(selmon); + } + ++void ++incgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incigaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incihgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv ++ ); ++} ++ ++void ++incivgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incogaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incohgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incovgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ + void + inputdevice(struct wl_listener *listener, void *data) + { +@@ -2357,6 +2460,16 @@ setfullscreen(Client *c, int fullscreen) + printstatus(); + } + ++void ++setgaps(int oh, int ov, int ih, int iv) ++{ ++ selmon->gappoh = MAX(oh, 0); ++ selmon->gappov = MAX(ov, 0); ++ selmon->gappih = MAX(ih, 0); ++ selmon->gappiv = MAX(iv, 0); ++ arrange(selmon); ++} ++ + void + setlayout(const Arg *arg) + { +@@ -2701,7 +2814,7 @@ tagmon(const Arg *arg) + void + tile(Monitor *m) + { +- unsigned int mw, my, ty; ++ unsigned int mw, my, ty, h, r, oe = enablegaps, ie = enablegaps; + int i, n = 0; + Client *c; + +@@ -2711,22 +2824,31 @@ tile(Monitor *m) + if (n == 0) + return; + ++ if (smartgaps == n) { ++ oe = 0; // outer gaps disabled ++ } ++ + if (n > m->nmaster) +- mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; ++ mw = m->nmaster ? (int)roundf((m->w.width + m->gappiv*ie) * m->mfact) : 0; + else +- mw = m->w.width; +- i = my = ty = 0; ++ mw = m->w.width - 2*m->gappov*oe + m->gappiv*ie; ++ i = 0; ++ my = ty = m->gappoh*oe; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, +- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); +- my += c->geom.height; ++ r = MIN(n, m->nmaster) - i; ++ h = (m->w.height - my - m->gappoh*oe - m->gappih*ie * (r - 1)) / r; ++ resize(c, (struct wlr_box){.x = m->w.x + m->gappov*oe, .y = m->w.y + my, ++ .width = mw - m->gappiv*ie, .height = h}, 0); ++ my += c->geom.height + m->gappih*ie; + } else { +- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, +- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); +- ty += c->geom.height; ++ r = n - i; ++ h = (m->w.height - ty - m->gappoh*oe - m->gappih*ie * (r - 1)) / r; ++ resize(c, (struct wlr_box){.x = m->w.x + mw + m->gappov*oe, .y = m->w.y + ty, ++ .width = m->w.width - mw - 2*m->gappov*oe, .height = h}, 0); ++ ty += c->geom.height + m->gappih*ie; + } + i++; + } +@@ -2749,6 +2871,13 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglegaps(const Arg *arg) ++{ ++ enablegaps = !enablegaps; ++ arrange(selmon); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.48.0 + + +From e3d10f01df9b7d6735ce9e43ebfdca35b8639f0e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= + +Date: Wed, 20 Jul 2022 00:15:32 -0500 +Subject: [PATCH 2/2] allow gaps in monocle layout if requested +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + config.def.h | 1 + + dwl.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 39e528b1..f4d4095d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,7 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ ++static const int monoclegaps = 0; /* 1 means outer gaps in monocle layout */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int gappih = 10; /* horiz inner gap between windows */ + static const unsigned int gappiv = 10; /* vert inner gap between windows */ +diff --git a/dwl.c b/dwl.c +index fa823957..59eabb54 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1922,8 +1922,12 @@ monocle(Monitor *m) + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; +- resize(c, m->w, 0); + n++; ++ if (!monoclegaps) ++ resize(c, m->w, 0); ++ else ++ resize(c, (struct wlr_box){.x = m->w.x + gappoh, .y = m->w.y + gappov, ++ .width = m->w.width - 2 * gappoh, .height = m->w.height - 2 * gappov}, 0); + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); +-- +2.48.0 + diff --git a/dwl/dwl-patches/patches/varcol/README.md b/dwl/dwl-patches/patches/varcol/README.md new file mode 100755 index 0000000..9e5b1b0 --- /dev/null +++ b/dwl/dwl-patches/patches/varcol/README.md @@ -0,0 +1,15 @@ +### Description +A variable column layout. + +This layout behaves much the same as the `tile` layout, but adds key bindings that can be used to: +- Increase/decrease the number of non-master columns +- Increase/decrease the colfact to adjust the column spacing +- Push a client in or out of a special `left` column +- Toggle displaying the special `left` column + +### Download +- [git branch](https://codeberg.org/minego/dwl/src/branch/varcol) +- [2024-03-27](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/varcol/varcol.patch) + +### Authors +- [minego](https://codeberg.org/minego) diff --git a/dwl/dwl-patches/patches/varcol/varcol.patch b/dwl/dwl-patches/patches/varcol/varcol.patch new file mode 100755 index 0000000..b94baa2 --- /dev/null +++ b/dwl/dwl-patches/patches/varcol/varcol.patch @@ -0,0 +1,618 @@ +From 24c197ea93388c222b72c2192b968aa80b444a9a Mon Sep 17 00:00:00 2001 +From: Micah N Gorrell +Date: Wed, 27 Mar 2024 12:32:49 -0600 +Subject: [PATCH] varcol layout + +--- + config.def.h | 25 ++- + dwl.c | 29 ++++ + varcol.c | 429 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 480 insertions(+), 3 deletions(-) + create mode 100644 varcol.c + +diff --git a/config.def.h b/config.def.h +index 9009517..9345ff2 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -21,16 +21,18 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + static int log_level = WLR_ERROR; + + static const Rule rules[] = { +- /* app_id title tags mask isfloating monitor */ ++ /* app_id title tags mask isfloating monitor isLeft */ + /* examples: +- { "Gimp", NULL, 0, 1, -1 }, ++ { "Gimp", NULL, 0, 1, -1, 0 }, ++ { "slack", NULL, 0, 1, -1, 1 }, + */ +- { "firefox", NULL, 1 << 8, 0, -1 }, ++ { "firefox", NULL, 1 << 8, 0, -1, 0 }, + }; + + /* layout(s) */ + static const Layout layouts[] = { + /* symbol arrange function */ ++ { "=O=", varcol }, /* first entry is default */ + { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +@@ -152,8 +154,25 @@ static const Key keys[] = { + TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), + TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), + TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), ++ + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Tab, pushleft, {0}}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_ISO_Left_Tab,pushleft, {0}}, ++ ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_I, incncols, {.i = +1 }}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_D, incncols, {.i = -1 }}, ++ { MODKEY, XKB_KEY_h, setcolfact, {.f = -0.05 }}, ++ { MODKEY, XKB_KEY_l, setcolfact, {.f = +0.05 }}, ++ ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Tab, pushleft, {0}}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_ISO_Left_Tab,pushleft, {0}}, ++ ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_I, incncols, {.i = +1}}, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_D, incncols, {.i = -1 }}, ++ { MODKEY, XKB_KEY_h, setcolfact, {.f = -0.05 }}, ++ { MODKEY, XKB_KEY_l, setcolfact, {.f = +0.05 }}, ++ + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ + { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, + /* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is +diff --git a/dwl.c b/dwl.c +index 5867b0c..35343e7 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -139,6 +139,8 @@ typedef struct { + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ ++ int isLeft; ++ float cfact; + } Client; + + typedef struct { +@@ -205,6 +207,18 @@ struct Monitor { + int gamma_lut_changed; + int nmaster; + char ltsymbol[16]; ++ float colfact[3]; /* Relative sizes of the different column types */ ++ int nmastercols; /* The number of master columns to use */ ++ int nrightcols; /* The number of right "stack" columns to use */ ++ ++ /* ++ NOTE: This patch does not set these values, but leaves these here as a ++ placeholder to make it easier to merge with patches that do set gaps. ++ */ ++ int gappih; /* horizontal gap between windows */ ++ int gappiv; /* vertical gap between windows */ ++ int gappoh; /* horizontal outer gaps */ ++ int gappov; /* vertical outer gaps */ + }; + + typedef struct { +@@ -228,6 +242,7 @@ typedef struct { + uint32_t tags; + int isfloating; + int monitor; ++ int isLeft; + } Rule; + + typedef struct { +@@ -284,6 +299,7 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); ++static void incncols(const Arg *arg); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); + static int keybinding(uint32_t mods, xkb_keysym_t sym); +@@ -307,6 +323,7 @@ static void outputmgrtest(struct wl_listener *listener, void *data); + static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); + static void printstatus(void); ++static void pushleft(const Arg *arg); + static void quit(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); +@@ -314,6 +331,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); + static void run(char *startup_cmd); ++static void setcolfact(const Arg *arg); + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -340,6 +358,7 @@ static void unmapnotify(struct wl_listener *listener, void *data); + static void updatemons(struct wl_listener *listener, void *data); + static void updatetitle(struct wl_listener *listener, void *data); + static void urgent(struct wl_listener *listener, void *data); ++static void varcol(Monitor *m); + static void view(const Arg *arg); + static void virtualkeyboard(struct wl_listener *listener, void *data); + static void virtualpointer(struct wl_listener *listener, void *data); +@@ -351,6 +370,7 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static pid_t child_pid = -1; ++static const float colfact[3] = { 0.1f, 0.6f, 0.3f }; /* The relative factors for the size of each column */ + static int locked; + static void *exclusive_focus; + static struct wl_display *dpy; +@@ -457,12 +477,16 @@ applyrules(Client *c) + appid = broken; + if (!(title = client_get_title(c))) + title = broken; ++ c->isLeft = 0; + + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; + newtags |= r->tags; ++ if (r->isLeft >= 0) { ++ c->isLeft = r->isLeft; ++ } + i = 0; + wl_list_for_each(m, &mons, link) { + if (r->monitor == i++) +@@ -882,6 +906,9 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->tagset[0] = m->tagset[1] = 1; ++ m->colfact[0] = colfact[0]; ++ m->colfact[1] = colfact[1]; ++ m->colfact[2] = colfact[2]; + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; +@@ -2929,6 +2956,8 @@ zoom(const Arg *arg) + arrange(selmon); + } + ++#include "varcol.c" ++ + #ifdef XWAYLAND + void + activatex11(struct wl_listener *listener, void *data) +diff --git a/varcol.c b/varcol.c +new file mode 100644 +index 0000000..30fdb85 +--- /dev/null ++++ b/varcol.c +@@ -0,0 +1,429 @@ ++#include ++ ++static inline void ++client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min) ++{ ++ struct wlr_xdg_toplevel *toplevel; ++ struct wlr_xdg_toplevel_state *state; ++#ifdef XWAYLAND ++ if (client_is_x11(c)) { ++ xcb_size_hints_t *size_hints = c->surface.xwayland->size_hints; ++ if (size_hints) { ++ max->width = size_hints->max_width; ++ max->height = size_hints->max_height; ++ min->width = size_hints->min_width; ++ min->height = size_hints->min_height; ++ } ++ return; ++ } ++#endif ++ toplevel = c->surface.xdg->toplevel; ++ state = &toplevel->current; ++ max->width = state->max_width; ++ max->height = state->max_height; ++ min->width = state->min_width; ++ min->height = state->min_height; ++} ++ ++static int isleft(Client *c); ++ ++/* ++ Variable Column Layout ++ ++ - Special 'left' column, with helper to move clients in or out of the left ++ column. This is useful for things like chat, or status monitor windows that ++ you want to keep visible. ++ ++ - Variable number of master columns ++ - Variable number of right columns ++ - Variable number of master windows ++ ++ // TODO Calculate remainders ++*/ ++ ++/* ++ Move a client within a column ++ ++ w The width of the column ++ x The left position of the column ++ offset The offset of this client within the column ++ count The number of clients in the column ++*/ ++static void placeClientInColumn(Monitor *m, Client *c, int w, int x, int offset, int count, int totaln) ++{ ++ struct wlr_box geom = {0}; ++ int monheight = m->w.height; ++ ++ if (totaln > 1) { ++ /* The total available space does not include the outer vertical gapps */ ++ monheight -= (2 * m->gappov); ++ ++ /* ++ Each client removes the inner vertical gapp from its own height, ++ but that leaves us off by one so account for that here. ++ */ ++ monheight += m->gappiv; ++ } ++ ++ geom.width = w; ++ geom.height = (int) floor(monheight / count); ++ ++ geom.x = x; ++ geom.y = m->w.y + (offset * geom.height); ++ ++ /* Adjust the height to account for gapps AFTER adjusting the y position */ ++ if (totaln > 1) { ++ geom.height -= m->gappiv; ++ } ++ ++ resize(c, geom, 0); ++} ++ ++/* ++ variable column layout ++ ++ This layout has a variable number of columns, in 3 categories. ++ 0-1 small left columns, containing clients that have been "pushed" left ++ 1-n master columns ++ 0-n right columns ++*/ ++void varcol(Monitor *m) ++{ ++ int i, mastern, masterw, rightn, leftw, rightw, x, monwidth; ++ unsigned int leftn, totaln, coln, offset; ++ float colfacts; ++ Client *c, *tmp; ++ int nmastercols = m->nmastercols; ++ int nrightcols = m->nrightcols; ++ struct wl_list left_clients; ++ ++ /* ++ Remove each of window that belongs in the left column, so they can be ++ reattached at the end of the list below. ++ */ ++ wl_list_init(&left_clients); ++ ++ i = 0; ++ wl_list_for_each_safe(c, tmp, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) { ++ continue; ++ } ++ ++ if (i < m->nmaster) { ++ /* Master */ ++ ; ++ } else if (isleft(c)) { ++ /* Left; Detach and put in the left list */ ++ wl_list_remove(&c->link); ++ wl_list_insert(&left_clients, &c->link); ++ } ++ ++ i++; ++ } ++ ++ /* Reattach the left clients to the main list */ ++ wl_list_for_each_reverse_safe(c, tmp, &left_clients, link) { ++ wl_list_remove(&c->link); ++ wl_list_insert(clients.prev, &c->link); ++ } ++ ++ /* Count the windows for each column type */ ++ totaln = leftn = rightn = mastern = 0; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) { ++ continue; ++ } ++ ++ if (mastern < m->nmaster) { ++ mastern++; ++ } else if (isleft(c)) { ++ leftn++; ++ } else { ++ rightn++; ++ } ++ ++ totaln++; ++ } ++ ++ nmastercols = MAX(MIN(mastern, nmastercols), 1); ++ nrightcols = MAX(MIN(rightn, nrightcols), 1); ++ ++ if (mastern == 0) { ++ return; ++ } ++ ++ /* Calculate the total colfacts value */ ++ colfacts = 0; ++ ++ /* Left column */ ++ if (leftn > 0) { ++ colfacts += m->colfact[0]; ++ } ++ ++ /* Center column(s) */ ++ for (i = 0; i < nmastercols; i++) { ++ colfacts += m->colfact[1]; ++ } ++ ++ /* Right column(s) */ ++ if (rightn > 0) { ++ for (i = 0; i < nrightcols; i++) { ++ colfacts += m->colfact[2]; ++ } ++ } ++ ++ /* Calculate the usable width, with gapps removed */ ++ monwidth = m->w.width; ++ ++ if (rightn > 0) { ++ /* Gap to the left of reach right column */ ++ monwidth -= m->gappih * nrightcols; ++ } ++ if (leftn > 0) { ++ /* Gap on the right of the left column */ ++ monwidth -= m->gappih; ++ } ++ ++ if (totaln > 1) { ++ /* Outer gaps */ ++ monwidth -= (2 * m->gappoh); ++ } ++ ++ /* Calculate the width for each column type */ ++ leftw = (int) ((monwidth / colfacts) * m->colfact[0]); ++ masterw = (int) ((monwidth / colfacts) * m->colfact[1]); ++ rightw = (int) ((monwidth / colfacts) * m->colfact[2]); ++ ++ /* Adjust right and left column to fit all clients */ ++ wl_list_for_each(c, &clients, link) { ++ struct wlr_box min = {0}, max = {0}; ++ ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) { ++ continue; ++ } ++ ++ /* Get client size hints */ ++ client_get_size_hints(c, &max, &min); ++ ++ if (i < mastern) { ++ /* Master columns */ ++ ++ } else if (!isleft(c)) { ++ /* Right columns */ ++ x = min.width - rightw; ++ if (x > 0) { ++ rightw += x; ++ masterw -= x; ++ } ++ } else if (leftn > 0) { ++ /* left column */ ++ x = min.width - leftw; ++ if (x > 0) { ++ leftw += x; ++ masterw -= x; ++ } ++ } ++ } ++ ++ /* Place each client */ ++ x = m->w.x; ++ if (leftn > 0) { ++ x += leftw; ++ x += m->gappih; ++ } ++ if (totaln > 1) { ++ x += m->gappoh; ++ } ++ ++ i = 0; ++ wl_list_for_each(c, &clients, link) { ++ struct wlr_box min = {0}, max = {0}; ++ ++ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) { ++ continue; ++ } ++ ++ /* Get client size hints */ ++ client_get_size_hints(c, &max, &min); ++ ++ if (i < mastern) { ++ /* Master columns */ ++ ++ /* Offset within the section */ ++ offset = i; ++ ++ /* Max number of items in each master column */ ++ coln = (unsigned int) ceil((float) mastern / nmastercols); ++ ++ placeClientInColumn(m, c, masterw, x, offset % coln, coln, totaln); ++ ++ /* Only increment x if this is the last client in this column */ ++ if ((++offset % coln) == 0) { ++ x += masterw; ++ x += m->gappih; ++ } ++ } else if (!isleft(c)) { ++ /* Right columns */ ++ ++ /* Offset within the section */ ++ offset = (i - mastern); ++ ++ /* Max number of items in each right column */ ++ coln = (unsigned int) ceil((float) rightn / nrightcols); ++ ++ placeClientInColumn(m, c, rightw, x, offset % coln, coln, totaln); ++ ++ /* Only increment x if this is the last client in this column */ ++ if ((++offset % coln) == 0) { ++ x += rightw; ++ x += m->gappih; ++ } ++ } else if (leftn > 0) { ++ /* left column */ ++ x = m->w.x; ++ if (totaln > 1) { ++ x += m->gappoh; ++ } ++ ++ /* Offset within the section */ ++ offset = i - (mastern + rightn); ++ ++ /* There is only one left column */ ++ coln = leftn; ++ ++ placeClientInColumn(m, c, leftw, x, offset, leftn, totaln); ++ } ++ ++ i++; ++ } ++} ++ ++static int isleft(Client *c) ++{ ++ if (c == NULL) { ++ return 0; ++ } ++ ++ if (c->mon != NULL && c->mon->m.width <= 2000) { ++ /* The left column is not worth using on a small monitor */ ++ return 0; ++ } ++ ++ return c->isLeft; ++} ++ ++/* Return non-zero if the currently selected client is in a master column */ ++static int ismaster(void) ++{ ++ Client *c, *sel = focustop(selmon); ++ int i; ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) { ++ return 0; ++ } ++ ++ i = 0; ++ wl_list_for_each(c, &clients, link) { ++ if (!VISIBLEON(c, selmon) || c->isfloating || c->isfullscreen) { ++ continue; ++ } ++ ++ if (sel == c) { ++ /* c is the selected client, and is index i */ ++ if (i < selmon->nmaster) { ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++ i++; ++ } ++ ++ return 0; ++} ++ ++/* A value >= 1.0 sets that colfact to that value - 1.0 */ ++void setcolfact(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ int index = 1; ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) { ++ return; ++ } ++ ++ if (ismaster()) { ++ index = 0; ++ /* master */ ++ index = 0; ++ } else if (isleft(sel)) { ++ /* left */ ++ index = -1; ++ } else { ++ /* right */ ++ index = 1; ++ } ++ index++; ++ ++ if (arg->f >= 1.0) { ++ selmon->colfact[index] = arg->f - 1.0f; ++ } else { ++ /* Adjust the argument based on the selected column */ ++ selmon->colfact[index] += arg->f; ++ } ++ ++ if (selmon->colfact[index] < 0.1) { ++ selmon->colfact[index] = 0.1f; ++ } else if (selmon->colfact[index] > 0.9) { ++ selmon->colfact[index] = 0.9f; ++ } ++ arrange(selmon); ++} ++ ++static void pushleft(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) { ++ return; ++ } ++ ++ sel->isLeft = !sel->isLeft; ++ focusclient(sel, 1); ++ arrange(selmon); ++} ++ ++/* ++ Modify either the right or master column count ++*/ ++void incncols(const Arg *arg) ++{ ++ Client *sel = focustop(selmon); ++ ++ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) { ++ return; ++ } ++ ++ if (selmon->nmastercols < 1) selmon->nmastercols = 1; ++ if (selmon->nrightcols < 1) selmon->nrightcols = 1; ++ ++ if (ismaster()) { ++ /* master */ ++ selmon->nmastercols += arg->i; ++ ++ /* Auto adjust nmaster as well */ ++ selmon->nmaster = selmon->nmastercols; ++ } else if (isleft(sel)) { ++ /* left */ ++ ; ++ } else { ++ /* right */ ++ selmon->nrightcols += arg->i; ++ } ++ ++ if (selmon->nmastercols < 1) selmon->nmastercols = 1; ++ if (selmon->nrightcols < 1) selmon->nrightcols = 1; ++ ++ arrange(selmon); ++} ++ +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/viewnextocctag/README.md b/dwl/dwl-patches/patches/viewnextocctag/README.md new file mode 100755 index 0000000..d1a43d2 --- /dev/null +++ b/dwl/dwl-patches/patches/viewnextocctag/README.md @@ -0,0 +1,9 @@ +### Description +View the next or previous tag, skipping any tags that do not have any clients. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/viewnextocctag) +- [2023-01-06](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/viewnextocctag/viewnextocctag.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) diff --git a/dwl/dwl-patches/patches/viewnextocctag/viewnextocctag.patch b/dwl/dwl-patches/patches/viewnextocctag/viewnextocctag.patch new file mode 100755 index 0000000..f797431 --- /dev/null +++ b/dwl/dwl-patches/patches/viewnextocctag/viewnextocctag.patch @@ -0,0 +1,92 @@ +From 330fa634a83e9b332494fade75552e02583bad6c Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Sat, 30 Dec 2023 13:39:31 +1000 +Subject: [PATCH] viewnextocctag + +--- + config.def.h | 2 ++ + dwl.c | 34 ++++++++++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a784eb4f..e1a6a428 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -130,6 +130,8 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, viewnextocctag, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, viewnextocctag, {.i = +1} }, + { MODKEY, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, +diff --git a/dwl.c b/dwl.c +index 6f041a0d..df5461d0 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -304,6 +304,7 @@ static void motionnotify(uint32_t time, struct wlr_input_device *device, double + double sy, double sx_unaccel, double sy_unaccel); + static void motionrelative(struct wl_listener *listener, void *data); + static void moveresize(const Arg *arg); ++unsigned int nextocctag(int); + static void outputmgrapply(struct wl_listener *listener, void *data); + static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); + static void outputmgrtest(struct wl_listener *listener, void *data); +@@ -344,6 +345,7 @@ static void updatemons(struct wl_listener *listener, void *data); + static void updatetitle(struct wl_listener *listener, void *data); + static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); ++static void viewnextocctag(const Arg *argint); + static void virtualkeyboard(struct wl_listener *listener, void *data); + static void virtualpointer(struct wl_listener *listener, void *data); + static Monitor *xytomon(double x, double y); +@@ -1868,6 +1870,27 @@ moveresize(const Arg *arg) + } + } + ++unsigned int ++nextocctag(int direction) ++{ ++ unsigned int seltag = selmon->tagset[selmon->seltags]; ++ unsigned int occ = 0, i; ++ Client *c; ++ ++ wl_list_for_each(c, &clients, link) ++ occ |= c->tags; ++ ++ for (i=0; i 0) ? ++ (seltag == (1u << (TAGCOUNT - 1)) ? 1u : seltag << 1) : ++ (seltag == 1 ? (1u << (TAGCOUNT - 1)) : seltag >> 1); ++ if (seltag & occ) ++ break; ++ } ++ ++ return seltag & TAGMASK; ++} ++ + void + outputmgrapply(struct wl_listener *listener, void *data) + { +@@ -2852,6 +2875,17 @@ view(const Arg *arg) + printstatus(); + } + ++void ++viewnextocctag(const Arg *arg) ++{ ++ unsigned int tmp; ++ ++ if ((tmp = nextocctag(arg->i)) == selmon->tagset[selmon->seltags]) ++ return; ++ ++ view(&(const Arg){.ui = tmp}); ++} ++ + void + virtualkeyboard(struct wl_listener *listener, void *data) + { +-- +2.45.1 + diff --git a/dwl/dwl-patches/patches/virtual-pointer/README.md b/dwl/dwl-patches/patches/virtual-pointer/README.md new file mode 100755 index 0000000..451d26e --- /dev/null +++ b/dwl/dwl-patches/patches/virtual-pointer/README.md @@ -0,0 +1,12 @@ +### Description +implement wlr_virtual_pointer_v1 for things like wayvnc server to work + +**NOTE:** no longer neccessary if you are using a DWL version after https://codeberg.org/dwl/dwl/commit/ac6074f4fdb8cc263c877f08e16a5805d3bb22d2 + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/v0.5/virtual-pointer) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/0096e49402bc59b4050e12cdb9befb79d0011006/virtual-pointer/virtual-pointer.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [youbitchoc](https://github.com/youbitchoc) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/virtual-pointer/virtual-pointer.patch b/dwl/dwl-patches/patches/virtual-pointer/virtual-pointer.patch new file mode 100755 index 0000000..e0a1803 --- /dev/null +++ b/dwl/dwl-patches/patches/virtual-pointer/virtual-pointer.patch @@ -0,0 +1,126 @@ +From 4ab53a41256c8f2eac4c003c43b798b6aa312919 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Mon, 8 Apr 2024 11:39:18 -0500 +Subject: [PATCH] implement virtual-pointer + +--- + dwl.c | 49 +++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 39 insertions(+), 10 deletions(-) + +diff --git a/dwl.c b/dwl.c +index ef27a1d..20840cd 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -318,11 +319,13 @@ static void toggleview(const Arg *arg); + static void unlocksession(struct wl_listener *listener, void *data); + static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); + static void unmapnotify(struct wl_listener *listener, void *data); ++static void updatecapabilities(void); + static void updatemons(struct wl_listener *listener, void *data); + static void updatetitle(struct wl_listener *listener, void *data); + static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); + static void virtualkeyboard(struct wl_listener *listener, void *data); ++static void virtualpointer(struct wl_listener *listener, void *data); + static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); +@@ -357,6 +360,7 @@ static struct wlr_output_manager_v1 *output_mgr; + static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; + static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; + static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; ++static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; + + static struct wlr_cursor *cursor; + static struct wlr_xcursor_manager *cursor_mgr; +@@ -1338,7 +1342,6 @@ inputdevice(struct wl_listener *listener, void *data) + /* This event is raised by the backend when a new input device becomes + * available. */ + struct wlr_input_device *device = data; +- uint32_t caps; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: +@@ -1351,15 +1354,8 @@ inputdevice(struct wl_listener *listener, void *data) + /* TODO handle other input device types */ + break; + } +- +- /* We need to let the wlr_seat know what our capabilities are, which is +- * communiciated to the client. In dwl we always have a cursor, even if +- * there are no pointer devices, so we always include that capability. */ +- /* TODO do we actually require a cursor? */ +- caps = WL_SEAT_CAPABILITY_POINTER; +- if (!wl_list_empty(&keyboards)) +- caps |= WL_SEAT_CAPABILITY_KEYBOARD; +- wlr_seat_set_capabilities(seat, caps); ++ ++ updatecapabilities(); + } + + int +@@ -2331,6 +2327,8 @@ setup(void) + LISTEN_STATIC(&backend->events.new_input, inputdevice); + virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); ++ virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); ++ LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); + seat = wlr_seat_create(dpy, "seat0"); + LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); + LISTEN_STATIC(&seat->events.request_set_selection, setsel); +@@ -2536,6 +2534,21 @@ unmapnotify(struct wl_listener *listener, void *data) + motionnotify(0); + } + ++void ++updatecapabilities(void) ++{ ++ uint32_t caps; ++ ++ /* We need to let the wlr_seat know what our capabilities are, which is ++ * communicated to the client. In dwl we always have a cursor, even if ++ * there are no pointer devices, so we always include that capability. */ ++ /* TODO do we actually require a cursor? */ ++ caps = WL_SEAT_CAPABILITY_POINTER; ++ if (!wl_list_empty(&keyboards)) ++ caps |= WL_SEAT_CAPABILITY_KEYBOARD; ++ wlr_seat_set_capabilities(seat, caps); ++} ++ + void + updatemons(struct wl_listener *listener, void *data) + { +@@ -2674,6 +2687,22 @@ virtualkeyboard(struct wl_listener *listener, void *data) + { + struct wlr_virtual_keyboard_v1 *keyboard = data; + createkeyboard(&keyboard->keyboard); ++ updatecapabilities(); ++} ++ ++void ++virtualpointer(struct wl_listener *listener, void *data) ++{ ++ struct wlr_virtual_pointer_v1_new_pointer_event *event = data; ++ struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; ++ struct wlr_input_device *device = &pointer->pointer.base; ++ createpointer(&pointer->pointer); ++ updatecapabilities(); ++ ++ if (event->suggested_output) { ++ wlr_cursor_map_input_to_output(cursor, device, ++ event->suggested_output); ++ } + } + + Monitor * +-- +2.43.2 + diff --git a/dwl/dwl-patches/patches/warpcursor/README.md b/dwl/dwl-patches/patches/warpcursor/README.md new file mode 100755 index 0000000..34dadb9 --- /dev/null +++ b/dwl/dwl-patches/patches/warpcursor/README.md @@ -0,0 +1,15 @@ +### Description +Warp cursor to the centre of newly focused clients. + +Only moves the cursor if the cursor is currently not on the new client. + +This is my version of the orphaned cursorwarp patch except I left out the +config flag as I think it is unnecessary. + +### Download +- [git branch](https://codeberg.org/bencc/dwl/src/branch/warpcursor) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/warpcursor/warpcursor.patch) + +### Authors +- [Ben Collerson](https://codeberg.org/bencc) +- [Faerryn](https://github.com/faerryn) diff --git a/dwl/dwl-patches/patches/warpcursor/warpcursor.patch b/dwl/dwl-patches/patches/warpcursor/warpcursor.patch new file mode 100755 index 0000000..6ac0329 --- /dev/null +++ b/dwl/dwl-patches/patches/warpcursor/warpcursor.patch @@ -0,0 +1,71 @@ +From 4951ccc89dac2b557994b2f6c3aacb2398e2d1b1 Mon Sep 17 00:00:00 2001 +From: Ben Collerson +Date: Thu, 4 Jan 2024 20:30:01 +1000 +Subject: [PATCH] warpcursor + +--- + dwl.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/dwl.c b/dwl.c +index 145fd018..f7ad6c13 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -347,6 +347,7 @@ static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); + static void virtualkeyboard(struct wl_listener *listener, void *data); + static void virtualpointer(struct wl_listener *listener, void *data); ++static void warpcursor(const Client *c); + static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); +@@ -514,6 +515,7 @@ arrange(Monitor *m) + m->lt[m->sellt]->arrange(m); + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); ++ warpcursor(focustop(selmon)); + } + + void +@@ -1323,6 +1325,10 @@ focusclient(Client *c, int lift) + if (locked) + return; + ++ /* Warp cursor to center of client if it is outside */ ++ if (lift) ++ warpcursor(c); ++ + /* Raise client in stacking order if requested */ + if (c && lift) + wlr_scene_node_raise_to_top(&c->scene->node); +@@ -2927,6 +2933,27 @@ virtualpointer(struct wl_listener *listener, void *data) + wlr_cursor_map_input_to_output(cursor, &pointer.base, event->suggested_output); + } + ++void ++warpcursor(const Client *c) { ++ if (cursor_mode != CurNormal) { ++ return; ++ } ++ if (!c && selmon) { ++ wlr_cursor_warp_closest(cursor, ++ NULL, ++ selmon->w.x + selmon->w.width / 2.0 , ++ selmon->w.y + selmon->w.height / 2.0); ++ } ++ else if ( c && (cursor->x < c->geom.x || ++ cursor->x > c->geom.x + c->geom.width || ++ cursor->y < c->geom.y || ++ cursor->y > c->geom.y + c->geom.height)) ++ wlr_cursor_warp_closest(cursor, ++ NULL, ++ c->geom.x + c->geom.width / 2.0, ++ c->geom.y + c->geom.height / 2.0); ++} ++ + Monitor * + xytomon(double x, double y) + { +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/wayland-socket-handover/README.md b/dwl/dwl-patches/patches/wayland-socket-handover/README.md new file mode 100755 index 0000000..ffc278a --- /dev/null +++ b/dwl/dwl-patches/patches/wayland-socket-handover/README.md @@ -0,0 +1,21 @@ +### Description + +When your Wayland compositor crashes, your entire session dies with it. This +patch allows your session to survive a restart or crash of dwl by passing in +the Wayland socket from an outside wrapper program such as +[wl-restart](https://github.com/Ferdi265/wl-restart). + +To use, apply this patch and start dwl with `wl-restart --env dwl [args...]`. +This automatically restarts dwl when it crashes and tries to keep applications +alive. + +Currently, only **Qt6** supports surviving a compositor restart. The +environment variable `QT_WAYLAND_RECONNECT=1` needs to be set in order for Qt +apps to stay alive when the compositor crashes. + +## Download +- [git branch](https://codeberg.org/yrlf/dwl/src/branch/feature-socket-handover) +- [2025-03-26](https://codeberg.org/yrlf/dwl-patches/raw/branch/main/patches/wayland-socket-handover/wayland-socket-handover.patch) + +### Authors +- [yrlf](https://codeberg.org/yrlf) diff --git a/dwl/dwl-patches/patches/wayland-socket-handover/wayland-socket-handover.patch b/dwl/dwl-patches/patches/wayland-socket-handover/wayland-socket-handover.patch new file mode 100755 index 0000000..ad026ff --- /dev/null +++ b/dwl/dwl-patches/patches/wayland-socket-handover/wayland-socket-handover.patch @@ -0,0 +1,81 @@ +From 1513c816f834b1620313e69318e2789aa2f091d0 Mon Sep 17 00:00:00 2001 +From: Ferdinand Bachmann +Date: Wed, 26 Mar 2025 17:18:17 +0100 +Subject: [PATCH] startup: implement wayland socket handover (wl-restart --env + mechanism) + +--- + dwl.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 45 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index 4816159..2f2ed02 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2232,11 +2233,54 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + } + ++static const char* ++perform_socket_handover(void) ++{ ++ char *socket_name = NULL; ++ int socket_fd = -1; ++ ++ /* Parse wayland socket handover environment variables */ ++ if (getenv("WAYLAND_SOCKET_NAME")) { ++ socket_name = getenv("WAYLAND_SOCKET_NAME"); ++ unsetenv("WAYLAND_SOCKET_NAME"); ++ } ++ ++ if (getenv("WAYLAND_SOCKET_FD")) { ++ socket_fd = atoi(getenv("WAYLAND_SOCKET_FD")); ++ unsetenv("WAYLAND_SOCKET_FD"); ++ fcntl(socket_fd, F_SETFD, FD_CLOEXEC); ++ } ++ ++ /* Warn if either environment variable is missing */ ++ if (!socket_name && socket_fd == -1) { ++ return NULL; ++ } else if (!socket_name) { ++ fprintf(stderr, "Wayland socket handover failed, missing WAYLAND_SOCKET_FD\n"); ++ return NULL; ++ } else if (socket_fd == -1) { ++ fprintf(stderr, "Wayland socket handover failed, missing WAYLAND_SOCKET_NAME\n"); ++ return NULL; ++ } ++ ++ /* Add socket to the Wayland display */ ++ if (wl_display_add_socket_fd(dpy, socket_fd) < 0) { ++ fprintf(stderr, "Wayland socket handover failed, failed to add socket FD to display\n"); ++ return NULL; ++ } ++ ++ return socket_name; ++} ++ + void + run(char *startup_cmd) + { ++ /* Attempt Wayland socket handover. */ ++ const char *socket = perform_socket_handover(); ++ + /* Add a Unix socket to the Wayland display. */ +- const char *socket = wl_display_add_socket_auto(dpy); ++ if (!socket) ++ socket = wl_display_add_socket_auto(dpy); ++ + if (!socket) + die("startup: display_add_socket_auto"); + setenv("WAYLAND_DISPLAY", socket, 1); +-- +2.49.0 + diff --git a/dwl/dwl-patches/patches/winview/README.md b/dwl/dwl-patches/patches/winview/README.md new file mode 100755 index 0000000..4fb8dd5 --- /dev/null +++ b/dwl/dwl-patches/patches/winview/README.md @@ -0,0 +1,35 @@ +### Description +Implements the function `winview` which switches the visible tags to the tags on which the current client is visible. + +This patch is inspired from . Citing the description of the dwm patch: + +> Dwm tags are a powerfull feature that allows organizing windows in workspaces. Sometime it can be difficult to remember the tag to activate to unhide a window. With the winview patch the window to unhide can be selected from the all-window view. The user switches to the all-window view (Mod1-0), selects the window (Mod1-j/k or using the mouse) and press Mod1-o. The key Mod1-o switches the view to the selected window tag. +> +> #### Recommend patches +> +> The grid layout is well adapted to display many windows in a limited space. Using both grid and pertag patches you will be able to select this layout for the all-window view while keeping your preferred layout for the other views. +> Configuration and Installation +> Using the default configuration file +> +> Make sure the directory where you build dwm does not contain a config.h file; +> Apply the patch; +> Run make and make install. +> +> Using an existing customised configuration file +> +> Apply the patch; Add the following element in the keys array: +> +> `{ MODKEY, XK_o, winview, {0} },` +> +> Run make and make install. +> +> An example of how to insert this line can be found in the default config file template, config.def.h. + +### Download +- [2024-09-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/winview/winview.patch) +- [2024-06-06](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/winview/winview-20240606.patch) +- [git branch](https://codeberg.org/dhruva_sambrani/dwl/src/branch/winview) + +### Authors +- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani) + diff --git a/dwl/dwl-patches/patches/winview/winview-20240606.patch b/dwl/dwl-patches/patches/winview/winview-20240606.patch new file mode 100755 index 0000000..d3fc099 --- /dev/null +++ b/dwl/dwl-patches/patches/winview/winview-20240606.patch @@ -0,0 +1,42 @@ +diff --git a/config.def.h b/config.def.h +index a784eb4..d09ee55 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -140,6 +140,7 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, ++ { MODKEY, XKB_KEY_o, winview, {0}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, +diff --git a/dwl.c b/dwl.c +index 6f041a0..65df112 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -346,6 +346,7 @@ static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); + static void virtualkeyboard(struct wl_listener *listener, void *data); + static void virtualpointer(struct wl_listener *listener, void *data); ++static void winview(const Arg *a); + static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); +@@ -2877,6 +2878,17 @@ virtualpointer(struct wl_listener *listener, void *data) + wlr_cursor_map_input_to_output(cursor, &pointer.base, event->suggested_output); + } + ++void ++winview(const Arg *a) { ++ Arg b = {0}; ++ Client *sel = focustop(selmon); ++ if(!sel) ++ return; ++ b.ui = sel -> tags; ++ view(&b); ++ return; ++} ++ + Monitor * + xytomon(double x, double y) + { diff --git a/dwl/dwl-patches/patches/winview/winview.patch b/dwl/dwl-patches/patches/winview/winview.patch new file mode 100755 index 0000000..66e6b20 --- /dev/null +++ b/dwl/dwl-patches/patches/winview/winview.patch @@ -0,0 +1,42 @@ +diff --git a/config.def.h b/config.def.h +index 22d2171..b812525 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -143,6 +143,7 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, ++ { MODKEY, XKB_KEY_o, winview, {0}}, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, +diff --git a/dwl.c b/dwl.c +index dc0c861..5c6862c 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -351,6 +351,7 @@ static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); + static void virtualkeyboard(struct wl_listener *listener, void *data); + static void virtualpointer(struct wl_listener *listener, void *data); ++static void winview(const Arg *a); + static Monitor *xytomon(double x, double y); + static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); +@@ -2942,6 +2943,17 @@ virtualpointer(struct wl_listener *listener, void *data) + wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); + } + ++void ++winview(const Arg *a) { ++ Arg b = {0}; ++ Client *sel = focustop(selmon); ++ if(!sel) ++ return; ++ b.ui = sel -> tags; ++ view(&b); ++ return; ++} ++ + Monitor * + xytomon(double x, double y) + { diff --git a/dwl/dwl-patches/patches/xwayland-handle-minimize/README.md b/dwl/dwl-patches/patches/xwayland-handle-minimize/README.md new file mode 100755 index 0000000..dde0935 --- /dev/null +++ b/dwl/dwl-patches/patches/xwayland-handle-minimize/README.md @@ -0,0 +1,9 @@ +### Description +Some windows (wine) games go black screen after losing focus and never recover https://github.com/swaywm/sway/issues/4324. This patch fixes this by handling minimize requests that some xwayland clients do. + + ## Download +- [git branch](https://codeberg.org/korei999/dwl/src/branch/xwayland-handle-minimize) +- [2024-04-01](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/xwayland-handle-minimize/xwayland-handle-minimize.patch) + +### Authors +- [korei999](https://codeberg.org/korei999) \ No newline at end of file diff --git a/dwl/dwl-patches/patches/xwayland-handle-minimize/xwayland-handle-minimize.patch b/dwl/dwl-patches/patches/xwayland-handle-minimize/xwayland-handle-minimize.patch new file mode 100755 index 0000000..d6d1f8f --- /dev/null +++ b/dwl/dwl-patches/patches/xwayland-handle-minimize/xwayland-handle-minimize.patch @@ -0,0 +1,91 @@ +From 7277f668f19f5a7fcfbbc96e80cb2829487848ca Mon Sep 17 00:00:00 2001 +From: korei999 +Date: Mon, 1 Apr 2024 15:13:11 +0300 +Subject: [PATCH] handle minimize request for xwayland clients + +--- + client.h | 9 ++++++--- + dwl.c | 19 +++++++++++++++++++ + 2 files changed, 25 insertions(+), 3 deletions(-) + +diff --git a/client.h b/client.h +index 800b867..c46cfb2 100644 +--- a/client.h ++++ b/client.h +@@ -94,9 +94,12 @@ client_activate_surface(struct wlr_surface *s, int activated) + { + struct wlr_xdg_toplevel *toplevel; + #ifdef XWAYLAND +- struct wlr_xwayland_surface *xsurface; +- if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { +- wlr_xwayland_surface_activate(xsurface, activated); ++ struct wlr_xwayland_surface *surface; ++ if ((surface = wlr_xwayland_surface_try_from_wlr_surface(s))) { ++ if (activated && surface->minimized) ++ wlr_xwayland_surface_set_minimized(surface, false); ++ ++ wlr_xwayland_surface_activate(surface, activated); + return; + } + #endif +diff --git a/dwl.c b/dwl.c +index 39ce68c..b49f57b 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -131,6 +131,7 @@ typedef struct { + #ifdef XWAYLAND + struct wl_listener activate; + struct wl_listener associate; ++ struct wl_listener minimize; + struct wl_listener dissociate; + struct wl_listener configure; + struct wl_listener set_hints; +@@ -412,6 +413,7 @@ static void configurex11(struct wl_listener *listener, void *data); + static void createnotifyx11(struct wl_listener *listener, void *data); + static void dissociatex11(struct wl_listener *listener, void *data); + static xcb_atom_t getatom(xcb_connection_t *xc, const char *name); ++static void minimizenotify(struct wl_listener *listener, void *data); + static void sethints(struct wl_listener *listener, void *data); + static void xwaylandready(struct wl_listener *listener, void *data); + static struct wlr_xwayland *xwayland; +@@ -1177,6 +1179,7 @@ destroynotify(struct wl_listener *listener, void *data) + wl_list_remove(&c->activate.link); + wl_list_remove(&c->associate.link); + wl_list_remove(&c->configure.link); ++ wl_list_remove(&c->minimize.link); + wl_list_remove(&c->dissociate.link); + wl_list_remove(&c->set_hints.link); + } else +@@ -2984,6 +2987,7 @@ createnotifyx11(struct wl_listener *listener, void *data) + LISTEN(&xsurface->events.destroy, &c->destroy, destroynotify); + LISTEN(&xsurface->events.dissociate, &c->dissociate, dissociatex11); + LISTEN(&xsurface->events.request_activate, &c->activate, activatex11); ++ LISTEN(&xsurface->events.request_minimize, &c->minimize, minimizenotify); + LISTEN(&xsurface->events.request_configure, &c->configure, configurex11); + LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify); + LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints); +@@ -3011,6 +3015,21 @@ getatom(xcb_connection_t *xc, const char *name) + return atom; + } + ++void ++minimizenotify(struct wl_listener *listener, void *data) ++{ ++ Client *c = wl_container_of(listener, c, minimize); ++ struct wlr_xwayland_surface *xsurface = c->surface.xwayland; ++ struct wlr_xwayland_minimize_event *e = data; ++ int focused; ++ ++ if (xsurface->surface == NULL || !xsurface->surface->mapped) ++ return; ++ ++ focused = seat->keyboard_state.focused_surface == xsurface->surface; ++ wlr_xwayland_surface_set_minimized(xsurface, !focused && e->minimize); ++} ++ + void + sethints(struct wl_listener *listener, void *data) + { +-- +2.44.0 + diff --git a/dwl/dwl-patches/patches/zoomswap/README.md b/dwl/dwl-patches/patches/zoomswap/README.md new file mode 100755 index 0000000..83cbeb1 --- /dev/null +++ b/dwl/dwl-patches/patches/zoomswap/README.md @@ -0,0 +1,54 @@ +### Description +This patch swaps the current window (C) with the previous master (P) when zooming. +``` +Original behaviour : ++-----------------+-------+ +| | | +| | | +| | | +| P +-------| +| | | +| | C | +| | | ++-----------------+-------+ + ++-----------------+-------+ +| | | +| | P | +| | | +| C +-------| +| | | +| | | +| | | ++-----------------+-------+ + +New Behaviour : ++-----------------+-------+ +| | | +| | | +| | | +| C +-------+ +| | | +| | P | +| | | ++-----------------+-------+ + ++-----------------+-------+ +| | | +| | | +| | | +| P +-------+ +| | | +| | C | +| | | ++-----------------+-------+ +``` + +### Download +- [git branch](https://codeberg.org/Palanix/dwl/src/branch/zoomswap) +- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/zoomswap/zoomswap-v0.7.patch) +- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/zoomswap/zoomswap-v0.6.patch) +- [2024-02-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/zoomswap/zoomswap.patch) + +### Authors +- [Palanix](https://codeberg.org/Palanix) diff --git a/dwl/dwl-patches/patches/zoomswap/zoomswap-v0.6.patch b/dwl/dwl-patches/patches/zoomswap/zoomswap-v0.6.patch new file mode 100755 index 0000000..93de288 --- /dev/null +++ b/dwl/dwl-patches/patches/zoomswap/zoomswap-v0.6.patch @@ -0,0 +1,55 @@ +From 2b4e1a8bbb2d17a3da5ca54f2995469dfec5bbbb Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 28 Jul 2023 02:14:32 +0200 +Subject: [PATCH] Implement zoomswap + +--- + dwl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 145fd01..e84202c 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -207,6 +207,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ Client *prevc; + }; + + typedef struct { +@@ -943,6 +944,7 @@ createmon(struct wl_listener *listener, void *data) + + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; ++ m->prevc = NULL; + + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); +@@ -2968,7 +2970,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + void + zoom(const Arg *arg) + { +- Client *c, *sel = focustop(selmon); ++ Client *c, *sel = focustop(selmon), *tmp = sel; + + if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) + return; +@@ -2990,9 +2992,12 @@ zoom(const Arg *arg) + /* If we passed sel, move c to the front; otherwise, move sel to the + * front */ + if (!sel) +- sel = c; ++ sel = selmon->prevc ? selmon->prevc : c, c = tmp; ++ wl_list_remove(&c->link); ++ wl_list_insert(&sel->link, &c->link); + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); ++ selmon->prevc = c; + + focusclient(sel, 1); + arrange(selmon); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/zoomswap/zoomswap-v0.7.patch b/dwl/dwl-patches/patches/zoomswap/zoomswap-v0.7.patch new file mode 100755 index 0000000..d20ff32 --- /dev/null +++ b/dwl/dwl-patches/patches/zoomswap/zoomswap-v0.7.patch @@ -0,0 +1,55 @@ +From cd4ce3f98b4231515c1363070a7fb5f9654a40bc Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 28 Jul 2023 02:14:32 +0200 +Subject: [PATCH] Implement zoomswap + +--- + dwl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 5bf995e..4e2b44e 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -208,6 +208,7 @@ struct Monitor { + int nmaster; + char ltsymbol[16]; + int asleep; ++ Client *prevc; + }; + + typedef struct { +@@ -984,6 +985,7 @@ createmon(struct wl_listener *listener, void *data) + + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; ++ m->prevc = NULL; + + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); +@@ -3023,7 +3025,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + void + zoom(const Arg *arg) + { +- Client *c, *sel = focustop(selmon); ++ Client *c, *sel = focustop(selmon), *tmp = sel; + + if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) + return; +@@ -3045,9 +3047,12 @@ zoom(const Arg *arg) + /* If we passed sel, move c to the front; otherwise, move sel to the + * front */ + if (!sel) +- sel = c; ++ sel = selmon->prevc ? selmon->prevc : c, c = tmp; ++ wl_list_remove(&c->link); ++ wl_list_insert(&sel->link, &c->link); + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); ++ selmon->prevc = c; + + focusclient(sel, 1); + arrange(selmon); +-- +2.45.2 + diff --git a/dwl/dwl-patches/patches/zoomswap/zoomswap.patch b/dwl/dwl-patches/patches/zoomswap/zoomswap.patch new file mode 100755 index 0000000..76e4466 --- /dev/null +++ b/dwl/dwl-patches/patches/zoomswap/zoomswap.patch @@ -0,0 +1,55 @@ +From c82be3e2069fdb9cbea0da22a4c9ed69f4ab5aea Mon Sep 17 00:00:00 2001 +From: Palanix +Date: Fri, 28 Jul 2023 02:14:32 +0200 +Subject: [PATCH] Implement zoomswap + +--- + dwl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index fa76db2..1dea8fe 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -202,6 +202,7 @@ struct Monitor { + int gamma_lut_changed; + int nmaster; + char ltsymbol[16]; ++ Client *prevc; + }; + + typedef struct { +@@ -858,6 +859,7 @@ createmon(struct wl_listener *listener, void *data) + + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; ++ m->prevc = NULL; + + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); +@@ -2793,7 +2795,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + void + zoom(const Arg *arg) + { +- Client *c, *sel = focustop(selmon); ++ Client *c, *sel = focustop(selmon), *tmp = sel; + + if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) + return; +@@ -2815,9 +2817,12 @@ zoom(const Arg *arg) + /* If we passed sel, move c to the front; otherwise, move sel to the + * front */ + if (!sel) +- sel = c; ++ sel = selmon->prevc ? selmon->prevc : c, c = tmp; ++ wl_list_remove(&c->link); ++ wl_list_insert(&sel->link, &c->link); + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); ++ selmon->prevc = c; + + focusclient(sel, 1); + arrange(selmon); +-- +2.43.1 + diff --git a/dwl/dwl-patches/stale-patches/bar-systray-old/README.md b/dwl/dwl-patches/stale-patches/bar-systray-old/README.md new file mode 100755 index 0000000..9c8b94e --- /dev/null +++ b/dwl/dwl-patches/stale-patches/bar-systray-old/README.md @@ -0,0 +1,33 @@ +### Description +Add a system tray next to the [bar](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar). Heed the warning, this is far from suckless ^^ + +![preview](systray.png) + +**Superseded by [bar-systray](/dwl/dwl-patches/src/branch/main/patches/bar-systray).** + +### Dependencies +- GTK4 +- [bar.patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar) as mentioned. +- [gtk4-layer-shell](https://github.com/wmww/gtk4-layer-shell) +- [statusnotifier-systray-gtk4](https://codeberg.org/janetski/statusnotifier-systray-gtk4) built as a static library. + +### Applying the patch +The patch applies on top of the bar patch. That needs to be applied first. + +The patch creates subdirectories `lib` and `include`. After patching, but before `make`, install +`libstatusnotifier-systray-gtk4.a` and `snsystray.h` from statusnotifier-systray-gtk4 in the +directories. One possible way to do that: + +1. Clone [https://codeberg.org/janetski/statusnotifier-systray-gtk4](https://codeberg.org/janetski/statusnotifier-systray-gtk4). Can clone to any location. +2. From statusnotifier-systray-gtk4 root: + 1. `$ meson setup --default-library=static --prefix=/ -Dgir=false -Dvala=false -Ddocs=false build` + 2. `$ meson compile -C build` + 3. `$ DESTDIR=$DWLDIR meson install -C build`, where $DWLDIR is the path to dwl root. +3. Finally, from dwl root, run `make`. + +### Download +- [git branch](/janetski/dwl/src/branch/0.7-systray) +- [0.7](/dwl/dwl-patches/raw/branch/main/patches/bar-systray/bar-systray-0.7.patch) + +### Authors +- [janetski](https://codeberg.org/janetski) ([.vetu](https://discordapp.com/users/355488216469471242) on discord) diff --git a/dwl/dwl-patches/stale-patches/bar-systray-old/bar-systray-0.7.patch b/dwl/dwl-patches/stale-patches/bar-systray-old/bar-systray-0.7.patch new file mode 100755 index 0000000..eae4561 --- /dev/null +++ b/dwl/dwl-patches/stale-patches/bar-systray-old/bar-systray-0.7.patch @@ -0,0 +1,398 @@ +From 71f7b97dca2d781668e826aae7e06544958534f6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Janne=20Vetel=C3=A4inen?= +Date: Fri, 23 Aug 2024 18:39:17 +0300 +Subject: [PATCH 1/1] Add a system tray next to the sewn's bar + +--- + Makefile | 8 +- + config.def.h | 2 + + dwl.c | 222 ++++++++++++++++++++++++++++++++++++++++++++- + include/.gitignore | 1 + + lib/.gitignore | 1 + + 5 files changed, 225 insertions(+), 9 deletions(-) + create mode 100644 include/.gitignore + create mode 100644 lib/.gitignore + +diff --git a/Makefile b/Makefile +index 9bc67db..853b04c 100644 +--- a/Makefile ++++ b/Makefile +@@ -7,14 +7,14 @@ include config.mk + DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \ + -DVERSION=\"$(VERSION)\" $(XWAYLAND) + DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ +- -Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \ ++ -Wno-unused-parameter -Wshadow -Wunused-macros \ + -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \ + -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) +-DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) +-LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) ++PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) gtk4 gtk4-layer-shell-0 ++DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) -Iinclude ++LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) -Llib -lstatusnotifier-systray-gtk4 + + all: dwl + dwl: dwl.o util.o +diff --git a/config.def.h b/config.def.h +index 5d1dc2b..bb9366f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -11,6 +11,8 @@ 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 float rootcolor[] = COLOR(0x000000ff); ++static const int trayspacing = 4; /* Spacing between icons in system tray */ ++static const int traymargins = 4; /* System tray inner margins */ + /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ + static uint32_t colors[][3] = { +diff --git a/dwl.c b/dwl.c +index ece537a..24f550a 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -72,9 +72,22 @@ + #include "util.h" + #include "drwl.h" + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ + /* macros */ ++#ifndef MAX + #define MAX(A, B) ((A) > (B) ? (A) : (B)) ++#endif /* MAX */ ++#ifndef MIN + #define MIN(A, B) ((A) < (B) ? (A) : (B)) ++#endif /* MIN */ + #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) +@@ -324,6 +337,15 @@ static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void gpureset(struct wl_listener *listener, void *data); ++static void gtkactivate(GtkApplication *app, void *data); ++static void gtkclosewindows(void *data, void *udata); ++static void gtkhandletogglebarmsg(void *data); ++static void gtkhandlewidthnotify(SnSystray *systray, GParamSpec *pspec, void *data); ++static void* gtkinit(void *data); ++static void gtkspawnstray(Monitor *m, GtkApplication *app); ++static void gtkterminate(void *data); ++static void gtktoggletray(void *data, void *udata); ++static GdkMonitor* gtkwlrtogdkmon(Monitor *wlrmon); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +@@ -380,7 +402,7 @@ static void unlocksession(struct wl_listener *listener, void *data); + static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); + static void unmapnotify(struct wl_listener *listener, void *data); + static void updatemons(struct wl_listener *listener, void *data); +-static void updatebar(Monitor *m); ++static void updatebar(Monitor *m, int traywidth); + static void updatetitle(struct wl_listener *listener, void *data); + static void urgent(struct wl_listener *listener, void *data); + static void view(const Arg *arg); +@@ -394,6 +416,8 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static pid_t child_pid = -1; ++static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_t gtkthread; /* Gtk functions are only allowed to be called from this thread */ + static int locked; + static void *exclusive_focus; + static struct wl_display *dpy; +@@ -1187,7 +1211,7 @@ createmon(struct wl_listener *listener, void *data) + + m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL); + m->scene_buffer->point_accepts_input = baracceptsinput; +- updatebar(m); ++ updatebar(m, 0); + + wl_list_insert(&mons, &m->link); + drawbars(); +@@ -1518,6 +1542,8 @@ drawbar(Monitor *m) + if (!(buf = bufmon(m))) + return; + ++ pthread_mutex_lock(&mutex); ++ + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drwl_setscheme(m->drw, colors[SchemeNorm]); +@@ -1566,6 +1592,7 @@ drawbar(Monitor *m) + m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); + wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); + wlr_buffer_unlock(&buf->base); ++ pthread_mutex_unlock(&mutex); + } + + void +@@ -1710,6 +1737,174 @@ fullscreennotify(struct wl_listener *listener, void *data) + setfullscreen(c, client_wants_fullscreen(c)); + } + ++void ++gtkactivate(GtkApplication *app, void *data) ++{ ++ GdkDisplay *display; ++ GtkCssProvider *cssp; ++ char csss[64]; ++ Monitor *m; ++ uint32_t bgcolor; ++ ++ bgcolor = colors[SchemeNorm][1] >> 8; ++ display = gdk_display_get_default(); ++ cssp = gtk_css_provider_new(); ++ sprintf(csss, "window{background-color:#%06x;}", bgcolor); ++ gtk_css_provider_load_from_string(cssp, csss); ++ gtk_style_context_add_provider_for_display(display, ++ GTK_STYLE_PROVIDER(cssp), ++ GTK_STYLE_PROVIDER_PRIORITY_USER); ++ ++ wl_list_for_each(m, &mons, link) ++ gtkspawnstray(m, app); ++ ++ g_object_unref(cssp); ++} ++ ++void ++gtkclosewindows(void *data, void *udata) ++{ ++ GtkWindow *window = GTK_WINDOW(data); ++ ++ gtk_window_close(window); ++} ++ ++void ++gtkhandletogglebarmsg(void *data) ++{ ++ GtkApplication *app; ++ GList *windows; ++ ++ app = GTK_APPLICATION(g_application_get_default()); ++ windows = gtk_application_get_windows(app); ++ g_list_foreach(windows, gtktoggletray, data); ++} ++ ++void ++gtkhandlewidthnotify(SnSystray *systray, GParamSpec *pspec, void *data) ++{ ++ Monitor *m = (Monitor *)data; ++ int traywidth; ++ ++ traywidth = sn_systray_get_width(systray); ++ ++ updatebar(m, traywidth); ++ drawbar(m); ++} ++ ++void* ++gtkinit(void *data) ++{ ++ GtkApplication *app = gtk_application_new("org.dwl.systray", ++ G_APPLICATION_NON_UNIQUE); ++ g_signal_connect(app, "activate", G_CALLBACK(gtkactivate), NULL); ++ g_application_run(G_APPLICATION(app), 0, NULL); ++ ++ g_object_unref(app); ++ ++ return NULL; ++} ++ ++void ++gtkspawnstray(Monitor *m, GtkApplication *app) ++{ ++ GdkMonitor *gdkmon; ++ GtkWindow *window; ++ SnSystray *systray; ++ const char *conn; ++ gboolean anchors[4]; ++ int iconsize, tray_init_width, tray_height; ++ ++ gdkmon = gtkwlrtogdkmon(m); ++ if (gdkmon == NULL) ++ die("Failed to get gdkmon"); ++ ++ conn = gdk_monitor_get_connector(gdkmon); ++ iconsize = m->b.real_height - 2 * traymargins; ++ tray_height = m->b.real_height; ++ tray_init_width = m->b.real_height; ++ ++ if (topbar) { ++ anchors[GTK_LAYER_SHELL_EDGE_LEFT] = false; ++ anchors[GTK_LAYER_SHELL_EDGE_RIGHT] = true; ++ anchors[GTK_LAYER_SHELL_EDGE_TOP] = true; ++ anchors[GTK_LAYER_SHELL_EDGE_BOTTOM] = false; ++ } else { ++ anchors[GTK_LAYER_SHELL_EDGE_LEFT] = false; ++ anchors[GTK_LAYER_SHELL_EDGE_RIGHT] = true; ++ anchors[GTK_LAYER_SHELL_EDGE_TOP] = false; ++ anchors[GTK_LAYER_SHELL_EDGE_BOTTOM] = true; ++ } ++ ++ systray = sn_systray_new(iconsize, ++ traymargins, ++ trayspacing, ++ conn); ++ window = GTK_WINDOW(gtk_window_new()); ++ ++ gtk_window_set_default_size(window, tray_init_width, tray_height); ++ gtk_window_set_child(window, GTK_WIDGET(systray)); ++ gtk_window_set_application(window, app); ++ gtk_layer_init_for_window(window); ++ gtk_layer_set_layer(window, GTK_LAYER_SHELL_LAYER_BOTTOM); ++ gtk_layer_set_exclusive_zone(window, -1); ++ gtk_layer_set_monitor(window, gdkmon); ++ ++ for (int j = 0; j < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; j++) { ++ gtk_layer_set_anchor(window, j, anchors[j]); ++ } ++ ++ updatebar(m, tray_init_width); ++ g_signal_connect(systray, "notify::curwidth", G_CALLBACK(gtkhandlewidthnotify), m); ++ gtk_window_present(window); ++} ++ ++void ++gtkterminate(void *data) ++{ ++ GtkApplication *app; ++ GList *windows; ++ ++ app = GTK_APPLICATION(g_application_get_default()); ++ windows = gtk_application_get_windows(app); ++ g_list_foreach(windows, gtkclosewindows, NULL); ++} ++ ++GdkMonitor* ++gtkwlrtogdkmon(Monitor *wlrmon) ++{ ++ GdkMonitor *gdkmon = NULL; ++ ++ GListModel *gdkmons; ++ GdkDisplay *display; ++ const char *gdkname; ++ const char *wlrname; ++ unsigned int i; ++ ++ wlrname = wlrmon->wlr_output->name; ++ display = gdk_display_get_default(); ++ gdkmons = gdk_display_get_monitors(display); ++ ++ for (i = 0; i < g_list_model_get_n_items(gdkmons); i++) { ++ GdkMonitor *mon = g_list_model_get_item(gdkmons, i); ++ gdkname = gdk_monitor_get_connector(mon); ++ if (strcmp(wlrname, gdkname) == 0) ++ gdkmon = mon; ++ } ++ ++ return gdkmon; ++} ++ ++void ++gtktoggletray(void *data, void *udata) ++{ ++ GtkWidget *widget = GTK_WIDGET(data); ++ int *pbarvisible = (int *)udata; ++ int barvisible = GPOINTER_TO_INT(pbarvisible); ++ ++ gtk_widget_set_visible(widget, barvisible); ++} ++ + void + gpureset(struct wl_listener *listener, void *data) + { +@@ -2293,6 +2488,8 @@ powermgrsetmode(struct wl_listener *listener, void *data) + void + quit(const Arg *arg) + { ++ g_idle_add_once(gtkterminate, NULL); ++ pthread_join(gtkthread, NULL); + wl_display_terminate(dpy); + } + +@@ -2836,6 +3033,9 @@ setup(void) + fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); + } + #endif ++ ++ // Gtk functions are only allowed to be called from this thread. ++ pthread_create(>kthread, NULL, >kinit, NULL); + } + + void +@@ -2943,9 +3143,21 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { ++ int barvisible; ++ int *pbarvisible; ++ + wlr_scene_node_set_enabled(&selmon->scene_buffer->node, + !selmon->scene_buffer->node.enabled); + arrangelayers(selmon); ++ ++ // Notify gtkthread ++ if (selmon->scene_buffer->node.enabled) ++ barvisible = 1; ++ else ++ barvisible = 0; ++ ++ pbarvisible = GINT_TO_POINTER(barvisible); ++ g_idle_add_once(gtkhandletogglebarmsg, pbarvisible); + } + + void +@@ -3140,7 +3352,7 @@ updatemons(struct wl_listener *listener, void *data) + if (stext[0] == '\0') + strncpy(stext, "dwl-"VERSION, sizeof(stext)); + wl_list_for_each(m, &mons, link) { +- updatebar(m); ++ updatebar(m, 0); + drawbar(m); + } + +@@ -3155,7 +3367,7 @@ updatemons(struct wl_listener *listener, void *data) + } + + void +-updatebar(Monitor *m) ++updatebar(Monitor *m, int traywidth) + { + size_t i; + int rw, rh; +@@ -3163,7 +3375,7 @@ updatebar(Monitor *m) + + wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); + m->b.width = rw; +- m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); ++ m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale) - traywidth; + + wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0); + +diff --git a/include/.gitignore b/include/.gitignore +new file mode 100644 +index 0000000..424c745 +--- /dev/null ++++ b/include/.gitignore +@@ -0,0 +1 @@ ++*.h +diff --git a/lib/.gitignore b/lib/.gitignore +new file mode 100644 +index 0000000..10301e2 +--- /dev/null ++++ b/lib/.gitignore +@@ -0,0 +1 @@ ++*.a +-- +2.46.0 + diff --git a/dwl/dwl-patches/stale-patches/bar-systray-old/systray.png b/dwl/dwl-patches/stale-patches/bar-systray-old/systray.png new file mode 100755 index 0000000..54f9f98 Binary files /dev/null and b/dwl/dwl-patches/stale-patches/bar-systray-old/systray.png differ diff --git a/dwl/dwl-patches/stale-patches/master-right/README.md b/dwl/dwl-patches/stale-patches/master-right/README.md new file mode 100755 index 0000000..0f69bbc --- /dev/null +++ b/dwl/dwl-patches/stale-patches/master-right/README.md @@ -0,0 +1,13 @@ +### Description +Show the master area to the right. + +### Reason for deprecation +I created this patch for a user on Discord and I have never used it. + +### Download +- [git branch](https://codeberg.org/sevz/dwl/src/branch/master-right) +- [main 2024-09-01](/dwl/dwl-patches/raw/branch/main/patches/master-right/master-right.patch) +- [master-right-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/master-right/master-right-0.7.patch) + +### Authors +- [sevz](https://codeberg.org/sevz) diff --git a/dwl/dwl-patches/stale-patches/master-right/master-right-0.7.patch b/dwl/dwl-patches/stale-patches/master-right/master-right-0.7.patch new file mode 100755 index 0000000..e4845f4 --- /dev/null +++ b/dwl/dwl-patches/stale-patches/master-right/master-right-0.7.patch @@ -0,0 +1,35 @@ +From f72236247e5e7cb23c3cac86b496cdd2c523f7ff Mon Sep 17 00:00:00 2001 +From: Sevz17 +Date: Fri, 25 Jun 2021 19:50:56 -0500 +Subject: [PATCH] show master area to the right +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + dwl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index a2711f67..50b057a7 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2710,11 +2710,12 @@ tile(Monitor *m) + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, ++ resize(c, (struct wlr_box){.x = m->w.x + m->w.width - mw, ++ .y = m->w.y + my, .width = mw, + .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); + my += c->geom.height; + } else { +- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, ++ resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ty, + .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); + ty += c->geom.height; + } +-- +2.46.0 + diff --git a/dwl/dwl-patches/stale-patches/master-right/master-right.patch b/dwl/dwl-patches/stale-patches/master-right/master-right.patch new file mode 100755 index 0000000..70c80a1 --- /dev/null +++ b/dwl/dwl-patches/stale-patches/master-right/master-right.patch @@ -0,0 +1,35 @@ +From 0afd0a98998dda20e4fe4f4d2b5fcdec49c448c3 Mon Sep 17 00:00:00 2001 +From: Sevz17 +Date: Fri, 25 Jun 2021 19:50:56 -0500 +Subject: [PATCH] show master area to the right +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Hernández Hernández +--- + dwl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 9021e442..2bd354a3 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2670,11 +2670,12 @@ tile(Monitor *m) + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { +- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw, ++ resize(c, (struct wlr_box){.x = m->w.x + m->w.width - mw, ++ .y = m->w.y + my, .width = mw, + .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0); + my += c->geom.height; + } else { +- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, ++ resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ty, + .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0); + ty += c->geom.height; + } +-- +2.46.0 + diff --git a/dwl/dwl-patches/stale-patches/press_repeat_release/README.md b/dwl/dwl-patches/stale-patches/press_repeat_release/README.md new file mode 100755 index 0000000..b9b4ff3 --- /dev/null +++ b/dwl/dwl-patches/stale-patches/press_repeat_release/README.md @@ -0,0 +1,15 @@ +### Description +This patch adds 3 additional options to the `Key` struct, `on_press`, `on_repeat` and `on_release` which can be used to control which events a key binding should be triggered on. + +NOTE: Due to concerns about patching difficulties this patch does NOT include any changes to `config.def.h`. After applying you will need to add the 3 additional initializers to each key binding that you would like to modify. Any key binding that is not updated will cause a build warning but should function as it does in vanilla. + +2025-01-04 Moved to stale patches. +Outstanding issues with this patch: https://codeberg.org/dwl/dwl-patches/issues/98 +Patch maintainer notes he is no longer maintaining dwl patches: https://codeberg.org/dwl/dwl-patches/pulls/102 + +### Download +- [git branch](https://codeberg.org/USERNAME/dwl/src/branch/press_repeat_release) +- [2024-03-27](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/press_repeat_release/press_repeat_release.patch) + +### Authors +- [minego](https://codeberg.org/minego) diff --git a/dwl/dwl-patches/stale-patches/press_repeat_release/press_repeat_release.patch b/dwl/dwl-patches/stale-patches/press_repeat_release/press_repeat_release.patch new file mode 100755 index 0000000..b86666d --- /dev/null +++ b/dwl/dwl-patches/stale-patches/press_repeat_release/press_repeat_release.patch @@ -0,0 +1,108 @@ +From aee1dc3e9ca4d8deec5432d0c64921af6e301ecd Mon Sep 17 00:00:00 2001 +From: Micah N Gorrell +Date: Wed, 27 Mar 2024 15:59:50 -0600 +Subject: [PATCH 1/2] onpress, onrepeat, onrelease + +--- + dwl.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/dwl.c b/dwl.c +index 5867b0c..43bbf0c 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -146,6 +146,10 @@ typedef struct { + xkb_keysym_t keysym; + void (*func)(const Arg *); + const Arg arg; ++ ++ int on_press; ++ int on_repeat; ++ int on_release; + } Key; + + typedef struct { +@@ -286,7 +290,7 @@ static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); + static void inputdevice(struct wl_listener *listener, void *data); +-static int keybinding(uint32_t mods, xkb_keysym_t sym); ++static int keybinding(uint32_t mods, xkb_keysym_t sym, int on_press, int on_repeat, int on_release); + static void keypress(struct wl_listener *listener, void *data); + static void keypressmod(struct wl_listener *listener, void *data); + static int keyrepeat(void *data); +@@ -1428,7 +1432,7 @@ inputdevice(struct wl_listener *listener, void *data) + } + + int +-keybinding(uint32_t mods, xkb_keysym_t sym) ++keybinding(uint32_t mods, xkb_keysym_t sym, int on_press, int on_repeat, int on_release) + { + /* + * Here we handle compositor keybindings. This is when the compositor is +@@ -1439,8 +1443,10 @@ keybinding(uint32_t mods, xkb_keysym_t sym) + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) + && sym == k->keysym && k->func) { +- k->func(&k->arg); +- return 1; ++ if ((on_press && k->on_press) || (on_repeat && k->on_repeat) || (on_release && k->on_release)) { ++ k->func(&k->arg); ++ return 1; ++ } + } + } + return 0; +@@ -1470,7 +1476,7 @@ keypress(struct wl_listener *listener, void *data) + * attempt to process a compositor keybinding. */ + if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + for (i = 0; i < nsyms; i++) +- handled = keybinding(mods, syms[i]) || handled; ++ handled = keybinding(mods, syms[i], event->state == WL_KEYBOARD_KEY_STATE_PRESSED, 0, event->state == WL_KEYBOARD_KEY_STATE_RELEASED) || handled; + } + + if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { +@@ -1518,7 +1524,7 @@ keyrepeat(void *data) + 1000 / group->wlr_group->keyboard.repeat_info.rate); + + for (i = 0; i < group->nsyms; i++) +- keybinding(group->mods, group->keysyms[i]); ++ keybinding(group->mods, group->keysyms[i], 0, 1, 0); + + return 0; + } +-- +2.44.0 + + +From 1875bb171c9b0cd2fb03bb7e6c3fb400e33eeaf1 Mon Sep 17 00:00:00 2001 +From: Micah N Gorrell +Date: Wed, 27 Mar 2024 16:26:52 -0600 +Subject: [PATCH 2/2] Modified logic so that an unmodified keybinding with + default values for the new flags will behave as it does in vanilla, while + keybindings with customized flags will function as expected + +--- + dwl.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index 43bbf0c..55e7a40 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1443,7 +1443,11 @@ keybinding(uint32_t mods, xkb_keysym_t sym, int on_press, int on_repeat, int on_ + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) + && sym == k->keysym && k->func) { +- if ((on_press && k->on_press) || (on_repeat && k->on_repeat) || (on_release && k->on_release)) { ++ if ((k->on_press == 0 && k->on_repeat == 0 && k->on_release == 0) || ++ (on_press && k->on_press) || ++ (on_repeat && k->on_repeat) || ++ (on_release && k->on_release) ++ ) { + k->func(&k->arg); + return 1; + } +-- +2.44.0 + diff --git a/dwl/dwl-patches/stale-patches/remembertags/README.md b/dwl/dwl-patches/stale-patches/remembertags/README.md new file mode 100755 index 0000000..b45e87c --- /dev/null +++ b/dwl/dwl-patches/stale-patches/remembertags/README.md @@ -0,0 +1,16 @@ +### Description +This patch modifies the behavior when selecting tags so that selecting a tag will also enable any other tags that were previously visible. + +For example: +1. Select tag 5, with mod+5 +2. Toggle tag 8, with ctrl+mod+8 +3. Select tag 1, with mod+1. Tags 5 and 8 should no longer be visible. +4. Select tag 5 again, with mod+5. Tag 8 should be visible since it was remembered. +5. Select tag 5 again, with mod_5. Selecting the already selected tag resets any remembered tags, so now tag 5 should be the only one visible. + +### Download +- [git branch](https://codeberg.org/minego/dwl/src/branch/remembertags) +- [2024-03-27](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/remembertags/remembertags.patch) + +### Authors +- [minego](https://codeberg.org/minego) \ No newline at end of file diff --git a/dwl/dwl-patches/stale-patches/remembertags/remembertags.patch b/dwl/dwl-patches/stale-patches/remembertags/remembertags.patch new file mode 100755 index 0000000..fd6135e --- /dev/null +++ b/dwl/dwl-patches/stale-patches/remembertags/remembertags.patch @@ -0,0 +1,105 @@ +From fea6eb3cfc84ede8403c89a3230f5c658a6c7bd1 Mon Sep 17 00:00:00 2001 +From: Micah N Gorrell +Date: Wed, 27 Mar 2024 13:05:09 -0600 +Subject: [PATCH] remembertags + +--- + config.def.h | 8 ++++---- + dwl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 52 insertions(+), 4 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9009517..2312802 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -105,10 +105,10 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA + #define MODKEY WLR_MODIFIER_ALT + + #define TAGKEYS(KEY,SKEY,TAG) \ +- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ +- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } ++ { MODKEY, KEY, remembertagsview, {.i = TAG} }, \ ++ { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ ++ { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ ++ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT, SKEY, 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 } } +diff --git a/dwl.c b/dwl.c +index 5867b0c..31a81aa 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -205,6 +205,11 @@ struct Monitor { + int gamma_lut_changed; + int nmaster; + char ltsymbol[16]; ++ unsigned int createtag[2]; /* Create windows on the last tag directly selected, not all selected */ ++ struct { ++ unsigned int tagset; ++ Client *zoomed; ++ } remembered[31]; + }; + + typedef struct { +@@ -308,6 +313,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); + static void printstatus(void); + static void quit(const Arg *arg); ++static void remembertagsview(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); +@@ -1951,6 +1957,48 @@ quit(const Arg *arg) + wl_display_terminate(dpy); + } + ++void ++remembertagsview(const Arg *arg) { ++ unsigned newtags = (1 << arg->i) & TAGMASK; ++ int oldtag; ++ int active; ++ unsigned int newcreate; ++ ++ if (selmon == NULL) { ++ return; ++ } ++ ++ oldtag = selmon->createtag[selmon->seltags]; ++ active = (oldtag == arg->i); ++ ++ if (oldtag < TAGCOUNT) { ++ selmon->remembered[oldtag].tagset = selmon->tagset[selmon->seltags]; ++ } ++ ++ selmon->seltags ^= 1; /*toggle tagset*/ ++ ++ if (-1 == arg->i) { ++ /* A specific tag was not specified */ ++ active = 0; ++ newcreate = selmon->createtag[selmon->seltags]; ++ } else { ++ newcreate = arg->i; ++ } ++ ++ if (active) { ++ /* Select twice to isolate the tag */ ++ selmon->tagset[selmon->seltags] = newtags; ++ } else if (arg->i < TAGCOUNT) { ++ /* Restore whatever was previously on this tag */ ++ selmon->tagset[selmon->seltags] = newtags | selmon->remembered[newcreate].tagset; ++ } ++ ++ selmon->createtag[selmon->seltags] = newcreate; ++ focusclient(focustop(selmon), 1); ++ arrange(selmon); ++ printstatus(); ++} ++ + void + rendermon(struct wl_listener *listener, void *data) + { +-- +2.44.0 + diff --git a/dwl/dwl-patches/stale-patches/tab-pango/README.md b/dwl/dwl-patches/stale-patches/tab-pango/README.md new file mode 100755 index 0000000..c7e4a1c --- /dev/null +++ b/dwl/dwl-patches/stale-patches/tab-pango/README.md @@ -0,0 +1,10 @@ +### Description +Add a tab bar or window title to the top or bottom of windows. + +**This is the old version of the `tab` patch. Deprecated because the [new version](https://codeberg.org/dwl/dwl-patches/raw/branch-main/patches/tab) is significantly more efficient and well-written than this, and it better adheres to the suckless philosophy.** + +### Download +- [2024-03-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tab/tab.patch) + +### Authors +- [dev-gm](https://codeberg.org/dev-gm) diff --git a/dwl/dwl-patches/stale-patches/tab-pango/tab.patch b/dwl/dwl-patches/stale-patches/tab-pango/tab.patch new file mode 100755 index 0000000..5b7b8a0 --- /dev/null +++ b/dwl/dwl-patches/stale-patches/tab-pango/tab.patch @@ -0,0 +1,461 @@ +From b624206781513cdff1b9609fc5ac4b848094e1b4 Mon Sep 17 00:00:00 2001 +From: Gavin M +Date: Fri, 15 Mar 2024 16:37:23 -0500 +Subject: [PATCH] Tabbed patch + +--- + Makefile | 2 +- + config.def.h | 18 +++- + dwl.c | 276 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 281 insertions(+), 15 deletions(-) + +diff --git a/Makefile b/Makefile +index a67fdd3..182eb87 100644 +--- a/Makefile ++++ b/Makefile +@@ -9,7 +9,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unu + -Werror=strict-prototypes -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots wayland-server xkbcommon libinput $(XLIBS) ++PKGS = wlroots wayland-server xkbcommon libinput cairo pangocairo $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 9009517..1ca270f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,6 +7,16 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const double title_border_width = 0.75; ++static const unsigned int title_padding = 11; ++static const int title_top = 0; ++static const LayoutType floating_title_type = LAYOUT_TYPE_LABEL; ++static const char title_font[] = "Dejavu Sans Mono 10.5"; ++static const float title_font_color[] = COLOR(0xffffffff); ++static const float title_focus_bg[] = COLOR(0x3b3b3bff); ++static const float title_root_bg[] = COLOR(0x131313ff); ++static const float title_urgent_bg[] = COLOR(0x00ff00ff); ++static const float title_border_color[] = COLOR(0x3b3b3bff); + static const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); +@@ -30,10 +40,10 @@ static const Rule rules[] = { + + /* layout(s) */ + static const Layout layouts[] = { +- /* symbol arrange function */ +- { "[]=", tile }, +- { "><>", NULL }, /* no layout function means floating behavior */ +- { "[M]", monocle }, ++ /* symbol type render_only_top arrange function */ ++ { "[]=", LAYOUT_TYPE_NONE, 0, tile }, ++ { "><>", LAYOUT_TYPE_LABEL, 0, NULL }, /* no layout function means floating behavior */ ++ { "[M]", LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS, 1, monocle }, + }; + + /* monitors */ +diff --git a/dwl.c b/dwl.c +index 5867b0c..e613d17 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2,6 +2,11 @@ + * See LICENSE file for copyright and license details. + */ + #include ++#include ++#include ++#include ++#include ++#include + #include + #include + #include +@@ -13,8 +18,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + #include + #include + #include +@@ -110,6 +117,7 @@ typedef struct { + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; ++ struct wlr_scene_buffer *titlebar; + struct wl_list link; + struct wl_list flink; + union { +@@ -137,7 +145,7 @@ typedef struct { + #endif + unsigned int bw; + uint32_t tags; +- int isfloating, isurgent, isfullscreen; ++ int isfloating, isurgent, isfullscreen, titleisinit, istabbed; + uint32_t resize; /* configure serial of a pending resize */ + } Client; + +@@ -179,8 +187,17 @@ typedef struct { + struct wl_listener surface_commit; + } LayerSurface; + ++typedef enum { ++ LAYOUT_TYPE_NONE, ++ LAYOUT_TYPE_LABEL, ++ LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS, ++ LAYOUT_TYPE_TABS_ALWAYS ++} LayoutType; ++ + typedef struct { + const char *symbol; ++ LayoutType type; ++ int render_top_only; + void (*arrange)(Monitor *); + } Layout; + +@@ -282,6 +299,7 @@ static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Client *focustop(Monitor *m); ++static Client *focustop_onlytiled(Monitor *m, int onlytiled); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); + static void incnmaster(const Arg *arg); +@@ -309,6 +327,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface, + static void printstatus(void); + static void quit(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); ++static void rendertitlebar(Client *client); + static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); +@@ -349,6 +368,7 @@ static void xytonode(double x, double y, struct wlr_surface **psurface, + static void zoom(const Arg *arg); + + /* variables */ ++static int title_height; + static const char broken[] = "broken"; + static pid_t child_pid = -1; + static int locked; +@@ -973,6 +993,7 @@ createnotify(struct wl_listener *listener, void *data) + c = xdg_surface->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = xdg_surface; + c->bw = borderpx; ++ c->titleisinit = c->istabbed = 0; + + wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); +@@ -1360,6 +1381,22 @@ focustop(Monitor *m) + return NULL; + } + ++Client * ++focustop_onlytiled(Monitor *m, int onlytiled) ++{ ++ Client *c; ++ if (!m) ++ return NULL; ++ wl_list_for_each(c, &fstack, flink) { ++ if (VISIBLEON(c, m)) { ++ if ((onlytiled == 1 && c->isfloating) || (onlytiled == 2 && (!c->isfloating || !m->lt[m->sellt]->arrange))) ++ continue; ++ return c; ++ } ++ } ++ return NULL; ++} ++ + void + fullscreennotify(struct wl_listener *listener, void *data) + { +@@ -2003,6 +2040,195 @@ skip: + wlr_output_state_finish(&pending); + } + ++struct text_buffer { ++ struct wlr_buffer base; ++ void *data; ++ uint32_t format; ++ size_t stride; ++}; ++ ++static void text_buffer_destroy(struct wlr_buffer *wlr_buffer) { ++ struct text_buffer *buffer = wl_container_of(wlr_buffer, buffer, base); ++ free(buffer->data); ++ free(buffer); ++} ++ ++static bool text_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, ++ uint32_t flags, void **data, uint32_t *format, size_t *stride) { ++ struct text_buffer *buffer = wl_container_of(wlr_buffer, buffer, base); ++ if(data != NULL) { ++ *data = (void *)buffer->data; ++ } ++ if(format != NULL) { ++ *format = buffer->format; ++ } ++ if(stride != NULL) { ++ *stride = buffer->stride; ++ } ++ return true; ++} ++ ++static void text_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) { ++ // This space is intentionally left blank ++} ++ ++static const struct wlr_buffer_impl text_buffer_impl = { ++ .destroy = text_buffer_destroy, ++ .begin_data_ptr_access = text_buffer_begin_data_ptr_access, ++ .end_data_ptr_access = text_buffer_end_data_ptr_access, ++}; ++ ++static struct text_buffer *text_buffer_create(uint32_t width, uint32_t height, uint32_t stride) { ++ struct text_buffer *buffer = calloc(1, sizeof(*buffer)); ++ if (buffer == NULL) { ++ return NULL; ++ } ++ ++ wlr_buffer_init(&buffer->base, &text_buffer_impl, width, height); ++ buffer->format = DRM_FORMAT_ARGB8888; ++ buffer->stride = stride; ++ ++ buffer->data = malloc(buffer->stride * height); ++ if (buffer->data == NULL) { ++ free(buffer); ++ return NULL; ++ } ++ ++ return buffer; ++} ++ ++void ++rendertitlebar(Client *c) ++{ ++ struct wl_list *init_destroy, *cursor_destroy; ++ cairo_surface_t *surface; ++ cairo_status_t status; ++ cairo_t *cr; ++ PangoFontDescription *desc; ++ PangoLayout *layout; ++ LayoutType title_type; ++ Client *l, *sel; ++ unsigned int len, tabsize, i; ++ const char *title; ++ const float *color; ++ unsigned char *data; ++ int stride; ++ struct text_buffer *text_buffer; ++ void *data_ptr; ++ ++ if (!c || !c->scene || !c->mon || !selmon || (!VISIBLEON(c, selmon) && c->mon == selmon)) ++ return; ++ ++ if (c->titleisinit) { ++ init_destroy = cursor_destroy = &c->titlebar->node.events.destroy.listener_list; ++ do { ++ cursor_destroy = cursor_destroy->next; ++ } while (cursor_destroy && cursor_destroy != init_destroy); ++ if (!cursor_destroy) { ++ return; ++ } ++ wlr_scene_node_destroy(&c->titlebar->node); ++ } ++ c->titleisinit = c->istabbed = 0; ++ ++ sel = focustop_onlytiled(c->mon, c->isfloating + 1); ++ ++ if (c->isfullscreen) ++ return; ++ title_type = c->isfloating ? floating_title_type : c->mon->lt[c->mon->sellt]->type; ++ ++ if (title_type == LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS || title_type == LAYOUT_TYPE_TABS_ALWAYS) { ++ len = 0; ++ wl_list_for_each(l, &clients, link) { ++ if (VISIBLEON(l, c->mon) && l->isfloating == c->isfloating) ++ len++; ++ } ++ if (title_type == LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS && len <= 1) ++ return; ++ } ++ ++ if (c->mon->lt[c->mon->sellt]->render_top_only == 1 && !c->isfloating && c != sel) { ++ c->istabbed = 1; ++ return; ++ } /*else if (c->mon->lt[c->mon->sellt]->render_top_only == 2 && c != sel) { ++ c->istabbed = 1; ++ return; ++ }*/ ++ ++ if (title_type == LAYOUT_TYPE_NONE) ++ return; ++ ++ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, c->geom.width, title_height); ++ if ((status = cairo_surface_status(surface)) != CAIRO_STATUS_SUCCESS) { ++ wlr_log(WLR_ERROR, "cairo_image_surface_create failed: %s", ++ cairo_status_to_string(status)); ++ return; ++ } ++ cr = cairo_create(surface); ++ desc = pango_font_description_from_string(title_font); ++ layout = pango_cairo_create_layout(cr); ++ pango_layout_set_font_description(layout, desc); ++ pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); ++ ++ cairo_set_line_width(cr, title_border_width); ++ ++ if (title_type == LAYOUT_TYPE_LABEL) { ++ cairo_rectangle(cr, 0, 0, c->geom.width, title_height); ++ cairo_set_source_rgba(cr, title_focus_bg[0], title_focus_bg[1], title_focus_bg[2], title_focus_bg[3]); ++ cairo_fill_preserve(cr); ++ cairo_set_source_rgba(cr, title_border_color[0], title_border_color[1], title_border_color[2], title_border_color[3]); ++ cairo_stroke(cr); ++ cairo_set_source_rgba(cr, title_font_color[0], title_font_color[1], title_font_color[2], title_font_color[3]); ++ title = client_get_title(c); ++ pango_layout_set_text(layout, title ? title : " ", (c->geom.width - title_padding) * PANGO_SCALE); ++ cairo_move_to(cr, title_padding, 0); ++ pango_cairo_show_layout(cr, layout); ++ } else { ++ tabsize = c->geom.width / len; ++ i = 0; ++ wl_list_for_each(l, &clients, link) { ++ if (VISIBLEON(l, c->mon) && l->isfloating == c->isfloating) { ++ cairo_rectangle(cr, i * tabsize, 0, (i + 1) * tabsize, title_height); ++ color = (l == sel) ? title_focus_bg ++ : (c->isurgent ? title_urgent_bg : title_root_bg); ++ cairo_set_source_rgba(cr, color[0], color[1], color[2], color[3]); ++ cairo_fill_preserve(cr); ++ cairo_set_source_rgba(cr, title_border_color[0], title_border_color[1], title_border_color[2], title_border_color[3]); ++ cairo_stroke(cr); ++ cairo_set_source_rgba(cr, title_font_color[0], title_font_color[1], title_font_color[2], title_font_color[3]); ++ title = client_get_title(l); ++ pango_layout_set_text(layout, title ? title : " ", (tabsize - title_padding) * PANGO_SCALE); ++ cairo_move_to(cr, (i * tabsize) + title_padding, 0); ++ pango_cairo_show_layout(cr, layout); ++ i++; ++ } ++ } ++ } ++ ++ data = cairo_image_surface_get_data(surface); ++ stride = cairo_image_surface_get_stride(surface); ++ text_buffer = text_buffer_create(c->geom.width, title_height, stride); ++ ++ if(!wlr_buffer_begin_data_ptr_access(&text_buffer->base, ++ WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data_ptr, NULL, NULL)) { ++ wlr_log(WLR_ERROR, "%s", "Failed to get pointer access to text buffer"); ++ return; ++ } ++ memcpy(data_ptr, data, stride * title_height); ++ wlr_buffer_end_data_ptr_access(&text_buffer->base); ++ cairo_surface_destroy(surface); ++ ++ c->titlebar = wlr_scene_buffer_create(c->scene, &text_buffer->base); ++ c->titleisinit = c->istabbed = 1; ++ ++ wlr_scene_node_set_position(&c->titlebar->node, 0, !title_top ? c->geom.height - title_height : 0); ++ wlr_scene_node_raise_to_top(&c->titlebar->node); ++ ++ pango_font_description_free(desc); ++ g_object_unref(layout); ++ cairo_destroy(cr); ++} ++ + void + requestdecorationmode(struct wl_listener *listener, void *data) + { +@@ -2036,24 +2262,30 @@ resize(Client *c, struct wlr_box geo, int interact) + { + struct wlr_box *bbox = interact ? &sgeom : &c->mon->w; + struct wlr_box clip; ++ unsigned int th; ++ int draw_borders = 1; + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; ++ c->bw = draw_borders ? borderpx : 0; + applybounds(c, bbox); + ++ rendertitlebar(c); ++ th = c->istabbed ? title_height : c->bw; ++ + /* Update scene-graph, including borders */ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); +- wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); +- wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); +- wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); +- wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); +- wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); +- wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); +- wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); ++ wlr_scene_node_set_position(&c->scene_surface->node, c->bw, title_top ? th : c->bw); ++ wlr_scene_rect_set_size(c->border[0], c->geom.width, (title_top && c->istabbed) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[1], c->geom.width, (!title_top && c->istabbed) ? 0 : c->bw); ++ wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - (c->bw + th)); ++ wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - (c->bw + th)); ++ wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - (title_top ? c->bw : th)); ++ wlr_scene_node_set_position(&c->border[2]->node, 0, title_top ? th : c->bw); ++ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, title_top ? th : c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, +- c->geom.height - 2 * c->bw); ++ c->geom.height - (c->bw + th)); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + } +@@ -2274,6 +2506,11 @@ setup(void) + + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; ++ cairo_surface_t *surface; ++ cairo_t *cr; ++ PangoFontDescription *desc; ++ PangoLayout *layout; ++ + sigemptyset(&sa.sa_mask); + + for (i = 0; i < (int)LENGTH(sig); i++) +@@ -2506,6 +2743,24 @@ setup(void) + + wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); + ++ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); ++ ++ cr = cairo_create(surface); ++ ++ desc = pango_font_description_from_string(title_font); ++ /* Create Pango layout. */ ++ layout = pango_cairo_create_layout(cr); ++ pango_layout_set_font_description(layout, desc); ++ pango_layout_set_text(layout, " ", -1); ++ /* Set width and height to text size */ ++ pango_layout_get_pixel_size(layout, NULL, &title_height); ++ ++ /* Cleanup */ ++ pango_font_description_free (desc); ++ cairo_surface_destroy(surface); ++ g_object_unref (layout); ++ cairo_destroy(cr); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2978,6 +3233,7 @@ createnotifyx11(struct wl_listener *listener, void *data) + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = borderpx; ++ c->titleisinit = c->istabbed = 0; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); +-- +2.44.0 + diff --git a/dwl/dwl-patches/stale-patches/togglekblayout/README.md b/dwl/dwl-patches/stale-patches/togglekblayout/README.md new file mode 100755 index 0000000..366a6d8 --- /dev/null +++ b/dwl/dwl-patches/stale-patches/togglekblayout/README.md @@ -0,0 +1,14 @@ +### Description + +> This patch is no longer being maintained by me [wochap](https://codeberg.org/wochap), since I'm now using a different patch specific to my use case: https://codeberg.org/wochap/dwl/src/branch/v0.6-b/xkb-rules-switcher/xkb-rules-switcher.patch + +Switch between multiple keyboard layouts at runtime. + +### Download +- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/togglekblayout) +- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/togglekblayout/togglekblayout.patch) + +### Authors +- [wochap](https://codeberg.org/wochap) +- [Stivvo](https://github.com/Stivvo) + diff --git a/dwl/dwl-patches/stale-patches/togglekblayout/togglekblayout.patch b/dwl/dwl-patches/stale-patches/togglekblayout/togglekblayout.patch new file mode 100755 index 0000000..4ef802a --- /dev/null +++ b/dwl/dwl-patches/stale-patches/togglekblayout/togglekblayout.patch @@ -0,0 +1,107 @@ +From 1bb99c78da484ce6036dc997962ed2f4c0d11208 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Thu, 19 Oct 2023 23:21:49 -0500 +Subject: [PATCH 1/2] apply main...Stivvo:toggleKbLayout.patch + +--- + config.def.h | 6 ++++++ + dwl.c | 20 ++++++++++++++++++++ + 2 files changed, 26 insertions(+) + +diff --git a/config.def.h b/config.def.h +index db0babc..caa09ea 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -57,6 +57,11 @@ static const struct xkb_rule_names xkb_rules = { + static const int repeat_rate = 25; + static const int repeat_delay = 600; + ++/* gb will be set the first time togglekblayout is called, then us.. it is ++ * recommended to set the same layout in position 0 of kblayouts and in ++ * xkb_rules */ ++static const char *kblayouts[] = {"us", "gb"}; ++ + /* Trackpad */ + static const int tap_to_click = 1; + static const int tap_and_drag = 1; +@@ -141,6 +146,7 @@ static const Key keys[] = { + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, ++ { MODKEY, XKB_KEY_w, togglekblayout, {0} }, + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), +diff --git a/dwl.c b/dwl.c +index ef27a1d..25458e6 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -312,6 +312,7 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglefloating(const Arg *arg); ++static void togglekblayout(const Arg *arg); + static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +@@ -368,6 +369,7 @@ static struct wl_listener lock_listener = {.notify = locksession}; + + static struct wlr_seat *seat; + static struct wl_list keyboards; ++static unsigned int kblayout = 0; /* index of kblayouts */ + static unsigned int cursor_mode; + static Client *grabc; + static int grabcx, grabcy; /* client-relative */ +@@ -2454,6 +2456,24 @@ togglefullscreen(const Arg *arg) + setfullscreen(sel, !sel->isfullscreen); + } + ++void ++togglekblayout(const Arg *arg) ++{ ++ Keyboard *kb; ++ struct xkb_rule_names newrule = xkb_rules; ++ ++ kblayout = (kblayout + 1) % LENGTH(kblayouts); ++ newrule.layout = kblayouts[kblayout]; ++ wl_list_for_each(kb, &keyboards, link) { ++ struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); ++ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &newrule, ++ XKB_KEYMAP_COMPILE_NO_FLAGS); ++ wlr_keyboard_set_keymap(kb->device->keyboard, keymap); ++ xkb_keymap_unref(keymap); ++ xkb_context_unref(context); ++ } ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.42.0 + + +From 3428168a686e2da8ba8a9dc1473350610afaef19 Mon Sep 17 00:00:00 2001 +From: wochap +Date: Thu, 19 Oct 2023 23:46:06 -0500 +Subject: [PATCH 2/2] fix build + +--- + dwl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dwl.c b/dwl.c +index 25458e6..090280f 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -2468,7 +2468,7 @@ togglekblayout(const Arg *arg) + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + struct xkb_keymap *keymap = xkb_map_new_from_names(context, &newrule, + XKB_KEYMAP_COMPILE_NO_FLAGS); +- wlr_keyboard_set_keymap(kb->device->keyboard, keymap); ++ wlr_keyboard_set_keymap(kb->wlr_keyboard, keymap); + xkb_keymap_unref(keymap); + xkb_context_unref(context); + } +-- +2.42.0 diff --git a/dwl/dwl.1 b/dwl/dwl.1 new file mode 100755 index 0000000..780c78f --- /dev/null +++ b/dwl/dwl.1 @@ -0,0 +1,158 @@ +.Dd January 8, 2021 +.Dt DWL 1 +.Os +.Sh NAME +.Nm dwl +.Nd dwm for Wayland +.Sh SYNOPSIS +.Nm +.Op Fl v +.Op Fl d +.Op Fl s Ar startup command +.Sh DESCRIPTION +.Nm +is a Wayland compositor based on wlroots. +It is intended to fill the same space in the Wayland world that +.Nm dwm +does for X11. +.Pp +When given the +.Fl v +option, +.Nm +writes its name and version to standard error and exits unsuccessfully. +.Pp +When given the +.Fl d +option, +.Nm +enables full wlroots logging, including debug information. +.Pp +When given the +.Fl s +option, +.Nm +starts a shell process running +.Ar command +when starting. +When stopping, it sends +.Dv SIGTERM +to the child process and waits for it to exit. +.Pp +Users are encouraged to customize +.Nm +by editing the sources, in particular +.Pa config.h . +The default key bindings are as follows: +.Bl -tag -width 20n -offset indent -compact +.It Mod-[1-9] +Show only all windows with a tag. +.It Mod-Ctrl-[1-9] +Show all windows with a tag. +.It Mod-Shift-[1-9] +Move window to a single tag. +.It Mod-Ctrl-Shift-[1-9] +Toggle tag for window. +.It Mod-p +Spawn +.Nm wmenu-run . +.It Mod-Shift-Return +Spawn +.Nm foot . +.It Mod-[jk] +Move focus down/up the stack. +.It Mod-[id] +Increase/decrease number of windows in master area. +.It Mod-[hl] +Decrease/increase master area. +.It Mod-Return +Move window on top of stack or switch top of stack with second window. +.It Mod-Tab +Show only all windows with previous tag. +.It Mod-Shift-c +Close window. +.It Mod-t +Switch to tabbed layout. +.It Mod-f +Switch to floating layout. +.It Mod-m +Switch to monocle layout. +.It Mod-Space +Switch to previous layout. +.It Mod-Shift-Space +Toggle floating state of window. +.It Mod-e +Toggle fullscreen state of window. +.It Mod-0 +Show all windows. +.It Mod-Shift-0 +Set all tags for window. +.It Mod-, +Move focus to previous monitor. +.It Mod-. +Move focus to next monitor. +.It Mod-Shift-, +Move window to previous monitor. +.It Mod-Shift-. +Move window to next monitor. +.It Mod-Shift-q +Quit +.Nm . +.El +These might differ depending on your keyboard layout. +.Sh ENVIRONMENT +These environment variables are used by +.Nm : +.Bl -tag -width XDG_RUNTIME_DIR +.It Ev XDG_RUNTIME_DIR +A directory where temporary user files, such as the Wayland socket, +are stored. +.It Ev XDG_CONFIG_DIR +A directory containing configuration of various programs and +libraries, including libxkbcommon. +.It Ev DISPLAY , WAYLAND_DISPLAY , WAYLAND_SOCKET +Tell how to connect to an underlying X11 or Wayland server. +.It Ev WLR_* +Various variables specific to wlroots. +.It Ev XKB_* , XLOCALEDIR , XCOMPOSEFILE +Various variables specific to libxkbcommon. +.It Ev XCURSOR_PATH +List of directories to search for XCursor themes in. +.It Ev HOME +A directory where there are always dear files there for you. +Waiting for you to clean them up. +.El +.Pp +These are set by +.Nm : +.Bl -tag -width WAYLAND_DISPLAY +.It Ev WAYLAND_DISPLAY +Tell how to connect to +.Nm . +.It Ev DISPLAY +If using +.Nm Xwayland , +tell how to connect to the +.Nm Xwayland +server. +.El +.Sh EXAMPLES +Start +.Nm +with s6 in the background: +.Dl dwl \-s \(aqs6\-svscan <&\-\(aq +.Sh SEE ALSO +.Xr foot 1 , +.Xr wmenu 1 , +.Xr dwm 1 , +.Xr xkeyboard-config 7 +.Sh CAVEATS +The child process's standard input is connected with a pipe to +.Nm . +If the child process neither reads from the pipe nor closes its +standard input, +.Nm +will freeze after a while due to it blocking when writing to the full +pipe buffer. +.Sh BUGS +All of them. diff --git a/dwl/dwl.c b/dwl/dwl.c new file mode 100755 index 0000000..b048466 --- /dev/null +++ b/dwl/dwl.c @@ -0,0 +1,3645 @@ +/* + * See LICENSE file for copyright and license details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XWAYLAND +#include +#include +#include +#endif + +#include "util.h" +#include "drwl.h" + +/* macros */ +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) +#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define END(A) ((A) + LENGTH(A)) +#define TAGMASK ((1u << LENGTH(tags)) - 1) +#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) +#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) +#define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) + +/* enums */ +enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ +enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ +enum { XDGShell, LayerShell, X11 }; /* client types */ +enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ +enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ +#ifdef XWAYLAND +enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +#endif + +typedef union { + int i; + uint32_t ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int click; + unsigned int mod; + unsigned int button; + void (*func)(const Arg *); + const Arg arg; +} Button; + +typedef struct Monitor Monitor; +typedef struct { + /* Must keep these three elements in this order */ + unsigned int type; /* XDGShell or X11* */ + struct wlr_box geom; /* layout-relative, includes border */ + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; + union { + struct wlr_xdg_surface *xdg; + struct wlr_xwayland_surface *xwayland; + } surface; + struct wlr_xdg_toplevel_decoration_v1 *decoration; + struct wl_listener commit; + struct wl_listener map; + struct wl_listener maximize; + struct wl_listener unmap; + struct wl_listener destroy; + struct wl_listener set_title; + struct wl_listener fullscreen; + struct wl_listener set_decoration_mode; + struct wl_listener destroy_decoration; + struct wlr_box prev; /* layout-relative, includes border */ + struct wlr_box bounds; +#ifdef XWAYLAND + struct wl_listener activate; + struct wl_listener associate; + struct wl_listener dissociate; + struct wl_listener configure; + struct wl_listener set_hints; +#endif + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ +} Client; + +typedef struct { + uint32_t mod; + xkb_keysym_t keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + struct wl_list link; + struct wlr_keyboard_group *wlr_group; + + int nsyms; + const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */ + uint32_t mods; /* invalid if nsyms == 0 */ + struct wl_event_source *key_repeat_source; + + struct wl_listener modifiers; + struct wl_listener key; + struct wl_listener destroy; +} KeyboardGroup; + +typedef struct { + /* Must keep these three elements in this order */ + unsigned int type; /* LayerShell */ + struct wlr_box geom; + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_tree *popups; + struct wlr_scene_layer_surface_v1 *scene_layer; + struct wl_list link; + int mapped; + struct wlr_layer_surface_v1 *layer_surface; + + struct wl_listener destroy; + struct wl_listener unmap; + struct wl_listener surface_commit; +} LayerSurface; + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + +typedef struct { + struct wlr_buffer base; + struct wl_listener release; + bool busy; + Img *image; + uint32_t data[]; +} Buffer; + +struct Monitor { + struct wl_list link; + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; + struct wlr_scene_buffer *scene_buffer; /* bar buffer */ + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ + struct wl_listener frame; + struct wl_listener destroy; + struct wl_listener request_state; + struct wl_listener destroy_lock_surface; + struct wlr_session_lock_surface_v1 *lock_surface; + struct wlr_box m; /* monitor area, layout-relative */ + struct { + int width, height; + int real_width, real_height; /* non-scaled */ + float scale; + } b; /* bar area */ + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; + int gaps; + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; + float mfact; + int gamma_lut_changed; + int nmaster; + char ltsymbol[16]; + int asleep; + Drwl *drw; + Buffer *pool[2]; + int lrpad; +}; + +typedef struct { + const char *name; + float mfact; + int nmaster; + float scale; + const Layout *lt; + enum wl_output_transform rr; + int x, y; +} MonitorRule; + +typedef struct { + struct wlr_pointer_constraint_v1 *constraint; + struct wl_listener destroy; +} PointerConstraint; + +typedef struct { + const char *id; + const char *title; + uint32_t tags; + int isfloating; + int monitor; +} Rule; + +typedef struct { + struct wlr_scene_tree *scene; + + struct wlr_session_lock_v1 *lock; + struct wl_listener new_surface; + struct wl_listener unlock; + struct wl_listener destroy; +} SessionLock; + +/* function declarations */ +static void applybounds(Client *c, struct wlr_box *bbox); +static void applyrules(Client *c); +static void arrange(Monitor *m); +static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); +static void arrangelayers(Monitor *m); +static void autostartexec(void); +static void axisnotify(struct wl_listener *listener, void *data); +static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy); +static void bufdestroy(struct wlr_buffer *buffer); +static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags, + void **data, uint32_t *format, size_t *stride); +static void bufdataend(struct wlr_buffer *buffer); +static Buffer *bufmon(Monitor *m); +static void bufrelease(struct wl_listener *listener, void *data); +static void buttonpress(struct wl_listener *listener, void *data); +static void chvt(const Arg *arg); +static void checkidleinhibitor(struct wlr_surface *exclude); +static void cleanup(void); +static void cleanupmon(struct wl_listener *listener, void *data); +static void closemon(Monitor *m); +static void commitlayersurfacenotify(struct wl_listener *listener, void *data); +static void commitnotify(struct wl_listener *listener, void *data); +static void commitpopup(struct wl_listener *listener, void *data); +static void createdecoration(struct wl_listener *listener, void *data); +static void createidleinhibitor(struct wl_listener *listener, void *data); +static void createkeyboard(struct wlr_keyboard *keyboard); +static KeyboardGroup *createkeyboardgroup(void); +static void createlayersurface(struct wl_listener *listener, void *data); +static void createlocksurface(struct wl_listener *listener, void *data); +static void createmon(struct wl_listener *listener, void *data); +static void createnotify(struct wl_listener *listener, void *data); +static void createpointer(struct wlr_pointer *pointer); +static void createpointerconstraint(struct wl_listener *listener, void *data); +static void createpopup(struct wl_listener *listener, void *data); +static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); +static void cursorframe(struct wl_listener *listener, void *data); +static void cursorwarptohint(void); +static void destroydecoration(struct wl_listener *listener, void *data); +static void destroydragicon(struct wl_listener *listener, void *data); +static void destroyidleinhibitor(struct wl_listener *listener, void *data); +static void destroylayersurfacenotify(struct wl_listener *listener, void *data); +static void destroylock(SessionLock *lock, int unlocked); +static void destroylocksurface(struct wl_listener *listener, void *data); +static void destroynotify(struct wl_listener *listener, void *data); +static void moveresizekb(const Arg *arg); +static void destroypointerconstraint(struct wl_listener *listener, void *data); +static void destroysessionlock(struct wl_listener *listener, void *data); +static void destroysessionmgr(struct wl_listener *listener, void *data); +static void destroykeyboardgroup(struct wl_listener *listener, void *data); +static Monitor *dirtomon(enum wlr_direction dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void focusclient(Client *c, int lift); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Client *focustop(Monitor *m); +static void fullscreennotify(struct wl_listener *listener, void *data); +static void gpureset(struct wl_listener *listener, void *data); +static void handlesig(int signo); +static void incnmaster(const Arg *arg); +static void inputdevice(struct wl_listener *listener, void *data); +static int keybinding(uint32_t mods, xkb_keysym_t sym); +static void keypress(struct wl_listener *listener, void *data); +static void keypressmod(struct wl_listener *listener, void *data); +static int keyrepeat(void *data); +static void killclient(const Arg *arg); +static void locksession(struct wl_listener *listener, void *data); +static void mapnotify(struct wl_listener *listener, void *data); +static void maximizenotify(struct wl_listener *listener, void *data); +static void monocle(Monitor *m); +static void movestack(const Arg *arg); +static void motionabsolute(struct wl_listener *listener, void *data); +static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, + double sy, double sx_unaccel, double sy_unaccel); +static void motionrelative(struct wl_listener *listener, void *data); +static void moveresize(const Arg *arg); +static void outputmgrapply(struct wl_listener *listener, void *data); +static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); +static void outputmgrtest(struct wl_listener *listener, void *data); +static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); +static void powermgrsetmode(struct wl_listener *listener, void *data); +static void quit(const Arg *arg); +static void rendermon(struct wl_listener *listener, void *data); +static void requestdecorationmode(struct wl_listener *listener, void *data); +static void requeststartdrag(struct wl_listener *listener, void *data); +static void requestmonstate(struct wl_listener *listener, void *data); +static void resize(Client *c, struct wlr_box geo, int interact); +static void run(char *startup_cmd); +static void setcursor(struct wl_listener *listener, void *data); +static void setcursorshape(struct wl_listener *listener, void *data); +static void setfloating(Client *c, int floating); +static void setfullscreen(Client *c, int fullscreen); +static void setgamma(struct wl_listener *listener, void *data); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setmon(Client *c, Monitor *m, uint32_t newtags); +static void setpsel(struct wl_listener *listener, void *data); +static void setsel(struct wl_listener *listener, void *data); +static void setup(void); +static void spawn(const Arg *arg); +static void startdrag(struct wl_listener *listener, void *data); +static int statusin(int fd, unsigned int mask, void *data); +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 togglefullscreen(const Arg *arg); +static void togglegaps(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unlocksession(struct wl_listener *listener, void *data); +static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); +static void unmapnotify(struct wl_listener *listener, void *data); +static void updatemons(struct wl_listener *listener, void *data); +static void updatebar(Monitor *m); +static void updatetitle(struct wl_listener *listener, void *data); +static void urgent(struct wl_listener *listener, void *data); +static void view(const Arg *arg); +static void virtualkeyboard(struct wl_listener *listener, void *data); +static void virtualpointer(struct wl_listener *listener, void *data); +static void warpcursor(const Client *c); +static Monitor *xytomon(double x, double y); +static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); +static void zoom(const Arg *arg); + +/* variables */ +static const char broken[] = "broken"; +static pid_t child_pid = -1; +static int locked; +static void *exclusive_focus; +static struct wl_display *dpy; +static struct wl_event_loop *event_loop; +static struct wlr_backend *backend; +static struct wlr_scene *scene; +static struct wlr_scene_tree *layers[NUM_LAYERS]; +static struct wlr_scene_tree *drag_icon; +/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */ +static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay }; +static struct wlr_renderer *drw; +static struct wlr_allocator *alloc; +static struct wlr_compositor *compositor; +static struct wlr_session *session; + +static struct wlr_xdg_shell *xdg_shell; +static struct wlr_xdg_activation_v1 *activation; +static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; +static struct wl_list clients; /* tiling order */ +static struct wl_list fstack; /* focus order */ +static struct wlr_idle_notifier_v1 *idle_notifier; +static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; +static struct wlr_layer_shell_v1 *layer_shell; +static struct wlr_output_manager_v1 *output_mgr; +static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; +static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; +static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; +static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; +static struct wlr_output_power_manager_v1 *power_mgr; + +static struct wlr_pointer_constraints_v1 *pointer_constraints; +static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; +static struct wlr_pointer_constraint_v1 *active_constraint; + +static struct wlr_cursor *cursor; +static struct wlr_xcursor_manager *cursor_mgr; + +static struct wlr_scene_rect *root_bg; +static struct wlr_session_lock_manager_v1 *session_lock_mgr; +static struct wlr_scene_rect *locked_bg; +static struct wlr_session_lock_v1 *cur_lock; +static struct wl_listener lock_listener = {.notify = locksession}; + +static struct wlr_seat *seat; +static KeyboardGroup *kb_group; +static unsigned int cursor_mode; +static Client *grabc; +static int grabcx, grabcy; /* client-relative */ + +static struct wlr_output_layout *output_layout; +static struct wlr_box sgeom; +static struct wl_list mons; +static Monitor *selmon; + +static char stext[256]; +static struct wl_event_source *status_event_source; + +static const struct wlr_buffer_impl buffer_impl = { + .destroy = bufdestroy, + .begin_data_ptr_access = bufdatabegin, + .end_data_ptr_access = bufdataend, +}; + +#ifdef XWAYLAND +static void activatex11(struct wl_listener *listener, void *data); +static void associatex11(struct wl_listener *listener, void *data); +static void configurex11(struct wl_listener *listener, void *data); +static void createnotifyx11(struct wl_listener *listener, void *data); +static void dissociatex11(struct wl_listener *listener, void *data); +static xcb_atom_t getatom(xcb_connection_t *xc, const char *name); +static void sethints(struct wl_listener *listener, void *data); +static void xwaylandready(struct wl_listener *listener, void *data); +static struct wlr_xwayland *xwayland; +static xcb_atom_t netatom[NetLast]; +#endif + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* attempt to encapsulate suck into one file */ +#include "client.h" + +static pid_t *autostart_pids; +static size_t autostart_len; + +/* function implementations */ +void +applybounds(Client *c, struct wlr_box *bbox) +{ + /* set minimum possible */ + c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width); + c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height); + + if (c->geom.x >= bbox->x + bbox->width) + c->geom.x = bbox->x + bbox->width - c->geom.width; + if (c->geom.y >= bbox->y + bbox->height) + c->geom.y = bbox->y + bbox->height - c->geom.height; + if (c->geom.x + c->geom.width <= bbox->x) + c->geom.x = bbox->x; + if (c->geom.y + c->geom.height <= bbox->y) + c->geom.y = bbox->y; +} + +void +applyrules(Client *c) +{ + /* rule matching */ + const char *appid, *title; + uint32_t newtags = 0; + int i; + const Rule *r; + Monitor *mon = selmon, *m; + + c->isfloating = client_is_float_type(c); + if (!(appid = client_get_appid(c))) + appid = broken; + if (!(title = client_get_title(c))) + title = broken; + + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { + if (r->monitor == i++) + mon = m; + } + } + } + setmon(c, mon, newtags); +} + +void +arrange(Monitor *m) +{ + Client *c; + + if (!m->wlr_output->enabled) + return; + + wl_list_for_each(c, &clients, link) { + if (c->mon == m) { + wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m)); + client_set_suspended(c, !VISIBLEON(c, m)); + } + } + + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, + (c = focustop(m)) && c->isfullscreen); + + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + + /* We move all clients (except fullscreen and unmanaged) to LyrTile while + * in floating layout to avoid "real" floating clients be always on top */ + wl_list_for_each(c, &clients, link) { + if (c->mon != m || c->scene->node.parent == layers[LyrFS]) + continue; + + wlr_scene_node_reparent(&c->scene->node, + (!m->lt[m->sellt]->arrange && c->isfloating) + ? layers[LyrTile] + : (m->lt[m->sellt]->arrange && c->isfloating) + ? layers[LyrFloat] + : c->scene->node.parent); + } + + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); + warpcursor(focustop(selmon)); +} + +void +arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive) +{ + LayerSurface *l; + struct wlr_box full_area = m->m; + + wl_list_for_each(l, list, link) { + struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; + + if (exclusive != (layer_surface->current.exclusive_zone > 0)) + continue; + + wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area); + wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y); + l->geom.x = l->scene->node.x; + l->geom.y = l->scene->node.y; + } +} + +void +arrangelayers(Monitor *m) +{ + int i; + struct wlr_box usable_area = m->m; + LayerSurface *l; + uint32_t layers_above_shell[] = { + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, + }; + if (!m->wlr_output->enabled) + return; + + if (m->scene_buffer->node.enabled) { + usable_area.height -= m->b.real_height; + usable_area.y += topbar ? m->b.real_height : 0; + } + + /* Arrange exclusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 1); + + if (!wlr_box_equal(&usable_area, &m->w)) { + m->w = usable_area; + arrange(m); + } + + /* Arrange non-exlusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 0); + + /* Find topmost keyboard interactive layer, if such a layer exists */ + for (i = 0; i < (int)LENGTH(layers_above_shell); i++) { + wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) { + if (locked || !l->layer_surface->current.keyboard_interactive || !l->mapped) + continue; + /* Deactivate the focused client. */ + focusclient(NULL, 0); + exclusive_focus = l; + client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat)); + return; + } + } +} + +void +autostartexec(void) { + const char *const *p; + size_t i = 0; + + /* count entries */ + for (p = autostart; *p; autostart_len++, p++) + while (*++p); + + autostart_pids = calloc(autostart_len, sizeof(pid_t)); + for (p = autostart; *p; i++, p++) { + if ((autostart_pids[i] = fork()) == 0) { + setsid(); + execvp(*p, (char *const *)p); + die("dwl: execvp %s:", *p); + } + /* skip arguments */ + while (*++p); + } +} + +void +axisnotify(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits an axis event, + * for example when you move the scroll wheel. */ + struct wlr_pointer_axis_event *event = data; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + /* TODO: allow usage of scroll whell for mousebindings, it can be implemented + * checking the event's orientation and the delta of the event */ + /* Notify the client with pointer focus of the axis event. */ + wlr_seat_pointer_notify_axis(seat, + event->time_msec, event->orientation, event->delta, + event->delta_discrete, event->source, event->relative_direction); +} + +bool +baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy) +{ + return true; +} + +void +bufdestroy(struct wlr_buffer *wlr_buffer) +{ + Buffer *buf = wl_container_of(wlr_buffer, buf, base); + if (buf->busy) + wl_list_remove(&buf->release.link); + drwl_image_destroy(buf->image); + free(buf); +} + +bool +bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, + void **data, uint32_t *format, size_t *stride) +{ + Buffer *buf = wl_container_of(wlr_buffer, buf, base); + + if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; + + *data = buf->data; + *stride = wlr_buffer->width * 4; + *format = DRM_FORMAT_ARGB8888; + + return true; +} + +void +bufdataend(struct wlr_buffer *wlr_buffer) +{ +} + +Buffer * +bufmon(Monitor *m) +{ + size_t i; + Buffer *buf = NULL; + + for (i = 0; i < LENGTH(m->pool); i++) { + if (m->pool[i]) { + if (m->pool[i]->busy) + continue; + buf = m->pool[i]; + break; + } + + buf = ecalloc(1, sizeof(Buffer) + (m->b.width * 4 * m->b.height)); + buf->image = drwl_image_create(NULL, m->b.width, m->b.height, buf->data); + wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height); + m->pool[i] = buf; + break; + } + if (!buf) + return NULL; + + buf->busy = true; + LISTEN(&buf->base.events.release, &buf->release, bufrelease); + wlr_buffer_lock(&buf->base); + drwl_setimage(m->drw, buf->image); + return buf; +} + +void +bufrelease(struct wl_listener *listener, void *data) +{ + Buffer *buf = wl_container_of(listener, buf, release); + buf->busy = false; + wl_list_remove(&buf->release.link); +} + +void +buttonpress(struct wl_listener *listener, void *data) +{ + unsigned int i = 0, x = 0; + double cx; + unsigned int click; + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; + struct wlr_scene_node *node; + struct wlr_scene_buffer *buffer; + uint32_t mods; + Arg arg = {0}; + Client *c; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + + click = ClkRoot; + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); + if (c) + click = ClkClient; + + switch (event->state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + cursor_mode = CurPressed; + selmon = xytomon(cursor->x, cursor->y); + if (locked) + break; + + if (!c && !exclusive_focus && + (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && + (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { + cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; + do + x += TEXTW(selmon, tags[i]); + while (cx >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (cx < x + TEXTW(selmon, selmon->ltsymbol)) + click = ClkLtSymbol; + else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) { + click = ClkStatus; + } else + click = ClkTitle; + } + + /* Change focus if the button was _pressed_ over a client */ + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); + if (click == ClkClient && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { + if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) { + b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg); + return; + } + } + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + /* If you released any buttons, we exit interactive move/resize mode. */ + /* TODO should reset to the pointer focus's current setcursor */ + if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + cursor_mode = CurNormal; + /* Drop the window off on its new monitor */ + selmon = xytomon(cursor->x, cursor->y); + setmon(grabc, selmon, 0); + return; + } else { + cursor_mode = CurNormal; + } + break; + } + /* If the event wasn't handled by the compositor, notify the client with + * pointer focus that a button press has occurred */ + wlr_seat_pointer_notify_button(seat, + event->time_msec, event->button, event->state); +} + +void +chvt(const Arg *arg) +{ + wlr_session_change_vt(session, arg->ui); +} + +void +checkidleinhibitor(struct wlr_surface *exclude) +{ + int inhibited = 0, unused_lx, unused_ly; + struct wlr_idle_inhibitor_v1 *inhibitor; + wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { + struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface); + struct wlr_scene_tree *tree = surface->data; + if (exclude != surface && (bypass_surface_visibility || (!tree + || wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) { + inhibited = 1; + break; + } + } + + wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); +} + +void +cleanup(void) +{ + size_t i; +#ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; +#endif + wl_display_destroy_clients(dpy); + + /* kill child processes */ + for (i = 0; i < autostart_len; i++) { + if (0 < autostart_pids[i]) { + kill(autostart_pids[i], SIGTERM); + waitpid(autostart_pids[i], NULL, 0); + } + } + + if (child_pid > 0) { + kill(-child_pid, SIGTERM); + waitpid(child_pid, NULL, 0); + } + wlr_xcursor_manager_destroy(cursor_mgr); + + destroykeyboardgroup(&kb_group->destroy, NULL); + + /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. + * Destroy it until it's fixed in the wlroots side */ + wlr_backend_destroy(backend); + + wl_display_destroy(dpy); + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); + + drwl_fini(); +} + +void +cleanupmon(struct wl_listener *listener, void *data) +{ + Monitor *m = wl_container_of(listener, m, destroy); + LayerSurface *l, *tmp; + size_t i; + + /* m->layers[i] are intentionally not unlinked */ + for (i = 0; i < LENGTH(m->layers); i++) { + wl_list_for_each_safe(l, tmp, &m->layers[i], link) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + + for (i = 0; i < LENGTH(m->pool); i++) + wlr_buffer_drop(&m->pool[i]->base); + + drwl_setimage(m->drw, NULL); + drwl_destroy(m->drw); + + wl_list_remove(&m->destroy.link); + wl_list_remove(&m->frame.link); + wl_list_remove(&m->link); + wl_list_remove(&m->request_state.link); + m->wlr_output->data = NULL; + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); + + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); + wlr_scene_node_destroy(&m->scene_buffer->node); + free(m); +} + +void +closemon(Monitor *m) +{ + /* update selmon if needed and + * move closed monitor's clients to the focused one */ + Client *c; + int i = 0, nmons = wl_list_length(&mons); + if (!nmons) { + selmon = NULL; + } else if (m == selmon) { + do /* don't switch to disabled mons */ + selmon = wl_container_of(mons.next, selmon, link); + while (!selmon->wlr_output->enabled && i++ < nmons); + + if (!selmon->wlr_output->enabled) + selmon = NULL; + } + + wl_list_for_each(c, &clients, link) { + if (c->isfloating && c->geom.x > m->m.width) + resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y, + .width = c->geom.width, .height = c->geom.height}, 0); + if (c->mon == m) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); + drawbars(); +} + +void +commitlayersurfacenotify(struct wl_listener *listener, void *data) +{ + LayerSurface *l = wl_container_of(listener, l, surface_commit); + struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; + struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->current.layer]]; + struct wlr_layer_surface_v1_state old_state; + + if (l->layer_surface->initial_commit) { + wlr_fractional_scale_v1_notify_scale(layer_surface->surface, l->mon->wlr_output->scale); + wlr_surface_set_preferred_buffer_scale(layer_surface->surface, (int32_t)ceilf(l->mon->wlr_output->scale)); + + /* Temporarily set the layer's current state to pending + * so that we can easily arrange it */ + old_state = l->layer_surface->current; + l->layer_surface->current = l->layer_surface->pending; + arrangelayers(l->mon); + l->layer_surface->current = old_state; + return; + } + + if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped) + return; + l->mapped = layer_surface->surface->mapped; + + if (scene_layer != l->scene->node.parent) { + wlr_scene_node_reparent(&l->scene->node, scene_layer); + wl_list_remove(&l->link); + wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link); + wlr_scene_node_reparent(&l->popups->node, (layer_surface->current.layer + < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer)); + } + + arrangelayers(l->mon); +} + +void +commitnotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, commit); + + if (c->surface.xdg->initial_commit) { + /* + * Get the monitor this client will be rendered on + * Note that if the user set a rule in which the client is placed on + * a different monitor based on its title this will likely select + * a wrong monitor. + */ + applyrules(c); + wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale)); + wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale); + setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */ + + wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); + wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0); + if (c->decoration) + requestdecorationmode(&c->set_decoration_mode, c->decoration); + return; + } + + if (client_surface(c)->mapped && c->mon) + resize(c, c->geom, (c->isfloating && !c->isfullscreen)); + + /* mark a pending resize as completed */ + if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) + c->resize = 0; +} + +void +commitpopup(struct wl_listener *listener, void *data) +{ + struct wlr_surface *surface = data; + struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface); + LayerSurface *l = NULL; + Client *c = NULL; + struct wlr_box box; + int type = -1; + + if (!popup->base->initial_commit) + return; + + type = toplevel_from_wlr_surface(popup->base->surface, &c, &l); + if (!popup->parent || type < 0) + return; + popup->base->surface->data = wlr_scene_xdg_surface_create( + popup->parent->data, popup->base); + if ((l && !l->mon) || (c && !c->mon)) + return; + box = type == LayerShell ? l->mon->m : c->mon->w; + box.x -= (type == LayerShell ? l->geom.x : c->geom.x); + box.y -= (type == LayerShell ? l->geom.y : c->geom.y); + wlr_xdg_popup_unconstrain_from_box(popup, &box); + wl_list_remove(&listener->link); +} + +void +createdecoration(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_toplevel_decoration_v1 *deco = data; + Client *c = deco->toplevel->base->data; + c->decoration = deco; + + LISTEN(&deco->events.request_mode, &c->set_decoration_mode, requestdecorationmode); + LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration); + + requestdecorationmode(&c->set_decoration_mode, deco); +} + +void +createidleinhibitor(struct wl_listener *listener, void *data) +{ + struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; + LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); + + checkidleinhibitor(NULL); +} + +void +createkeyboard(struct wlr_keyboard *keyboard) +{ + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); + + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard); +} + +KeyboardGroup * +createkeyboardgroup(void) +{ + KeyboardGroup *group = ecalloc(1, sizeof(*group)); + struct xkb_context *context; + struct xkb_keymap *keymap; + + group->wlr_group = wlr_keyboard_group_create(); + group->wlr_group->data = group; + + /* Prepare an XKB keymap and assign it to the keyboard group. */ + context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules, + XKB_KEYMAP_COMPILE_NO_FLAGS))) + die("failed to compile keymap"); + + wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap); + xkb_keymap_unref(keymap); + xkb_context_unref(context); + + wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay); + + /* Set up listeners for keyboard events */ + LISTEN(&group->wlr_group->keyboard.events.key, &group->key, keypress); + LISTEN(&group->wlr_group->keyboard.events.modifiers, &group->modifiers, keypressmod); + + group->key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, group); + + /* A seat can only have one keyboard, but this is a limitation of the + * Wayland protocol - not wlroots. We assign all connected keyboards to the + * same wlr_keyboard_group, which provides a single wlr_keyboard interface for + * all of them. Set this combined wlr_keyboard as the seat keyboard. + */ + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); + return group; +} + +void +createlayersurface(struct wl_listener *listener, void *data) +{ + struct wlr_layer_surface_v1 *layer_surface = data; + LayerSurface *l; + struct wlr_surface *surface = layer_surface->surface; + struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->pending.layer]]; + + if (!layer_surface->output + && !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) { + wlr_layer_surface_v1_destroy(layer_surface); + return; + } + + l = layer_surface->data = ecalloc(1, sizeof(*l)); + l->type = LayerShell; + LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify); + LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify); + LISTEN(&layer_surface->events.destroy, &l->destroy, destroylayersurfacenotify); + + l->layer_surface = layer_surface; + l->mon = layer_surface->output->data; + l->scene_layer = wlr_scene_layer_surface_v1_create(scene_layer, layer_surface); + l->scene = l->scene_layer->tree; + l->popups = surface->data = wlr_scene_tree_create(layer_surface->current.layer + < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer); + l->scene->node.data = l->popups->node.data = l; + + wl_list_insert(&l->mon->layers[layer_surface->pending.layer],&l->link); + wlr_surface_send_enter(surface, layer_surface->output); +} + +void +createlocksurface(struct wl_listener *listener, void *data) +{ + SessionLock *lock = wl_container_of(listener, lock, new_surface); + struct wlr_session_lock_surface_v1 *lock_surface = data; + Monitor *m = lock_surface->output->data; + struct wlr_scene_tree *scene_tree = lock_surface->surface->data + = wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface); + m->lock_surface = lock_surface; + + wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); + wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height); + + LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface); + + if (m == selmon) + client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat)); +} + +void +createmon(struct wl_listener *listener, void *data) +{ + /* This event is raised by the backend when a new output (aka a display or + * monitor) becomes available. */ + struct wlr_output *wlr_output = data; + const MonitorRule *r; + size_t i; + struct wlr_output_state state; + Monitor *m; + + if (!wlr_output_init_render(wlr_output, alloc, drw)) + return; + + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; + + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); + + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->gaps = gaps; + + m->tagset[0] = m->tagset[1] = 1; + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; + m->m.y = r->y; + m->mfact = r->mfact; + m->nmaster = r->nmaster; + m->lt[0] = r->lt; + m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + wlr_output_state_set_scale(&state, r->scale); + wlr_output_state_set_transform(&state, r->rr); + break; + } + } + + /* The mode is a tuple of (width, height, refresh rate), and each + * monitor supports only a specific set of modes. We just pick the + * monitor's preferred mode; a more sophisticated compositor would let + * the user configure it. */ + wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); + + /* Set up event listeners */ + LISTEN(&wlr_output->events.frame, &m->frame, rendermon); + LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); + LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate); + + wlr_output_state_set_enabled(&state, 1); + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + + if (!(m->drw = drwl_create())) + die("failed to create drwl context"); + + m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL); + m->scene_buffer->point_accepts_input = baracceptsinput; + updatebar(m); + + wl_list_insert(&mons, &m->link); + drawbars(); + + /* The xdg-protocol specifies: + * + * If the fullscreened surface is not opaque, the compositor must make + * sure that other screen content not part of the same surface tree (made + * up of subsurfaces, popups or similarly coupled surfaces) are not + * visible below the fullscreened surface. + * + */ + /* updatemons() will resize and set correct position */ + m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); + + /* Adds this to the output layout in the order it was configured. + * + * The output layout utility automatically adds a wl_output global to the + * display, which Wayland clients can see to find out information about the + * output (such as DPI, scale factor, manufacturer, etc). + */ + m->scene_output = wlr_scene_output_create(scene, wlr_output); + if (m->m.x == -1 && m->m.y == -1) + wlr_output_layout_add_auto(output_layout, wlr_output); + else + wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); +} + +void +createnotify(struct wl_listener *listener, void *data) +{ + /* This event is raised when a client creates a new toplevel (application window). */ + struct wlr_xdg_toplevel *toplevel = data; + Client *c = NULL; + + /* Allocate a Client for this surface */ + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); + LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify); + LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify); + LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, fullscreennotify); + LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify); + LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle); +} + +void +createpointer(struct wlr_pointer *pointer) +{ + struct libinput_device *device; + if (wlr_input_device_is_libinput(&pointer->base) + && (device = wlr_libinput_get_device_handle(&pointer->base))) { + + if (libinput_device_config_tap_get_finger_count(device)) { + libinput_device_config_tap_set_enabled(device, tap_to_click); + libinput_device_config_tap_set_drag_enabled(device, tap_and_drag); + libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock); + libinput_device_config_tap_set_button_map(device, button_map); + } + + if (libinput_device_config_scroll_has_natural_scroll(device)) + libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling); + + if (libinput_device_config_dwt_is_available(device)) + libinput_device_config_dwt_set_enabled(device, disable_while_typing); + + if (libinput_device_config_left_handed_is_available(device)) + libinput_device_config_left_handed_set(device, left_handed); + + if (libinput_device_config_middle_emulation_is_available(device)) + libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation); + + if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) + libinput_device_config_scroll_set_method (device, scroll_method); + + if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) + libinput_device_config_click_set_method (device, click_method); + + if (libinput_device_config_send_events_get_modes(device)) + libinput_device_config_send_events_set_mode(device, send_events_mode); + + if (libinput_device_config_accel_is_available(device)) { + libinput_device_config_accel_set_profile(device, accel_profile); + libinput_device_config_accel_set_speed(device, accel_speed); + } + } + + wlr_cursor_attach_input_device(cursor, &pointer->base); +} + +void +createpointerconstraint(struct wl_listener *listener, void *data) +{ + PointerConstraint *pointer_constraint = ecalloc(1, sizeof(*pointer_constraint)); + pointer_constraint->constraint = data; + LISTEN(&pointer_constraint->constraint->events.destroy, + &pointer_constraint->destroy, destroypointerconstraint); +} + +void +createpopup(struct wl_listener *listener, void *data) +{ + /* This event is raised when a client (either xdg-shell or layer-shell) + * creates a new popup. */ + struct wlr_xdg_popup *popup = data; + LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); +} + +void +cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) +{ + if (active_constraint == constraint) + return; + + if (active_constraint) + wlr_pointer_constraint_v1_send_deactivated(active_constraint); + + active_constraint = constraint; + wlr_pointer_constraint_v1_send_activated(constraint); +} + +void +cursorframe(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits an frame + * event. Frame events are sent after regular pointer events to group + * multiple events together. For instance, two axis events may happen at the + * same time, in which case a frame event won't be sent in between. */ + /* Notify the client with pointer focus of the frame event. */ + wlr_seat_pointer_notify_frame(seat); +} + +void +cursorwarptohint(void) +{ + Client *c = NULL; + double sx = active_constraint->current.cursor_hint.x; + double sy = active_constraint->current.cursor_hint.y; + + toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); + if (c && active_constraint->current.cursor_hint.enabled) { + wlr_cursor_warp(cursor, NULL, sx + c->geom.x + c->bw, sy + c->geom.y + c->bw); + wlr_seat_pointer_warp(active_constraint->seat, sx, sy); + } +} + +void +destroydecoration(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, destroy_decoration); + c->decoration = NULL; + + wl_list_remove(&c->destroy_decoration.link); + wl_list_remove(&c->set_decoration_mode.link); +} + +void +destroydragicon(struct wl_listener *listener, void *data) +{ + /* Focus enter isn't sent during drag, so refocus the focused node. */ + focusclient(focustop(selmon), 1); + motionnotify(0, NULL, 0, 0, 0, 0); +} + +void +destroyidleinhibitor(struct wl_listener *listener, void *data) +{ + /* `data` is the wlr_surface of the idle inhibitor being destroyed, + * at this point the idle inhibitor is still in the list of the manager */ + checkidleinhibitor(wlr_surface_get_root_surface(data)); +} + +void +destroylayersurfacenotify(struct wl_listener *listener, void *data) +{ + LayerSurface *l = wl_container_of(listener, l, destroy); + + wl_list_remove(&l->link); + wl_list_remove(&l->destroy.link); + wl_list_remove(&l->unmap.link); + wl_list_remove(&l->surface_commit.link); + wlr_scene_node_destroy(&l->scene->node); + wlr_scene_node_destroy(&l->popups->node); + free(l); +} + +void +destroylock(SessionLock *lock, int unlock) +{ + wlr_seat_keyboard_notify_clear_focus(seat); + if ((locked = !unlock)) + goto destroy; + + wlr_scene_node_set_enabled(&locked_bg->node, 0); + + focusclient(focustop(selmon), 0); + motionnotify(0, NULL, 0, 0, 0, 0); + +destroy: + wl_list_remove(&lock->new_surface.link); + wl_list_remove(&lock->unlock.link); + wl_list_remove(&lock->destroy.link); + + wlr_scene_node_destroy(&lock->scene->node); + cur_lock = NULL; + free(lock); +} + +void +destroylocksurface(struct wl_listener *listener, void *data) +{ + Monitor *m = wl_container_of(listener, m, destroy_lock_surface); + struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; + + m->lock_surface = NULL; + wl_list_remove(&m->destroy_lock_surface.link); + + if (lock_surface->surface != seat->keyboard_state.focused_surface) + return; + + if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { + surface = wl_container_of(cur_lock->surfaces.next, surface, link); + client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); + } else if (!locked) { + focusclient(focustop(selmon), 1); + } else { + wlr_seat_keyboard_clear_focus(seat); + } +} + +void +destroynotify(struct wl_listener *listener, void *data) +{ + /* Called when the xdg_toplevel is destroyed. */ + Client *c = wl_container_of(listener, c, destroy); + wl_list_remove(&c->destroy.link); + wl_list_remove(&c->set_title.link); + wl_list_remove(&c->fullscreen.link); +#ifdef XWAYLAND + if (c->type != XDGShell) { + wl_list_remove(&c->activate.link); + wl_list_remove(&c->associate.link); + wl_list_remove(&c->configure.link); + wl_list_remove(&c->dissociate.link); + wl_list_remove(&c->set_hints.link); + } else +#endif + { + wl_list_remove(&c->commit.link); + wl_list_remove(&c->map.link); + wl_list_remove(&c->unmap.link); + } + free(c); +} + +void +destroypointerconstraint(struct wl_listener *listener, void *data) +{ + PointerConstraint *pointer_constraint = wl_container_of(listener, pointer_constraint, destroy); + + if (active_constraint == pointer_constraint->constraint) { + cursorwarptohint(); + active_constraint = NULL; + } + + wl_list_remove(&pointer_constraint->destroy.link); + free(pointer_constraint); +} + +void +destroysessionlock(struct wl_listener *listener, void *data) +{ + SessionLock *lock = wl_container_of(listener, lock, destroy); + destroylock(lock, 0); +} + +void +destroysessionmgr(struct wl_listener *listener, void *data) +{ + wl_list_remove(&lock_listener.link); + wl_list_remove(&listener->link); +} + +void +destroykeyboardgroup(struct wl_listener *listener, void *data) +{ + KeyboardGroup *group = wl_container_of(listener, group, destroy); + wl_event_source_remove(group->key_repeat_source); + wlr_keyboard_group_destroy(group->wlr_group); + wl_list_remove(&group->key.link); + wl_list_remove(&group->modifiers.link); + wl_list_remove(&group->destroy.link); + free(group); +} + +Monitor * +dirtomon(enum wlr_direction dir) +{ + struct wlr_output *next; + if (!wlr_output_layout_get(output_layout, selmon->wlr_output)) + return selmon; + if ((next = wlr_output_layout_adjacent_output(output_layout, + dir, selmon->wlr_output, selmon->m.x, selmon->m.y))) + return next->data; + if ((next = wlr_output_layout_farthest_output(output_layout, + dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT), + selmon->wlr_output, selmon->m.x, selmon->m.y))) + return next->data; + return selmon; +} + +void +drawbar(Monitor *m) +{ + int x, w, tw = 0; + int boxs = m->drw->font->height / 9; + int boxw = m->drw->font->height / 6 + 2; + uint32_t i, occ = 0, urg = 0; + Client *c; + Buffer *buf; + + if (!m->scene_buffer->node.enabled) + return; + if (!(buf = bufmon(m))) + return; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drwl_setscheme(m->drw, colors[SchemeNorm]); + tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ + drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); + } + + wl_list_for_each(c, &clients, link) { + if (c->mon != m) + continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + c = focustop(m); + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(m, tags[i]); + drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, + m == selmon && c && c->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = TEXTW(m, m->ltsymbol); + drwl_setscheme(m->drw, colors[SchemeNorm]); + x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0); + + if ((w = m->b.width - tw - x) > m->b.height) { + if (c) { + drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); + drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); + if (c && c->isfloating) + drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0); + } else { + drwl_setscheme(m->drw, colors[SchemeNorm]); + drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1); + } + } + + wlr_scene_buffer_set_dest_size(m->scene_buffer, + m->b.real_width, m->b.real_height); + wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, + m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); + wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); + wlr_buffer_unlock(&buf->base); +} + +void +drawbars(void) +{ + Monitor *m = NULL; + + wl_list_for_each(m, &mons, link) + drawbar(m); +} + +void +focusclient(Client *c, int lift) +{ + struct wlr_surface *old = seat->keyboard_state.focused_surface; + int unused_lx, unused_ly, old_client_type; + Client *old_c = NULL; + LayerSurface *old_l = NULL; + + if (locked) + return; + + /* Warp cursor to center of client if it is outside */ + if (lift) + warpcursor(c); + + /* Raise client in stacking order if requested */ + if (c && lift) + wlr_scene_node_raise_to_top(&c->scene->node); + + if (c && client_surface(c) == old) + return; + + if ((old_client_type = toplevel_from_wlr_surface(old, &old_c, &old_l)) == XDGShell) { + struct wlr_xdg_popup *popup, *tmp; + wl_list_for_each_safe(popup, tmp, &old_c->surface.xdg->popups, link) + wlr_xdg_popup_destroy(popup); + } + + /* Put the new client atop the focus stack and select its monitor */ + if (c && !client_is_unmanaged(c)) { + wl_list_remove(&c->flink); + wl_list_insert(&fstack, &c->flink); + selmon = c->mon; + c->isurgent = 0; + client_restack_surface(c); + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) + client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder])); + } + + /* Deactivate old client if focus is changing */ + if (old && (!c || client_surface(c) != old)) { + /* If an overlay is focused, don't focus or activate the client, + * but only update its position in fstack to render its border with its color + * and focus it after the overlay is closed. */ + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) + && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { + return; + } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) { + return; + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder])); + client_activate_surface(old, 0); + } + } + drawbars(); + + if (!c) { + /* With no client, all we have left is to clear focus */ + wlr_seat_keyboard_notify_clear_focus(seat); + return; + } + + /* Change cursor surface */ + motionnotify(0, NULL, 0, 0, 0, 0); + + /* Have a client, so focus its top-level wlr_surface */ + client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat)); + + /* Activate the new client */ + client_activate_surface(client_surface(c), 1); +} + +void +focusmon(const Arg *arg) +{ + int i = 0, nmons = wl_list_length(&mons); + if (nmons) { + do /* don't switch to disabled mons */ + selmon = dirtomon(arg->i); + while (!selmon->wlr_output->enabled && i++ < nmons); + } + focusclient(focustop(selmon), 1); +} + +void +focusstack(const Arg *arg) +{ + /* Focus the next or previous client (in tiling order) on selmon */ + Client *c, *sel = focustop(selmon); + if (!sel || (sel->isfullscreen && !client_has_children(sel))) + return; + if (arg->i > 0) { + wl_list_for_each(c, &sel->link, link) { + if (&c->link == &clients) + continue; /* wrap past the sentinel node */ + if (VISIBLEON(c, selmon)) + break; /* found it */ + } + } else { + wl_list_for_each_reverse(c, &sel->link, link) { + if (&c->link == &clients) + continue; /* wrap past the sentinel node */ + if (VISIBLEON(c, selmon)) + break; /* found it */ + } + } + /* If only one client is visible on selmon, then c == sel */ + focusclient(c, 1); +} + +/* We probably should change the name of this, it sounds like + * will focus the topmost client of this mon, when actually will + * only return that client */ +Client * +focustop(Monitor *m) +{ + Client *c; + wl_list_for_each(c, &fstack, flink) { + if (VISIBLEON(c, m)) + return c; + } + return NULL; +} + +void +fullscreennotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, fullscreen); + setfullscreen(c, client_wants_fullscreen(c)); +} + +void +gpureset(struct wl_listener *listener, void *data) +{ + struct wlr_renderer *old_drw = drw; + struct wlr_allocator *old_alloc = alloc; + struct Monitor *m; + if (!(drw = wlr_renderer_autocreate(backend))) + die("couldn't recreate renderer"); + + if (!(alloc = wlr_allocator_autocreate(backend, drw))) + die("couldn't recreate allocator"); + + LISTEN_STATIC(&drw->events.lost, gpureset); + + wlr_compositor_set_renderer(compositor, drw); + + wl_list_for_each(m, &mons, link) { + wlr_output_init_render(m->wlr_output, alloc, drw); + } + + wlr_allocator_destroy(old_alloc); + wlr_renderer_destroy(old_drw); +} + +void +handlesig(int signo) +{ + if (signo == SIGCHLD) { + siginfo_t in; + /* wlroots expects to reap the XWayland process itself, so we + * use WNOWAIT to keep the child waitable until we know it's not + * XWayland. + */ + while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid +#ifdef XWAYLAND + && (!xwayland || in.si_pid != xwayland->server->pid) +#endif + ) { + pid_t *p, *lim; + waitpid(in.si_pid, NULL, 0); + if (in.si_pid == child_pid) + child_pid = -1; + if (!(p = autostart_pids)) + continue; + lim = &p[autostart_len]; + + for (; p < lim; p++) { + if (*p == in.si_pid) { + *p = -1; + break; + } + } + } + } else if (signo == SIGINT || signo == SIGTERM) { + quit(NULL); + } +} + +void +incnmaster(const Arg *arg) +{ + if (!arg || !selmon) + return; + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +void +inputdevice(struct wl_listener *listener, void *data) +{ + /* This event is raised by the backend when a new input device becomes + * available. */ + struct wlr_input_device *device = data; + uint32_t caps; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + createkeyboard(wlr_keyboard_from_input_device(device)); + break; + case WLR_INPUT_DEVICE_POINTER: + createpointer(wlr_pointer_from_input_device(device)); + break; + default: + /* TODO handle other input device types */ + break; + } + + /* We need to let the wlr_seat know what our capabilities are, which is + * communiciated to the client. In dwl we always have a cursor, even if + * there are no pointer devices, so we always include that capability. */ + /* TODO do we actually require a cursor? */ + caps = WL_SEAT_CAPABILITY_POINTER; + if (!wl_list_empty(&kb_group->wlr_group->devices)) + caps |= WL_SEAT_CAPABILITY_KEYBOARD; + wlr_seat_set_capabilities(seat, caps); +} + +int +keybinding(uint32_t mods, xkb_keysym_t sym) +{ + /* + * Here we handle compositor keybindings. This is when the compositor is + * processing keys, rather than passing them on to the client for its own + * processing. + */ + const Key *k; + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) + && sym == k->keysym && k->func) { + k->func(&k->arg); + return 1; + } + } + return 0; +} + +void +keypress(struct wl_listener *listener, void *data) +{ + int i; + /* This event is raised when a key is pressed or released. */ + KeyboardGroup *group = wl_container_of(listener, group, key); + struct wlr_keyboard_key_event *event = data; + + /* Translate libinput keycode -> xkbcommon */ + uint32_t keycode = event->keycode + 8; + /* Get a list of keysyms based on the keymap for this keyboard */ + const xkb_keysym_t *syms; + int nsyms = xkb_state_key_get_syms( + group->wlr_group->keyboard.xkb_state, keycode, &syms); + + int handled = 0; + uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + + /* On _press_ if there is no active screen locker, + * attempt to process a compositor keybinding. */ + if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + for (i = 0; i < nsyms; i++) + handled = keybinding(mods, syms[i]) || handled; + } + + if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { + group->mods = mods; + group->keysyms = syms; + group->nsyms = nsyms; + wl_event_source_timer_update(group->key_repeat_source, + group->wlr_group->keyboard.repeat_info.delay); + } else { + group->nsyms = 0; + wl_event_source_timer_update(group->key_repeat_source, 0); + } + + if (handled) + return; + + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); + /* Pass unhandled keycodes along to the client. */ + wlr_seat_keyboard_notify_key(seat, event->time_msec, + event->keycode, event->state); +} + +void +keypressmod(struct wl_listener *listener, void *data) +{ + /* This event is raised when a modifier key, such as shift or alt, is + * pressed. We simply communicate this to the client. */ + KeyboardGroup *group = wl_container_of(listener, group, modifiers); + + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); + /* Send modifiers to the client. */ + wlr_seat_keyboard_notify_modifiers(seat, + &group->wlr_group->keyboard.modifiers); +} + +int +keyrepeat(void *data) +{ + KeyboardGroup *group = data; + int i; + if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0) + return 0; + + wl_event_source_timer_update(group->key_repeat_source, + 1000 / group->wlr_group->keyboard.repeat_info.rate); + + for (i = 0; i < group->nsyms; i++) + keybinding(group->mods, group->keysyms[i]); + + return 0; +} + +void +killclient(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (sel) + client_send_close(sel); +} + +void +locksession(struct wl_listener *listener, void *data) +{ + struct wlr_session_lock_v1 *session_lock = data; + SessionLock *lock; + wlr_scene_node_set_enabled(&locked_bg->node, 1); + if (cur_lock) { + wlr_session_lock_v1_destroy(session_lock); + return; + } + lock = session_lock->data = ecalloc(1, sizeof(*lock)); + focusclient(NULL, 0); + + lock->scene = wlr_scene_tree_create(layers[LyrBlock]); + cur_lock = lock->lock = session_lock; + locked = 1; + + LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface); + LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock); + LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession); + + wlr_session_lock_v1_send_locked(session_lock); +} + +void +mapnotify(struct wl_listener *listener, void *data) +{ + /* Called when the surface is mapped, or ready to display on-screen. */ + Client *p = NULL; + Client *w, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; + + /* Create scene tree for this client and its border */ + c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); + wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell); + c->scene_surface = c->type == XDGShell + ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg) + : wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); + c->scene->node.data = c->scene_surface->node.data = c; + + client_get_geometry(c, &c->geom); + + /* Handle unmanaged clients first so we can return prior create borders */ + if (client_is_unmanaged(c)) { + /* Unmanaged clients always are floating */ + wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + if (client_wants_focus(c)) { + focusclient(c, 1); + exclusive_focus = c; + } + goto unset_fullscreen; + } + + for (i = 0; i < 4; i++) { + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, + (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder])); + c->border[i]->node.data = c; + } + + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; + c->geom.height += 2 * c->bw; + + /* Insert this client into client lists. */ + Client* focused = focustop(selmon); + if (focused) + wl_list_insert(&focused->link, &c->link); + else + wl_list_insert(&clients, &c->link); + wl_list_insert(&fstack, &c->flink); + + /* Set initial monitor, tags, floating status, and focus: + * we always consider floating, clients that have parent and thus + * we set the same tags and monitor than its parent, if not + * try to apply rules for them */ + if ((p = client_get_parent(c))) { + c->isfloating = 1; + setmon(c, p->mon, p->tags); + } else { + applyrules(c); + } + drawbars(); + +unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); + wl_list_for_each(w, &clients, link) { + if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) + setfullscreen(w, 0); + } +} + +void +maximizenotify(struct wl_listener *listener, void *data) +{ + /* This event is raised when a client would like to maximize itself, + * typically because the user clicked on the maximize button on + * client-side decorations. dwl doesn't support maximization, but + * to conform to xdg-shell protocol we still must send a configure. + * Since xdg-shell protocol v5 we should ignore request of unsupported + * capabilities, just schedule a empty configure when the client uses <5 + * protocol version + * wlr_xdg_surface_schedule_configure() is used to send an empty reply. */ + Client *c = wl_container_of(listener, c, maximize); + if (c->surface.xdg->initialized + && wl_resource_get_version(c->surface.xdg->toplevel->resource) + < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) + wlr_xdg_surface_schedule_configure(c->surface.xdg); +} + +void +monocle(Monitor *m) +{ + Client *c; + int n = 0; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + resize(c, m->w, 0); + n++; + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); + if ((c = focustop(m))) + wlr_scene_node_raise_to_top(&c->scene->node); +} + +void +movestack(const Arg *arg) +{ + Client *c, *sel = focustop(selmon); + + if (!sel) { + return; + } + + if (wl_list_length(&clients) <= 1) { + return; + } + + if (arg->i > 0) { + wl_list_for_each(c, &sel->link, link) { + if (&c->link == &clients) { + c = wl_container_of(&clients, c, link); + break; /* wrap past the sentinel node */ + } + if (VISIBLEON(c, selmon) || &c->link == &clients) { + break; /* found it */ + } + } + } else { + wl_list_for_each_reverse(c, &sel->link, link) { + if (&c->link == &clients) { + c = wl_container_of(&clients, c, link); + break; /* wrap past the sentinel node */ + } + if (VISIBLEON(c, selmon) || &c->link == &clients) { + break; /* found it */ + } + } + /* backup one client */ + c = wl_container_of(c->link.prev, c, link); + } + + wl_list_remove(&sel->link); + wl_list_insert(&c->link, &sel->link); + arrange(selmon); +} + +void +motionabsolute(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits an _absolute_ + * motion event, from 0..1 on each axis. This happens, for example, when + * wlroots is running under a Wayland window rather than KMS+DRM, and you + * move the mouse over the window. You could enter the window from any edge, + * so we have to warp the mouse there. There is also some hardware which + * emits these events. */ + struct wlr_pointer_motion_absolute_event *event = data; + double lx, ly, dx, dy; + + if (!event->time_msec) /* this is 0 with virtual pointers */ + wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); + + wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly); + dx = lx - cursor->x; + dy = ly - cursor->y; + motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); +} + +void +motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel) +{ + double sx = 0, sy = 0, sx_confined, sy_confined; + Client *c = NULL, *w = NULL; + LayerSurface *l = NULL; + struct wlr_surface *surface = NULL; + struct wlr_pointer_constraint_v1 *constraint; + + /* Find the client under the pointer and send the event along. */ + xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy); + + if (cursor_mode == CurPressed && !seat->drag + && surface != seat->pointer_state.focused_surface + && toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) { + c = w; + surface = seat->pointer_state.focused_surface; + sx = cursor->x - (l ? l->geom.x : w->geom.x); + sy = cursor->y - (l ? l->geom.y : w->geom.y); + } + + /* time is 0 in internal calls meant to restore pointer focus. */ + if (time) { + wlr_relative_pointer_manager_v1_send_relative_motion( + relative_pointer_mgr, seat, (uint64_t)time * 1000, + dx, dy, dx_unaccel, dy_unaccel); + + wl_list_for_each(constraint, &pointer_constraints->constraints, link) + cursorconstrain(constraint); + + if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) { + toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); + if (c && active_constraint->surface == seat->pointer_state.focused_surface) { + sx = cursor->x - c->geom.x - c->bw; + sy = cursor->y - c->geom.y - c->bw; + if (wlr_region_confine(&active_constraint->region, sx, sy, + sx + dx, sy + dy, &sx_confined, &sy_confined)) { + dx = sx_confined - sx; + dy = sy_confined - sy; + } + + if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) + return; + } + } + + wlr_cursor_move(cursor, device, dx, dy); + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + + /* Update selmon (even while dragging a window) */ + if (sloppyfocus) + selmon = xytomon(cursor->x, cursor->y); + } + + /* Update drag icon's position */ + wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); + + /* If we are currently grabbing the mouse, handle and return */ + if (cursor_mode == CurMove) { + /* Move the grabbed client to the new position. */ + resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, + .width = grabc->geom.width, .height = grabc->geom.height}, 1); + return; + } else if (cursor_mode == CurResize) { + resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, + .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); + return; + } + + /* If there's no client surface under the cursor, set the cursor image to a + * default. This is what makes the cursor image appear when you move it + * off of a client or over its border. */ + if (!surface && !seat->drag) + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + + pointerfocus(c, surface, sx, sy, time); +} + +void +motionrelative(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits a _relative_ + * pointer motion event (i.e. a delta) */ + struct wlr_pointer_motion_event *event = data; + /* The cursor doesn't move unless we tell it to. The cursor automatically + * handles constraining the motion to the output layout, as well as any + * special configuration applied for the specific input device which + * generated the event. You can pass NULL for the device if you want to move + * the cursor around without any input. */ + motionnotify(event->time_msec, &event->pointer->base, event->delta_x, event->delta_y, + event->unaccel_dx, event->unaccel_dy); +} + +void +moveresize(const Arg *arg) +{ + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); + if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) + return; + + /* Float the window and tell motionnotify to grab it */ + setfloating(grabc, 1); + switch (cursor_mode = arg->ui) { + case CurMove: + grabcx = (int)round(cursor->x) - grabc->geom.x; + grabcy = (int)round(cursor->y) - grabc->geom.y; + wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); + break; + case CurResize: + /* Doesn't work for X11 output - the next absolute motion event + * returns the cursor to where it started */ + wlr_cursor_warp_closest(cursor, NULL, + grabc->geom.x + grabc->geom.width, + grabc->geom.y + grabc->geom.height); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); + break; + } +} + +void +outputmgrapply(struct wl_listener *listener, void *data) +{ + struct wlr_output_configuration_v1 *config = data; + outputmgrapplyortest(config, 0); +} + +void +outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) +{ + /* + * Called when a client such as wlr-randr requests a change in output + * configuration. This is only one way that the layout can be changed, + * so any Monitor information should be updated by updatemons() after an + * output_layout.change event, not here. + */ + struct wlr_output_configuration_head_v1 *config_head; + int ok = 1; + + wl_list_for_each(config_head, &config->heads, link) { + struct wlr_output *wlr_output = config_head->state.output; + Monitor *m = wlr_output->data; + struct wlr_output_state state; + + /* Ensure displays previously disabled by wlr-output-power-management-v1 + * are properly handled*/ + m->asleep = 0; + + wlr_output_state_init(&state); + wlr_output_state_set_enabled(&state, config_head->state.enabled); + if (!config_head->state.enabled) + goto apply_or_test; + + if (config_head->state.mode) + wlr_output_state_set_mode(&state, config_head->state.mode); + else + wlr_output_state_set_custom_mode(&state, + config_head->state.custom_mode.width, + config_head->state.custom_mode.height, + config_head->state.custom_mode.refresh); + + wlr_output_state_set_transform(&state, config_head->state.transform); + wlr_output_state_set_scale(&state, config_head->state.scale); + wlr_output_state_set_adaptive_sync_enabled(&state, + config_head->state.adaptive_sync_enabled); + +apply_or_test: + ok &= test ? wlr_output_test_state(wlr_output, &state) + : wlr_output_commit_state(wlr_output, &state); + + /* Don't move monitors if position wouldn't change, this to avoid + * wlroots marking the output as manually configured. + * wlr_output_layout_add does not like disabled outputs */ + if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y)) + wlr_output_layout_add(output_layout, wlr_output, + config_head->state.x, config_head->state.y); + + wlr_output_state_finish(&state); + } + + if (ok) + wlr_output_configuration_v1_send_succeeded(config); + else + wlr_output_configuration_v1_send_failed(config); + wlr_output_configuration_v1_destroy(config); + + /* https://codeberg.org/dwl/dwl/issues/577 */ + updatemons(NULL, NULL); +} + +void +outputmgrtest(struct wl_listener *listener, void *data) +{ + struct wlr_output_configuration_v1 *config = data; + outputmgrapplyortest(config, 1); +} + +void +pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + uint32_t time) +{ + struct timespec now; + + if (surface != seat->pointer_state.focused_surface && + sloppyfocus && time && c && !client_is_unmanaged(c)) + focusclient(c, 0); + + /* If surface is NULL, clear pointer focus */ + if (!surface) { + wlr_seat_pointer_notify_clear_focus(seat); + return; + } + + if (!time) { + clock_gettime(CLOCK_MONOTONIC, &now); + time = now.tv_sec * 1000 + now.tv_nsec / 1000000; + } + + /* Let the client know that the mouse cursor has entered one + * of its surfaces, and make keyboard focus follow if desired. + * wlroots makes this a no-op if surface is already focused */ + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(seat, time, sx, sy); +} + + +void +powermgrsetmode(struct wl_listener *listener, void *data) +{ + struct wlr_output_power_v1_set_mode_event *event = data; + struct wlr_output_state state = {0}; + Monitor *m = event->output->data; + + if (!m) + return; + + m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the ouput */ + wlr_output_state_set_enabled(&state, event->mode); + wlr_output_commit_state(m->wlr_output, &state); + + m->asleep = !event->mode; +} + +void +quit(const Arg *arg) +{ + wl_display_terminate(dpy); +} + +void +rendermon(struct wl_listener *listener, void *data) +{ + /* This function is called every time an output is ready to display a frame, + * generally at the output's refresh rate (e.g. 60Hz). */ + Monitor *m = wl_container_of(listener, m, frame); + Client *c; + struct wlr_output_state pending = {0}; + struct wlr_gamma_control_v1 *gamma_control; + struct timespec now; + + /* Render if no XDG clients have an outstanding resize and are visible on + * this monitor. */ + wl_list_for_each(c, &clients, link) { + if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) + goto skip; + } + + /* + * HACK: The "correct" way to set the gamma is to commit it together with + * the rest of the state in one go, but to do that we would need to rewrite + * wlr_scene_output_commit() in order to add the gamma to the pending + * state before committing, instead try to commit the gamma in one frame, + * and commit the rest of the state in the next one (or in the same frame if + * the gamma can not be committed). + */ + if (m->gamma_lut_changed) { + gamma_control + = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output); + m->gamma_lut_changed = 0; + + if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) + goto commit; + + if (!wlr_output_test_state(m->wlr_output, &pending)) { + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); + goto commit; + } + wlr_output_commit_state(m->wlr_output, &pending); + wlr_output_schedule_frame(m->wlr_output); + } else { +commit: + wlr_scene_output_commit(m->scene_output, NULL); + } + +skip: + /* Let clients know a frame has been rendered */ + clock_gettime(CLOCK_MONOTONIC, &now); + wlr_scene_output_send_frame_done(m->scene_output, &now); + wlr_output_state_finish(&pending); +} + +void +requestdecorationmode(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, set_decoration_mode); + if (c->surface.xdg->initialized) + wlr_xdg_toplevel_decoration_v1_set_mode(c->decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); +} + +void +requeststartdrag(struct wl_listener *listener, void *data) +{ + struct wlr_seat_request_start_drag_event *event = data; + + if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, + event->serial)) + wlr_seat_start_pointer_drag(seat, event->drag, event->serial); + else + wlr_data_source_destroy(event->drag->source); +} + +void +requestmonstate(struct wl_listener *listener, void *data) +{ + struct wlr_output_event_request_state *event = data; + wlr_output_commit_state(event->output, event->state); + updatemons(NULL, NULL); +} + +void +resize(Client *c, struct wlr_box geo, int interact) +{ + struct wlr_box *bbox; + struct wlr_box clip; + + if (!c->mon || !client_surface(c)->mapped) + return; + + bbox = interact ? &sgeom : &c->mon->w; + + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); + wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); + wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); + wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, + c->geom.height - 2 * c->bw); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); +} + +void +run(char *startup_cmd) +{ + /* Add a Unix socket to the Wayland display. */ + const char *socket = wl_display_add_socket_auto(dpy); + if (!socket) + die("startup: display_add_socket_auto"); + setenv("WAYLAND_DISPLAY", socket, 1); + + /* Start the backend. This will enumerate outputs and inputs, become the DRM + * master, etc */ + if (!wlr_backend_start(backend)) + die("startup: backend_start"); + + /* Now that the socket exists and the backend is started, run the startup command */ + autostartexec(); + if (startup_cmd) { + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { + close(STDIN_FILENO); + setsid(); + execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); + die("startup: execl:"); + } + } + + drawbars(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ + selmon = xytomon(cursor->x, cursor->y); + + /* TODO hack to get cursor to display in its initial location (100, 100) + * instead of (0, 0) and then jumping. still may not be fully + * initialized, as the image/coordinates are not transformed for the + * monitor when displayed here */ + wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + + /* Run the Wayland event loop. This does not return until you exit the + * compositor. Starting the backend rigged up all of the necessary event + * loop configuration to listen to libinput events, DRM events, generate + * frame events at the refresh rate, and so on. */ + wl_display_run(dpy); +} + +void +setcursor(struct wl_listener *listener, void *data) +{ + /* This event is raised by the seat when a client provides a cursor image */ + struct wlr_seat_pointer_request_set_cursor_event *event = data; + /* If we're "grabbing" the cursor, don't use the client's image, we will + * restore it after "grabbing" sending a leave event, followed by a enter + * event, which will result in the client requesting set the cursor surface */ + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + /* This can be sent by any client, so we check to make sure this one is + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided surface as the cursor image. It will set the + * hardware cursor on the output that it's currently on and continue to + * do so as the cursor moves between outputs. */ + if (event->seat_client == seat->pointer_state.focused_client) + wlr_cursor_set_surface(cursor, event->surface, + event->hotspot_x, event->hotspot_y); +} + +void +setcursorshape(struct wl_listener *listener, void *data) +{ + struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + /* This can be sent by any client, so we check to make sure this one is + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided cursor shape. */ + if (event->seat_client == seat->pointer_state.focused_client) + wlr_cursor_set_xcursor(cursor, cursor_mgr, + wlr_cursor_shape_v1_name(event->shape)); +} + +void +setfloating(Client *c, int floating) +{ + Client *p = client_get_parent(c); + c->isfloating = floating; + /* If in floating layout do not change the client's layer */ + if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange) + return; + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); + drawbars(); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + c->isfullscreen = fullscreen; + if (!c->mon || !client_surface(c)->mapped) + return; + c->bw = fullscreen ? 0 : borderpx; + client_set_fullscreen(c, fullscreen); + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen + ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); + + if (fullscreen) { + c->prev = c->geom; + resize(c, c->mon->m, 0); + } else { + /* restore previous size instead of arrange for floating windows since + * client positions are set by the user and cannot be recalculated */ + resize(c, c->prev, 0); + } + arrange(c->mon); + drawbars(); +} + +void +setgamma(struct wl_listener *listener, void *data) +{ + struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; + Monitor *m = event->output->data; + if (!m) + return; + m->gamma_lut_changed = 1; + wlr_output_schedule_frame(m->wlr_output); +} + +void +setlayout(const Arg *arg) +{ + if (!selmon) + return; + 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, LENGTH(selmon->ltsymbol)); + arrange(selmon); + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f; + if (f < 0.1 || f > 0.9) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setmon(Client *c, Monitor *m, uint32_t newtags) +{ + Monitor *oldmon = c->mon; + + if (oldmon == m) + return; + c->mon = m; + c->prev = c->geom; + + /* Scene graph sends surface leave/enter events on move and resize */ + if (oldmon) + arrange(oldmon); + if (m) { + /* Make sure window actually overlaps with the monitor */ + resize(c, c->geom, 0); + c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); + } + focusclient(focustop(selmon), 1); +} + +void +setpsel(struct wl_listener *listener, void *data) +{ + /* This event is raised by the seat when a client wants to set the selection, + * usually when the user copies something. wlroots allows compositors to + * ignore such requests if they so choose, but in dwl we always honor + */ + struct wlr_seat_request_set_primary_selection_event *event = data; + wlr_seat_set_primary_selection(seat, event->source, event->serial); +} + +void +setsel(struct wl_listener *listener, void *data) +{ + /* This event is raised by the seat when a client wants to set the selection, + * usually when the user copies something. wlroots allows compositors to + * ignore such requests if they so choose, but in dwl we always honor + */ + struct wlr_seat_request_set_selection_event *event = data; + wlr_seat_set_selection(seat, event->source, event->serial); +} + +void +setup(void) +{ + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; + sigemptyset(&sa.sa_mask); + + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + + + wlr_log_init(log_level, NULL); + + /* The Wayland display is managed by libwayland. It handles accepting + * clients from the Unix socket, manging Wayland globals, and so on. */ + dpy = wl_display_create(); + event_loop = wl_display_get_event_loop(dpy); + + /* The backend is a wlroots feature which abstracts the underlying input and + * output hardware. The autocreate option will choose the most suitable + * backend based on the current environment, such as opening an X11 window + * if an X11 server is running. */ + if (!(backend = wlr_backend_autocreate(event_loop, &session))) + die("couldn't create backend"); + + /* Initialize the scene graph used to lay out windows */ + scene = wlr_scene_create(); + root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor); + for (i = 0; i < NUM_LAYERS; i++) + layers[i] = wlr_scene_tree_create(&scene->tree); + drag_icon = wlr_scene_tree_create(&scene->tree); + wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); + + /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user + * can also specify a renderer using the WLR_RENDERER env var. + * The renderer is responsible for defining the various pixel formats it + * supports for shared memory, this configures that for clients. */ + if (!(drw = wlr_renderer_autocreate(backend))) + die("couldn't create renderer"); + LISTEN_STATIC(&drw->events.lost, gpureset); + + /* Create shm, drm and linux_dmabuf interfaces by ourselves. + * The simplest way is call: + * wlr_renderer_init_wl_display(drw); + * but we need to create manually the linux_dmabuf interface to integrate it + * with wlr_scene. */ + wlr_renderer_init_wl_shm(drw, dpy); + + if (wlr_renderer_get_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) { + wlr_drm_create(dpy, drw); + wlr_scene_set_linux_dmabuf_v1(scene, + wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, drw)); + } + + /* Autocreates an allocator for us. + * The allocator is the bridge between the renderer and the backend. It + * handles the buffer creation, allowing wlroots to render onto the + * screen */ + if (!(alloc = wlr_allocator_autocreate(backend, drw))) + die("couldn't create allocator"); + + /* This creates some hands-off wlroots interfaces. The compositor is + * necessary for clients to allocate surfaces and the data device manager + * handles the clipboard. Each of these wlroots interfaces has room for you + * to dig your fingers in and play with their behavior if you want. Note that + * the clients cannot set the selection directly without compositor approval, + * see the setsel() function. */ + compositor = wlr_compositor_create(dpy, 6, drw); + wlr_subcompositor_create(dpy); + wlr_data_device_manager_create(dpy); + wlr_export_dmabuf_manager_v1_create(dpy); + wlr_screencopy_manager_v1_create(dpy); + wlr_data_control_manager_v1_create(dpy); + wlr_primary_selection_v1_device_manager_create(dpy); + wlr_viewporter_create(dpy); + wlr_single_pixel_buffer_manager_v1_create(dpy); + wlr_fractional_scale_manager_v1_create(dpy, 1); + wlr_presentation_create(dpy, backend); + wlr_alpha_modifier_v1_create(dpy); + + /* Initializes the interface used to implement urgency hints */ + activation = wlr_xdg_activation_v1_create(dpy); + LISTEN_STATIC(&activation->events.request_activate, urgent); + + gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy); + LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma); + + power_mgr = wlr_output_power_manager_v1_create(dpy); + LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode); + + /* Creates an output layout, which a wlroots utility for working with an + * arrangement of screens in a physical layout. */ + output_layout = wlr_output_layout_create(dpy); + LISTEN_STATIC(&output_layout->events.change, updatemons); + wlr_xdg_output_manager_v1_create(dpy, output_layout); + + /* Configure a listener to be notified when new outputs are available on the + * backend. */ + wl_list_init(&mons); + LISTEN_STATIC(&backend->events.new_output, createmon); + + /* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a + * Wayland protocol which is used for application windows. For more + * detail on shells, refer to the article: + * + * https://drewdevault.com/2018/07/29/Wayland-shells.html + */ + wl_list_init(&clients); + wl_list_init(&fstack); + + xdg_shell = wlr_xdg_shell_create(dpy, 6); + LISTEN_STATIC(&xdg_shell->events.new_toplevel, createnotify); + LISTEN_STATIC(&xdg_shell->events.new_popup, createpopup); + + layer_shell = wlr_layer_shell_v1_create(dpy, 3); + LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface); + + idle_notifier = wlr_idle_notifier_v1_create(dpy); + + idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); + LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); + + session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); + wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener); + LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr); + locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height, + (float [4]){0.1f, 0.1f, 0.1f, 1.0f}); + wlr_scene_node_set_enabled(&locked_bg->node, 0); + + /* Use decoration protocols to negotiate server-side decorations */ + wlr_server_decoration_manager_set_default_mode( + wlr_server_decoration_manager_create(dpy), + WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); + LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration); + + pointer_constraints = wlr_pointer_constraints_v1_create(dpy); + LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint); + + relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); + + /* + * Creates a cursor, which is a wlroots utility for tracking the cursor + * image shown on screen. + */ + cursor = wlr_cursor_create(); + wlr_cursor_attach_output_layout(cursor, output_layout); + + /* Creates an xcursor manager, another wlroots utility which loads up + * Xcursor themes to source cursor images from and makes sure that cursor + * images are available at all scale factors on the screen (necessary for + * HiDPI support). Scaled cursors will be loaded with each output. */ + cursor_mgr = wlr_xcursor_manager_create(NULL, 24); + setenv("XCURSOR_SIZE", "24", 1); + + /* + * wlr_cursor *only* displays an image on screen. It does not move around + * when the pointer moves. However, we can attach input devices to it, and + * it will generate aggregate events for all of them. In these events, we + * can choose how we want to process them, forwarding them to clients and + * moving the cursor around. More detail on this process is described in + * https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html + * + * And more comments are sprinkled throughout the notify functions above. + */ + LISTEN_STATIC(&cursor->events.motion, motionrelative); + LISTEN_STATIC(&cursor->events.motion_absolute, motionabsolute); + LISTEN_STATIC(&cursor->events.button, buttonpress); + LISTEN_STATIC(&cursor->events.axis, axisnotify); + LISTEN_STATIC(&cursor->events.frame, cursorframe); + + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape); + + /* + * Configures a seat, which is a single "seat" at which a user sits and + * operates the computer. This conceptually includes up to one keyboard, + * pointer, touch, and drawing tablet device. We also rig up a listener to + * let us know when new input devices are available on the backend. + */ + LISTEN_STATIC(&backend->events.new_input, inputdevice); + virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); + virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); + + seat = wlr_seat_create(dpy, "seat0"); + LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); + LISTEN_STATIC(&seat->events.request_set_selection, setsel); + LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel); + LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); + LISTEN_STATIC(&seat->events.start_drag, startdrag); + + kb_group = createkeyboardgroup(); + wl_list_init(&kb_group->destroy.link); + + output_mgr = wlr_output_manager_v1_create(dpy); + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); + LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); + + drwl_init(); + + status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy), + STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL); + + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ + unsetenv("DISPLAY"); +#ifdef XWAYLAND + /* + * Initialise the XWayland X server. + * It will be started when the first X client is started. + */ + if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) { + LISTEN_STATIC(&xwayland->events.ready, xwaylandready); + LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11); + + setenv("DISPLAY", xwayland->display_name, 1); + } else { + fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); + } +#endif +} + +void +spawn(const Arg *arg) +{ + if (fork() == 0) { + close(STDIN_FILENO); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + die("dwl: execvp %s failed:", ((char **)arg->v)[0]); + } +} + +void +startdrag(struct wl_listener *listener, void *data) +{ + struct wlr_drag *drag = data; + if (!drag->icon) + return; + + drag->icon->data = &wlr_scene_drag_icon_create(drag_icon, drag->icon)->node; + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); +} + +int +statusin(int fd, unsigned int mask, void *data) +{ + char status[1024]; + ssize_t n; + + if (mask & WL_EVENT_ERROR) + die("status in event error"); + if (mask & WL_EVENT_HANGUP) + wl_event_source_remove(status_event_source); + + n = read(fd, status, sizeof(status) - 1); + if (n < 0 && errno != EWOULDBLOCK) + die("read:"); + + status[n] = '\0'; + status[strcspn(status, "\n")] = '\0'; + + strncpy(stext, status, sizeof(stext)); + drawbars(); + + return 0; +} + +void +tag(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (!sel || (arg->ui & TAGMASK) == 0) + return; + + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +tagmon(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (sel) + setmon(sel, dirtomon(arg->i), 0); +} + +void +tile(Monitor *m) +{ + unsigned int h, r, e = m->gaps, mw, my, ty; + int i, n = 0; + Client *c; + + wl_list_for_each(c, &clients, link) + if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) + n++; + if (n == 0) + return; + if (smartgaps == n) + e = 0; + + if (n > m->nmaster) + mw = m->nmaster ? (int)roundf((m->w.width + gappx*e) * m->mfact) : 0; + else + mw = m->w.width; + i = 0; + my = ty = gappx*e; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { + r = MIN(n, m->nmaster) - i; + h = (m->w.height - my - gappx*e - gappx*e * (r - 1)) / r; + resize(c, (struct wlr_box){.x = m->w.x + gappx*e, .y = m->w.y + my, + .width = mw - 2*gappx*e, .height = h}, 0); + my += c->geom.height + gappx*e; + } else { + r = n - i; + h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r; + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, + .width = m->w.width - mw - gappx*e, .height = h}, 0); + ty += c->geom.height + gappx*e; + } + i++; + } +} + +void +togglebar(const Arg *arg) +{ + wlr_scene_node_set_enabled(&selmon->scene_buffer->node, + !selmon->scene_buffer->node.enabled); + arrangelayers(selmon); +} + +void +togglefloating(const Arg *arg) +{ + Client *sel = focustop(selmon); + /* return if fullscreen */ + if (sel && !sel->isfullscreen) + setfloating(sel, !sel->isfloating); +} + +void +togglefullscreen(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (sel) + setfullscreen(sel, !sel->isfullscreen); +} + +void +togglegaps(const Arg *arg) +{ + selmon->gaps = !selmon->gaps; + arrange(selmon); +} + +void +moveresizekb(const Arg *arg) +{ + Client *c = focustop(selmon); + Monitor *m = selmon; + + if(!(m && arg && arg->v && c && c->isfloating)) { + return; + } + + resize(c, (struct wlr_box){ + .x = c->geom.x + ((int *)arg->v)[0], + .y = c->geom.y + ((int *)arg->v)[1], + .width = c->geom.width + ((int *)arg->v)[2], + .height = c->geom.height + ((int *)arg->v)[3], + }, 1); +} + +void +toggletag(const Arg *arg) +{ + uint32_t newtags; + Client *sel = focustop(selmon); + if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) + return; + + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +toggleview(const Arg *arg) +{ + uint32_t newtagset; + if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) + return; + + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +unlocksession(struct wl_listener *listener, void *data) +{ + SessionLock *lock = wl_container_of(listener, lock, unlock); + destroylock(lock, 1); +} + +void +unmaplayersurfacenotify(struct wl_listener *listener, void *data) +{ + LayerSurface *l = wl_container_of(listener, l, unmap); + + l->mapped = 0; + wlr_scene_node_set_enabled(&l->scene->node, 0); + if (l == exclusive_focus) + exclusive_focus = NULL; + if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) + arrangelayers(l->mon); + if (l->layer_surface->surface == seat->keyboard_state.focused_surface) + focusclient(focustop(selmon), 1); + motionnotify(0, NULL, 0, 0, 0, 0); +} + +void +unmapnotify(struct wl_listener *listener, void *data) +{ + /* Called when the surface is unmapped, and should no longer be shown. */ + Client *c = wl_container_of(listener, c, unmap); + if (c == grabc) { + cursor_mode = CurNormal; + grabc = NULL; + } + + if (client_is_unmanaged(c)) { + if (c == exclusive_focus) { + exclusive_focus = NULL; + focusclient(focustop(selmon), 1); + } + } else { + wl_list_remove(&c->link); + setmon(c, NULL, 0); + wl_list_remove(&c->flink); + } + + wlr_scene_node_destroy(&c->scene->node); + drawbars(); + motionnotify(0, NULL, 0, 0, 0, 0); +} + +void +updatemons(struct wl_listener *listener, void *data) +{ + /* + * Called whenever the output layout changes: adding or removing a + * monitor, changing an output's mode or position, etc. This is where + * the change officially happens and we update geometry, window + * positions, focus, and the stored configuration in wlroots' + * output-manager implementation. + */ + struct wlr_output_configuration_v1 *config + = wlr_output_configuration_v1_create(); + Client *c; + struct wlr_output_configuration_head_v1 *config_head; + Monitor *m; + + /* First remove from the layout the disabled monitors */ + wl_list_for_each(m, &mons, link) { + if (m->wlr_output->enabled || m->asleep) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); + config_head->state.enabled = 0; + /* Remove this output from the layout to avoid cursor enter inside it */ + wlr_output_layout_remove(output_layout, m->wlr_output); + closemon(m); + m->m = m->w = (struct wlr_box){0}; + } + /* Insert outputs that need to */ + wl_list_for_each(m, &mons, link) { + if (m->wlr_output->enabled + && !wlr_output_layout_get(output_layout, m->wlr_output)) + wlr_output_layout_add_auto(output_layout, m->wlr_output); + } + + /* Now that we update the output layout we can get its box */ + wlr_output_layout_get_box(output_layout, NULL, &sgeom); + + wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y); + wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height); + + /* Make sure the clients are hidden when dwl is locked */ + wlr_scene_node_set_position(&locked_bg->node, sgeom.x, sgeom.y); + wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height); + + wl_list_for_each(m, &mons, link) { + if (!m->wlr_output->enabled) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); + + /* Get the effective monitor geometry to use for surfaces */ + wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m); + m->w = m->m; + wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y); + + wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); + wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); + + if (m->lock_surface) { + struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; + wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); + wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, m->m.height); + } + + /* Calculate the effective monitor geometry to use for clients */ + arrangelayers(m); + /* Don't move clients to the left output when plugging monitors */ + arrange(m); + /* make sure fullscreen clients have the right size */ + if ((c = focustop(m)) && c->isfullscreen) + resize(c, m->m, 0); + + /* Try to re-set the gamma LUT when updating monitors, + * it's only really needed when enabling a disabled output, but meh. */ + m->gamma_lut_changed = 1; + + config_head->state.x = m->m.x; + config_head->state.y = m->m.y; + + if (!selmon) { + selmon = m; + } + } + + if (selmon && selmon->wlr_output->enabled) { + wl_list_for_each(c, &clients, link) { + if (!c->mon && client_surface(c)->mapped) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); + if (selmon->lock_surface) { + client_notify_enter(selmon->lock_surface->surface, + wlr_seat_get_keyboard(seat)); + client_activate_surface(selmon->lock_surface->surface, 1); + } + } + + if (stext[0] == '\0') + strncpy(stext, "dwl-"VERSION, sizeof(stext)); + wl_list_for_each(m, &mons, link) { + updatebar(m); + drawbar(m); + } + + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a + * wl_pointer.motion event for the clients, it's only the image what it's + * at the wrong position after all. */ + wlr_cursor_move(cursor, NULL, 0, 0); + + wlr_output_manager_v1_set_configuration(output_mgr, config); +} + +void +updatebar(Monitor *m) +{ + size_t i; + int rw, rh; + char fontattrs[12]; + + wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); + m->b.width = rw; + m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); + + wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0); + + for (i = 0; i < LENGTH(m->pool); i++) + if (m->pool[i]) { + wlr_buffer_drop(&m->pool[i]->base); + m->pool[i] = NULL; + } + + if (m->b.scale == m->wlr_output->scale && m->drw) + return; + + drwl_font_destroy(m->drw->font); + snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * m->wlr_output->scale); + if (!(drwl_font_create(m->drw, LENGTH(fonts), fonts, fontattrs))) + die("Could not load font"); + + m->b.scale = m->wlr_output->scale; + m->lrpad = m->drw->font->height; + m->b.height = m->drw->font->height + 2; + m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale); +} + +void +updatetitle(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) + drawbars(); +} + +void +urgent(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *c = NULL; + toplevel_from_wlr_surface(event->surface, &c, NULL); + if (!c || c == focustop(selmon)) + return; + + c->isurgent = 1; + drawbars(); + + if (client_surface(c)->mapped) + client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); +} + +void +view(const Arg *arg) +{ + if (!selmon || (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; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +virtualkeyboard(struct wl_listener *listener, void *data) +{ + struct wlr_virtual_keyboard_v1 *kb = data; + /* virtual keyboards shouldn't share keyboard group */ + KeyboardGroup *group = createkeyboardgroup(); + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); + LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup); + + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); +} + +void +virtualpointer(struct wl_listener *listener, void *data) +{ + struct wlr_virtual_pointer_v1_new_pointer_event *event = data; + struct wlr_input_device *device = &event->new_pointer->pointer.base; + + wlr_cursor_attach_input_device(cursor, device); + if (event->suggested_output) + wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); +} + +void +warpcursor(const Client *c) { + if (cursor_mode != CurNormal) { + return; + } + if (!c && selmon) { + wlr_cursor_warp_closest(cursor, + NULL, + selmon->w.x + selmon->w.width / 2.0 , + selmon->w.y + selmon->w.height / 2.0); + } + else if ( c && (cursor->x < c->geom.x || + cursor->x > c->geom.x + c->geom.width || + cursor->y < c->geom.y || + cursor->y > c->geom.y + c->geom.height)) + wlr_cursor_warp_closest(cursor, + NULL, + c->geom.x + c->geom.width / 2.0, + c->geom.y + c->geom.height / 2.0); +} + +Monitor * +xytomon(double x, double y) +{ + struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); + return o ? o->data : NULL; +} + +void +xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny) +{ + struct wlr_scene_node *node, *pnode; + struct wlr_surface *surface = NULL; + struct wlr_scene_surface *scene_surface = NULL; + Client *c = NULL; + LayerSurface *l = NULL; + int layer; + + for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) { + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + + if (node->type == WLR_SCENE_NODE_BUFFER) { + scene_surface = wlr_scene_surface_try_from_buffer( + wlr_scene_buffer_from_node(node)); + if (!scene_surface) continue; + surface = scene_surface->surface; + } + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; + if (c && c->type == LayerShell) { + c = NULL; + l = pnode->data; + } + } + + if (psurface) *psurface = surface; + if (pc) *pc = c; + if (pl) *pl = l; +} + +void +zoom(const Arg *arg) +{ + Client *c, *sel = focustop(selmon); + + if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) + return; + + /* Search for the first tiled window that is not sel, marking sel as + * NULL if we pass it along the way */ + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, selmon) && !c->isfloating) { + if (c != sel) + break; + sel = NULL; + } + } + + /* Return if no other tiled window was found */ + if (&c->link == &clients) + return; + + /* If we passed sel, move c to the front; otherwise, move sel to the + * front */ + if (!sel) + sel = c; + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); + + focusclient(sel, 1); + arrange(selmon); +} + +#ifdef XWAYLAND +void +activatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, activate); + + /* Only "managed" windows can be activated */ + if (!client_is_unmanaged(c)) + wlr_xwayland_surface_activate(c->surface.xwayland, 1); +} + +void +associatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, associate); + + LISTEN(&client_surface(c)->events.map, &c->map, mapnotify); + LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify); +} + +void +configurex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, configure); + struct wlr_xwayland_surface_configure_event *event = data; + /* TODO: figure out if there is another way to do this */ + if (!c->mon) { + wlr_xwayland_surface_configure(c->surface.xwayland, + event->x, event->y, event->width, event->height); + return; + } + if (c->isfloating || client_is_unmanaged(c)) + resize(c, (struct wlr_box){.x = event->x, .y = event->y, + .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0); + else + arrange(c->mon); +} + +void +createnotifyx11(struct wl_listener *listener, void *data) +{ + struct wlr_xwayland_surface *xsurface = data; + Client *c; + + /* Allocate a Client for this surface */ + c = xsurface->data = ecalloc(1, sizeof(*c)); + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); + LISTEN(&xsurface->events.destroy, &c->destroy, destroynotify); + LISTEN(&xsurface->events.dissociate, &c->dissociate, dissociatex11); + LISTEN(&xsurface->events.request_activate, &c->activate, activatex11); + LISTEN(&xsurface->events.request_configure, &c->configure, configurex11); + LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify); + LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints); + LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle); +} + +void +dissociatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, dissociate); + wl_list_remove(&c->map.link); + wl_list_remove(&c->unmap.link); +} + +xcb_atom_t +getatom(xcb_connection_t *xc, const char *name) +{ + xcb_atom_t atom = 0; + xcb_intern_atom_reply_t *reply; + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xc, 0, strlen(name), name); + if ((reply = xcb_intern_atom_reply(xc, cookie, NULL))) + atom = reply->atom; + free(reply); + + return atom; +} + +void +sethints(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, set_hints); + struct wlr_surface *surface = client_surface(c); + if (c == focustop(selmon)) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); + drawbars(); + + if (c->isurgent && surface && surface->mapped) + client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); +} + +void +xwaylandready(struct wl_listener *listener, void *data) +{ + struct wlr_xcursor *xcursor; + xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL); + int err = xcb_connection_has_error(xc); + if (err) { + fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err); + return; + } + + /* Collect atoms we are interested in. If getatom returns 0, we will + * not detect that window type. */ + netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG"); + netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH"); + netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR"); + netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY"); + + /* assign the one and only seat */ + wlr_xwayland_set_seat(xwayland, seat); + + /* Set the default XWayland cursor to match the rest of dwl. */ + if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1))) + wlr_xwayland_set_cursor(xwayland, + xcursor->images[0]->buffer, xcursor->images[0]->width * 4, + xcursor->images[0]->width, xcursor->images[0]->height, + xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); + + xcb_disconnect(xc); +} +#endif + +int +main(int argc, char *argv[]) +{ + char *startup_cmd = NULL; + int c; + + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') + startup_cmd = optarg; + else if (c == 'd') + log_level = WLR_DEBUG; + else if (c == 'v') + die("dwl " VERSION); + else + goto usage; + } + if (optind < argc) + goto usage; + + /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */ + if (!getenv("XDG_RUNTIME_DIR")) + die("XDG_RUNTIME_DIR must be set"); + setup(); + run(startup_cmd); + cleanup(); + return EXIT_SUCCESS; + +usage: + die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); +} diff --git a/dwl/dwl.c.orig b/dwl/dwl.c.orig new file mode 100755 index 0000000..9b5663e --- /dev/null +++ b/dwl/dwl.c.orig @@ -0,0 +1,3618 @@ +/* + * See LICENSE file for copyright and license details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XWAYLAND +#include +#include +#include +#endif + +#include "util.h" +#include "drwl.h" + +/* macros */ +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) +#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define END(A) ((A) + LENGTH(A)) +#define TAGMASK ((1u << LENGTH(tags)) - 1) +#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) +#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) +#define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) + +/* enums */ +enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ +enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ +enum { XDGShell, LayerShell, X11 }; /* client types */ +enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ +enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ +#ifdef XWAYLAND +enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +#endif + +typedef union { + int i; + uint32_t ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int click; + unsigned int mod; + unsigned int button; + void (*func)(const Arg *); + const Arg arg; +} Button; + +typedef struct Monitor Monitor; +typedef struct { + /* Must keep these three elements in this order */ + unsigned int type; /* XDGShell or X11* */ + struct wlr_box geom; /* layout-relative, includes border */ + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_tree *scene_surface; + struct wl_list link; + struct wl_list flink; + union { + struct wlr_xdg_surface *xdg; + struct wlr_xwayland_surface *xwayland; + } surface; + struct wlr_xdg_toplevel_decoration_v1 *decoration; + struct wl_listener commit; + struct wl_listener map; + struct wl_listener maximize; + struct wl_listener unmap; + struct wl_listener destroy; + struct wl_listener set_title; + struct wl_listener fullscreen; + struct wl_listener set_decoration_mode; + struct wl_listener destroy_decoration; + struct wlr_box prev; /* layout-relative, includes border */ + struct wlr_box bounds; +#ifdef XWAYLAND + struct wl_listener activate; + struct wl_listener associate; + struct wl_listener dissociate; + struct wl_listener configure; + struct wl_listener set_hints; +#endif + unsigned int bw; + uint32_t tags; + int isfloating, isurgent, isfullscreen; + uint32_t resize; /* configure serial of a pending resize */ +} Client; + +typedef struct { + uint32_t mod; + xkb_keysym_t keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + struct wl_list link; + struct wlr_keyboard_group *wlr_group; + + int nsyms; + const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */ + uint32_t mods; /* invalid if nsyms == 0 */ + struct wl_event_source *key_repeat_source; + + struct wl_listener modifiers; + struct wl_listener key; + struct wl_listener destroy; +} KeyboardGroup; + +typedef struct { + /* Must keep these three elements in this order */ + unsigned int type; /* LayerShell */ + struct wlr_box geom; + Monitor *mon; + struct wlr_scene_tree *scene; + struct wlr_scene_tree *popups; + struct wlr_scene_layer_surface_v1 *scene_layer; + struct wl_list link; + int mapped; + struct wlr_layer_surface_v1 *layer_surface; + + struct wl_listener destroy; + struct wl_listener unmap; + struct wl_listener surface_commit; +} LayerSurface; + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + +typedef struct { + struct wlr_buffer base; + struct wl_listener release; + bool busy; + Img *image; + uint32_t data[]; +} Buffer; + +struct Monitor { + struct wl_list link; + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; + struct wlr_scene_buffer *scene_buffer; /* bar buffer */ + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ + struct wl_listener frame; + struct wl_listener destroy; + struct wl_listener request_state; + struct wl_listener destroy_lock_surface; + struct wlr_session_lock_surface_v1 *lock_surface; + struct wlr_box m; /* monitor area, layout-relative */ + struct { + int width, height; + int real_width, real_height; /* non-scaled */ + float scale; + } b; /* bar area */ + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; + int gaps; + unsigned int seltags; + unsigned int sellt; + uint32_t tagset[2]; + float mfact; + int gamma_lut_changed; + int nmaster; + char ltsymbol[16]; + int asleep; + Drwl *drw; + Buffer *pool[2]; + int lrpad; +}; + +typedef struct { + const char *name; + float mfact; + int nmaster; + float scale; + const Layout *lt; + enum wl_output_transform rr; + int x, y; +} MonitorRule; + +typedef struct { + struct wlr_pointer_constraint_v1 *constraint; + struct wl_listener destroy; +} PointerConstraint; + +typedef struct { + const char *id; + const char *title; + uint32_t tags; + int isfloating; + int monitor; +} Rule; + +typedef struct { + struct wlr_scene_tree *scene; + + struct wlr_session_lock_v1 *lock; + struct wl_listener new_surface; + struct wl_listener unlock; + struct wl_listener destroy; +} SessionLock; + +/* function declarations */ +static void applybounds(Client *c, struct wlr_box *bbox); +static void applyrules(Client *c); +static void arrange(Monitor *m); +static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); +static void arrangelayers(Monitor *m); +static void autostartexec(void); +static void axisnotify(struct wl_listener *listener, void *data); +static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy); +static void bufdestroy(struct wlr_buffer *buffer); +static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags, + void **data, uint32_t *format, size_t *stride); +static void bufdataend(struct wlr_buffer *buffer); +static Buffer *bufmon(Monitor *m); +static void bufrelease(struct wl_listener *listener, void *data); +static void buttonpress(struct wl_listener *listener, void *data); +static void chvt(const Arg *arg); +static void checkidleinhibitor(struct wlr_surface *exclude); +static void cleanup(void); +static void cleanupmon(struct wl_listener *listener, void *data); +static void closemon(Monitor *m); +static void commitlayersurfacenotify(struct wl_listener *listener, void *data); +static void commitnotify(struct wl_listener *listener, void *data); +static void commitpopup(struct wl_listener *listener, void *data); +static void createdecoration(struct wl_listener *listener, void *data); +static void createidleinhibitor(struct wl_listener *listener, void *data); +static void createkeyboard(struct wlr_keyboard *keyboard); +static KeyboardGroup *createkeyboardgroup(void); +static void createlayersurface(struct wl_listener *listener, void *data); +static void createlocksurface(struct wl_listener *listener, void *data); +static void createmon(struct wl_listener *listener, void *data); +static void createnotify(struct wl_listener *listener, void *data); +static void createpointer(struct wlr_pointer *pointer); +static void createpointerconstraint(struct wl_listener *listener, void *data); +static void createpopup(struct wl_listener *listener, void *data); +static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); +static void cursorframe(struct wl_listener *listener, void *data); +static void cursorwarptohint(void); +static void destroydecoration(struct wl_listener *listener, void *data); +static void destroydragicon(struct wl_listener *listener, void *data); +static void destroyidleinhibitor(struct wl_listener *listener, void *data); +static void destroylayersurfacenotify(struct wl_listener *listener, void *data); +static void destroylock(SessionLock *lock, int unlocked); +static void destroylocksurface(struct wl_listener *listener, void *data); +static void destroynotify(struct wl_listener *listener, void *data); +static void moveresizekb(const Arg *arg); +static void destroypointerconstraint(struct wl_listener *listener, void *data); +static void destroysessionlock(struct wl_listener *listener, void *data); +static void destroysessionmgr(struct wl_listener *listener, void *data); +static void destroykeyboardgroup(struct wl_listener *listener, void *data); +static Monitor *dirtomon(enum wlr_direction dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void focusclient(Client *c, int lift); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Client *focustop(Monitor *m); +static void fullscreennotify(struct wl_listener *listener, void *data); +static void gpureset(struct wl_listener *listener, void *data); +static void handlesig(int signo); +static void incnmaster(const Arg *arg); +static void inputdevice(struct wl_listener *listener, void *data); +static int keybinding(uint32_t mods, xkb_keysym_t sym); +static void keypress(struct wl_listener *listener, void *data); +static void keypressmod(struct wl_listener *listener, void *data); +static int keyrepeat(void *data); +static void killclient(const Arg *arg); +static void locksession(struct wl_listener *listener, void *data); +static void mapnotify(struct wl_listener *listener, void *data); +static void maximizenotify(struct wl_listener *listener, void *data); +static void monocle(Monitor *m); +static void movestack(const Arg *arg); +static void motionabsolute(struct wl_listener *listener, void *data); +static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, + double sy, double sx_unaccel, double sy_unaccel); +static void motionrelative(struct wl_listener *listener, void *data); +static void moveresize(const Arg *arg); +static void outputmgrapply(struct wl_listener *listener, void *data); +static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test); +static void outputmgrtest(struct wl_listener *listener, void *data); +static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); +static void powermgrsetmode(struct wl_listener *listener, void *data); +static void quit(const Arg *arg); +static void rendermon(struct wl_listener *listener, void *data); +static void requestdecorationmode(struct wl_listener *listener, void *data); +static void requeststartdrag(struct wl_listener *listener, void *data); +static void requestmonstate(struct wl_listener *listener, void *data); +static void resize(Client *c, struct wlr_box geo, int interact); +static void run(char *startup_cmd); +static void setcursor(struct wl_listener *listener, void *data); +static void setcursorshape(struct wl_listener *listener, void *data); +static void setfloating(Client *c, int floating); +static void setfullscreen(Client *c, int fullscreen); +static void setgamma(struct wl_listener *listener, void *data); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setmon(Client *c, Monitor *m, uint32_t newtags); +static void setpsel(struct wl_listener *listener, void *data); +static void setsel(struct wl_listener *listener, void *data); +static void setup(void); +static void spawn(const Arg *arg); +static void startdrag(struct wl_listener *listener, void *data); +static int statusin(int fd, unsigned int mask, void *data); +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 togglefullscreen(const Arg *arg); +static void togglegaps(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unlocksession(struct wl_listener *listener, void *data); +static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); +static void unmapnotify(struct wl_listener *listener, void *data); +static void updatemons(struct wl_listener *listener, void *data); +static void updatebar(Monitor *m); +static void updatetitle(struct wl_listener *listener, void *data); +static void urgent(struct wl_listener *listener, void *data); +static void view(const Arg *arg); +static void virtualkeyboard(struct wl_listener *listener, void *data); +static void virtualpointer(struct wl_listener *listener, void *data); +static Monitor *xytomon(double x, double y); +static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); +static void zoom(const Arg *arg); + +/* variables */ +static const char broken[] = "broken"; +static pid_t child_pid = -1; +static int locked; +static void *exclusive_focus; +static struct wl_display *dpy; +static struct wl_event_loop *event_loop; +static struct wlr_backend *backend; +static struct wlr_scene *scene; +static struct wlr_scene_tree *layers[NUM_LAYERS]; +static struct wlr_scene_tree *drag_icon; +/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */ +static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay }; +static struct wlr_renderer *drw; +static struct wlr_allocator *alloc; +static struct wlr_compositor *compositor; +static struct wlr_session *session; + +static struct wlr_xdg_shell *xdg_shell; +static struct wlr_xdg_activation_v1 *activation; +static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; +static struct wl_list clients; /* tiling order */ +static struct wl_list fstack; /* focus order */ +static struct wlr_idle_notifier_v1 *idle_notifier; +static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; +static struct wlr_layer_shell_v1 *layer_shell; +static struct wlr_output_manager_v1 *output_mgr; +static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; +static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; +static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; +static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; +static struct wlr_output_power_manager_v1 *power_mgr; + +static struct wlr_pointer_constraints_v1 *pointer_constraints; +static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; +static struct wlr_pointer_constraint_v1 *active_constraint; + +static struct wlr_cursor *cursor; +static struct wlr_xcursor_manager *cursor_mgr; + +static struct wlr_scene_rect *root_bg; +static struct wlr_session_lock_manager_v1 *session_lock_mgr; +static struct wlr_scene_rect *locked_bg; +static struct wlr_session_lock_v1 *cur_lock; +static struct wl_listener lock_listener = {.notify = locksession}; + +static struct wlr_seat *seat; +static KeyboardGroup *kb_group; +static unsigned int cursor_mode; +static Client *grabc; +static int grabcx, grabcy; /* client-relative */ + +static struct wlr_output_layout *output_layout; +static struct wlr_box sgeom; +static struct wl_list mons; +static Monitor *selmon; + +static char stext[256]; +static struct wl_event_source *status_event_source; + +static const struct wlr_buffer_impl buffer_impl = { + .destroy = bufdestroy, + .begin_data_ptr_access = bufdatabegin, + .end_data_ptr_access = bufdataend, +}; + +#ifdef XWAYLAND +static void activatex11(struct wl_listener *listener, void *data); +static void associatex11(struct wl_listener *listener, void *data); +static void configurex11(struct wl_listener *listener, void *data); +static void createnotifyx11(struct wl_listener *listener, void *data); +static void dissociatex11(struct wl_listener *listener, void *data); +static xcb_atom_t getatom(xcb_connection_t *xc, const char *name); +static void sethints(struct wl_listener *listener, void *data); +static void xwaylandready(struct wl_listener *listener, void *data); +static struct wlr_xwayland *xwayland; +static xcb_atom_t netatom[NetLast]; +#endif + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* attempt to encapsulate suck into one file */ +#include "client.h" + +static pid_t *autostart_pids; +static size_t autostart_len; + +/* function implementations */ +void +applybounds(Client *c, struct wlr_box *bbox) +{ + /* set minimum possible */ + c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width); + c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height); + + if (c->geom.x >= bbox->x + bbox->width) + c->geom.x = bbox->x + bbox->width - c->geom.width; + if (c->geom.y >= bbox->y + bbox->height) + c->geom.y = bbox->y + bbox->height - c->geom.height; + if (c->geom.x + c->geom.width <= bbox->x) + c->geom.x = bbox->x; + if (c->geom.y + c->geom.height <= bbox->y) + c->geom.y = bbox->y; +} + +void +applyrules(Client *c) +{ + /* rule matching */ + const char *appid, *title; + uint32_t newtags = 0; + int i; + const Rule *r; + Monitor *mon = selmon, *m; + + c->isfloating = client_is_float_type(c); + if (!(appid = client_get_appid(c))) + appid = broken; + if (!(title = client_get_title(c))) + title = broken; + + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) + && (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { + if (r->monitor == i++) + mon = m; + } + } + } + setmon(c, mon, newtags); +} + +void +arrange(Monitor *m) +{ + Client *c; + + if (!m->wlr_output->enabled) + return; + + wl_list_for_each(c, &clients, link) { + if (c->mon == m) { + wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m)); + client_set_suspended(c, !VISIBLEON(c, m)); + } + } + + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, + (c = focustop(m)) && c->isfullscreen); + + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + + /* We move all clients (except fullscreen and unmanaged) to LyrTile while + * in floating layout to avoid "real" floating clients be always on top */ + wl_list_for_each(c, &clients, link) { + if (c->mon != m || c->scene->node.parent == layers[LyrFS]) + continue; + + wlr_scene_node_reparent(&c->scene->node, + (!m->lt[m->sellt]->arrange && c->isfloating) + ? layers[LyrTile] + : (m->lt[m->sellt]->arrange && c->isfloating) + ? layers[LyrFloat] + : c->scene->node.parent); + } + + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); + motionnotify(0, NULL, 0, 0, 0, 0); + checkidleinhibitor(NULL); +} + +void +arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive) +{ + LayerSurface *l; + struct wlr_box full_area = m->m; + + wl_list_for_each(l, list, link) { + struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; + + if (exclusive != (layer_surface->current.exclusive_zone > 0)) + continue; + + wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area); + wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y); + l->geom.x = l->scene->node.x; + l->geom.y = l->scene->node.y; + } +} + +void +arrangelayers(Monitor *m) +{ + int i; + struct wlr_box usable_area = m->m; + LayerSurface *l; + uint32_t layers_above_shell[] = { + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, + }; + if (!m->wlr_output->enabled) + return; + + if (m->scene_buffer->node.enabled) { + usable_area.height -= m->b.real_height; + usable_area.y += topbar ? m->b.real_height : 0; + } + + /* Arrange exclusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 1); + + if (!wlr_box_equal(&usable_area, &m->w)) { + m->w = usable_area; + arrange(m); + } + + /* Arrange non-exlusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 0); + + /* Find topmost keyboard interactive layer, if such a layer exists */ + for (i = 0; i < (int)LENGTH(layers_above_shell); i++) { + wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) { + if (locked || !l->layer_surface->current.keyboard_interactive || !l->mapped) + continue; + /* Deactivate the focused client. */ + focusclient(NULL, 0); + exclusive_focus = l; + client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat)); + return; + } + } +} + +void +autostartexec(void) { + const char *const *p; + size_t i = 0; + + /* count entries */ + for (p = autostart; *p; autostart_len++, p++) + while (*++p); + + autostart_pids = calloc(autostart_len, sizeof(pid_t)); + for (p = autostart; *p; i++, p++) { + if ((autostart_pids[i] = fork()) == 0) { + setsid(); + execvp(*p, (char *const *)p); + die("dwl: execvp %s:", *p); + } + /* skip arguments */ + while (*++p); + } +} + +void +axisnotify(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits an axis event, + * for example when you move the scroll wheel. */ + struct wlr_pointer_axis_event *event = data; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + /* TODO: allow usage of scroll whell for mousebindings, it can be implemented + * checking the event's orientation and the delta of the event */ + /* Notify the client with pointer focus of the axis event. */ + wlr_seat_pointer_notify_axis(seat, + event->time_msec, event->orientation, event->delta, + event->delta_discrete, event->source, event->relative_direction); +} + +bool +baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy) +{ + return true; +} + +void +bufdestroy(struct wlr_buffer *wlr_buffer) +{ + Buffer *buf = wl_container_of(wlr_buffer, buf, base); + if (buf->busy) + wl_list_remove(&buf->release.link); + drwl_image_destroy(buf->image); + free(buf); +} + +bool +bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags, + void **data, uint32_t *format, size_t *stride) +{ + Buffer *buf = wl_container_of(wlr_buffer, buf, base); + + if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; + + *data = buf->data; + *stride = wlr_buffer->width * 4; + *format = DRM_FORMAT_ARGB8888; + + return true; +} + +void +bufdataend(struct wlr_buffer *wlr_buffer) +{ +} + +Buffer * +bufmon(Monitor *m) +{ + size_t i; + Buffer *buf = NULL; + + for (i = 0; i < LENGTH(m->pool); i++) { + if (m->pool[i]) { + if (m->pool[i]->busy) + continue; + buf = m->pool[i]; + break; + } + + buf = ecalloc(1, sizeof(Buffer) + (m->b.width * 4 * m->b.height)); + buf->image = drwl_image_create(NULL, m->b.width, m->b.height, buf->data); + wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height); + m->pool[i] = buf; + break; + } + if (!buf) + return NULL; + + buf->busy = true; + LISTEN(&buf->base.events.release, &buf->release, bufrelease); + wlr_buffer_lock(&buf->base); + drwl_setimage(m->drw, buf->image); + return buf; +} + +void +bufrelease(struct wl_listener *listener, void *data) +{ + Buffer *buf = wl_container_of(listener, buf, release); + buf->busy = false; + wl_list_remove(&buf->release.link); +} + +void +buttonpress(struct wl_listener *listener, void *data) +{ + unsigned int i = 0, x = 0; + double cx; + unsigned int click; + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; + struct wlr_scene_node *node; + struct wlr_scene_buffer *buffer; + uint32_t mods; + Arg arg = {0}; + Client *c; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + + click = ClkRoot; + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); + if (c) + click = ClkClient; + + switch (event->state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + cursor_mode = CurPressed; + selmon = xytomon(cursor->x, cursor->y); + if (locked) + break; + + if (!c && !exclusive_focus && + (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && + (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) { + cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; + do + x += TEXTW(selmon, tags[i]); + while (cx >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (cx < x + TEXTW(selmon, selmon->ltsymbol)) + click = ClkLtSymbol; + else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) { + click = ClkStatus; + } else + click = ClkTitle; + } + + /* Change focus if the button was _pressed_ over a client */ + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); + if (click == ClkClient && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { + if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) { + b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg); + return; + } + } + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + /* If you released any buttons, we exit interactive move/resize mode. */ + /* TODO should reset to the pointer focus's current setcursor */ + if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + cursor_mode = CurNormal; + /* Drop the window off on its new monitor */ + selmon = xytomon(cursor->x, cursor->y); + setmon(grabc, selmon, 0); + return; + } else { + cursor_mode = CurNormal; + } + break; + } + /* If the event wasn't handled by the compositor, notify the client with + * pointer focus that a button press has occurred */ + wlr_seat_pointer_notify_button(seat, + event->time_msec, event->button, event->state); +} + +void +chvt(const Arg *arg) +{ + wlr_session_change_vt(session, arg->ui); +} + +void +checkidleinhibitor(struct wlr_surface *exclude) +{ + int inhibited = 0, unused_lx, unused_ly; + struct wlr_idle_inhibitor_v1 *inhibitor; + wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { + struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface); + struct wlr_scene_tree *tree = surface->data; + if (exclude != surface && (bypass_surface_visibility || (!tree + || wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) { + inhibited = 1; + break; + } + } + + wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); +} + +void +cleanup(void) +{ + size_t i; +#ifdef XWAYLAND + wlr_xwayland_destroy(xwayland); + xwayland = NULL; +#endif + wl_display_destroy_clients(dpy); + + /* kill child processes */ + for (i = 0; i < autostart_len; i++) { + if (0 < autostart_pids[i]) { + kill(autostart_pids[i], SIGTERM); + waitpid(autostart_pids[i], NULL, 0); + } + } + + if (child_pid > 0) { + kill(-child_pid, SIGTERM); + waitpid(child_pid, NULL, 0); + } + wlr_xcursor_manager_destroy(cursor_mgr); + + destroykeyboardgroup(&kb_group->destroy, NULL); + + /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. + * Destroy it until it's fixed in the wlroots side */ + wlr_backend_destroy(backend); + + wl_display_destroy(dpy); + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); + + drwl_fini(); +} + +void +cleanupmon(struct wl_listener *listener, void *data) +{ + Monitor *m = wl_container_of(listener, m, destroy); + LayerSurface *l, *tmp; + size_t i; + + /* m->layers[i] are intentionally not unlinked */ + for (i = 0; i < LENGTH(m->layers); i++) { + wl_list_for_each_safe(l, tmp, &m->layers[i], link) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + + for (i = 0; i < LENGTH(m->pool); i++) + wlr_buffer_drop(&m->pool[i]->base); + + drwl_setimage(m->drw, NULL); + drwl_destroy(m->drw); + + wl_list_remove(&m->destroy.link); + wl_list_remove(&m->frame.link); + wl_list_remove(&m->link); + wl_list_remove(&m->request_state.link); + m->wlr_output->data = NULL; + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); + + closemon(m); + wlr_scene_node_destroy(&m->fullscreen_bg->node); + wlr_scene_node_destroy(&m->scene_buffer->node); + free(m); +} + +void +closemon(Monitor *m) +{ + /* update selmon if needed and + * move closed monitor's clients to the focused one */ + Client *c; + int i = 0, nmons = wl_list_length(&mons); + if (!nmons) { + selmon = NULL; + } else if (m == selmon) { + do /* don't switch to disabled mons */ + selmon = wl_container_of(mons.next, selmon, link); + while (!selmon->wlr_output->enabled && i++ < nmons); + + if (!selmon->wlr_output->enabled) + selmon = NULL; + } + + wl_list_for_each(c, &clients, link) { + if (c->isfloating && c->geom.x > m->m.width) + resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y, + .width = c->geom.width, .height = c->geom.height}, 0); + if (c->mon == m) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); + drawbars(); +} + +void +commitlayersurfacenotify(struct wl_listener *listener, void *data) +{ + LayerSurface *l = wl_container_of(listener, l, surface_commit); + struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; + struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->current.layer]]; + struct wlr_layer_surface_v1_state old_state; + + if (l->layer_surface->initial_commit) { + wlr_fractional_scale_v1_notify_scale(layer_surface->surface, l->mon->wlr_output->scale); + wlr_surface_set_preferred_buffer_scale(layer_surface->surface, (int32_t)ceilf(l->mon->wlr_output->scale)); + + /* Temporarily set the layer's current state to pending + * so that we can easily arrange it */ + old_state = l->layer_surface->current; + l->layer_surface->current = l->layer_surface->pending; + arrangelayers(l->mon); + l->layer_surface->current = old_state; + return; + } + + if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped) + return; + l->mapped = layer_surface->surface->mapped; + + if (scene_layer != l->scene->node.parent) { + wlr_scene_node_reparent(&l->scene->node, scene_layer); + wl_list_remove(&l->link); + wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link); + wlr_scene_node_reparent(&l->popups->node, (layer_surface->current.layer + < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer)); + } + + arrangelayers(l->mon); +} + +void +commitnotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, commit); + + if (c->surface.xdg->initial_commit) { + /* + * Get the monitor this client will be rendered on + * Note that if the user set a rule in which the client is placed on + * a different monitor based on its title this will likely select + * a wrong monitor. + */ + applyrules(c); + wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale)); + wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale); + setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */ + + wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); + wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0); + if (c->decoration) + requestdecorationmode(&c->set_decoration_mode, c->decoration); + return; + } + + if (client_surface(c)->mapped && c->mon) + resize(c, c->geom, (c->isfloating && !c->isfullscreen)); + + /* mark a pending resize as completed */ + if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) + c->resize = 0; +} + +void +commitpopup(struct wl_listener *listener, void *data) +{ + struct wlr_surface *surface = data; + struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface); + LayerSurface *l = NULL; + Client *c = NULL; + struct wlr_box box; + int type = -1; + + if (!popup->base->initial_commit) + return; + + type = toplevel_from_wlr_surface(popup->base->surface, &c, &l); + if (!popup->parent || type < 0) + return; + popup->base->surface->data = wlr_scene_xdg_surface_create( + popup->parent->data, popup->base); + if ((l && !l->mon) || (c && !c->mon)) + return; + box = type == LayerShell ? l->mon->m : c->mon->w; + box.x -= (type == LayerShell ? l->geom.x : c->geom.x); + box.y -= (type == LayerShell ? l->geom.y : c->geom.y); + wlr_xdg_popup_unconstrain_from_box(popup, &box); + wl_list_remove(&listener->link); +} + +void +createdecoration(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_toplevel_decoration_v1 *deco = data; + Client *c = deco->toplevel->base->data; + c->decoration = deco; + + LISTEN(&deco->events.request_mode, &c->set_decoration_mode, requestdecorationmode); + LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration); + + requestdecorationmode(&c->set_decoration_mode, deco); +} + +void +createidleinhibitor(struct wl_listener *listener, void *data) +{ + struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; + LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); + + checkidleinhibitor(NULL); +} + +void +createkeyboard(struct wlr_keyboard *keyboard) +{ + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); + + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard); +} + +KeyboardGroup * +createkeyboardgroup(void) +{ + KeyboardGroup *group = ecalloc(1, sizeof(*group)); + struct xkb_context *context; + struct xkb_keymap *keymap; + + group->wlr_group = wlr_keyboard_group_create(); + group->wlr_group->data = group; + + /* Prepare an XKB keymap and assign it to the keyboard group. */ + context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules, + XKB_KEYMAP_COMPILE_NO_FLAGS))) + die("failed to compile keymap"); + + wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap); + xkb_keymap_unref(keymap); + xkb_context_unref(context); + + wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay); + + /* Set up listeners for keyboard events */ + LISTEN(&group->wlr_group->keyboard.events.key, &group->key, keypress); + LISTEN(&group->wlr_group->keyboard.events.modifiers, &group->modifiers, keypressmod); + + group->key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, group); + + /* A seat can only have one keyboard, but this is a limitation of the + * Wayland protocol - not wlroots. We assign all connected keyboards to the + * same wlr_keyboard_group, which provides a single wlr_keyboard interface for + * all of them. Set this combined wlr_keyboard as the seat keyboard. + */ + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); + return group; +} + +void +createlayersurface(struct wl_listener *listener, void *data) +{ + struct wlr_layer_surface_v1 *layer_surface = data; + LayerSurface *l; + struct wlr_surface *surface = layer_surface->surface; + struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->pending.layer]]; + + if (!layer_surface->output + && !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) { + wlr_layer_surface_v1_destroy(layer_surface); + return; + } + + l = layer_surface->data = ecalloc(1, sizeof(*l)); + l->type = LayerShell; + LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify); + LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify); + LISTEN(&layer_surface->events.destroy, &l->destroy, destroylayersurfacenotify); + + l->layer_surface = layer_surface; + l->mon = layer_surface->output->data; + l->scene_layer = wlr_scene_layer_surface_v1_create(scene_layer, layer_surface); + l->scene = l->scene_layer->tree; + l->popups = surface->data = wlr_scene_tree_create(layer_surface->current.layer + < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer); + l->scene->node.data = l->popups->node.data = l; + + wl_list_insert(&l->mon->layers[layer_surface->pending.layer],&l->link); + wlr_surface_send_enter(surface, layer_surface->output); +} + +void +createlocksurface(struct wl_listener *listener, void *data) +{ + SessionLock *lock = wl_container_of(listener, lock, new_surface); + struct wlr_session_lock_surface_v1 *lock_surface = data; + Monitor *m = lock_surface->output->data; + struct wlr_scene_tree *scene_tree = lock_surface->surface->data + = wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface); + m->lock_surface = lock_surface; + + wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); + wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height); + + LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface); + + if (m == selmon) + client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat)); +} + +void +createmon(struct wl_listener *listener, void *data) +{ + /* This event is raised by the backend when a new output (aka a display or + * monitor) becomes available. */ + struct wlr_output *wlr_output = data; + const MonitorRule *r; + size_t i; + struct wlr_output_state state; + Monitor *m; + + if (!wlr_output_init_render(wlr_output, alloc, drw)) + return; + + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; + + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); + + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->gaps = gaps; + + m->tagset[0] = m->tagset[1] = 1; + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; + m->m.y = r->y; + m->mfact = r->mfact; + m->nmaster = r->nmaster; + m->lt[0] = r->lt; + m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + wlr_output_state_set_scale(&state, r->scale); + wlr_output_state_set_transform(&state, r->rr); + break; + } + } + + /* The mode is a tuple of (width, height, refresh rate), and each + * monitor supports only a specific set of modes. We just pick the + * monitor's preferred mode; a more sophisticated compositor would let + * the user configure it. */ + wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); + + /* Set up event listeners */ + LISTEN(&wlr_output->events.frame, &m->frame, rendermon); + LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); + LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate); + + wlr_output_state_set_enabled(&state, 1); + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + + if (!(m->drw = drwl_create())) + die("failed to create drwl context"); + + m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL); + m->scene_buffer->point_accepts_input = baracceptsinput; + updatebar(m); + + wl_list_insert(&mons, &m->link); + drawbars(); + + /* The xdg-protocol specifies: + * + * If the fullscreened surface is not opaque, the compositor must make + * sure that other screen content not part of the same surface tree (made + * up of subsurfaces, popups or similarly coupled surfaces) are not + * visible below the fullscreened surface. + * + */ + /* updatemons() will resize and set correct position */ + m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); + + /* Adds this to the output layout in the order it was configured. + * + * The output layout utility automatically adds a wl_output global to the + * display, which Wayland clients can see to find out information about the + * output (such as DPI, scale factor, manufacturer, etc). + */ + m->scene_output = wlr_scene_output_create(scene, wlr_output); + if (m->m.x == -1 && m->m.y == -1) + wlr_output_layout_add_auto(output_layout, wlr_output); + else + wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); +} + +void +createnotify(struct wl_listener *listener, void *data) +{ + /* This event is raised when a client creates a new toplevel (application window). */ + struct wlr_xdg_toplevel *toplevel = data; + Client *c = NULL; + + /* Allocate a Client for this surface */ + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); + LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify); + LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify); + LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, fullscreennotify); + LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify); + LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle); +} + +void +createpointer(struct wlr_pointer *pointer) +{ + struct libinput_device *device; + if (wlr_input_device_is_libinput(&pointer->base) + && (device = wlr_libinput_get_device_handle(&pointer->base))) { + + if (libinput_device_config_tap_get_finger_count(device)) { + libinput_device_config_tap_set_enabled(device, tap_to_click); + libinput_device_config_tap_set_drag_enabled(device, tap_and_drag); + libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock); + libinput_device_config_tap_set_button_map(device, button_map); + } + + if (libinput_device_config_scroll_has_natural_scroll(device)) + libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling); + + if (libinput_device_config_dwt_is_available(device)) + libinput_device_config_dwt_set_enabled(device, disable_while_typing); + + if (libinput_device_config_left_handed_is_available(device)) + libinput_device_config_left_handed_set(device, left_handed); + + if (libinput_device_config_middle_emulation_is_available(device)) + libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation); + + if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) + libinput_device_config_scroll_set_method (device, scroll_method); + + if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) + libinput_device_config_click_set_method (device, click_method); + + if (libinput_device_config_send_events_get_modes(device)) + libinput_device_config_send_events_set_mode(device, send_events_mode); + + if (libinput_device_config_accel_is_available(device)) { + libinput_device_config_accel_set_profile(device, accel_profile); + libinput_device_config_accel_set_speed(device, accel_speed); + } + } + + wlr_cursor_attach_input_device(cursor, &pointer->base); +} + +void +createpointerconstraint(struct wl_listener *listener, void *data) +{ + PointerConstraint *pointer_constraint = ecalloc(1, sizeof(*pointer_constraint)); + pointer_constraint->constraint = data; + LISTEN(&pointer_constraint->constraint->events.destroy, + &pointer_constraint->destroy, destroypointerconstraint); +} + +void +createpopup(struct wl_listener *listener, void *data) +{ + /* This event is raised when a client (either xdg-shell or layer-shell) + * creates a new popup. */ + struct wlr_xdg_popup *popup = data; + LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); +} + +void +cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) +{ + if (active_constraint == constraint) + return; + + if (active_constraint) + wlr_pointer_constraint_v1_send_deactivated(active_constraint); + + active_constraint = constraint; + wlr_pointer_constraint_v1_send_activated(constraint); +} + +void +cursorframe(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits an frame + * event. Frame events are sent after regular pointer events to group + * multiple events together. For instance, two axis events may happen at the + * same time, in which case a frame event won't be sent in between. */ + /* Notify the client with pointer focus of the frame event. */ + wlr_seat_pointer_notify_frame(seat); +} + +void +cursorwarptohint(void) +{ + Client *c = NULL; + double sx = active_constraint->current.cursor_hint.x; + double sy = active_constraint->current.cursor_hint.y; + + toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); + if (c && active_constraint->current.cursor_hint.enabled) { + wlr_cursor_warp(cursor, NULL, sx + c->geom.x + c->bw, sy + c->geom.y + c->bw); + wlr_seat_pointer_warp(active_constraint->seat, sx, sy); + } +} + +void +destroydecoration(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, destroy_decoration); + c->decoration = NULL; + + wl_list_remove(&c->destroy_decoration.link); + wl_list_remove(&c->set_decoration_mode.link); +} + +void +destroydragicon(struct wl_listener *listener, void *data) +{ + /* Focus enter isn't sent during drag, so refocus the focused node. */ + focusclient(focustop(selmon), 1); + motionnotify(0, NULL, 0, 0, 0, 0); +} + +void +destroyidleinhibitor(struct wl_listener *listener, void *data) +{ + /* `data` is the wlr_surface of the idle inhibitor being destroyed, + * at this point the idle inhibitor is still in the list of the manager */ + checkidleinhibitor(wlr_surface_get_root_surface(data)); +} + +void +destroylayersurfacenotify(struct wl_listener *listener, void *data) +{ + LayerSurface *l = wl_container_of(listener, l, destroy); + + wl_list_remove(&l->link); + wl_list_remove(&l->destroy.link); + wl_list_remove(&l->unmap.link); + wl_list_remove(&l->surface_commit.link); + wlr_scene_node_destroy(&l->scene->node); + wlr_scene_node_destroy(&l->popups->node); + free(l); +} + +void +destroylock(SessionLock *lock, int unlock) +{ + wlr_seat_keyboard_notify_clear_focus(seat); + if ((locked = !unlock)) + goto destroy; + + wlr_scene_node_set_enabled(&locked_bg->node, 0); + + focusclient(focustop(selmon), 0); + motionnotify(0, NULL, 0, 0, 0, 0); + +destroy: + wl_list_remove(&lock->new_surface.link); + wl_list_remove(&lock->unlock.link); + wl_list_remove(&lock->destroy.link); + + wlr_scene_node_destroy(&lock->scene->node); + cur_lock = NULL; + free(lock); +} + +void +destroylocksurface(struct wl_listener *listener, void *data) +{ + Monitor *m = wl_container_of(listener, m, destroy_lock_surface); + struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; + + m->lock_surface = NULL; + wl_list_remove(&m->destroy_lock_surface.link); + + if (lock_surface->surface != seat->keyboard_state.focused_surface) + return; + + if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { + surface = wl_container_of(cur_lock->surfaces.next, surface, link); + client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); + } else if (!locked) { + focusclient(focustop(selmon), 1); + } else { + wlr_seat_keyboard_clear_focus(seat); + } +} + +void +destroynotify(struct wl_listener *listener, void *data) +{ + /* Called when the xdg_toplevel is destroyed. */ + Client *c = wl_container_of(listener, c, destroy); + wl_list_remove(&c->destroy.link); + wl_list_remove(&c->set_title.link); + wl_list_remove(&c->fullscreen.link); +#ifdef XWAYLAND + if (c->type != XDGShell) { + wl_list_remove(&c->activate.link); + wl_list_remove(&c->associate.link); + wl_list_remove(&c->configure.link); + wl_list_remove(&c->dissociate.link); + wl_list_remove(&c->set_hints.link); + } else +#endif + { + wl_list_remove(&c->commit.link); + wl_list_remove(&c->map.link); + wl_list_remove(&c->unmap.link); + } + free(c); +} + +void +destroypointerconstraint(struct wl_listener *listener, void *data) +{ + PointerConstraint *pointer_constraint = wl_container_of(listener, pointer_constraint, destroy); + + if (active_constraint == pointer_constraint->constraint) { + cursorwarptohint(); + active_constraint = NULL; + } + + wl_list_remove(&pointer_constraint->destroy.link); + free(pointer_constraint); +} + +void +destroysessionlock(struct wl_listener *listener, void *data) +{ + SessionLock *lock = wl_container_of(listener, lock, destroy); + destroylock(lock, 0); +} + +void +destroysessionmgr(struct wl_listener *listener, void *data) +{ + wl_list_remove(&lock_listener.link); + wl_list_remove(&listener->link); +} + +void +destroykeyboardgroup(struct wl_listener *listener, void *data) +{ + KeyboardGroup *group = wl_container_of(listener, group, destroy); + wl_event_source_remove(group->key_repeat_source); + wlr_keyboard_group_destroy(group->wlr_group); + wl_list_remove(&group->key.link); + wl_list_remove(&group->modifiers.link); + wl_list_remove(&group->destroy.link); + free(group); +} + +Monitor * +dirtomon(enum wlr_direction dir) +{ + struct wlr_output *next; + if (!wlr_output_layout_get(output_layout, selmon->wlr_output)) + return selmon; + if ((next = wlr_output_layout_adjacent_output(output_layout, + dir, selmon->wlr_output, selmon->m.x, selmon->m.y))) + return next->data; + if ((next = wlr_output_layout_farthest_output(output_layout, + dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT), + selmon->wlr_output, selmon->m.x, selmon->m.y))) + return next->data; + return selmon; +} + +void +drawbar(Monitor *m) +{ + int x, w, tw = 0; + int boxs = m->drw->font->height / 9; + int boxw = m->drw->font->height / 6 + 2; + uint32_t i, occ = 0, urg = 0; + Client *c; + Buffer *buf; + + if (!m->scene_buffer->node.enabled) + return; + if (!(buf = bufmon(m))) + return; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drwl_setscheme(m->drw, colors[SchemeNorm]); + tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ + drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); + } + + wl_list_for_each(c, &clients, link) { + if (c->mon != m) + continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + c = focustop(m); + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(m, tags[i]); + drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, + m == selmon && c && c->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = TEXTW(m, m->ltsymbol); + drwl_setscheme(m->drw, colors[SchemeNorm]); + x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0); + + if ((w = m->b.width - tw - x) > m->b.height) { + if (c) { + drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]); + drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0); + if (c && c->isfloating) + drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0); + } else { + drwl_setscheme(m->drw, colors[SchemeNorm]); + drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1); + } + } + + wlr_scene_buffer_set_dest_size(m->scene_buffer, + m->b.real_width, m->b.real_height); + wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, + m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); + wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); + wlr_buffer_unlock(&buf->base); +} + +void +drawbars(void) +{ + Monitor *m = NULL; + + wl_list_for_each(m, &mons, link) + drawbar(m); +} + +void +focusclient(Client *c, int lift) +{ + struct wlr_surface *old = seat->keyboard_state.focused_surface; + int unused_lx, unused_ly, old_client_type; + Client *old_c = NULL; + LayerSurface *old_l = NULL; + + if (locked) + return; + + /* Raise client in stacking order if requested */ + if (c && lift) + wlr_scene_node_raise_to_top(&c->scene->node); + + if (c && client_surface(c) == old) + return; + + if ((old_client_type = toplevel_from_wlr_surface(old, &old_c, &old_l)) == XDGShell) { + struct wlr_xdg_popup *popup, *tmp; + wl_list_for_each_safe(popup, tmp, &old_c->surface.xdg->popups, link) + wlr_xdg_popup_destroy(popup); + } + + /* Put the new client atop the focus stack and select its monitor */ + if (c && !client_is_unmanaged(c)) { + wl_list_remove(&c->flink); + wl_list_insert(&fstack, &c->flink); + selmon = c->mon; + c->isurgent = 0; + client_restack_surface(c); + + /* Don't change border color if there is an exclusive focus or we are + * handling a drag operation */ + if (!exclusive_focus && !seat->drag) + client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder])); + } + + /* Deactivate old client if focus is changing */ + if (old && (!c || client_surface(c) != old)) { + /* If an overlay is focused, don't focus or activate the client, + * but only update its position in fstack to render its border with its color + * and focus it after the overlay is closed. */ + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) + && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { + return; + } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) { + return; + /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg + * and probably other clients */ + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { + client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder])); + client_activate_surface(old, 0); + } + } + drawbars(); + + if (!c) { + /* With no client, all we have left is to clear focus */ + wlr_seat_keyboard_notify_clear_focus(seat); + return; + } + + /* Change cursor surface */ + motionnotify(0, NULL, 0, 0, 0, 0); + + /* Have a client, so focus its top-level wlr_surface */ + client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat)); + + /* Activate the new client */ + client_activate_surface(client_surface(c), 1); +} + +void +focusmon(const Arg *arg) +{ + int i = 0, nmons = wl_list_length(&mons); + if (nmons) { + do /* don't switch to disabled mons */ + selmon = dirtomon(arg->i); + while (!selmon->wlr_output->enabled && i++ < nmons); + } + focusclient(focustop(selmon), 1); +} + +void +focusstack(const Arg *arg) +{ + /* Focus the next or previous client (in tiling order) on selmon */ + Client *c, *sel = focustop(selmon); + if (!sel || (sel->isfullscreen && !client_has_children(sel))) + return; + if (arg->i > 0) { + wl_list_for_each(c, &sel->link, link) { + if (&c->link == &clients) + continue; /* wrap past the sentinel node */ + if (VISIBLEON(c, selmon)) + break; /* found it */ + } + } else { + wl_list_for_each_reverse(c, &sel->link, link) { + if (&c->link == &clients) + continue; /* wrap past the sentinel node */ + if (VISIBLEON(c, selmon)) + break; /* found it */ + } + } + /* If only one client is visible on selmon, then c == sel */ + focusclient(c, 1); +} + +/* We probably should change the name of this, it sounds like + * will focus the topmost client of this mon, when actually will + * only return that client */ +Client * +focustop(Monitor *m) +{ + Client *c; + wl_list_for_each(c, &fstack, flink) { + if (VISIBLEON(c, m)) + return c; + } + return NULL; +} + +void +fullscreennotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, fullscreen); + setfullscreen(c, client_wants_fullscreen(c)); +} + +void +gpureset(struct wl_listener *listener, void *data) +{ + struct wlr_renderer *old_drw = drw; + struct wlr_allocator *old_alloc = alloc; + struct Monitor *m; + if (!(drw = wlr_renderer_autocreate(backend))) + die("couldn't recreate renderer"); + + if (!(alloc = wlr_allocator_autocreate(backend, drw))) + die("couldn't recreate allocator"); + + LISTEN_STATIC(&drw->events.lost, gpureset); + + wlr_compositor_set_renderer(compositor, drw); + + wl_list_for_each(m, &mons, link) { + wlr_output_init_render(m->wlr_output, alloc, drw); + } + + wlr_allocator_destroy(old_alloc); + wlr_renderer_destroy(old_drw); +} + +void +handlesig(int signo) +{ + if (signo == SIGCHLD) { + siginfo_t in; + /* wlroots expects to reap the XWayland process itself, so we + * use WNOWAIT to keep the child waitable until we know it's not + * XWayland. + */ + while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid +#ifdef XWAYLAND + && (!xwayland || in.si_pid != xwayland->server->pid) +#endif + ) { + pid_t *p, *lim; + waitpid(in.si_pid, NULL, 0); + if (in.si_pid == child_pid) + child_pid = -1; + if (!(p = autostart_pids)) + continue; + lim = &p[autostart_len]; + + for (; p < lim; p++) { + if (*p == in.si_pid) { + *p = -1; + break; + } + } + } + } else if (signo == SIGINT || signo == SIGTERM) { + quit(NULL); + } +} + +void +incnmaster(const Arg *arg) +{ + if (!arg || !selmon) + return; + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +void +inputdevice(struct wl_listener *listener, void *data) +{ + /* This event is raised by the backend when a new input device becomes + * available. */ + struct wlr_input_device *device = data; + uint32_t caps; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + createkeyboard(wlr_keyboard_from_input_device(device)); + break; + case WLR_INPUT_DEVICE_POINTER: + createpointer(wlr_pointer_from_input_device(device)); + break; + default: + /* TODO handle other input device types */ + break; + } + + /* We need to let the wlr_seat know what our capabilities are, which is + * communiciated to the client. In dwl we always have a cursor, even if + * there are no pointer devices, so we always include that capability. */ + /* TODO do we actually require a cursor? */ + caps = WL_SEAT_CAPABILITY_POINTER; + if (!wl_list_empty(&kb_group->wlr_group->devices)) + caps |= WL_SEAT_CAPABILITY_KEYBOARD; + wlr_seat_set_capabilities(seat, caps); +} + +int +keybinding(uint32_t mods, xkb_keysym_t sym) +{ + /* + * Here we handle compositor keybindings. This is when the compositor is + * processing keys, rather than passing them on to the client for its own + * processing. + */ + const Key *k; + for (k = keys; k < END(keys); k++) { + if (CLEANMASK(mods) == CLEANMASK(k->mod) + && sym == k->keysym && k->func) { + k->func(&k->arg); + return 1; + } + } + return 0; +} + +void +keypress(struct wl_listener *listener, void *data) +{ + int i; + /* This event is raised when a key is pressed or released. */ + KeyboardGroup *group = wl_container_of(listener, group, key); + struct wlr_keyboard_key_event *event = data; + + /* Translate libinput keycode -> xkbcommon */ + uint32_t keycode = event->keycode + 8; + /* Get a list of keysyms based on the keymap for this keyboard */ + const xkb_keysym_t *syms; + int nsyms = xkb_state_key_get_syms( + group->wlr_group->keyboard.xkb_state, keycode, &syms); + + int handled = 0; + uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard); + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + + /* On _press_ if there is no active screen locker, + * attempt to process a compositor keybinding. */ + if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + for (i = 0; i < nsyms; i++) + handled = keybinding(mods, syms[i]) || handled; + } + + if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) { + group->mods = mods; + group->keysyms = syms; + group->nsyms = nsyms; + wl_event_source_timer_update(group->key_repeat_source, + group->wlr_group->keyboard.repeat_info.delay); + } else { + group->nsyms = 0; + wl_event_source_timer_update(group->key_repeat_source, 0); + } + + if (handled) + return; + + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); + /* Pass unhandled keycodes along to the client. */ + wlr_seat_keyboard_notify_key(seat, event->time_msec, + event->keycode, event->state); +} + +void +keypressmod(struct wl_listener *listener, void *data) +{ + /* This event is raised when a modifier key, such as shift or alt, is + * pressed. We simply communicate this to the client. */ + KeyboardGroup *group = wl_container_of(listener, group, modifiers); + + wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); + /* Send modifiers to the client. */ + wlr_seat_keyboard_notify_modifiers(seat, + &group->wlr_group->keyboard.modifiers); +} + +int +keyrepeat(void *data) +{ + KeyboardGroup *group = data; + int i; + if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0) + return 0; + + wl_event_source_timer_update(group->key_repeat_source, + 1000 / group->wlr_group->keyboard.repeat_info.rate); + + for (i = 0; i < group->nsyms; i++) + keybinding(group->mods, group->keysyms[i]); + + return 0; +} + +void +killclient(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (sel) + client_send_close(sel); +} + +void +locksession(struct wl_listener *listener, void *data) +{ + struct wlr_session_lock_v1 *session_lock = data; + SessionLock *lock; + wlr_scene_node_set_enabled(&locked_bg->node, 1); + if (cur_lock) { + wlr_session_lock_v1_destroy(session_lock); + return; + } + lock = session_lock->data = ecalloc(1, sizeof(*lock)); + focusclient(NULL, 0); + + lock->scene = wlr_scene_tree_create(layers[LyrBlock]); + cur_lock = lock->lock = session_lock; + locked = 1; + + LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface); + LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock); + LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession); + + wlr_session_lock_v1_send_locked(session_lock); +} + +void +mapnotify(struct wl_listener *listener, void *data) +{ + /* Called when the surface is mapped, or ready to display on-screen. */ + Client *p = NULL; + Client *w, *c = wl_container_of(listener, c, map); + Monitor *m; + int i; + + /* Create scene tree for this client and its border */ + c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); + wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell); + c->scene_surface = c->type == XDGShell + ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg) + : wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); + c->scene->node.data = c->scene_surface->node.data = c; + + client_get_geometry(c, &c->geom); + + /* Handle unmanaged clients first so we can return prior create borders */ + if (client_is_unmanaged(c)) { + /* Unmanaged clients always are floating */ + wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + if (client_wants_focus(c)) { + focusclient(c, 1); + exclusive_focus = c; + } + goto unset_fullscreen; + } + + for (i = 0; i < 4; i++) { + c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, + (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder])); + c->border[i]->node.data = c; + } + + /* Initialize client geometry with room for border */ + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + c->geom.width += 2 * c->bw; + c->geom.height += 2 * c->bw; + + /* Insert this client into client lists. */ + Client* focused = focustop(selmon); + if (focused) + wl_list_insert(&focused->link, &c->link); + else + wl_list_insert(&clients, &c->link); + wl_list_insert(&fstack, &c->flink); + + /* Set initial monitor, tags, floating status, and focus: + * we always consider floating, clients that have parent and thus + * we set the same tags and monitor than its parent, if not + * try to apply rules for them */ + if ((p = client_get_parent(c))) { + c->isfloating = 1; + setmon(c, p->mon, p->tags); + } else { + applyrules(c); + } + drawbars(); + +unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); + wl_list_for_each(w, &clients, link) { + if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) + setfullscreen(w, 0); + } +} + +void +maximizenotify(struct wl_listener *listener, void *data) +{ + /* This event is raised when a client would like to maximize itself, + * typically because the user clicked on the maximize button on + * client-side decorations. dwl doesn't support maximization, but + * to conform to xdg-shell protocol we still must send a configure. + * Since xdg-shell protocol v5 we should ignore request of unsupported + * capabilities, just schedule a empty configure when the client uses <5 + * protocol version + * wlr_xdg_surface_schedule_configure() is used to send an empty reply. */ + Client *c = wl_container_of(listener, c, maximize); + if (c->surface.xdg->initialized + && wl_resource_get_version(c->surface.xdg->toplevel->resource) + < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) + wlr_xdg_surface_schedule_configure(c->surface.xdg); +} + +void +monocle(Monitor *m) +{ + Client *c; + int n = 0; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + resize(c, m->w, 0); + n++; + } + if (n) + snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); + if ((c = focustop(m))) + wlr_scene_node_raise_to_top(&c->scene->node); +} + +void +movestack(const Arg *arg) +{ + Client *c, *sel = focustop(selmon); + + if (!sel) { + return; + } + + if (wl_list_length(&clients) <= 1) { + return; + } + + if (arg->i > 0) { + wl_list_for_each(c, &sel->link, link) { + if (&c->link == &clients) { + c = wl_container_of(&clients, c, link); + break; /* wrap past the sentinel node */ + } + if (VISIBLEON(c, selmon) || &c->link == &clients) { + break; /* found it */ + } + } + } else { + wl_list_for_each_reverse(c, &sel->link, link) { + if (&c->link == &clients) { + c = wl_container_of(&clients, c, link); + break; /* wrap past the sentinel node */ + } + if (VISIBLEON(c, selmon) || &c->link == &clients) { + break; /* found it */ + } + } + /* backup one client */ + c = wl_container_of(c->link.prev, c, link); + } + + wl_list_remove(&sel->link); + wl_list_insert(&c->link, &sel->link); + arrange(selmon); +} + +void +motionabsolute(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits an _absolute_ + * motion event, from 0..1 on each axis. This happens, for example, when + * wlroots is running under a Wayland window rather than KMS+DRM, and you + * move the mouse over the window. You could enter the window from any edge, + * so we have to warp the mouse there. There is also some hardware which + * emits these events. */ + struct wlr_pointer_motion_absolute_event *event = data; + double lx, ly, dx, dy; + + if (!event->time_msec) /* this is 0 with virtual pointers */ + wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); + + wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly); + dx = lx - cursor->x; + dy = ly - cursor->y; + motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); +} + +void +motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel) +{ + double sx = 0, sy = 0, sx_confined, sy_confined; + Client *c = NULL, *w = NULL; + LayerSurface *l = NULL; + struct wlr_surface *surface = NULL; + struct wlr_pointer_constraint_v1 *constraint; + + /* Find the client under the pointer and send the event along. */ + xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy); + + if (cursor_mode == CurPressed && !seat->drag + && surface != seat->pointer_state.focused_surface + && toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) { + c = w; + surface = seat->pointer_state.focused_surface; + sx = cursor->x - (l ? l->geom.x : w->geom.x); + sy = cursor->y - (l ? l->geom.y : w->geom.y); + } + + /* time is 0 in internal calls meant to restore pointer focus. */ + if (time) { + wlr_relative_pointer_manager_v1_send_relative_motion( + relative_pointer_mgr, seat, (uint64_t)time * 1000, + dx, dy, dx_unaccel, dy_unaccel); + + wl_list_for_each(constraint, &pointer_constraints->constraints, link) + cursorconstrain(constraint); + + if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) { + toplevel_from_wlr_surface(active_constraint->surface, &c, NULL); + if (c && active_constraint->surface == seat->pointer_state.focused_surface) { + sx = cursor->x - c->geom.x - c->bw; + sy = cursor->y - c->geom.y - c->bw; + if (wlr_region_confine(&active_constraint->region, sx, sy, + sx + dx, sy + dy, &sx_confined, &sy_confined)) { + dx = sx_confined - sx; + dy = sy_confined - sy; + } + + if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) + return; + } + } + + wlr_cursor_move(cursor, device, dx, dy); + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + + /* Update selmon (even while dragging a window) */ + if (sloppyfocus) + selmon = xytomon(cursor->x, cursor->y); + } + + /* Update drag icon's position */ + wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); + + /* If we are currently grabbing the mouse, handle and return */ + if (cursor_mode == CurMove) { + /* Move the grabbed client to the new position. */ + resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, + .width = grabc->geom.width, .height = grabc->geom.height}, 1); + return; + } else if (cursor_mode == CurResize) { + resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, + .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); + return; + } + + /* If there's no client surface under the cursor, set the cursor image to a + * default. This is what makes the cursor image appear when you move it + * off of a client or over its border. */ + if (!surface && !seat->drag) + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + + pointerfocus(c, surface, sx, sy, time); +} + +void +motionrelative(struct wl_listener *listener, void *data) +{ + /* This event is forwarded by the cursor when a pointer emits a _relative_ + * pointer motion event (i.e. a delta) */ + struct wlr_pointer_motion_event *event = data; + /* The cursor doesn't move unless we tell it to. The cursor automatically + * handles constraining the motion to the output layout, as well as any + * special configuration applied for the specific input device which + * generated the event. You can pass NULL for the device if you want to move + * the cursor around without any input. */ + motionnotify(event->time_msec, &event->pointer->base, event->delta_x, event->delta_y, + event->unaccel_dx, event->unaccel_dy); +} + +void +moveresize(const Arg *arg) +{ + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); + if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) + return; + + /* Float the window and tell motionnotify to grab it */ + setfloating(grabc, 1); + switch (cursor_mode = arg->ui) { + case CurMove: + grabcx = (int)round(cursor->x) - grabc->geom.x; + grabcy = (int)round(cursor->y) - grabc->geom.y; + wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); + break; + case CurResize: + /* Doesn't work for X11 output - the next absolute motion event + * returns the cursor to where it started */ + wlr_cursor_warp_closest(cursor, NULL, + grabc->geom.x + grabc->geom.width, + grabc->geom.y + grabc->geom.height); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); + break; + } +} + +void +outputmgrapply(struct wl_listener *listener, void *data) +{ + struct wlr_output_configuration_v1 *config = data; + outputmgrapplyortest(config, 0); +} + +void +outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test) +{ + /* + * Called when a client such as wlr-randr requests a change in output + * configuration. This is only one way that the layout can be changed, + * so any Monitor information should be updated by updatemons() after an + * output_layout.change event, not here. + */ + struct wlr_output_configuration_head_v1 *config_head; + int ok = 1; + + wl_list_for_each(config_head, &config->heads, link) { + struct wlr_output *wlr_output = config_head->state.output; + Monitor *m = wlr_output->data; + struct wlr_output_state state; + + /* Ensure displays previously disabled by wlr-output-power-management-v1 + * are properly handled*/ + m->asleep = 0; + + wlr_output_state_init(&state); + wlr_output_state_set_enabled(&state, config_head->state.enabled); + if (!config_head->state.enabled) + goto apply_or_test; + + if (config_head->state.mode) + wlr_output_state_set_mode(&state, config_head->state.mode); + else + wlr_output_state_set_custom_mode(&state, + config_head->state.custom_mode.width, + config_head->state.custom_mode.height, + config_head->state.custom_mode.refresh); + + wlr_output_state_set_transform(&state, config_head->state.transform); + wlr_output_state_set_scale(&state, config_head->state.scale); + wlr_output_state_set_adaptive_sync_enabled(&state, + config_head->state.adaptive_sync_enabled); + +apply_or_test: + ok &= test ? wlr_output_test_state(wlr_output, &state) + : wlr_output_commit_state(wlr_output, &state); + + /* Don't move monitors if position wouldn't change, this to avoid + * wlroots marking the output as manually configured. + * wlr_output_layout_add does not like disabled outputs */ + if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y)) + wlr_output_layout_add(output_layout, wlr_output, + config_head->state.x, config_head->state.y); + + wlr_output_state_finish(&state); + } + + if (ok) + wlr_output_configuration_v1_send_succeeded(config); + else + wlr_output_configuration_v1_send_failed(config); + wlr_output_configuration_v1_destroy(config); + + /* https://codeberg.org/dwl/dwl/issues/577 */ + updatemons(NULL, NULL); +} + +void +outputmgrtest(struct wl_listener *listener, void *data) +{ + struct wlr_output_configuration_v1 *config = data; + outputmgrapplyortest(config, 1); +} + +void +pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + uint32_t time) +{ + struct timespec now; + + if (surface != seat->pointer_state.focused_surface && + sloppyfocus && time && c && !client_is_unmanaged(c)) + focusclient(c, 0); + + /* If surface is NULL, clear pointer focus */ + if (!surface) { + wlr_seat_pointer_notify_clear_focus(seat); + return; + } + + if (!time) { + clock_gettime(CLOCK_MONOTONIC, &now); + time = now.tv_sec * 1000 + now.tv_nsec / 1000000; + } + + /* Let the client know that the mouse cursor has entered one + * of its surfaces, and make keyboard focus follow if desired. + * wlroots makes this a no-op if surface is already focused */ + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(seat, time, sx, sy); +} + + +void +powermgrsetmode(struct wl_listener *listener, void *data) +{ + struct wlr_output_power_v1_set_mode_event *event = data; + struct wlr_output_state state = {0}; + Monitor *m = event->output->data; + + if (!m) + return; + + m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the ouput */ + wlr_output_state_set_enabled(&state, event->mode); + wlr_output_commit_state(m->wlr_output, &state); + + m->asleep = !event->mode; +} + +void +quit(const Arg *arg) +{ + wl_display_terminate(dpy); +} + +void +rendermon(struct wl_listener *listener, void *data) +{ + /* This function is called every time an output is ready to display a frame, + * generally at the output's refresh rate (e.g. 60Hz). */ + Monitor *m = wl_container_of(listener, m, frame); + Client *c; + struct wlr_output_state pending = {0}; + struct wlr_gamma_control_v1 *gamma_control; + struct timespec now; + + /* Render if no XDG clients have an outstanding resize and are visible on + * this monitor. */ + wl_list_for_each(c, &clients, link) { + if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) + goto skip; + } + + /* + * HACK: The "correct" way to set the gamma is to commit it together with + * the rest of the state in one go, but to do that we would need to rewrite + * wlr_scene_output_commit() in order to add the gamma to the pending + * state before committing, instead try to commit the gamma in one frame, + * and commit the rest of the state in the next one (or in the same frame if + * the gamma can not be committed). + */ + if (m->gamma_lut_changed) { + gamma_control + = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output); + m->gamma_lut_changed = 0; + + if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) + goto commit; + + if (!wlr_output_test_state(m->wlr_output, &pending)) { + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); + goto commit; + } + wlr_output_commit_state(m->wlr_output, &pending); + wlr_output_schedule_frame(m->wlr_output); + } else { +commit: + wlr_scene_output_commit(m->scene_output, NULL); + } + +skip: + /* Let clients know a frame has been rendered */ + clock_gettime(CLOCK_MONOTONIC, &now); + wlr_scene_output_send_frame_done(m->scene_output, &now); + wlr_output_state_finish(&pending); +} + +void +requestdecorationmode(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, set_decoration_mode); + if (c->surface.xdg->initialized) + wlr_xdg_toplevel_decoration_v1_set_mode(c->decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); +} + +void +requeststartdrag(struct wl_listener *listener, void *data) +{ + struct wlr_seat_request_start_drag_event *event = data; + + if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, + event->serial)) + wlr_seat_start_pointer_drag(seat, event->drag, event->serial); + else + wlr_data_source_destroy(event->drag->source); +} + +void +requestmonstate(struct wl_listener *listener, void *data) +{ + struct wlr_output_event_request_state *event = data; + wlr_output_commit_state(event->output, event->state); + updatemons(NULL, NULL); +} + +void +resize(Client *c, struct wlr_box geo, int interact) +{ + struct wlr_box *bbox; + struct wlr_box clip; + + if (!c->mon || !client_surface(c)->mapped) + return; + + bbox = interact ? &sgeom : &c->mon->w; + + client_set_bounds(c, geo.width, geo.height); + c->geom = geo; + applybounds(c, bbox); + + /* Update scene-graph, including borders */ + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw); + wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw); + wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw); + wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw); + wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw); + wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); + wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); + + /* this is a no-op if size hasn't changed */ + c->resize = client_set_size(c, c->geom.width - 2 * c->bw, + c->geom.height - 2 * c->bw); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); +} + +void +run(char *startup_cmd) +{ + /* Add a Unix socket to the Wayland display. */ + const char *socket = wl_display_add_socket_auto(dpy); + if (!socket) + die("startup: display_add_socket_auto"); + setenv("WAYLAND_DISPLAY", socket, 1); + + /* Start the backend. This will enumerate outputs and inputs, become the DRM + * master, etc */ + if (!wlr_backend_start(backend)) + die("startup: backend_start"); + + /* Now that the socket exists and the backend is started, run the startup command */ + autostartexec(); + if (startup_cmd) { + if ((child_pid = fork()) < 0) + die("startup: fork:"); + if (child_pid == 0) { + close(STDIN_FILENO); + setsid(); + execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); + die("startup: execl:"); + } + } + + drawbars(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ + selmon = xytomon(cursor->x, cursor->y); + + /* TODO hack to get cursor to display in its initial location (100, 100) + * instead of (0, 0) and then jumping. still may not be fully + * initialized, as the image/coordinates are not transformed for the + * monitor when displayed here */ + wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + + /* Run the Wayland event loop. This does not return until you exit the + * compositor. Starting the backend rigged up all of the necessary event + * loop configuration to listen to libinput events, DRM events, generate + * frame events at the refresh rate, and so on. */ + wl_display_run(dpy); +} + +void +setcursor(struct wl_listener *listener, void *data) +{ + /* This event is raised by the seat when a client provides a cursor image */ + struct wlr_seat_pointer_request_set_cursor_event *event = data; + /* If we're "grabbing" the cursor, don't use the client's image, we will + * restore it after "grabbing" sending a leave event, followed by a enter + * event, which will result in the client requesting set the cursor surface */ + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + /* This can be sent by any client, so we check to make sure this one is + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided surface as the cursor image. It will set the + * hardware cursor on the output that it's currently on and continue to + * do so as the cursor moves between outputs. */ + if (event->seat_client == seat->pointer_state.focused_client) + wlr_cursor_set_surface(cursor, event->surface, + event->hotspot_x, event->hotspot_y); +} + +void +setcursorshape(struct wl_listener *listener, void *data) +{ + struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + /* This can be sent by any client, so we check to make sure this one is + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided cursor shape. */ + if (event->seat_client == seat->pointer_state.focused_client) + wlr_cursor_set_xcursor(cursor, cursor_mgr, + wlr_cursor_shape_v1_name(event->shape)); +} + +void +setfloating(Client *c, int floating) +{ + Client *p = client_get_parent(c); + c->isfloating = floating; + /* If in floating layout do not change the client's layer */ + if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange) + return; + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); + drawbars(); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + c->isfullscreen = fullscreen; + if (!c->mon || !client_surface(c)->mapped) + return; + c->bw = fullscreen ? 0 : borderpx; + client_set_fullscreen(c, fullscreen); + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen + ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); + + if (fullscreen) { + c->prev = c->geom; + resize(c, c->mon->m, 0); + } else { + /* restore previous size instead of arrange for floating windows since + * client positions are set by the user and cannot be recalculated */ + resize(c, c->prev, 0); + } + arrange(c->mon); + drawbars(); +} + +void +setgamma(struct wl_listener *listener, void *data) +{ + struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; + Monitor *m = event->output->data; + if (!m) + return; + m->gamma_lut_changed = 1; + wlr_output_schedule_frame(m->wlr_output); +} + +void +setlayout(const Arg *arg) +{ + if (!selmon) + return; + 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, LENGTH(selmon->ltsymbol)); + arrange(selmon); + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f; + if (f < 0.1 || f > 0.9) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setmon(Client *c, Monitor *m, uint32_t newtags) +{ + Monitor *oldmon = c->mon; + + if (oldmon == m) + return; + c->mon = m; + c->prev = c->geom; + + /* Scene graph sends surface leave/enter events on move and resize */ + if (oldmon) + arrange(oldmon); + if (m) { + /* Make sure window actually overlaps with the monitor */ + resize(c, c->geom, 0); + c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ + setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); + } + focusclient(focustop(selmon), 1); +} + +void +setpsel(struct wl_listener *listener, void *data) +{ + /* This event is raised by the seat when a client wants to set the selection, + * usually when the user copies something. wlroots allows compositors to + * ignore such requests if they so choose, but in dwl we always honor + */ + struct wlr_seat_request_set_primary_selection_event *event = data; + wlr_seat_set_primary_selection(seat, event->source, event->serial); +} + +void +setsel(struct wl_listener *listener, void *data) +{ + /* This event is raised by the seat when a client wants to set the selection, + * usually when the user copies something. wlroots allows compositors to + * ignore such requests if they so choose, but in dwl we always honor + */ + struct wlr_seat_request_set_selection_event *event = data; + wlr_seat_set_selection(seat, event->source, event->serial); +} + +void +setup(void) +{ + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; + sigemptyset(&sa.sa_mask); + + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + + + wlr_log_init(log_level, NULL); + + /* The Wayland display is managed by libwayland. It handles accepting + * clients from the Unix socket, manging Wayland globals, and so on. */ + dpy = wl_display_create(); + event_loop = wl_display_get_event_loop(dpy); + + /* The backend is a wlroots feature which abstracts the underlying input and + * output hardware. The autocreate option will choose the most suitable + * backend based on the current environment, such as opening an X11 window + * if an X11 server is running. */ + if (!(backend = wlr_backend_autocreate(event_loop, &session))) + die("couldn't create backend"); + + /* Initialize the scene graph used to lay out windows */ + scene = wlr_scene_create(); + root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor); + for (i = 0; i < NUM_LAYERS; i++) + layers[i] = wlr_scene_tree_create(&scene->tree); + drag_icon = wlr_scene_tree_create(&scene->tree); + wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); + + /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user + * can also specify a renderer using the WLR_RENDERER env var. + * The renderer is responsible for defining the various pixel formats it + * supports for shared memory, this configures that for clients. */ + if (!(drw = wlr_renderer_autocreate(backend))) + die("couldn't create renderer"); + LISTEN_STATIC(&drw->events.lost, gpureset); + + /* Create shm, drm and linux_dmabuf interfaces by ourselves. + * The simplest way is call: + * wlr_renderer_init_wl_display(drw); + * but we need to create manually the linux_dmabuf interface to integrate it + * with wlr_scene. */ + wlr_renderer_init_wl_shm(drw, dpy); + + if (wlr_renderer_get_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) { + wlr_drm_create(dpy, drw); + wlr_scene_set_linux_dmabuf_v1(scene, + wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, drw)); + } + + /* Autocreates an allocator for us. + * The allocator is the bridge between the renderer and the backend. It + * handles the buffer creation, allowing wlroots to render onto the + * screen */ + if (!(alloc = wlr_allocator_autocreate(backend, drw))) + die("couldn't create allocator"); + + /* This creates some hands-off wlroots interfaces. The compositor is + * necessary for clients to allocate surfaces and the data device manager + * handles the clipboard. Each of these wlroots interfaces has room for you + * to dig your fingers in and play with their behavior if you want. Note that + * the clients cannot set the selection directly without compositor approval, + * see the setsel() function. */ + compositor = wlr_compositor_create(dpy, 6, drw); + wlr_subcompositor_create(dpy); + wlr_data_device_manager_create(dpy); + wlr_export_dmabuf_manager_v1_create(dpy); + wlr_screencopy_manager_v1_create(dpy); + wlr_data_control_manager_v1_create(dpy); + wlr_primary_selection_v1_device_manager_create(dpy); + wlr_viewporter_create(dpy); + wlr_single_pixel_buffer_manager_v1_create(dpy); + wlr_fractional_scale_manager_v1_create(dpy, 1); + wlr_presentation_create(dpy, backend); + wlr_alpha_modifier_v1_create(dpy); + + /* Initializes the interface used to implement urgency hints */ + activation = wlr_xdg_activation_v1_create(dpy); + LISTEN_STATIC(&activation->events.request_activate, urgent); + + gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy); + LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma); + + power_mgr = wlr_output_power_manager_v1_create(dpy); + LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode); + + /* Creates an output layout, which a wlroots utility for working with an + * arrangement of screens in a physical layout. */ + output_layout = wlr_output_layout_create(dpy); + LISTEN_STATIC(&output_layout->events.change, updatemons); + wlr_xdg_output_manager_v1_create(dpy, output_layout); + + /* Configure a listener to be notified when new outputs are available on the + * backend. */ + wl_list_init(&mons); + LISTEN_STATIC(&backend->events.new_output, createmon); + + /* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a + * Wayland protocol which is used for application windows. For more + * detail on shells, refer to the article: + * + * https://drewdevault.com/2018/07/29/Wayland-shells.html + */ + wl_list_init(&clients); + wl_list_init(&fstack); + + xdg_shell = wlr_xdg_shell_create(dpy, 6); + LISTEN_STATIC(&xdg_shell->events.new_toplevel, createnotify); + LISTEN_STATIC(&xdg_shell->events.new_popup, createpopup); + + layer_shell = wlr_layer_shell_v1_create(dpy, 3); + LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface); + + idle_notifier = wlr_idle_notifier_v1_create(dpy); + + idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy); + LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); + + session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); + wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener); + LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr); + locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height, + (float [4]){0.1f, 0.1f, 0.1f, 1.0f}); + wlr_scene_node_set_enabled(&locked_bg->node, 0); + + /* Use decoration protocols to negotiate server-side decorations */ + wlr_server_decoration_manager_set_default_mode( + wlr_server_decoration_manager_create(dpy), + WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy); + LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration); + + pointer_constraints = wlr_pointer_constraints_v1_create(dpy); + LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint); + + relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); + + /* + * Creates a cursor, which is a wlroots utility for tracking the cursor + * image shown on screen. + */ + cursor = wlr_cursor_create(); + wlr_cursor_attach_output_layout(cursor, output_layout); + + /* Creates an xcursor manager, another wlroots utility which loads up + * Xcursor themes to source cursor images from and makes sure that cursor + * images are available at all scale factors on the screen (necessary for + * HiDPI support). Scaled cursors will be loaded with each output. */ + cursor_mgr = wlr_xcursor_manager_create(NULL, 24); + setenv("XCURSOR_SIZE", "24", 1); + + /* + * wlr_cursor *only* displays an image on screen. It does not move around + * when the pointer moves. However, we can attach input devices to it, and + * it will generate aggregate events for all of them. In these events, we + * can choose how we want to process them, forwarding them to clients and + * moving the cursor around. More detail on this process is described in + * https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html + * + * And more comments are sprinkled throughout the notify functions above. + */ + LISTEN_STATIC(&cursor->events.motion, motionrelative); + LISTEN_STATIC(&cursor->events.motion_absolute, motionabsolute); + LISTEN_STATIC(&cursor->events.button, buttonpress); + LISTEN_STATIC(&cursor->events.axis, axisnotify); + LISTEN_STATIC(&cursor->events.frame, cursorframe); + + cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); + LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape); + + /* + * Configures a seat, which is a single "seat" at which a user sits and + * operates the computer. This conceptually includes up to one keyboard, + * pointer, touch, and drawing tablet device. We also rig up a listener to + * let us know when new input devices are available on the backend. + */ + LISTEN_STATIC(&backend->events.new_input, inputdevice); + virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); + virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); + + seat = wlr_seat_create(dpy, "seat0"); + LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); + LISTEN_STATIC(&seat->events.request_set_selection, setsel); + LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel); + LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); + LISTEN_STATIC(&seat->events.start_drag, startdrag); + + kb_group = createkeyboardgroup(); + wl_list_init(&kb_group->destroy.link); + + output_mgr = wlr_output_manager_v1_create(dpy); + LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply); + LISTEN_STATIC(&output_mgr->events.test, outputmgrtest); + + drwl_init(); + + status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy), + STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL); + + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ + unsetenv("DISPLAY"); +#ifdef XWAYLAND + /* + * Initialise the XWayland X server. + * It will be started when the first X client is started. + */ + if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) { + LISTEN_STATIC(&xwayland->events.ready, xwaylandready); + LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11); + + setenv("DISPLAY", xwayland->display_name, 1); + } else { + fprintf(stderr, "failed to setup XWayland X server, continuing without it\n"); + } +#endif +} + +void +spawn(const Arg *arg) +{ + if (fork() == 0) { + close(STDIN_FILENO); + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + die("dwl: execvp %s failed:", ((char **)arg->v)[0]); + } +} + +void +startdrag(struct wl_listener *listener, void *data) +{ + struct wlr_drag *drag = data; + if (!drag->icon) + return; + + drag->icon->data = &wlr_scene_drag_icon_create(drag_icon, drag->icon)->node; + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); +} + +int +statusin(int fd, unsigned int mask, void *data) +{ + char status[1024]; + ssize_t n; + + if (mask & WL_EVENT_ERROR) + die("status in event error"); + if (mask & WL_EVENT_HANGUP) + wl_event_source_remove(status_event_source); + + n = read(fd, status, sizeof(status) - 1); + if (n < 0 && errno != EWOULDBLOCK) + die("read:"); + + status[n] = '\0'; + status[strcspn(status, "\n")] = '\0'; + + strncpy(stext, status, sizeof(stext)); + drawbars(); + + return 0; +} + +void +tag(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (!sel || (arg->ui & TAGMASK) == 0) + return; + + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +tagmon(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (sel) + setmon(sel, dirtomon(arg->i), 0); +} + +void +tile(Monitor *m) +{ + unsigned int h, r, e = m->gaps, mw, my, ty; + int i, n = 0; + Client *c; + + wl_list_for_each(c, &clients, link) + if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) + n++; + if (n == 0) + return; + if (smartgaps == n) + e = 0; + + if (n > m->nmaster) + mw = m->nmaster ? (int)roundf((m->w.width + gappx*e) * m->mfact) : 0; + else + mw = m->w.width; + i = 0; + my = ty = gappx*e; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { + r = MIN(n, m->nmaster) - i; + h = (m->w.height - my - gappx*e - gappx*e * (r - 1)) / r; + resize(c, (struct wlr_box){.x = m->w.x + gappx*e, .y = m->w.y + my, + .width = mw - 2*gappx*e, .height = h}, 0); + my += c->geom.height + gappx*e; + } else { + r = n - i; + h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r; + resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty, + .width = m->w.width - mw - gappx*e, .height = h}, 0); + ty += c->geom.height + gappx*e; + } + i++; + } +} + +void +togglebar(const Arg *arg) +{ + wlr_scene_node_set_enabled(&selmon->scene_buffer->node, + !selmon->scene_buffer->node.enabled); + arrangelayers(selmon); +} + +void +togglefloating(const Arg *arg) +{ + Client *sel = focustop(selmon); + /* return if fullscreen */ + if (sel && !sel->isfullscreen) + setfloating(sel, !sel->isfloating); +} + +void +togglefullscreen(const Arg *arg) +{ + Client *sel = focustop(selmon); + if (sel) + setfullscreen(sel, !sel->isfullscreen); +} + +void +togglegaps(const Arg *arg) +{ + selmon->gaps = !selmon->gaps; + arrange(selmon); +} + +void +moveresizekb(const Arg *arg) +{ + Client *c = focustop(selmon); + Monitor *m = selmon; + + if(!(m && arg && arg->v && c && c->isfloating)) { + return; + } + + resize(c, (struct wlr_box){ + .x = c->geom.x + ((int *)arg->v)[0], + .y = c->geom.y + ((int *)arg->v)[1], + .width = c->geom.width + ((int *)arg->v)[2], + .height = c->geom.height + ((int *)arg->v)[3], + }, 1); +} + +void +toggletag(const Arg *arg) +{ + uint32_t newtags; + Client *sel = focustop(selmon); + if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK))) + return; + + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +toggleview(const Arg *arg) +{ + uint32_t newtagset; + if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0)) + return; + + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +unlocksession(struct wl_listener *listener, void *data) +{ + SessionLock *lock = wl_container_of(listener, lock, unlock); + destroylock(lock, 1); +} + +void +unmaplayersurfacenotify(struct wl_listener *listener, void *data) +{ + LayerSurface *l = wl_container_of(listener, l, unmap); + + l->mapped = 0; + wlr_scene_node_set_enabled(&l->scene->node, 0); + if (l == exclusive_focus) + exclusive_focus = NULL; + if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) + arrangelayers(l->mon); + if (l->layer_surface->surface == seat->keyboard_state.focused_surface) + focusclient(focustop(selmon), 1); + motionnotify(0, NULL, 0, 0, 0, 0); +} + +void +unmapnotify(struct wl_listener *listener, void *data) +{ + /* Called when the surface is unmapped, and should no longer be shown. */ + Client *c = wl_container_of(listener, c, unmap); + if (c == grabc) { + cursor_mode = CurNormal; + grabc = NULL; + } + + if (client_is_unmanaged(c)) { + if (c == exclusive_focus) { + exclusive_focus = NULL; + focusclient(focustop(selmon), 1); + } + } else { + wl_list_remove(&c->link); + setmon(c, NULL, 0); + wl_list_remove(&c->flink); + } + + wlr_scene_node_destroy(&c->scene->node); + drawbars(); + motionnotify(0, NULL, 0, 0, 0, 0); +} + +void +updatemons(struct wl_listener *listener, void *data) +{ + /* + * Called whenever the output layout changes: adding or removing a + * monitor, changing an output's mode or position, etc. This is where + * the change officially happens and we update geometry, window + * positions, focus, and the stored configuration in wlroots' + * output-manager implementation. + */ + struct wlr_output_configuration_v1 *config + = wlr_output_configuration_v1_create(); + Client *c; + struct wlr_output_configuration_head_v1 *config_head; + Monitor *m; + + /* First remove from the layout the disabled monitors */ + wl_list_for_each(m, &mons, link) { + if (m->wlr_output->enabled || m->asleep) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); + config_head->state.enabled = 0; + /* Remove this output from the layout to avoid cursor enter inside it */ + wlr_output_layout_remove(output_layout, m->wlr_output); + closemon(m); + m->m = m->w = (struct wlr_box){0}; + } + /* Insert outputs that need to */ + wl_list_for_each(m, &mons, link) { + if (m->wlr_output->enabled + && !wlr_output_layout_get(output_layout, m->wlr_output)) + wlr_output_layout_add_auto(output_layout, m->wlr_output); + } + + /* Now that we update the output layout we can get its box */ + wlr_output_layout_get_box(output_layout, NULL, &sgeom); + + wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y); + wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height); + + /* Make sure the clients are hidden when dwl is locked */ + wlr_scene_node_set_position(&locked_bg->node, sgeom.x, sgeom.y); + wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height); + + wl_list_for_each(m, &mons, link) { + if (!m->wlr_output->enabled) + continue; + config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); + + /* Get the effective monitor geometry to use for surfaces */ + wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m); + m->w = m->m; + wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y); + + wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); + wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); + + if (m->lock_surface) { + struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; + wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); + wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, m->m.height); + } + + /* Calculate the effective monitor geometry to use for clients */ + arrangelayers(m); + /* Don't move clients to the left output when plugging monitors */ + arrange(m); + /* make sure fullscreen clients have the right size */ + if ((c = focustop(m)) && c->isfullscreen) + resize(c, m->m, 0); + + /* Try to re-set the gamma LUT when updating monitors, + * it's only really needed when enabling a disabled output, but meh. */ + m->gamma_lut_changed = 1; + + config_head->state.x = m->m.x; + config_head->state.y = m->m.y; + + if (!selmon) { + selmon = m; + } + } + + if (selmon && selmon->wlr_output->enabled) { + wl_list_for_each(c, &clients, link) { + if (!c->mon && client_surface(c)->mapped) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); + if (selmon->lock_surface) { + client_notify_enter(selmon->lock_surface->surface, + wlr_seat_get_keyboard(seat)); + client_activate_surface(selmon->lock_surface->surface, 1); + } + } + + if (stext[0] == '\0') + strncpy(stext, "dwl-"VERSION, sizeof(stext)); + wl_list_for_each(m, &mons, link) { + updatebar(m); + drawbar(m); + } + + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a + * wl_pointer.motion event for the clients, it's only the image what it's + * at the wrong position after all. */ + wlr_cursor_move(cursor, NULL, 0, 0); + + wlr_output_manager_v1_set_configuration(output_mgr, config); +} + +void +updatebar(Monitor *m) +{ + size_t i; + int rw, rh; + char fontattrs[12]; + + wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); + m->b.width = rw; + m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); + + wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0); + + for (i = 0; i < LENGTH(m->pool); i++) + if (m->pool[i]) { + wlr_buffer_drop(&m->pool[i]->base); + m->pool[i] = NULL; + } + + if (m->b.scale == m->wlr_output->scale && m->drw) + return; + + drwl_font_destroy(m->drw->font); + snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * m->wlr_output->scale); + if (!(drwl_font_create(m->drw, LENGTH(fonts), fonts, fontattrs))) + die("Could not load font"); + + m->b.scale = m->wlr_output->scale; + m->lrpad = m->drw->font->height; + m->b.height = m->drw->font->height + 2; + m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale); +} + +void +updatetitle(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) + drawbars(); +} + +void +urgent(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *c = NULL; + toplevel_from_wlr_surface(event->surface, &c, NULL); + if (!c || c == focustop(selmon)) + return; + + c->isurgent = 1; + drawbars(); + + if (client_surface(c)->mapped) + client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); +} + +void +view(const Arg *arg) +{ + if (!selmon || (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; + focusclient(focustop(selmon), 1); + arrange(selmon); + drawbars(); +} + +void +virtualkeyboard(struct wl_listener *listener, void *data) +{ + struct wlr_virtual_keyboard_v1 *kb = data; + /* virtual keyboards shouldn't share keyboard group */ + KeyboardGroup *group = createkeyboardgroup(); + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); + LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup); + + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); +} + +void +virtualpointer(struct wl_listener *listener, void *data) +{ + struct wlr_virtual_pointer_v1_new_pointer_event *event = data; + struct wlr_input_device *device = &event->new_pointer->pointer.base; + + wlr_cursor_attach_input_device(cursor, device); + if (event->suggested_output) + wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); +} + +Monitor * +xytomon(double x, double y) +{ + struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); + return o ? o->data : NULL; +} + +void +xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny) +{ + struct wlr_scene_node *node, *pnode; + struct wlr_surface *surface = NULL; + struct wlr_scene_surface *scene_surface = NULL; + Client *c = NULL; + LayerSurface *l = NULL; + int layer; + + for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) { + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + + if (node->type == WLR_SCENE_NODE_BUFFER) { + scene_surface = wlr_scene_surface_try_from_buffer( + wlr_scene_buffer_from_node(node)); + if (!scene_surface) continue; + surface = scene_surface->surface; + } + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; + if (c && c->type == LayerShell) { + c = NULL; + l = pnode->data; + } + } + + if (psurface) *psurface = surface; + if (pc) *pc = c; + if (pl) *pl = l; +} + +void +zoom(const Arg *arg) +{ + Client *c, *sel = focustop(selmon); + + if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) + return; + + /* Search for the first tiled window that is not sel, marking sel as + * NULL if we pass it along the way */ + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, selmon) && !c->isfloating) { + if (c != sel) + break; + sel = NULL; + } + } + + /* Return if no other tiled window was found */ + if (&c->link == &clients) + return; + + /* If we passed sel, move c to the front; otherwise, move sel to the + * front */ + if (!sel) + sel = c; + wl_list_remove(&sel->link); + wl_list_insert(&clients, &sel->link); + + focusclient(sel, 1); + arrange(selmon); +} + +#ifdef XWAYLAND +void +activatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, activate); + + /* Only "managed" windows can be activated */ + if (!client_is_unmanaged(c)) + wlr_xwayland_surface_activate(c->surface.xwayland, 1); +} + +void +associatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, associate); + + LISTEN(&client_surface(c)->events.map, &c->map, mapnotify); + LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify); +} + +void +configurex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, configure); + struct wlr_xwayland_surface_configure_event *event = data; + /* TODO: figure out if there is another way to do this */ + if (!c->mon) { + wlr_xwayland_surface_configure(c->surface.xwayland, + event->x, event->y, event->width, event->height); + return; + } + if (c->isfloating || client_is_unmanaged(c)) + resize(c, (struct wlr_box){.x = event->x, .y = event->y, + .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0); + else + arrange(c->mon); +} + +void +createnotifyx11(struct wl_listener *listener, void *data) +{ + struct wlr_xwayland_surface *xsurface = data; + Client *c; + + /* Allocate a Client for this surface */ + c = xsurface->data = ecalloc(1, sizeof(*c)); + c->surface.xwayland = xsurface; + c->type = X11; + c->bw = client_is_unmanaged(c) ? 0 : borderpx; + + /* Listen to the various events it can emit */ + LISTEN(&xsurface->events.associate, &c->associate, associatex11); + LISTEN(&xsurface->events.destroy, &c->destroy, destroynotify); + LISTEN(&xsurface->events.dissociate, &c->dissociate, dissociatex11); + LISTEN(&xsurface->events.request_activate, &c->activate, activatex11); + LISTEN(&xsurface->events.request_configure, &c->configure, configurex11); + LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify); + LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints); + LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle); +} + +void +dissociatex11(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, dissociate); + wl_list_remove(&c->map.link); + wl_list_remove(&c->unmap.link); +} + +xcb_atom_t +getatom(xcb_connection_t *xc, const char *name) +{ + xcb_atom_t atom = 0; + xcb_intern_atom_reply_t *reply; + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xc, 0, strlen(name), name); + if ((reply = xcb_intern_atom_reply(xc, cookie, NULL))) + atom = reply->atom; + free(reply); + + return atom; +} + +void +sethints(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, set_hints); + struct wlr_surface *surface = client_surface(c); + if (c == focustop(selmon)) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); + drawbars(); + + if (c->isurgent && surface && surface->mapped) + client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder])); +} + +void +xwaylandready(struct wl_listener *listener, void *data) +{ + struct wlr_xcursor *xcursor; + xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL); + int err = xcb_connection_has_error(xc); + if (err) { + fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err); + return; + } + + /* Collect atoms we are interested in. If getatom returns 0, we will + * not detect that window type. */ + netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG"); + netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH"); + netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR"); + netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY"); + + /* assign the one and only seat */ + wlr_xwayland_set_seat(xwayland, seat); + + /* Set the default XWayland cursor to match the rest of dwl. */ + if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1))) + wlr_xwayland_set_cursor(xwayland, + xcursor->images[0]->buffer, xcursor->images[0]->width * 4, + xcursor->images[0]->width, xcursor->images[0]->height, + xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y); + + xcb_disconnect(xc); +} +#endif + +int +main(int argc, char *argv[]) +{ + char *startup_cmd = NULL; + int c; + + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') + startup_cmd = optarg; + else if (c == 'd') + log_level = WLR_DEBUG; + else if (c == 'v') + die("dwl " VERSION); + else + goto usage; + } + if (optind < argc) + goto usage; + + /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */ + if (!getenv("XDG_RUNTIME_DIR")) + die("XDG_RUNTIME_DIR must be set"); + setup(); + run(startup_cmd); + cleanup(); + return EXIT_SUCCESS; + +usage: + die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); +} diff --git a/dwl/dwl.desktop b/dwl/dwl.desktop new file mode 100755 index 0000000..e1380f7 --- /dev/null +++ b/dwl/dwl.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Name=dwl +Comment=dwm for Wayland +Exec=dwl +Type=Application diff --git a/dwl/protocols/wlr-layer-shell-unstable-v1.xml b/dwl/protocols/wlr-layer-shell-unstable-v1.xml new file mode 100755 index 0000000..d62fd51 --- /dev/null +++ b/dwl/protocols/wlr-layer-shell-unstable-v1.xml @@ -0,0 +1,390 @@ + + + + Copyright © 2017 Drew DeVault + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, 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. + + + + + Clients can use this interface to assign the surface_layer role to + wl_surfaces. Such surfaces are assigned to a "layer" of the output and + rendered with a defined z-depth respective to each other. They may also be + anchored to the edges and corners of a screen and specify input handling + semantics. This interface should be suitable for the implementation of + many desktop shell components, and a broad number of other applications + that interact with the desktop. + + + + + Create a layer surface for an existing surface. This assigns the role of + layer_surface, or raises a protocol error if another role is already + assigned. + + Creating a layer surface from a wl_surface which has a buffer attached + or committed is a client error, and any attempts by a client to attach + or manipulate a buffer prior to the first layer_surface.configure call + must also be treated as errors. + + After creating a layer_surface object and setting it up, the client + must perform an initial commit without any buffer attached. + The compositor will reply with a layer_surface.configure event. + The client must acknowledge it and is then allowed to attach a buffer + to map the surface. + + You may pass NULL for output to allow the compositor to decide which + output to use. Generally this will be the one that the user most + recently interacted with. + + Clients can specify a namespace that defines the purpose of the layer + surface. + + + + + + + + + + + + + + + + + These values indicate which layers a surface can be rendered in. They + are ordered by z depth, bottom-most first. Traditional shell surfaces + will typically be rendered between the bottom and top layers. + Fullscreen shell surfaces are typically rendered at the top layer. + Multiple surfaces can share a single layer, and ordering within a + single layer is undefined. + + + + + + + + + + + + + This request indicates that the client will not use the layer_shell + object any more. Objects that have been created through this instance + are not affected. + + + + + + + An interface that may be implemented by a wl_surface, for surfaces that + are designed to be rendered as a layer of a stacked desktop-like + environment. + + Layer surface state (layer, size, anchor, exclusive zone, + margin, interactivity) is double-buffered, and will be applied at the + time wl_surface.commit of the corresponding wl_surface is called. + + Attaching a null buffer to a layer surface unmaps it. + + Unmapping a layer_surface means that the surface cannot be shown by the + compositor until it is explicitly mapped again. The layer_surface + returns to the state it had right after layer_shell.get_layer_surface. + The client can re-map the surface by performing a commit without any + buffer attached, waiting for a configure event and handling it as usual. + + + + + Sets the size of the surface in surface-local coordinates. The + compositor will display the surface centered with respect to its + anchors. + + If you pass 0 for either value, the compositor will assign it and + inform you of the assignment in the configure event. You must set your + anchor to opposite edges in the dimensions you omit; not doing so is a + protocol error. Both values are 0 by default. + + Size is double-buffered, see wl_surface.commit. + + + + + + + + Requests that the compositor anchor the surface to the specified edges + and corners. If two orthogonal edges are specified (e.g. 'top' and + 'left'), then the anchor point will be the intersection of the edges + (e.g. the top left corner of the output); otherwise the anchor point + will be centered on that edge, or in the center if none is specified. + + Anchor is double-buffered, see wl_surface.commit. + + + + + + + Requests that the compositor avoids occluding an area with other + surfaces. The compositor's use of this information is + implementation-dependent - do not assume that this region will not + actually be occluded. + + A positive value is only meaningful if the surface is anchored to one + edge or an edge and both perpendicular edges. If the surface is not + anchored, anchored to only two perpendicular edges (a corner), anchored + to only two parallel edges or anchored to all edges, a positive value + will be treated the same as zero. + + A positive zone is the distance from the edge in surface-local + coordinates to consider exclusive. + + Surfaces that do not wish to have an exclusive zone may instead specify + how they should interact with surfaces that do. If set to zero, the + surface indicates that it would like to be moved to avoid occluding + surfaces with a positive exclusive zone. If set to -1, the surface + indicates that it would not like to be moved to accommodate for other + surfaces, and the compositor should extend it all the way to the edges + it is anchored to. + + For example, a panel might set its exclusive zone to 10, so that + maximized shell surfaces are not shown on top of it. A notification + might set its exclusive zone to 0, so that it is moved to avoid + occluding the panel, but shell surfaces are shown underneath it. A + wallpaper or lock screen might set their exclusive zone to -1, so that + they stretch below or over the panel. + + The default value is 0. + + Exclusive zone is double-buffered, see wl_surface.commit. + + + + + + + Requests that the surface be placed some distance away from the anchor + point on the output, in surface-local coordinates. Setting this value + for edges you are not anchored to has no effect. + + The exclusive zone includes the margin. + + Margin is double-buffered, see wl_surface.commit. + + + + + + + + + + Types of keyboard interaction possible for layer shell surfaces. The + rationale for this is twofold: (1) some applications are not interested + in keyboard events and not allowing them to be focused can improve the + desktop experience; (2) some applications will want to take exclusive + keyboard focus. + + + + + This value indicates that this surface is not interested in keyboard + events and the compositor should never assign it the keyboard focus. + + This is the default value, set for newly created layer shell surfaces. + + This is useful for e.g. desktop widgets that display information or + only have interaction with non-keyboard input devices. + + + + + Request exclusive keyboard focus if this surface is above the shell surface layer. + + For the top and overlay layers, the seat will always give + exclusive keyboard focus to the top-most layer which has keyboard + interactivity set to exclusive. If this layer contains multiple + surfaces with keyboard interactivity set to exclusive, the compositor + determines the one receiving keyboard events in an implementation- + defined manner. In this case, no guarantee is made when this surface + will receive keyboard focus (if ever). + + For the bottom and background layers, the compositor is allowed to use + normal focus semantics. + + This setting is mainly intended for applications that need to ensure + they receive all keyboard events, such as a lock screen or a password + prompt. + + + + + This requests the compositor to allow this surface to be focused and + unfocused by the user in an implementation-defined manner. The user + should be able to unfocus this surface even regardless of the layer + it is on. + + Typically, the compositor will want to use its normal mechanism to + manage keyboard focus between layer shell surfaces with this setting + and regular toplevels on the desktop layer (e.g. click to focus). + Nevertheless, it is possible for a compositor to require a special + interaction to focus or unfocus layer shell surfaces (e.g. requiring + a click even if focus follows the mouse normally, or providing a + keybinding to switch focus between layers). + + This setting is mainly intended for desktop shell components (e.g. + panels) that allow keyboard interaction. Using this option can allow + implementing a desktop shell that can be fully usable without the + mouse. + + + + + + + Set how keyboard events are delivered to this surface. By default, + layer shell surfaces do not receive keyboard events; this request can + be used to change this. + + This setting is inherited by child surfaces set by the get_popup + request. + + Layer surfaces receive pointer, touch, and tablet events normally. If + you do not want to receive them, set the input region on your surface + to an empty region. + + Keyboard interactivity is double-buffered, see wl_surface.commit. + + + + + + + This assigns an xdg_popup's parent to this layer_surface. This popup + should have been created via xdg_surface::get_popup with the parent set + to NULL, and this request must be invoked before committing the popup's + initial state. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + + + + + + + When a configure event is received, if a client commits the + surface in response to the configure event, then the client + must make an ack_configure request sometime before the commit + request, passing along the serial of the configure event. + + If the client receives multiple configure events before it + can respond to one, it only has to ack the last configure event. + + A client is not required to commit immediately after sending + an ack_configure request - it may even ack_configure several times + before its next surface commit. + + A client may send multiple ack_configure requests before committing, but + only the last request sent before a commit indicates which configure + event the client really is responding to. + + + + + + + This request destroys the layer surface. + + + + + + The configure event asks the client to resize its surface. + + Clients should arrange their surface for the new states, and then send + an ack_configure request with the serial sent in this configure event at + some point before committing the new surface. + + The client is free to dismiss all but the last configure event it + received. + + The width and height arguments specify the size of the window in + surface-local coordinates. + + The size is a hint, in the sense that the client is free to ignore it if + it doesn't resize, pick a smaller size (to satisfy aspect ratio or + resize in steps of NxM pixels). If the client picks a smaller size and + is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the + surface will be centered on this axis. + + If the width or height arguments are zero, it means the client should + decide its own window dimension. + + + + + + + + + The closed event is sent by the compositor when the surface will no + longer be shown. The output may have been destroyed or the user may + have asked for it to be removed. Further changes to the surface will be + ignored. The client should destroy the resource after receiving this + event, and create a new surface if they so choose. + + + + + + + + + + + + + + + + + + + + + + Change the layer that the surface is rendered on. + + Layer is double-buffered, see wl_surface.commit. + + + + + diff --git a/dwl/protocols/wlr-output-power-management-unstable-v1.xml b/dwl/protocols/wlr-output-power-management-unstable-v1.xml new file mode 100755 index 0000000..a977839 --- /dev/null +++ b/dwl/protocols/wlr-output-power-management-unstable-v1.xml @@ -0,0 +1,128 @@ + + + + Copyright © 2019 Purism SPC + + 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 (including the next + paragraph) 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. + + + + This protocol allows clients to control power management modes + of outputs that are currently part of the compositor space. The + intent is to allow special clients like desktop shells to power + down outputs when the system is idle. + + To modify outputs not currently part of the compositor space see + wlr-output-management. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible changes + may be added together with the corresponding interface version bump. + Backward incompatible changes are done by bumping the version number in + the protocol and interface names and resetting the interface version. + Once the protocol is to be declared stable, the 'z' prefix and the + version number in the protocol and interface names are removed and the + interface version number is reset. + + + + + This interface is a manager that allows creating per-output power + management mode controls. + + + + + Create a output power management mode control that can be used to + adjust the power management mode for a given output. + + + + + + + + All objects created by the manager will still remain valid, until their + appropriate destroy request has been called. + + + + + + + This object offers requests to set the power management mode of + an output. + + + + + + + + + + + + + + Set an output's power save mode to the given mode. The mode change + is effective immediately. If the output does not support the given + mode a failed event is sent. + + + + + + + Report the power management mode change of an output. + + The mode event is sent after an output changed its power + management mode. The reason can be a client using set_mode or the + compositor deciding to change an output's mode. + This event is also sent immediately when the object is created + so the client is informed about the current power management mode. + + + + + + + This event indicates that the output power management mode control + is no longer valid. This can happen for a number of reasons, + including: + - The output doesn't support power management + - Another client already has exclusive power management mode control + for this output + - The output disappeared + + Upon receiving this event, the client should destroy this object. + + + + + + Destroys the output power management mode control object. + + + + diff --git a/dwl/util.c b/dwl/util.c new file mode 100755 index 0000000..51130af --- /dev/null +++ b/dwl/util.c @@ -0,0 +1,51 @@ +/* See LICENSE.dwm file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "util.h" + +void +die(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} + +int +fd_set_nonblock(int fd) { + int flags = fcntl(fd, F_GETFL); + if (flags < 0) { + perror("fcntl(F_GETFL):"); + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { + perror("fcntl(F_SETFL):"); + return -1; + } + + return 0; +} diff --git a/dwl/util.h b/dwl/util.h new file mode 100755 index 0000000..226980d --- /dev/null +++ b/dwl/util.h @@ -0,0 +1,5 @@ +/* See LICENSE.dwm file for copyright and license details. */ + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); +int fd_set_nonblock(int fd); diff --git a/dwm/.github/FUNDING.yml b/dwm/.github/FUNDING.yml new file mode 100755 index 0000000..870c946 --- /dev/null +++ b/dwm/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +custom: ["https://suckless.org/donations/", "https://paypal.me/dwmflexipatch"] diff --git a/dwm/.gitignore b/dwm/.gitignore new file mode 100755 index 0000000..ca093f8 --- /dev/null +++ b/dwm/.gitignore @@ -0,0 +1,5 @@ +*.o +dwm +dwm-msg +config.h +patches.h diff --git a/dwm/LICENSE b/dwm/LICENSE new file mode 100755 index 0000000..995172f --- /dev/null +++ b/dwm/LICENSE @@ -0,0 +1,38 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk
+© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich +© 2020-2022 Chris Down + +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/Makefile b/dwm/Makefile new file mode 100755 index 0000000..bc984d7 --- /dev/null +++ b/dwm/Makefile @@ -0,0 +1,71 @@ +# 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} + +# FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef) + +ifdef YAJLLIBS +all: dwm dwm-msg +else +all: dwm +endif + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk patches.h + +config.h: + cp config.def.h $@ + +patches.h: + cp patches.def.h $@ + +dwm: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +ifdef YAJLLIBS +dwm-msg: + ${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS} +endif + +clean: + rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz + rm -f dwm-msg + +dist: clean + mkdir -p dwm-${VERSION} + 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 +ifdef YAJLLIBS + cp -f dwm-msg ${DESTDIR}${PREFIX}/bin +endif + #cp -f patch/dwmc ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm +ifdef YAJLLIBS + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg +endif + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 + mkdir -p ${DESTDIR}${PREFIX}/share/xsessions + test -f ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop || cp -n dwm.desktop ${DESTDIR}${PREFIX}/share/xsessions + chmod 644 ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/dwm\ + ${DESTDIR}${MANPREFIX}/man1/dwm.1\ + ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop + +.PHONY: all clean dist install uninstall diff --git a/dwm/README b/dwm/README new file mode 100755 index 0000000..95d4fd0 --- /dev/null +++ b/dwm/README @@ -0,0 +1,48 @@ +dwm - dynamic window manager +============================ +dwm is an extremely fast, small, and dynamic window manager for X. + + +Requirements +------------ +In order to build dwm you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (dwm is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install dwm (if +necessary as root): + + make clean install + + +Running dwm +----------- +Add the following line to your .xinitrc to start dwm using startx: + + exec dwm + +In order to connect dwm to a specific display, make sure that +the DISPLAY environment variable is set correctly, e.g.: + + DISPLAY=foo.bar:1 exec dwm + +(This will start dwm on display :1 of the host foo.bar.) + +In order to display status info in the bar, you can do something +like this in your .xinitrc: + + while xsetroot -name "`date` `uptime | sed 's/.*,//'`" + do + sleep 1 + done & + exec dwm + + +Configuration +------------- +The configuration of dwm is done by creating a custom config.h +and (re)compiling the source code. diff --git a/dwm/README.md b/dwm/README.md new file mode 100755 index 0000000..cd7db59 --- /dev/null +++ b/dwm/README.md @@ -0,0 +1,972 @@ +This dwm 6.8 (f63cde9, 2026-01-30) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). + +For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/dwm-flexipatch/blob/master/patches.def.h): +```c +#define BAR_ALPHA_PATCH 1 +``` + +So if you have ever been curious about trying out dwm, but have been discouraged by manual patching, then this may be a good starting point to see what a "fully fledged" dwm can look like. Want to try out the `pertag` patch? Just flip a config and recompile. Once you have found out what works for you and what doesn't then you should be in a better position to choose patches should you want to start patching from scratch. + +Alternatively if you have found the patches you want, but don't want the rest of the flexipatch entanglement on your plate then you may want to have a look at [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer); a custom pre-processor tool that removes all the unused flexipatch code leaving you with a build that contains the patches you selected. + +Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on the dwm window manager, how to install it and how it works. + +If you are experiencing issues then you may want to check out the [Known Issues](https://github.com/bakkeby/dwm-flexipatch/discussions/categories/known-issues) discussion category. + +Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6PTWOM9Wz) diagram which tries to organise patches into categories. + +--- + +### Changelog: + +2025-10-30 - Added the movecenter patch + +2025-09-21 - Added the games patch + +2025-06-27 - Added the banish patch + +2025-06-15 - Added the always on top patch + +2025-02-25 - Added the xresources patch + +2024-10-30 - Added the border rule patch + +2024-07-11 - Added variant of the launcher patch + +2024-01-31 - Added the placedir patch + +2023-12-22 - Added the do-not-die-on-color-allocation-failure patch + +2023-12-01 - Added the sendmoncenter patch + +2023-11-12 - Added the focusmaster-return patch variant + +2023-06-27 - Added the focusfollowmouse and unmanaged patches + +2023-06-25 - Added the toggletopbar patch + +2023-01-18 - Added the view history patch + +2022-10-08 - Added the alt-tab patch + +2022-08-12 - Added the nametag patch + +2022-08-02 - Added the bidi patch + +2022-07-05 - Added the tagpreview patch + +2022-07-04 - Added the shift-tools patch(es) with individual toggles + +2022-06-20 - Added the renamed scratchpads patch + +2022-06-17 - Ported the seamless restart feature from dusk into dwm-flexipatch + +2022-02-11 - Added the isfreesize version of the sizehints patch and the [tagsync](https://github.com/bakkeby/dwm-flexipatch/pull/219) patch (contributed by [Bagelli](https://github.com/Bagellll)) + +2021-11-23 - Added the taglabels and underlinetags patches + +2021-09-08 - Added the alwayscenter patch + +2021-07-27 - Added the winicon patch + +2021-05-30 - Added togglelayout and toggletag patches + +2021-04-16 - Vanitygaps: replaced smartgaps with smartgaps\_fact, allowing gaps to be disabled or increased when there is only one client. + +2021-04-14 - Upgraded the dwmblocks patch for statuscmd which changes the signalling mechanism from SIGUSR1 to SIGRTMIN which is likely to cause issues for those that already have a working setup. A compatibility option has been added which changes this back to SIGUSR1. Note that configuration was also changed. + +2021-04-07 - Added xkb patch + +2021-04-06 - Added the distributetags patch + +2021-04-04 - Added option for having different gaps on a per tag basis + +2021-03-31 - Added tapresize patch (contributed by [verschmelzen](https://github.com/verschmelzen)) + +2021-03-29 - Removed alwaysfullscreen patch (merged into dwm 6.2) + +2021-03-09 - Added the tab patch and the LG3D patch + +2021-02-11 - Added the riodraw and focusdir patches + +2021-01-22 - Added the placemouse patch + +2021-01-02 - Added the Layoutmenu patch + +2020-10-26 - Added the \_NET\_CLIENT\_LIST\_STACKING patch + +2020-09-29 - Added the on\_empty\_keys patch (ported from InstantOS) + +2020-09-28 - Added the \_IS\_FLOATING patch (embedded in the EWMHTAGS patch) + +2020-09-18 - Added the nomodbuttons patch allowing for toggleable mouse button bindings that have no modifiers + +2020-09-10 - Added the anybar patch (with experimental support for dwm bar(s) + anybar) + +2020-09-09 - Added the bar border patch + +2020-09-08 - Added ipc v1.5.5 patch + +2020-09-07 - Scratchpads improvement (multi-monitor support) + +2020-09-05 - Assortment of fullscreen improvements + +2020-08-27 - Added aspectresize patch + +2020-08-25 - Unified tag icon handling while adding support for different icons per monitor. Added alttagsdecoration patch. + +2020-08-22 - Added logic to auto-hide bars if nothing is drawn on them (e.g. for standalone bars that only show certain clients). Added clientindicators patch and unified indicator code. Simplified Pango integration by settling on common function signatures. + +2020-08-21 - Simplification of color configuration; settling on a set of color schemes that is shared between multiple patches (urgentborder, floatborder and titlecolor patches made non-optional) + +2020-08-20 - Added experimental flexwintitle patch based on bartabgroups + +2020-08-13 - Added bartabgroups patch + +2020-08-11 - Added decoration hints and focusmaster patches + +2020-08-10 - Added cool autostart, insets and steam patches + +2020-08-02 - Added reorganizetags patch + +2020-07-19 - Added barmodules patch - making extrabar, leftlayout, staticstatus and statusallmons patches redundant, added powerline patch + +2020-07-18 - **Note**: Up until now building dwm-flexipath without any patches selected would have given you something more or less identical with mainstream dwm. In order to reduce complexity when it comes to maintainance future versions of dwm-flexipatch may diverge from this by making some patches non-optional. For the classic dwm-flexipatch and its many patch integration hints refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0) which will be subject to bug fixes and mainstream dwm updates as far as feasible. + +2020-07-05 - Extrabar compatibility improvements (staticstatus, status2d, dwmblocks) and fix for systray randomly causing dwm to crash when first systray application starts + +2020-06-24 - Added resizepoint, statusbutton and sendmon_keepfocus patches + +2020-06-21 - Added floatpos and bar_height patches + +2020-06-19 - Added tagothermonitor patch + +2020-06-15 - Added sizehints patch + +2020-06-14 - Added RULE macro to replace rules setup making the default config less of an abomination and making it simpler to include new rules based patches + +2020-06-11 - Added the pango patch + +2020-06-10 - Added the staticstatus patch + +2020-05-31 - Added the keymodes patch + +2020-05-29 - Added the color emoji patch + +2020-05-26 - Added the status2d patch (with alpha, systray, statuspadding and dwmblocks compatibility, no statuscolors or extrabar compatibility) + +2020-05-21 - Added the moveplace and moveresize patches + +2020-05-03 - Added the shiftviewclients patch and the no transparent borders patch which removes opacity from window borders when the alpha patch is not used + +2020-05-02 - Added dwmblocks patch + +2020-04-27 - Upgraded the tagmonfixfs patch to better support moving fullscreen windows to adjacent monitors + +2020-04-26 - Expanded monitor rules patch to include nmaster, showbar and topbar options + +2020-04-23 - Improved swallow and switchtag compatibility + +2020-04-16 - Upgraded the scratchpad patch to the multiple scratchpads patch \[[ref](https://lists.suckless.org/hackers/2004/17205.html)\]. Updated the statuscolors patch with the width computation fix \[[ref](https://lists.suckless.org/hackers/2004/17207.html)\]. + +2020-04-13 - Added statuscmd patch + +2020-03-31 - Added the rounded corners patch + +2020-03-27 - Revamped the dragmfact patch to support both horizontal and vertical layout splits as well as centered master variants + +2020-03-25 - Added dragcfact patch + +2020-03-23 - Added stacker patch + +2020-03-21 - Reworked a series of layouts to re-allocate remaining pixels following an even (or cfacts) split with the aim of presenting a pixel perfect layout. This affects the following layouts: tile, bstack, bstackhoriz, centered master, centered floating master, columns, deck, and corresponding flextile-deluxe layouts + +2020-02-11 - Added swaptags and vtcolor patches + +2020-02-09 - Added alternative scratchpad patch + +2020-02-02 - Added fsignal and transferall patches + +2020-01-29 - Added swapfocus and shiftview patches + +2020-01-26 - Added transfer patch + +2020-01-24 - Added barpadding patch (incl. statusallmons, statuspadding, statuscolors, systray, alpha, holdbar and extrabar patch compatibility). Moved patches.h to patches.def.h to mimic the config pattern of having default and personal settings. + +2020-01-17 - Added inplacerotate patch + +2019-12-15 - Updated dragmfact patch to include fix patch to make it work with multiple monitors + +2019-11-26 - Added dmenumatchtop patch, added improvements to the switchtag patch based on ideas from the switchtotag patch + +2019-11-21 - Added fakefullscreenclient patch + +2019-10-24 - Added dragmfact, extrabar, exresize and nodmenu patches + +2019-10-22 - Added ispermanent and swallow patches + +2019-10-16 - Introduced [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer) + +2019-10-11 - Added the patch to ignore Xft errors when drawing text in the status bar + +2019-10-10 - Added mpdcontrol, scratchpad and spawn_cwd cpatches + +2019-10-08 - Added columns layout and fakefullscreen patch + +2019-10-07 - Added sortscreens and dwmc patches, fixed minor cross-compatibility issues for combo, holdbar, leftlayout, hidevacanttags, taggrid and activetagindicatorbar + +2019-10-06 - Added statuscolors and statusallmons patches, fixed minor cross-compatibility issues for killunsel, fullscreen, noborder, tagintostack patches + +2019-10-05 - Added killunsel, taggrid, hidevacanttags and cmdcustomize patches + +2019-10-04 - Added maximize, movestack, monoclesymbol, noborder, tagall and tagintostack patches + +2019-10-03 - Added onlyquitonempty and switchcol patches + +2019-10-02 - Added restartsig, emptyview, focusurgent and focusadjacenttag patches + +2019-10-01 - Added leftlayout, fullscreen, holdbar and unfloatvisible patches + +2019-09-30 - Replaced flextile with flextile-deluxe, refactored monitor rules to support predetermined layouts per tag + +2019-09-15 - Added focusonclick, xrdb, viewontag, urgentborder and winview patches + +2019-09-14 - Added setborderpx, selfrestart and push (no master variant), sticky and warp patches + +2019-09-13 - Added titlecolor and push patches + +2019-09-12 - Added activetagindicatorbar, alwaysfullscreen and autoresize patches + +2019-09-11 - Added monitor rules, combo and ewmhtags patches + +2019-09-10 - Minor tweaks to awesomebar patch (incl. alpha and systray compatibility). Added floatbordercolor patch. + +2019-09-09 - Added deck, fibonacci (dwindle and spiral), gridmode, gapplessgrid, horizgrid, nrowgrid, centeredmaster and flextile layouts. Added alternativetags and awesomebar patches. + +2019-09-08 - Added cfacts and vanitygaps patches, added bstack and bstackhoriz layouts + +2019-09-07 - Added cyclelayouts, resizecorners, rotatestack, savefloats, statuspadding, switchtag, center and windowrolerule patches + +2019-09-06 - Added attachabove, attachaside, attachbelow, attachbottom, autostart, fancybar, focusonnetactive and losefullscreen patches + +2019-09-05 - Alpha, systray, togglefullscreen, tagallmon, tagmonfixfs, tagswapmon, pertag and zoomswap patches added + +### Patches included: + + - [activetagindicatorbar](https://dwm.suckless.org/patches/activetagindicatorbar/) + - this patch changes the rectangle indicating if a tag is used by a client into a bar above + the tag name + + - [alpha](https://dwm.suckless.org/patches/alpha/) + - adds transparency for the status bar + + - [alt-tab](https://dwm.suckless.org/patches/alt-tab/) + - adds a window task switcher toggled using alt-tab + + - [alternativetags](https://dwm.suckless.org/patches/alternativetags/) + - adds alternative tags which can be toggled on the fly for the sole purpose of providing + visual aid + + - [alttagsdecoration](https://dwm.suckless.org/patches/alttagsdecoration/) + - provides the ability to use alternative text for tags which contain at least one window + + - [alwayscenter](https://dwm.suckless.org/patches/alwayscenter/) + - makes all floating windows centered, like the center patch, but without a rule + + - [~alwaysfullscreen~](https://dwm.suckless.org/patches/alwaysfullscreen/) + - ~prevents the focus to drift from the active fullscreen client when using focusstack\(\)~ + + - [alwaysontop](https://dwm.suckless.org/patches/alwaysontop/) + - allows for floating windows to be toggled to be always on top of other windows + + - [anybar](https://dwm.suckless.org/patches/anybar/) + - enables dwm to manage external status bars such as lemonbar and polybar + - dwm treats the external bar as it would its own, so all regular dwm commands such as + togglebar affect the external bar in the same way + + - [aspectresize](https://dwm.suckless.org/patches/aspectresize/) + - allows windows to be resized with its aspect ratio remaining constant + + - [attachabove](https://dwm.suckless.org/patches/attachabove/) + - new windows are placed above selected client + + - [attachaside](https://dwm.suckless.org/patches/attachaside/) + - new windows are placed on top of the stack + + - [attachbelow](https://dwm.suckless.org/patches/attachbelow/) + - new windows are placed below selected client + + - [attachbottom](https://dwm.suckless.org/patches/attachbottom/) + - new windows are placed at the bottom of the stack + + - [autoresize](https://dwm.suckless.org/patches/autoresize/) + - by default, windows that are not visible when requesting a resize/move will not get + resized/moved, with this patch, however, they will + + - [autostart](https://dwm.suckless.org/patches/autostart/) + - makes dwm run `~/.dwm/autostart_blocking.sh` and `~/.dwm/autostart.sh &` on startup + + - [awesomebar](https://dwm.suckless.org/patches/awesomebar/) + - enhanced taskbar that allows focus / hiding / unhiding of windows by clicking on the status + bar + + - [banish](https://github.com/bakkeby/patches/wiki/banish/) + - hides cursor when using the keyboard, akin to xbanish + + - [bar_border](https://codemadness.org/paste/dwm-border-bar.patch) + - adds a border around the bar similarly to how client windows have borders + + - [bar_height](https://dwm.suckless.org/patches/bar_height/) + - allows the bar height to be explicitly set rather than being derived from font + + - [barmodules](https://github.com/bakkeby/patches/wiki/barmodules/) + - splits the dwm bar into modules allowing for re-arrangement of the bar and easier + integration for new features + + - [barpadding](https://dwm.suckless.org/patches/barpadding/) + - adds vertical and horizontal space between the statusbar and the edge of the screen + + - [bartabgroups](https://dwm.suckless.org/patches/bartabgroups/) + - turns the titlebar area into a mfact-respecting tab-bar showing each client's title + + - [bidi](https://dwm.suckless.org/patches/bidi/) + - adds proper support for Right-To-Left (RTL) languages (such as Farsi, Arabic or Hebrew) + + - [borderrule](https://dwm.suckless.org/patches/borderrule/) + - adds a client rule option to set border width on a per client basis + + - [center](https://dwm.suckless.org/patches/center/) + - adds an iscentered rule to automatically center clients on the current monitor + + - [cfacts](https://dwm.suckless.org/patches/cfacts/) + - the cfacts patch provides the ability to assign different weights to clients in their + respective stack in tiled layout + + - [clientindicators](https://dwm.suckless.org/patches/clientindicators/) + - draws a dot indicator overlayed on each tag icon for each client + - the selected client is drawn as a larger horizontal line + + - [cmdcustomize](https://dwm.suckless.org/patches/cmdcustomize/) + - allows color attributes to be set through the command line + + - [colorbar](https://dwm.suckless.org/patches/colorbar/) + - lets you change the foreground and background color of every statusbar element + + - ~color_emoji~ + - ~enables color emoji in dmenu by removing a workaround for a BadLength error in the Xft~ + ~library when color glyphs are used~ + - ~enabling this will crash dwm on encountering such glyphs unless you also have an updated~ + ~Xft library that can handle them~ + + - [combo](https://dwm.suckless.org/patches/combo/) + - allows you to select multiple tags by pressing all the right keys as a combo, e.g. hold MOD + and press and hold 1 and 3 together to view those two tags + + - [cool_autostart](https://dwm.suckless.org/patches/cool_autostart/) + - allows dwm to execute commands from an array in the config.h file + - when dwm exits all processes from the autostart array will be killed automatically + + - [cyclelayouts](https://dwm.suckless.org/patches/cyclelayouts/) + - lets you cycle through all your layouts + + - [decoration_hints](https://dwm.suckless.org/patches/decoration_hints/) + - make dwm respect \_MOTIF\_WM\_HINTS property, and not draw borders around windows + requesting for it + - some applications use this property to notify window managers to not draw window + decorations + - not respecting this property leads to issues with applications that draw their own borders, + like chromium (with "Use system title bar and borders" turned off) or vlc in fullscreen mode + + - [distributetags](https://dwm.suckless.org/patches/reorganizetags/) + - this reorganisetags variant re-distributes all clients on the current monitor evenly across + all tags + + - [dmenumatchtop](https://dwm.suckless.org/patches/dmenumatchtop) + - updates the position of dmenu to match that of the bar + - i.e. if topbar is 0 then dmenu will appear at the bottom and if 1 then dmenu will appear at + the top + + - do-not-die-on-color-allocation-failure + - avoids dwm terminating (dying) on color allocation failures + - useful for the xrdb (xresources) and status2d patches + + - [dragcfact](https://github.com/bakkeby/patches/wiki/dragcfact/) + - lets you resize clients' size (i.e. modify cfact) by holding modkey + shift + right-click + and dragging the mouse + + - [dragmfact](https://github.com/bakkeby/patches/wiki/dragmfact/) + - lets you resize the split in layouts (i.e. modify mfact) by holding the modkey + shift + + left-click and dragging the mouse + - this is a bespoke patch that supports vertical and horizontal layout splits as well as + centered master variants + + - [dwmblocks](https://gist.github.com/danbyl/54f7c1d57fc6507242a95b71c3d8fdea) + - signal integration to use dwm with a patched [dwmblocks](https://github.com/torrinfail/dwmblocks) + - combined with the statuscmd patch this gives a clickable statusbar + + - [dwmc](http://dwm.suckless.org/patches/dwmc/) + - a simple dwmc client using a fork of fsignal to communicate with dwm + + - [emptyview](https://dwm.suckless.org/patches/emptyview/) + - allows no tag at all to be selected + - dwm will start with no tag selected and when a client with no tag rule is started and no + tag is selected then it will be opened on the first tag + + - [ewmhtags](https://dwm.suckless.org/patches/ewmhtags/) + - adds EWMH support for \_NET_NUMBER_OF_DESKTOPS, \_NET_CURRENT_DESKTOP, \_NET_DESKTOP_NAMES + and \_NET_DESKTOP_VIEWPORT, which allows for compatibility with other bars and programs + that request workspace information, e.g. polybar's xworkspaces module + + - [exresize](https://dwm.suckless.org/patches/exresize/) + - this patch allows the user to change size and placement of floating windows using only the + keyboard + - it also allows for temporary vertical and horizontal extension of windows similar to other + WMs fill command + + - [~extrabar~](https://dwm.suckless.org/patches/extrabar/) + - ~enables an extra status bar in dwm in a similar manner to the dualstatus patch~ + - ~if the primary status is at the top via topbar then the extra status bar will be placed at + the bottom and vice versa~ + + - extrastatus + - formerly extrabar - now only splits the status into to statuses by using a status separator + + - [fakefullscreen](https://dwm.suckless.org/patches/fakefullscreen/) + - only allow clients to "fullscreen" into the space currently given to them + - as an example, this will allow you to view a fullscreen video in your browser on one half + of the screen, while having the other half available for other tasks + + - [fakefullscreenclient](https://github.com/bakkeby/patches/wiki/fakefullscreenclient/) + - similarly to the fakefullscreen patch this patch only allows clients to "fullscreen" into + the space currently given to them + - as an example, this will allow you to view a fullscreen video in your browser on one half + of the screen, while having the other half available for other tasks + - the "twist" with this patch is that fake fullscreen can be toggled on a per client basis + rather than applying to all clients globally + + - [fancybar](https://dwm.suckless.org/patches/fancybar/) + - shows the titles of all visible windows in the status bar + + - flexwintitle + - based on the bartabgroups patch, this is a layout aware barmodules module for handling + window titles intended to be used with flextile-deluxe + + - [~floatbordercolor~](https://dwm.suckless.org/patches/float_border_color/) + - ~this patch allows a different border color to be chosen for floating windows~ + + - [floatpos](https://github.com/bakkeby/patches/wiki/floatpos/) + - adds a float rule allowing the size and position of floating windows to be specified + - control the size and position of floating windows similar to exresize, moveresize, + moveplace patches + - specify size and position using absolute, relative or fixed co-ordinates or + - position floating windows in a grid-like manner + + - [focusadjacenttag](https://dwm.suckless.org/patches/focusadjacenttag/) + - provides the ability to focus the tag on the immediate left or right of the currently + focused tag + - it also allows to send the focused window either on the left or the right tag + + - [focusdir](https://github.com/bakkeby/patches/wiki/focusdir) + - allows focusing on clients based on direction (up, down, left, right) instead of client + order + + - [focusfollowmouse](https://github.com/bakkeby/patches/wiki/focusfollowmouse) + - the window under the mouse cursor will receive focus when changing tags, closing windows or + moving client out of view (as opposed to the most recently focused client) + + - [focusmaster](https://dwm.suckless.org/patches/focusmaster/) + - a simple patch that just puts focus back to the master client + + - [focusmaster-return](https://dwm.suckless.org/patches/focusmaster/) + - a simple patch that just puts focus back to the master client + - additionally allows focus to be switched back to the previous client + + - [focusonclick](https://dwm.suckless.org/patches/focusonclick/) + - this patch makes you switch focus only by mouse click and not sloppy (focus follows mouse + pointer) + + - [focusonnetactive](https://dwm.suckless.org/patches/focusonnetactive/) + - by default, dwm responds to \_NET_ACTIVE_WINDOW client messages by setting the urgency bit + on the named window + - this patch activates the window instead + + - [focusurgent](https://dwm.suckless.org/patches/focusurgent/) + - adds a keyboard shortcut to select the next window having the urgent flag regardless of the + tag it is on + + - [fsignal](https://dwm.suckless.org/patches/fsignal/) + - send "fake signals" to dwm for handling, using xsetroot + - this will not conflict with the status bar, which also is managed using xsetroot + + - [fullscreen](https://dwm.suckless.org/patches/fullscreen/) + - applies the monocle layout with the focused client on top and hides the bar + - when pressed again it shows the bar and restores the layout that was active before going + fullscreen + + - [games](https://github.com/bakkeby/patches/wiki/steam) + - adds a new client rule option to flag clients as a "game", the effect of which is that + - if the client is in fullscreen and it loses focus (e.g. by moving to another tag) then it will automatically be minimized + - and the window will automatically be unminimized when receving focus (e.g. by going back to its tag) + + - [hidevacanttags](https://dwm.suckless.org/patches/hide_vacant_tags/) + - prevents dwm from drawing tags with no clients (i.e. vacant) on the bar + + - [holdbar](http://dwm.suckless.org/patches/holdbar/) + - with this patch dwm's built-in status bar is only shown when HOLDKEY is pressed + - additionally the bar will now overlay the display + + - [ignore-xft-errors-when-drawing-text](https://groups.google.com/forum/m/#!topic/wmii/7bncCahYIww) + - sometimes dwm crashes when it cannot render some glyphs in window titles (usually emoji) + - this patch is essentially a hack to ignore any errors when drawing text on the status bar + and may be removed if a more appropriate solution comes up + + - [inplacerotate](https://dwm.suckless.org/patches/inplacerotate/) + - allows rotation of all clients in the master or stack area without affecting the other area + + - [insets](https://dwm.suckless.org/patches/insets/) + - lets custom insets from each edge of the screen to be defined + - an example use case would be to make space for an external bar + + - [ipc](https://github.com/mihirlad55/dwm-ipc) + - implements inter-process communication through a UNIX socket for dwm + - allows for the window manager to be queried for information, e.g. listen for events such as + tag or layout changes, as well as send commands to control the window manager via other + programs + + - [\_IS\_FLOATING](https://github.com/bakkeby/dwm-flexipatch/issues/50) + - adds the \_IS\_FLOATING xproperty for floating windows + - this can allow for a compositor to handle floating windows differently to tiled windows, + e.g. only show shadows on floating windows + - this patch is enabled via the ewmhtags patch + + - [ispermanent](https://dwm.suckless.org/patches/ispermanent/) + - adds rule option for clients to avoid accidental termination by killclient for sticky + windows + + - [keymodes](https://dwm.suckless.org/patches/keymodes/) + - this patch adds key modes (like in vim or emacs) where chains of keyboard shortcuts can be + performed + + - [killunsel](https://dwm.suckless.org/patches/killunsel/) + - kills all visible clients that are not selected (only the selected client will remain) + + - [launcher](https://dwm.suckless.org/patches/launcher/) + - adds buttons to the bar that can be used to launch applications + + - [~leftlayout~](http://dwm.suckless.org/patches/leftlayout/) + - ~moves the layout symbol in the status bar to the left hand side~ + + - LG3D + - changes the window manager name to "LG3d" instead of "dwm" as a workaround for Java + applications that assume that the window manager is using window reparenting + - refer to the ISSUES secton of the dwm man page for more details + + - [losefullscreen](https://github.com/bakkeby/patches/wiki/losefullscreen/) + - by default in dwm it is possible to make an application fullscreen, then use the focusstack + keybindings to focus on other windows beneath the current window + - it is also possible to spawn new windows (e.g. a terminal) that end up getting focus while + the previous window remains in fullscreen + - this patch ensures that in such scenarios the previous window loses fullscreen + + - [maximize](https://dwm.suckless.org/patches/maximize/) + - adds helper functions for maximizing, horizontally and vertically, floating windows using + keybindings + + - [mpdcontrol](https://dwm.suckless.org/patches/mpdcontrol/) + - adds keyboard bindings to control MDP (Music Player Daemon) + + - [monitorrules](https://github.com/bakkeby/patches/wiki/monitorrules/) + - adds rules per monitor, e.g. have default layouts per monitor + - the use case for this is if the second monitor is vertical (i.e. rotated) then you may want + to use a different default layout for this monitor than what is used for the main monitor + (for example normal vertical split for main monitor and horizontal split for the second) + + - [monoclesymbol](https://dwm.suckless.org/patches/monoclesymbol/) + - always display the the monocle-symbol as defined in config.h if the monocle-layout is + activated + - do not display the number of open clients in the current tag + + - [movecenter](https://dwm.suckless.org/patches/movecenter/) + - adds a keybinding to center the focused window + + - [moveplace](https://dwm.suckless.org/patches/moveplace/) + - adds a function to place a window either centered or in one of 8 cardinal directions + - based on the exresize patch + + - [moveresize](https://dwm.suckless.org/patches/moveresize/) + - allows you to move and resize dwm's clients using keyboard bindings + + - [movestack](https://dwm.suckless.org/patches/movestack/) + - allows you to move clients around in the stack and swap them with the master + + - [nametag](https://dwm.suckless.org/patches/nametag/) + - allows the names of tags to be changed during runtime + + - [netclientliststacking](https://github.com/bakkeby/patches/wiki/netclientliststacking) + - adds support for the \_NET\_CLIENT\_LIST\_STACKING atom, needed by certain applications + like the Zoom video conferencing application + + - [noborder](https://dwm.suckless.org/patches/noborder/) + - removes the border when there is only one window visible + + - [nodmenu](https://git.suckless.org/sites/commit/ed68e3629de4ef2ca2d3f8893a79fb570b4c0cbc.html) + - enable modifying dmenu in config.def.h which resulted previously in a compilation error + because two lines of code hardcode dmenu into dwm + - allows complete removal of dmenu, should you want to do that + - NB: this patch was removed from the patches listing on the suckless page due to it's simplicity + + - nomodbuttons + - allows for toggleable client button bindings that have no modifiers + - this can, for example, allow you to move or resize using the mouse alone without holding + down a modifier key, which can be practical if you have extra buttons on your mouse + + - [no\_transparent\_borders](https://github.com/szatanjl/dwm/commit/1529909466206016f2101457bbf37c67195714c8) + - when terminals have transparency then their borders also become transparent + - this patch ensures that borders have no transparency + - note that this patch is only relevant if you are not using the alpha patch + + - [on\_empty\_keys](https://github.com/bakkeby/dwm-flexipatch/issues/51) + - port of InstantVM's on_empty_keys functionality allowing keybindings that apply only when a + tag/view is empty + - an example use case is being able to launch applications with first hand keys like "f" to + launch firefox + + - [onlyquitonempty](https://dwm.suckless.org/patches/onlyquitonempty/) + - makes it so dwm will only exit via quit() if no windows are open (in order to prevent + accidental loss of work) + + - [pango](https://dwm.suckless.org/patches/pango/) + - adds simple markup for status messages using pango markup + + - [pertag](https://dwm.suckless.org/patches/pertag/) + - adds nmaster, mfact, layouts and more per tag rather than per monitor + + - [placedir](https://github.com/bakkeby/patches/wiki/placedir) + - allows tiled windows to be moved in any direction (up, down, left, right) + + - [placemouse](https://github.com/bakkeby/patches/wiki/placemouse) + - lets the user change the position of a client in the stack using the mouse. + + - [powerline](https://gitlab.com/udiboy1209-suckless/dwm/-/commit/071f5063e8ac4280666828179f92788d893eea40#4b1a539194be7467cefbda22f675a3b7c19ceca7) + - adds drawing of powerline arrows (and diagonal lines) for both the status bar and the tags + + - [push](https://dwm.suckless.org/patches/push/) + - this patch provides a way to move clients up and down inside the client list + + - [renamed_scratchpads](https://github.com/bakkeby/patches/wiki/renamedscratchpads) + - variant of the [named scratchpads](https://dwm.suckless.org/patches/namedscratchpads/) patch + + - [reorganizetags](https://dwm.suckless.org/patches/reorganizetags/) + - shifts all clients per tag to leftmost unoccupied tags + - e.g. if clients A, B, C are tagged on tags 1, 5, 9 respectively, when reorganized they will + now be on tag 1, 2, and 3 + + - [resizecorners](https://dwm.suckless.org/patches/resizecorners/) + - by default, windows only resize from the bottom right corner + - with this patch the mouse is warped to the nearest corner and you resize from there + + - [resizepoint](https://github.com/bakkeby/patches/wiki/resizepoint/) + - practically the same as resizecorners, but the cursor does not warp to any of the window + corners + + - [restartsig](https://dwm.suckless.org/patches/restartsig/) + - adds a keyboard shortcut to restart dwm or alternatively by using kill -HUP dwmpid + - additionally dwm can quit cleanly by using kill -TERM dwmpid + + - [riodraw](https://github.com/bakkeby/patches/wiki/riodraw/) + - adds rio-like drawing to spawn new windows or to resize the selected client (ported from + instantWM) + - depends on an external tool slop being installed + + - [rotatestack](https://dwm.suckless.org/patches/rotatestack/) + - let's you rotate through the stack using keyboard shortcuts + + - [roundedcorners](https://github.com/mitchweaver/suckless/blob/master/dwm/inactive/mitch-06-rounded_corners-f04cac6d6e39cd9e3fc4fae526e3d1e8df5e34b2.patch) + - adds rounded corners to client windows + + - [savefloats](https://dwm.suckless.org/patches/save_floats/) + - saves size and position of every floating window before it is forced into tiled mode + - if the window is made floating again then the old dimensions will be restored + + - [scratchpad](https://dwm.suckless.org/patches/scratchpad/) + - the scratchpad patch allows you to spawn or restore a floating terminal window + + - [scratchpad\_alt\_1](https://github.com/GasparVardanyan/dwm-scratchpad) + - this alternative patch enables a scratchpad feature in dwm similar to the scratchpad + feature in i3wm + + - seamless\_restart + - allows for selected layout, assigned tags, etc. to be persisted across restarts + + - [selfrestart](https://dwm.suckless.org/patches/selfrestart/) + - restart dwm without the unnecessary dependency of an external script + + - [sendmoncenter](https://dwm.suckless.org/patches/sendmoncenter/) + - floating windows being sent to another monitor will be centered + + - [sendmon\_keepfocus](https://github.com/bakkeby/patches/wiki/sendmon_keepfocus/) + - minor patch that allow clients to keep focus when being sent to another monitor + + - [setborderpx](https://dwm.suckless.org/patches/setborderpx/) + - this patch allows border pixels to be changed during runtime + + - [shift-tools](https://dwm.suckless.org/patches/shift-tools/) + - a group of functions that shift clients or views left or right + + - [shiftview](https://github.com/chau-bao-long/dotfiles/blob/master/suckless/dwm/shiftview.diff) + - adds keybindings for left and right circular shift through tags + - also see focusadjacenttag + + - [shiftviewclients](https://github.com/bakkeby/patches/wiki/shiftviewclients/) + - variant of the shiftview patch which skips tags that have no clients + + - [sizehints](https://dwm.suckless.org/patches/sizehints/) + - makes dwm obey even "soft" sizehints for new clients + + - [sortscreens](https://www.mail-archive.com/hackers@suckless.org/msg09400.html) + - this patch aims to address some inconsistencies when it comes to focusmon, tagmon and + similar functionality by explicitly sorting screens left to right (or top to bottom in a + vertical layout) + + - [spawn\_cwd](https://dwm.suckless.org/patches/spawn_cwd/) + - spawns programs from currently focused client's working directory + + - [stacker](https://dwm.suckless.org/patches/stacker/) + - provides comprehensive utilities for managing the client stack + + - [staticstatus](https://dwm.suckless.org/patches/staticstatus/) + - allows the status text to be fixed to the bar on a specific monitor rather than being + drawn on the focused monitor + + - [status2d](https://dwm.suckless.org/patches/status2d/) + - allows colors and rectangle drawing in the dwm status bar + + - [statusallmons](https://dwm.suckless.org/patches/statusallmons/) + - this patch draws and updates the statusbar on all monitors + + - [statusbutton](https://dwm.suckless.org/patches/statusbutton/) + - adds a clickable button to the left hand side of the statusbar + + - [statuscmd](https://dwm.suckless.org/patches/statuscmd/) + - adds the ability to execute shell commands based on the mouse button and position when + clicking the status bar + + - [statuscolors](https://dwm.suckless.org/patches/statuscolors/) + - enables colored text in the status bar allowing multiple color combinations for use in the + status script + + - [statuspadding](https://dwm.suckless.org/patches/statuspadding/) + - adds configuration options for horizontal and vertical padding in the status bar + + - [steam](https://github.com/bakkeby/patches/wiki/steam) + - a minor patch that works around the issue of floating Steam windows jumping around the + screen when they receive focus + + - [sticky](https://dwm.suckless.org/patches/sticky/) + - adds toggleable keyboard shortcut to make a client 'sticky', i.e. visible on all tags + + - [swallow](https://dwm.suckless.org/patches/swallow/) + - this patch adds "window swallowing" to dwm as known from Plan 9's windowing system rio + - clients marked with isterminal in config.h swallow a window opened by any child process, + e.g. running xclock in a terminal + - closing the xclock window restores the terminal window in the current position + + - [swapfocus](https://dwm.suckless.org/patches/swapfocus/) + - this patch depends on the pertag patch and makes it possible to switch focus with a single + shortcut (mod-s) instead of having to think if you should use mod-j or mod-k for reaching + the previously used window + + - [swaptags](https://dwm.suckless.org/patches/swaptags/) + - allows swapping the contents of the currently selected tag with another tag by using + keyboard shortcuts + + - [switchcol](https://dwm.suckless.org/patches/switchcol/) + - allows you to switch focus between the master and stack columns using a single keybinding + + - [switchtag](https://github.com/bakkeby/patches/wiki/switchtag/) + - when an application opens on a specific tab this patch adds the option to also switch to + that tag when the application starts + - optionally, the previous view can also be restored when the client is closed + + - [systray](https://dwm.suckless.org/patches/systray/) + - adds system tray in the status bar + + - [tab](https://dwm.suckless.org/patches/tab/) + - transforms the monocle layout into a "tabbed" layout if more than one window is present on + the monocle view + - this is essentially just a specific bar + - the patch has been added for demonstration purposes only and has limited compatibility with + other patches + - it will conflict space-wise with a second bar + - note that fancybar, awesomebar, bartabgroups and similar patches make the tab patch + redundant + + - [tagall](https://dwm.suckless.org/patches/tagall/) + - adds keyboard shortcuts to move all (or only floating) windows from one tag to another + + - [tagallmon](https://github.com/bakkeby/patches/wiki/tagallmon/) + - move all visible windows to an adjacent monitor + + - [tagintostack](https://dwm.suckless.org/patches/tagintostack/) + - makes new clients attach into the stack area when you toggle a new tag into view + - this means your master area will remain unchanged when toggling views + + - [taggrid](https://dwm.suckless.org/patches/taggrid/) + - adds an option to place tags in rows like in many other window managers + + - [taglabels](https://dwm.suckless.org/patches/taglabels/) + - shows tag + class of master client in the tags section of the bar + + - [tagmonfixfs](https://github.com/bakkeby/patches/wiki/tagmonfixfs/) + - allows moving a fullscreen window to another monitor while remaining in fullscreen + + - [tagothermonitor](https://dwm.suckless.org/patches/tagothermonitor/) + - adds functions and keybindings to tag a window to a desired tag on an adjacent monitor + + - [tagpreview](https://dwm.suckless.org/patches/tag-previews/) + - shows a preview of a tag when hovering the tag icon using the mouse + + - [tagswapmon](https://github.com/bakkeby/patches/wiki/tagswapmon/) + - swap all visible windows on one monitor with those of an adjacent monitor + + - [tapresize](https://dwm.suckless.org/patches/tapresize/) + - allows resizing of windows using a touchpad + - uses vertical and horizontal scroll events allowing you to use one-finger tap for moving + windows and two-finger tap for resizing + + - [~titlecolor~](https://dwm.suckless.org/patches/titlecolor/) + - ~adds a new color scheme used by the (selected) window title in the bar~ + + - [togglefullscreen](https://github.com/bakkeby/patches/wiki/togglefullscreen/) + - allows you to toggle fullscreen on and off using a single shortcut key + + - [togglelayout](https://github.com/bakkeby/patches/wiki/togglelayout) + - toggle layout using the same keyboard shortcuts to set the layout + - e.g. hitting `MOD+m` switches to monocle layout, hitting the same keybinding again brings + you back to the previous layout + + - [toggletag](https://github.com/bakkeby/patches/wiki/toggletag) + - toggle tags using the same keyboard shortcuts to view tags + - e.g. hitting `MOD+4` lets you view tag 4 and hitting the keybinding a second time brings + you back to where you were before + + - [toggletopbar](https://dwm.suckless.org/patches/toggletopbar/) + - allows for the bar position (top or bottom) to be toggled during runtime + + - [transfer](https://dwm.suckless.org/patches/transfer/) + - lets you transfer the currently focused client between the master and stack area while + increasing or decreasing the master area (nmaster) accordingly + + - [transferall](https://dwm.suckless.org/patches/transfer/) + - lets you transfer all clients between the master and stack area while increasing or + decreasing the master area (nmaster) accordingly + + - [underlinetags](https://dwm.suckless.org/patches/underlinetags/) + - underlines the selected tag, or optionally all tags + + - [unfloatvisible](https://dwm.suckless.org/patches/unfloatvisible/) + - resets isfloating on any visible windows that have it set and optionally also applies a + layout + + - [unmanaged](https://github.com/bakkeby/patches/wiki/unmanaged) + - adds a client rule that allows for windows to not be managed by the window manager + - this can be useful for external bars, widgets, launchers, docks, desktop icons and more + + - [~urgentborder~](https://dwm.suckless.org/patches/urgentborder/) + - ~this patch makes "urgent" windows have different colors~ + + - [vanitygaps](https://github.com/bakkeby/patches/blob/master/dwm/dwm-vanitygaps-6.2.diff) + - adds configurable gaps between windows differentiating between outer, inner, horizontal and + vertical gaps + + - viewhistory + - adds a tag change history that is longer than the default current and previous tag + - `MOD`+Tab (`view(0)`) can be pressed multiple times to go further back to earlier tag + selections + + - [viewontag](https://dwm.suckless.org/patches/viewontag/) + - follow a window to the tag it is being moved to + + - [vtcolor](https://dwm.suckless.org/patches/vtcolors/) + - this patch adds the ability for dwm to read colors from the linux virtual console + essentially allowing you to use the same color scheme as your regular tty + + - [warp](https://dwm.suckless.org/patches/warp/) + - warps the mouse cursor to the center of the currently focused window or screen when the + mouse cursor is (a) on a different screen or (b) on top of a different window + + - [winicon](https://dwm.suckless.org/patches/winicon/) + - adds the window icon next to the window title in the bar + + - [windowrolerule](https://github.com/bakkeby/patches/wiki/windowrolerule/) + - sometimes a single application opens different windows depending on the task at hand and + this is often reflected in the WM_WINDOW_ROLE(STRING) x property + - this patch adds the role field to the rule configuration so that one can differentiate + between, say, Firefox "browser" vs "Preferences" vs "Manager" or Google-chrome "browser" + vs "pop-up". + + - [winview](http://dwm.suckless.org/patches/winview/) + - allows switching the view to that of a given client from the all-window view (Mod-0) using + a keyboard shortcut + + - [xkb](https://dwm.suckless.org/patches/xkb/) + - remembers keyboard layout per client + + - [xrdb](http://dwm.suckless.org/patches/xrdb/) + - allows dwm to read colors from xrdb (.Xresources) during runtime + + - [xresources](https://dwm.suckless.org/patches/xresources/) + - allows dwm to read strings, integers and float values from xrdb (.Xresources) during runtime + + - [zoomfloating](https://www.reddit.com/r/suckless/comments/ie5fe3/zoomfloating_my_own_simple_original_patch/) + - a simple patch that allows floating windows to be zoomed into the master stack position + + - [zoomswap](https://dwm.suckless.org/patches/zoomswap/) + - allows a master and a stack window to swap places rather than every window on the screen + changing position + +### Layouts included: + + - [bstack](https://dwm.suckless.org/patches/bottomstack/) + - bottomstack layout + + - [bstackhoriz](https://dwm.suckless.org/patches/bottomstack/) + - bottomstack horizontal layout + + - [centeredmaster](https://dwm.suckless.org/patches/centeredmaster/) + - centeredmaster layout + + - [centeredfloatingmaster](https://dwm.suckless.org/patches/centeredmaster/) + - centeredfloatingmaster layout + + - [columns](https://dwm.suckless.org/patches/columns/) + - same as the default tile layout except clients in the master area are arranged in columns + (i.e. left to right) + + - [deck](https://dwm.suckless.org/patches/deck/) + - deck layout - clients in the stack area are arranged on top of each other (like monocle) + + - [fibonacci](https://dwm.suckless.org/patches/fibonacci/) + - fibonacci (dwindle and spiral) layouts + + - [flextile-deluxe](https://github.com/bakkeby/patches/wiki/flextile-deluxe/) + - a re-envisioned, flexible and over-the-top version of the original + [flextile](https://dwm.suckless.org/patches/flextile/) patch supporting + - multiple split layouts (horizontal, vertical, centered, floating, fixed) + - tile arrangement on a per split basis (stack horizontally, stack vertically, grids, + fibonacci) + - pertag, cfacts, rmaster, vanitygaps compatibility + - tile, deck, monocle, centeredmaster, bstack, bstackhoriz, gapplessgrid and more + - this gives you a lot of versatility in terms of layout + + - [gapplessgrid](https://dwm.suckless.org/patches/gaplessgrid/) + - gappless grid layout + + - [gridmode](https://dwm.suckless.org/patches/gridmode/) + - gridmode (grid) layout + + - [horizgrid](https://dwm.suckless.org/patches/horizgrid/) + - horizontal grid layout + + - [nrowgrid](https://dwm.suckless.org/patches/nrowgrid/) + - nrowgrid layout, number of rows in grid controlled by nmaster diff --git a/dwm/config.def.h b/dwm/config.def.h new file mode 100755 index 0000000..0100503 --- /dev/null +++ b/dwm/config.def.h @@ -0,0 +1,2257 @@ +/* See LICENSE file for copyright and license details. */ + +/* Helper macros for spawning commands */ +#define SHCMD(cmd) \ + { \ + .v = (const char *[]) { "/bin/sh", "-c", cmd, NULL } \ + } +#define CMD(...) \ + { \ + .v = (const char *[]) { __VA_ARGS__, NULL } \ + } + +/* appearance */ +#if ROUNDED_CORNERS_PATCH +static const unsigned int borderpx = 0; /* border pixel of windows */ +static const int corner_radius = 10; +#else +static const unsigned int borderpx = 1; /* border pixel of windows */ +#endif // ROUNDED_CORNERS_PATCH +#if BAR_BORDER_PATCH +/* This allows the bar border size to be explicitly set separately from + * borderpx. If left as 0 then it will default to the borderpx value of the + * monitor and will automatically update with setborderpx. */ +static const unsigned int barborderpx = 0; /* border pixel of bar */ +#endif // BAR_BORDER_PATCH +static const unsigned int snap = 32; /* snap pixel */ +#if SWALLOW_PATCH +static const int swallowfloating = + 0; /* 1 means swallow floating windows by default */ +#endif // SWALLOW_PATCH +#if BAR_TAGPREVIEW_PATCH +static const int scalepreview = 4; /* Tag preview scaling */ +#endif // BAR_TAGPREVIEW_PATCH +#if NO_MOD_BUTTONS_PATCH +static int nomodbuttons = + 1; /* allow client mouse button bindings that have no modifier */ +#endif // NO_MOD_BUTTONS_PATCH +#if VANITYGAPS_PATCH +static const unsigned int gappih = 20; /* horiz inner gap between windows */ +static const unsigned int gappiv = 10; /* vert inner gap between windows */ +static const unsigned int gappoh = + 10; /* horiz outer gap between windows and screen edge */ +static const unsigned int gappov = + 30; /* vert outer gap between windows and screen edge */ +static const int smartgaps_fact = + 1; /* gap factor when there is only one client; 0 = no gaps, 3 = 3x outer + gaps */ +#endif // VANITYGAPS_PATCH +#if AUTOSTART_PATCH +static const char autostartblocksh[] = "autostart_blocking.sh"; +static const char autostartsh[] = "autostart.sh"; +static const char dwmdir[] = "dwm"; +static const char localshare[] = ".local/share"; +#endif // AUTOSTART_PATCH +#if BAR_ANYBAR_PATCH +static const int usealtbar = 1; /* 1 means use non-dwm status bar */ +static const char *altbarclass = "Polybar"; /* Alternate bar class name */ +static const char *altbarcmd = + "$HOME/bar.sh"; /* Alternate bar launch command */ +#endif // BAR_ANYBAR_PATCH +#if BAR_HOLDBAR_PATCH +static const int showbar = 0; /* 0 means no bar */ +#else +static const int showbar = 1; /* 0 means no bar */ +#endif // BAR_HOLDBAR_PATCH +static const int topbar = 1; /* 0 means bottom bar */ +#if TAB_PATCH +/* Display modes of the tab bar: never shown, always shown, shown only in */ +/* monocle mode in the presence of several windows. */ +/* Modes after showtab_nmodes are disabled. */ +enum showtab_modes { + showtab_never, + showtab_auto, + showtab_nmodes, + showtab_always +}; +static const int showtab = showtab_auto; /* Default tab bar show mode */ +static const int toptab = False; /* False means bottom tab bar */ +#endif // TAB_PATCH +#if BAR_HEIGHT_PATCH +static const int bar_height = + 0; /* 0 means derive from font, >= 1 explicit height */ +#endif // BAR_HEIGHT_PATCH +#if BAR_PADDING_PATCH +static const int vertpad = 10; /* vertical padding of bar */ +static const int sidepad = 10; /* horizontal padding of bar */ +#endif // BAR_PADDING_PATCH +#if BAR_WINICON_PATCH +#define ICONSIZE 20 /* icon size */ +#define ICONSPACING 5 /* space between icon and title */ +#endif // BAR_WINICON_PATCH +#if FOCUSONCLICK_PATCH +static const int focusonwheel = 0; +#endif // FOCUSONCLICK_PATCH +#if FLOATPOS_PATCH +static int floatposgrid_x = 5; /* float grid columns */ +static int floatposgrid_y = 5; /* float grid rows */ +#endif // FLOATPOS_PATCH +#if RIODRAW_PATCH +static const char slopspawnstyle[] = + "-t 0 -c 0.92,0.85,0.69,0.3 -o"; /* do NOT define -f (format) here */ +static const char slopresizestyle[] = + "-t 0 -c 0.92,0.85,0.69,0.3"; /* do NOT define -f (format) here */ +static const int riodraw_borders = + 0; /* 0 or 1, indicates whether the area drawn using slop includes the + window borders */ +#if SWALLOW_PATCH +static const int riodraw_matchpid = + 1; /* 0 or 1, indicates whether to match the PID of the client that was + spawned with riospawn */ +#endif // SWALLOW_PATCH +#endif // RIODRAW_PATCH +/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), + * 'A' (active monitor) */ +#if BAR_STATUSALLMONS_PATCH +static const int statusmon = -1; +#elif BAR_STATICSTATUS_PATCH +static const int statusmon = 0; +#else +static const int statusmon = 'A'; +#endif // BAR_STATUSALLMONS_PATCH | BAR_STATICSTATUS_PATCH +#if BAR_STATUSPADDING_PATCH +static const int horizpadbar = 2; /* horizontal padding for statusbar */ +static const int vertpadbar = 0; /* vertical padding for statusbar */ +#endif // BAR_STATUSPADDING_PATCH +#if BAR_STATUSBUTTON_PATCH +static const char buttonbar[] = ""; +#endif // BAR_STATUSBUTTON_PATCH +#if BAR_SYSTRAY_PATCH +static const unsigned int systrayspacing = 2; /* systray spacing */ +static const int showsystray = 1; /* 0 means no systray */ +#endif // BAR_SYSTRAY_PATCH +#if BAR_TAGLABELS_PATCH +static const char ptagf[] = "[%s %s]"; /* format of a tag label */ +static const char etagf[] = "[%s]"; /* format of an empty tag */ +static const int lcaselbl = 0; /* 1 means make tag label lowercase */ +#endif // BAR_TAGLABELS_PATCH +#if BAR_UNDERLINETAGS_PATCH +static const unsigned int ulinepad = + 5; /* horizontal padding between the underline and tag */ +static const unsigned int ulinestroke = + 2; /* thickness / height of the underline */ +static const unsigned int ulinevoffset = + 0; /* how far above the bottom of the bar the line should appear */ +static const int ulineall = + 0; /* 1 to show underline on all tags, 0 for just the active ones */ +#endif // BAR_UNDERLINETAGS_PATCH + +#if NAMETAG_PATCH +#if NAMETAG_PREPEND_PATCH +/* The format in which the tag is written when named. E.g. %d: %.12s will write + * the tag number followed the first 12 characters of the given string. You can + * also just use "%d: %s" here. */ +#define NAMETAG_FORMAT "%d: %.12s" +#else +#define NAMETAG_FORMAT "%s" +#endif // NAMETAG_PREPEND_PATCH +/* The maximum amount of bytes reserved for each tag text. */ +#define MAX_TAGLEN 16 +/* The command to run (via popen). This can be tailored by adding a prompt, + * passing other command line arguments or providing name options. Optionally + * you can use other dmenu like alternatives like rofi -dmenu. */ +#define NAMETAG_COMMAND "dmenu < /dev/null" +#endif // NAMETAG_PATCH + +#if ALT_TAB_PATCH +/* alt-tab configuration */ +static const unsigned int tabmodkey = + 0x40; /* (Alt) when this key is held down the alt-tab functionality stays + active. Must be the same modifier as used to run alttabstart */ +static const unsigned int tabcyclekey = + 0x17; /* (Tab) when this key is hit the menu moves one position forward in + client stack. Must be the same key as used to run alttabstart */ +static const unsigned int tabposy = + 1; /* tab position on Y axis, 0 = top, 1 = center, 2 = bottom */ +static const unsigned int tabposx = + 1; /* tab position on X axis, 0 = left, 1 = center, 2 = right */ +static const unsigned int maxwtab = 600; /* tab menu width */ +static const unsigned int maxhtab = 200; /* tab menu height */ +#endif // ALT_TAB_PATCH + +/* Indicators: see patch/bar_indicators.h for options */ +static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE; +static int tiledindicatortype = INDICATOR_NONE; +static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE; +#if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH +static int fakefsindicatortype = INDICATOR_PLUS; +static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE; +#endif // FAKEFULLSCREEN_CLIENT_PATCH +#if ALWAYSONTOP_PATCH +static int aotindicatortype = INDICATOR_TOP_LEFT_LARGER_SQUARE; +#endif // ALWAYSONTOP_PATCH +#if ONLYQUITONEMPTY_PATCH +static const int quit_empty_window_count = + 0; /* only allow dwm to quit if no (<= count) windows are open */ +#endif // ONLYQUITONEMPTY_PATCH +#if BAR_EXTRASTATUS_PATCH +static const char statussep = ';'; /* separator between status bars */ +#endif // BAR_EXTRASTATUS_PATCH +#if BAR_TABGROUPS_PATCH +#if MONOCLE_LAYOUT +static void (*bartabmonfns[])(Monitor *) = {monocle /* , customlayoutfn */}; +#else +static void (*bartabmonfns[])(Monitor *) = {NULL /* , customlayoutfn */}; +#endif // MONOCLE_LAYOUT +#endif // BAR_TABGROUPS_PATCH +#if BAR_PANGO_PATCH +static const char font[] = "monospace 10"; +#else +static const char *fonts[] = {"monospace:size=10"}; +#endif // BAR_PANGO_PATCH +static const char dmenufont[] = "monospace:size=10"; + +static char c000000[] = "#000000"; // placeholder value + +static char normfgcolor[] = "#bbbbbb"; +static char normbgcolor[] = "#222222"; +static char normbordercolor[] = "#444444"; +static char normfloatcolor[] = "#db8fd9"; + +static char selfgcolor[] = "#eeeeee"; +static char selbgcolor[] = "#005577"; +static char selbordercolor[] = "#005577"; +static char selfloatcolor[] = "#005577"; + +static char titlenormfgcolor[] = "#bbbbbb"; +static char titlenormbgcolor[] = "#222222"; +static char titlenormbordercolor[] = "#444444"; +static char titlenormfloatcolor[] = "#db8fd9"; + +static char titleselfgcolor[] = "#eeeeee"; +static char titleselbgcolor[] = "#005577"; +static char titleselbordercolor[] = "#005577"; +static char titleselfloatcolor[] = "#005577"; + +static char tagsnormfgcolor[] = "#bbbbbb"; +static char tagsnormbgcolor[] = "#222222"; +static char tagsnormbordercolor[] = "#444444"; +static char tagsnormfloatcolor[] = "#db8fd9"; + +static char tagsselfgcolor[] = "#eeeeee"; +static char tagsselbgcolor[] = "#005577"; +static char tagsselbordercolor[] = "#005577"; +static char tagsselfloatcolor[] = "#005577"; + +static char hidnormfgcolor[] = "#005577"; +static char hidselfgcolor[] = "#227799"; +static char hidnormbgcolor[] = "#222222"; +static char hidselbgcolor[] = "#222222"; + +static char urgfgcolor[] = "#bbbbbb"; +static char urgbgcolor[] = "#222222"; +static char urgbordercolor[] = "#ff0000"; +static char urgfloatcolor[] = "#db8fd9"; + +#if BAR_LTSYMBOL_SCHEME_PATCH +static char ltsymbolfgcolor[] = "#222222"; +static char ltsymbolbgcolor[] = "#fe9877"; +#endif // BAR_LTSYMBOL_SCHEME_PATCH + +#if RENAMED_SCRATCHPADS_PATCH +static char scratchselfgcolor[] = "#FFF7D4"; +static char scratchselbgcolor[] = "#77547E"; +static char scratchselbordercolor[] = "#894B9F"; +static char scratchselfloatcolor[] = "#894B9F"; + +static char scratchnormfgcolor[] = "#FFF7D4"; +static char scratchnormbgcolor[] = "#664C67"; +static char scratchnormbordercolor[] = "#77547E"; +static char scratchnormfloatcolor[] = "#77547E"; +#endif // RENAMED_SCRATCHPADS_PATCH + +#if BAR_FLEXWINTITLE_PATCH +static char normTTBbgcolor[] = "#330000"; +static char normLTRbgcolor[] = "#330033"; +static char normMONObgcolor[] = "#000033"; +static char normGRIDbgcolor[] = "#003300"; +static char normGRD1bgcolor[] = "#003300"; +static char normGRD2bgcolor[] = "#003300"; +static char normGRDMbgcolor[] = "#506600"; +static char normHGRDbgcolor[] = "#b96600"; +static char normDWDLbgcolor[] = "#003333"; +static char normSPRLbgcolor[] = "#333300"; +static char normfloatbgcolor[] = "#115577"; +static char actTTBbgcolor[] = "#440000"; +static char actLTRbgcolor[] = "#440044"; +static char actMONObgcolor[] = "#000044"; +static char actGRIDbgcolor[] = "#004400"; +static char actGRD1bgcolor[] = "#004400"; +static char actGRD2bgcolor[] = "#004400"; +static char actGRDMbgcolor[] = "#507711"; +static char actHGRDbgcolor[] = "#b97711"; +static char actDWDLbgcolor[] = "#004444"; +static char actSPRLbgcolor[] = "#444400"; +static char actfloatbgcolor[] = "#116688"; +static char selTTBbgcolor[] = "#550000"; +static char selLTRbgcolor[] = "#550055"; +static char selMONObgcolor[] = "#212171"; +static char selGRIDbgcolor[] = "#005500"; +static char selGRD1bgcolor[] = "#005500"; +static char selGRD2bgcolor[] = "#005500"; +static char selGRDMbgcolor[] = "#508822"; +static char selHGRDbgcolor[] = "#b98822"; +static char selDWDLbgcolor[] = "#005555"; +static char selSPRLbgcolor[] = "#555500"; +static char selfloatbgcolor[] = "#117799"; +#endif // BAR_FLEXWINTITLE_PATCH + +#if BAR_ALPHA_PATCH +static const unsigned int baralpha = 0xd0; +static const unsigned int borderalpha = OPAQUE; +static const unsigned int alphas[][3] = { + /* fg bg border */ + [SchemeNorm] = {OPAQUE, baralpha, borderalpha}, + [SchemeSel] = {OPAQUE, baralpha, borderalpha}, + [SchemeTitleNorm] = {OPAQUE, baralpha, borderalpha}, + [SchemeTitleSel] = {OPAQUE, baralpha, borderalpha}, + [SchemeTagsNorm] = {OPAQUE, baralpha, borderalpha}, + [SchemeTagsSel] = {OPAQUE, baralpha, borderalpha}, + [SchemeHidNorm] = {OPAQUE, baralpha, borderalpha}, + [SchemeHidSel] = {OPAQUE, baralpha, borderalpha}, + [SchemeUrg] = {OPAQUE, baralpha, borderalpha}, +#if BAR_LTSYMBOL_SCHEME_PATCH + [SchemeLtSymbol] = {OPAQUE, baralpha, borderalpha}, +#endif // BAR_LTSYMBOL_SCHEME_PATCH +#if RENAMED_SCRATCHPADS_PATCH + [SchemeScratchSel] = {OPAQUE, baralpha, borderalpha}, + [SchemeScratchNorm] = {OPAQUE, baralpha, borderalpha}, +#endif // RENAMED_SCRATCHPADS_PATCH +#if BAR_FLEXWINTITLE_PATCH + [SchemeFlexActTTB] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActLTR] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActMONO] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActGRID] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActGRD1] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActGRD2] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActGRDM] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActHGRD] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActDWDL] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActSPRL] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexActFloat] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaTTB] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaLTR] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaMONO] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaGRID] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaGRD1] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaGRD2] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaGRDM] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaHGRD] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaDWDL] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaSPRL] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexInaFloat] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelTTB] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelLTR] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelMONO] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelGRID] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelGRD1] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelGRD2] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelGRDM] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelHGRD] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelDWDL] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelSPRL] = {OPAQUE, baralpha, borderalpha}, + [SchemeFlexSelFloat] = {OPAQUE, baralpha, borderalpha}, +#endif // BAR_FLEXWINTITLE_PATCH +}; +#endif // BAR_ALPHA_PATCH +#if BAR_VTCOLORS_PATCH +static const char title_bg_dark[] = "#303030"; +static const char title_bg_light[] = "#fdfdfd"; +static const int color_ptrs[][ColCount] = { + /* fg bg border float */ + [SchemeNorm] = {-1, -1, 5, 12}, [SchemeSel] = {-1, -1, 11, 13}, + [SchemeTitleNorm] = {6, -1, -1, -1}, [SchemeTitleSel] = {6, -1, -1, -1}, + [SchemeTagsNorm] = {2, 0, 0, -1}, [SchemeTagsSel] = {6, 5, 5, -1}, + [SchemeHidNorm] = {5, 0, 0, -1}, [SchemeHidSel] = {6, -1, -1, -1}, + [SchemeUrg] = {7, 9, 9, 15}, +#if BAR_LTSYMBOL_SCHEME_PATCH + [SchemeLtSymbol] = {-1, 3, 0, 0}, +#endif // BAR_LTSYMBOL_SCHEME_PATCH +}; +#endif // BAR_VTCOLORS_PATCH + +static char *colors[][ColCount] = { + /* fg bg border float */ + [SchemeNorm] = {normfgcolor, normbgcolor, normbordercolor, normfloatcolor}, + [SchemeSel] = {selfgcolor, selbgcolor, selbordercolor, selfloatcolor}, + [SchemeTitleNorm] = {titlenormfgcolor, titlenormbgcolor, + titlenormbordercolor, titlenormfloatcolor}, + [SchemeTitleSel] = {titleselfgcolor, titleselbgcolor, titleselbordercolor, + titleselfloatcolor}, + [SchemeTagsNorm] = {tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, + tagsnormfloatcolor}, + [SchemeTagsSel] = {tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, + tagsselfloatcolor}, + [SchemeHidNorm] = {hidnormfgcolor, hidnormbgcolor, c000000, c000000}, + [SchemeHidSel] = {hidselfgcolor, hidselbgcolor, c000000, c000000}, + [SchemeUrg] = {urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor}, +#if BAR_LTSYMBOL_SCHEME_PATCH + [SchemeLtSymbol] = {ltsymbolfgcolor, ltsymbolbgcolor, c000000, c000000}, +#endif // BAR_LTSYMBOL_SCHEME_PATCH +#if RENAMED_SCRATCHPADS_PATCH + [SchemeScratchSel] = {scratchselfgcolor, scratchselbgcolor, + scratchselbordercolor, scratchselfloatcolor}, + [SchemeScratchNorm] = {scratchnormfgcolor, scratchnormbgcolor, + scratchnormbordercolor, scratchnormfloatcolor}, +#endif // RENAMED_SCRATCHPADS_PATCH +#if BAR_FLEXWINTITLE_PATCH + [SchemeFlexActTTB] = {titleselfgcolor, actTTBbgcolor, actTTBbgcolor, + c000000}, + [SchemeFlexActLTR] = {titleselfgcolor, actLTRbgcolor, actLTRbgcolor, + c000000}, + [SchemeFlexActMONO] = {titleselfgcolor, actMONObgcolor, actMONObgcolor, + c000000}, + [SchemeFlexActGRID] = {titleselfgcolor, actGRIDbgcolor, actGRIDbgcolor, + c000000}, + [SchemeFlexActGRD1] = {titleselfgcolor, actGRD1bgcolor, actGRD1bgcolor, + c000000}, + [SchemeFlexActGRD2] = {titleselfgcolor, actGRD2bgcolor, actGRD2bgcolor, + c000000}, + [SchemeFlexActGRDM] = {titleselfgcolor, actGRDMbgcolor, actGRDMbgcolor, + c000000}, + [SchemeFlexActHGRD] = {titleselfgcolor, actHGRDbgcolor, actHGRDbgcolor, + c000000}, + [SchemeFlexActDWDL] = {titleselfgcolor, actDWDLbgcolor, actDWDLbgcolor, + c000000}, + [SchemeFlexActSPRL] = {titleselfgcolor, actSPRLbgcolor, actSPRLbgcolor, + c000000}, + [SchemeFlexActFloat] = {titleselfgcolor, actfloatbgcolor, actfloatbgcolor, + c000000}, + [SchemeFlexInaTTB] = {titlenormfgcolor, normTTBbgcolor, normTTBbgcolor, + c000000}, + [SchemeFlexInaLTR] = {titlenormfgcolor, normLTRbgcolor, normLTRbgcolor, + c000000}, + [SchemeFlexInaMONO] = {titlenormfgcolor, normMONObgcolor, normMONObgcolor, + c000000}, + [SchemeFlexInaGRID] = {titlenormfgcolor, normGRIDbgcolor, normGRIDbgcolor, + c000000}, + [SchemeFlexInaGRD1] = {titlenormfgcolor, normGRD1bgcolor, normGRD1bgcolor, + c000000}, + [SchemeFlexInaGRD2] = {titlenormfgcolor, normGRD2bgcolor, normGRD2bgcolor, + c000000}, + [SchemeFlexInaGRDM] = {titlenormfgcolor, normGRDMbgcolor, normGRDMbgcolor, + c000000}, + [SchemeFlexInaHGRD] = {titlenormfgcolor, normHGRDbgcolor, normHGRDbgcolor, + c000000}, + [SchemeFlexInaDWDL] = {titlenormfgcolor, normDWDLbgcolor, normDWDLbgcolor, + c000000}, + [SchemeFlexInaSPRL] = {titlenormfgcolor, normSPRLbgcolor, normSPRLbgcolor, + c000000}, + [SchemeFlexInaFloat] = {titlenormfgcolor, normfloatbgcolor, + normfloatbgcolor, c000000}, + [SchemeFlexSelTTB] = {titleselfgcolor, selTTBbgcolor, selTTBbgcolor, + c000000}, + [SchemeFlexSelLTR] = {titleselfgcolor, selLTRbgcolor, selLTRbgcolor, + c000000}, + [SchemeFlexSelMONO] = {titleselfgcolor, selMONObgcolor, selMONObgcolor, + c000000}, + [SchemeFlexSelGRID] = {titleselfgcolor, selGRIDbgcolor, selGRIDbgcolor, + c000000}, + [SchemeFlexSelGRD1] = {titleselfgcolor, selGRD1bgcolor, selGRD1bgcolor, + c000000}, + [SchemeFlexSelGRD2] = {titleselfgcolor, selGRD2bgcolor, selGRD2bgcolor, + c000000}, + [SchemeFlexSelGRDM] = {titleselfgcolor, selGRDMbgcolor, selGRDMbgcolor, + c000000}, + [SchemeFlexSelHGRD] = {titleselfgcolor, selHGRDbgcolor, selHGRDbgcolor, + c000000}, + [SchemeFlexSelDWDL] = {titleselfgcolor, selDWDLbgcolor, selDWDLbgcolor, + c000000}, + [SchemeFlexSelSPRL] = {titleselfgcolor, selSPRLbgcolor, selSPRLbgcolor, + c000000}, + [SchemeFlexSelFloat] = {titleselfgcolor, selfloatbgcolor, selfloatbgcolor, + c000000}, +#endif // BAR_FLEXWINTITLE_PATCH +}; + +#if BAR_POWERLINE_STATUS_PATCH +static char *statuscolors[][ColCount] = { + /* fg bg border float */ + [SchemeNorm] = {normfgcolor, normbgcolor, normbordercolor, normfloatcolor}, + [SchemeSel] = {selfgcolor, selbgcolor, selbordercolor, selfloatcolor}, + [SchemeTitleNorm] = {titlenormfgcolor, titlenormbgcolor, + titlenormbordercolor, titlenormfloatcolor}, + [SchemeTitleSel] = {titleselfgcolor, titleselbgcolor, titleselbordercolor, + titleselfloatcolor}, + [SchemeTagsNorm] = {tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, + tagsnormfloatcolor}, + [SchemeTagsSel] = {tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, + tagsselfloatcolor}, + [SchemeHidNorm] = {hidnormfgcolor, hidnormbgcolor, c000000, c000000}, + [SchemeHidSel] = {hidselfgcolor, hidselbgcolor, c000000, c000000}, + [SchemeUrg] = {urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor}, +}; +#endif // BAR_POWERLINE_STATUS_PATCH + +#if BAR_LAYOUTMENU_PATCH +static const char *layoutmenu_cmd = "layoutmenu.sh"; +#endif + +#if BAR_LAUNCHER_PATCH +static const Launcher launchers[] = { + /* icon to display command */ + {"surf", CMD("surf", "duckduckgo.com")}, +}; +#endif // BAR_LAUNCHER_PATCH + +#if COOL_AUTOSTART_PATCH +static const char *const autostart[] = { + "st", NULL, NULL /* terminate */ +}; +#endif // COOL_AUTOSTART_PATCH + +#if RENAMED_SCRATCHPADS_PATCH +static const char *scratchpadcmd[] = {"s", "st", "-n", "spterm", NULL}; +#elif SCRATCHPADS_PATCH +const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x34", NULL}; +static Sp scratchpads[] = { + /* name cmd */ + {"spterm", spcmd1}, +}; +#endif // SCRATCHPADS_PATCH + +/* Tags + * In a traditional dwm the number of tags in use can be changed simply by + * changing the number of strings in the tags array. This build does things a + * bit different which has some added benefits. If you need to change the number + * of tags here then change the NUMTAGS macro in dwm.c. + * + * Examples: + * + * 1) static char *tagicons[][NUMTAGS*2] = { + * [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", + * "B", "C", "D", "E", "F", "G", "H", "I" }, + * } + * + * 2) static char *tagicons[][1] = { + * [DEFAULT_TAGS] = { "•" }, + * } + * + * The first example would result in the tags on the first monitor to be 1 + * through 9, while the tags for the second monitor would be named A through I. + * A third monitor would start again at 1 through 9 while the tags on a fourth + * monitor would also be named A through I. Note the tags count of NUMTAGS*2 in + * the array initialiser which defines how many tag text / icon exists in the + * array. This can be changed to *3 to add separate icons for a third monitor. + * + * For the second example each tag would be represented as a bullet point. Both + * cases work the same from a technical standpoint - the icon index is derived + * from the tag index and the monitor index. If the icon index is is greater + * than the number of tag icons then it will wrap around until it an icon + * matches. Similarly if there are two tag icons then it would alternate between + * them. This works seamlessly with alternative tags and alttagsdecoration + * patches. + */ +#if NAMETAG_PATCH +static char tagicons[][NUMTAGS][MAX_TAGLEN] = +#else +static char *tagicons[][NUMTAGS] = +#endif // NAMETAG_PATCH + { + [DEFAULT_TAGS] = {"1", "2", "3", "4", "5", "6", "7", "8", "9"}, + [ALTERNATIVE_TAGS] = {"A", "B", "C", "D", "E", "F", "G", "H", "I"}, + [ALT_TAGS_DECORATION] = {"<1>", "<2>", "<3>", "<4>", "<5>", "<6>", + "<7>", "<8>", "<9>"}, + }; + +#if BAR_TAGGRID_PATCH +/* grid of tags */ +#define SWITCHTAG_UP 1 << 0 +#define SWITCHTAG_DOWN 1 << 1 +#define SWITCHTAG_LEFT 1 << 2 +#define SWITCHTAG_RIGHT 1 << 3 +#define SWITCHTAG_TOGGLETAG 1 << 4 +#define SWITCHTAG_TAG 1 << 5 +#define SWITCHTAG_VIEW 1 << 6 +#define SWITCHTAG_TOGGLEVIEW 1 << 7 + +static const int tagrows = 2; +#endif // BAR_TAGGRID_PATCH + +/* There are two options when it comes to per-client rules: + * - a typical struct table or + * - using the RULE macro + * + * A traditional struct table looks like this: + * // class instance title wintype tags mask isfloating monitor + * { "Gimp", NULL, NULL, NULL, 1 << 4, 0, -1 }, + * { "Firefox", NULL, NULL, NULL, 1 << 7, 0, -1 }, + * + * The RULE macro has the default values set for each field allowing you to only + * specify the values that are relevant for your rule, e.g. + * + * RULE(.class = "Gimp", .tags = 1 << 4) + * RULE(.class = "Firefox", .tags = 1 << 7) + * + * Refer to the Rule struct definition for the list of available fields + * depending on the patches you enable. + */ +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + * WM_WINDOW_ROLE(STRING) = role + * _NET_WM_WINDOW_TYPE(ATOM) = wintype + */ + RULE(.wintype = WTYPE "DIALOG", .isfloating = 1) + RULE(.wintype = WTYPE "UTILITY", .isfloating = 1) + RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1) + RULE(.wintype = WTYPE "SPLASH", .isfloating = 1) + RULE(.class = "Gimp", .tags = 1 << 4) + RULE(.class = "Firefox", .tags = 1 << 7) +#if RENAMED_SCRATCHPADS_PATCH + RULE(.instance = "spterm", .scratchkey = 's', + .isfloating = 1) +#elif SCRATCHPADS_PATCH + RULE(.instance = "spterm", .tags = SPTAG(0), + .isfloating = 1) +#endif // SCRATCHPADS_PATCH +}; + +#if MONITOR_RULES_PATCH +#if PERTAG_PATCH +static const MonitorRule monrules[] = { + /* monitor tag layout mfact nmaster showbar topbar */ + {1, -1, 2, -1, -1, -1, -1}, // use a different layout for the second monitor + {-1, -1, 0, -1, -1, -1, -1}, // default +}; +#else +static const MonitorRule monrules[] = { + /* monitor layout mfact nmaster showbar topbar */ + {1, 2, -1, -1, -1, -1}, // use a different layout for the second monitor + {-1, 0, -1, -1, -1, -1}, // default +}; +#endif // PERTAG_PATCH +#endif // MONITOR_RULES_PATCH + +#if INSETS_PATCH +static const Inset default_inset = { + .x = 0, + .y = 30, + .w = 0, + .h = 0, +}; +#endif // INSETS_PATCH + +/* Bar rules allow you to configure what is shown where on the bar, as well as + * introducing your own bar modules. + * + * monitor: + * -1 show on all monitors + * 0 show on monitor 0 + * 'A' show on active monitor (i.e. focused / selected) (or just -1 for + * active?) bar - bar index, 0 is default, 1 is extrabar alignment - how the + * module is aligned compared to other modules widthfunc, drawfunc, clickfunc - + * providing bar module width, draw and click functions name - does nothing, + * intended for visual clue and for logging / debugging + */ +static const BarRule barrules[] = { +/* monitor bar alignment widthfunc drawfunc + * clickfunc hoverfunc name */ +#if BAR_STATUSBUTTON_PATCH + {-1, 0, BAR_ALIGN_LEFT, width_stbutton, draw_stbutton, click_stbutton, NULL, + "statusbutton"}, +#endif // BAR_STATUSBUTTON_PATCH +#if BAR_LAUNCHER_PATCH + {-1, 0, BAR_ALIGN_LEFT, width_launcher, draw_launcher, click_launcher, NULL, + "launcher"}, +#endif // BAR_LAUNCHER_PATCH +#if BAR_POWERLINE_TAGS_PATCH + {0, 0, BAR_ALIGN_LEFT, width_pwrl_tags, draw_pwrl_tags, click_pwrl_tags, + hover_pwrl_tags, "powerline_tags"}, +#endif // BAR_POWERLINE_TAGS_PATCH +#if BAR_TAGS_PATCH + {-1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, + "tags"}, +#endif // BAR_TAGS_PATCH +#if BAR_TAGLABELS_PATCH + {-1, 0, BAR_ALIGN_LEFT, width_taglabels, draw_taglabels, click_taglabels, + hover_taglabels, "taglabels"}, +#endif // BAR_TAGLABELS_PATCH +#if BAR_TAGGRID_PATCH + {-1, 0, BAR_ALIGN_LEFT, width_taggrid, draw_taggrid, click_taggrid, NULL, + "taggrid"}, +#endif // BAR_TAGGRID_PATCH +#if BAR_SYSTRAY_PATCH + {0, 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, NULL, + "systray"}, +#endif // BAR_SYSTRAY_PATCH +#if BAR_LTSYMBOL_PATCH + {-1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, + "layout"}, +#endif // BAR_LTSYMBOL_PATCH +#if BAR_STATUSCOLORS_PATCH && BAR_STATUSCMD_PATCH + {statusmon, 0, BAR_ALIGN_RIGHT, width_statuscolors, draw_statuscolors, + click_statuscmd, NULL, "statuscolors"}, +#elif BAR_STATUSCOLORS_PATCH + {statusmon, 0, BAR_ALIGN_RIGHT, width_statuscolors, draw_statuscolors, + click_statuscolors, NULL, "statuscolors"}, +#elif BAR_STATUS2D_PATCH && BAR_STATUSCMD_PATCH + {statusmon, 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, + click_statuscmd, NULL, "status2d"}, +#elif BAR_STATUS2D_PATCH + {statusmon, 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, + click_status2d, NULL, "status2d"}, +#elif BAR_POWERLINE_STATUS_PATCH + {statusmon, 0, BAR_ALIGN_RIGHT, width_pwrl_status, draw_pwrl_status, + click_pwrl_status, NULL, "powerline_status"}, +#elif BAR_STATUS_PATCH && BAR_STATUSCMD_PATCH + {statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_statuscmd, + NULL, "status"}, +#elif BAR_STATUS_PATCH + {statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, + NULL, "status"}, +#endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH +#if XKB_PATCH + {0, 0, BAR_ALIGN_RIGHT, width_xkb, draw_xkb, click_xkb, NULL, "xkb"}, +#endif // XKB_PATCH +#if BAR_FLEXWINTITLE_PATCH + {-1, 0, BAR_ALIGN_NONE, width_flexwintitle, draw_flexwintitle, + click_flexwintitle, NULL, "flexwintitle"}, +#elif BAR_TABGROUPS_PATCH + {-1, 0, BAR_ALIGN_NONE, width_bartabgroups, draw_bartabgroups, + click_bartabgroups, NULL, "bartabgroups"}, +#elif BAR_AWESOMEBAR_PATCH + {-1, 0, BAR_ALIGN_NONE, width_awesomebar, draw_awesomebar, click_awesomebar, + NULL, "awesomebar"}, +#elif BAR_FANCYBAR_PATCH + {-1, 0, BAR_ALIGN_NONE, width_fancybar, draw_fancybar, click_fancybar, NULL, + "fancybar"}, +#elif BAR_WINTITLE_PATCH + {-1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, + "wintitle"}, +#endif // BAR_TABGROUPS_PATCH | BAR_AWESOMEBAR_PATCH | BAR_FANCYBAR_PATCH | + // BAR_WINTITLE_PATCH +#if BAR_EXTRASTATUS_PATCH +#if BAR_STATUSCOLORS_PATCH && BAR_STATUSCMD_PATCH + {statusmon, 1, BAR_ALIGN_CENTER, width_statuscolors_es, + draw_statuscolors_es, click_statuscmd_es, NULL, "statuscolors_es"}, +#elif BAR_STATUSCOLORS_PATCH + {statusmon, 1, BAR_ALIGN_CENTER, width_statuscolors_es, + draw_statuscolors_es, click_statuscolors, NULL, "statuscolors_es"}, +#elif BAR_STATUS2D_PATCH && BAR_STATUSCMD_PATCH + {statusmon, 1, BAR_ALIGN_CENTER, width_status2d_es, draw_status2d_es, + click_statuscmd_es, NULL, "status2d_es"}, +#elif BAR_STATUS2D_PATCH + {statusmon, 1, BAR_ALIGN_CENTER, width_status2d_es, draw_status2d_es, + click_status2d, NULL, "status2d_es"}, +#elif BAR_POWERLINE_STATUS_PATCH + {statusmon, 1, BAR_ALIGN_RIGHT, width_pwrl_status_es, draw_pwrl_status_es, + click_pwrl_status, NULL, "powerline_status"}, +#elif BAR_STATUSCMD_PATCH && BAR_STATUS_PATCH + {statusmon, 1, BAR_ALIGN_CENTER, width_status_es, draw_status_es, + click_statuscmd_es, NULL, "status_es"}, +#elif BAR_STATUS_PATCH + {statusmon, 1, BAR_ALIGN_CENTER, width_status_es, draw_status_es, + click_status, NULL, "status_es"}, +#endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH +#endif // BAR_EXTRASTATUS_PATCH +#if BAR_FLEXWINTITLE_PATCH +#if BAR_WINTITLE_HIDDEN_PATCH + {-1, 1, BAR_ALIGN_RIGHT_RIGHT, width_wintitle_hidden, draw_wintitle_hidden, + click_wintitle_hidden, NULL, "wintitle_hidden"}, +#endif +#if BAR_WINTITLE_FLOATING_PATCH + {-1, 1, BAR_ALIGN_LEFT, width_wintitle_floating, draw_wintitle_floating, + click_wintitle_floating, NULL, "wintitle_floating"}, +#endif // BAR_WINTITLE_FLOATING_PATCH +#endif // BAR_FLEXWINTITLE_PATCH +}; + +/* 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 */ +#if FLEXTILE_DELUXE_LAYOUT +static const int nstack = 0; /* number of clients in primary stack area */ +#endif // FLEXTILE_DELUXE_LAYOUT +static const int resizehints = + 0; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = + 1; /* 1 will force focus on the fullscreen window */ +static const int refreshrate = + 120; /* refresh rate (per second) for client move/resize */ +#if PLACEMOUSE_PATCH +static const int refreshrate_placemouse = + 60; /* refresh rate (per second) for placemouse */ +#endif // PLACEMOUSE_PATCH +#if DRAGMFACT_PATCH +static const int refreshrate_dragmfact = + 40; /* refresh rate (per second) for dragmfact */ +#endif // DRAGMFACT_PATCH +#if DRAGCFACT_PATCH +static const int refreshrate_dragcfact = + 60; /* refresh rate (per second) for dragcfact */ +#endif // DRAGCFACT_PATCH +#if DECORATION_HINTS_PATCH +static const int decorhints = 1; /* 1 means respect decoration hints */ +#endif // DECORATION_HINTS_PATCH + +#if NROWGRID_LAYOUT +#define FORCE_VSPLIT 1 +#endif + +#if TAPRESIZE_PATCH +/* mouse scroll resize */ +static const int scrollsensetivity = + 30; /* 1 means resize window by 1 pixel for each scroll event */ +/* resizemousescroll direction argument list */ +static const int scrollargs[][2] = { + /* width change height change */ + {+scrollsensetivity, 0}, + {-scrollsensetivity, 0}, + {0, +scrollsensetivity}, + {0, -scrollsensetivity}, +}; +#endif // TAPRESIZE_PATCH + +#if FLEXTILE_DELUXE_LAYOUT +static const Layout layouts[] = { + /* symbol arrange function, { nmaster, nstack, layout, master axis, + stack axis, secondary stack axis, symbol func } */ + {"[]=", + flextile, + {-1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, TOP_TO_BOTTOM, 0, + NULL}}, // default tile layout + {"><>", NULL, {0}}, /* no layout function means floating behavior */ + {"[M]", flextile, {-1, -1, NO_SPLIT, MONOCLE, MONOCLE, 0, NULL}}, // monocle + {"|||", + flextile, + {-1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, + NULL}}, // columns (col) layout + {">M>", + flextile, + {-1, -1, FLOATING_MASTER, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, + NULL}}, // floating master + {"[D]", + flextile, + {-1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, MONOCLE, 0, NULL}}, // deck + {"TTT", + flextile, + {-1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, + NULL}}, // bstack + {"===", + flextile, + {-1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, + NULL}}, // bstackhoriz + {"|M|", + flextile, + {-1, -1, SPLIT_CENTERED_VERTICAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, + TOP_TO_BOTTOM, NULL}}, // centeredmaster + {"-M-", + flextile, + {-1, -1, SPLIT_CENTERED_HORIZONTAL, TOP_TO_BOTTOM, LEFT_TO_RIGHT, + LEFT_TO_RIGHT, NULL}}, // centeredmaster horiz + {":::", + flextile, + {-1, -1, NO_SPLIT, GAPPLESSGRID, GAPPLESSGRID, 0, NULL}}, // gappless grid + {"[\\]", + flextile, + {-1, -1, NO_SPLIT, DWINDLE, DWINDLE, 0, NULL}}, // fibonacci dwindle + {"(@)", + flextile, + {-1, -1, NO_SPLIT, SPIRAL, SPIRAL, 0, NULL}}, // fibonacci spiral + {"[T]", + flextile, + {-1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TATAMI, 0, NULL}}, // tatami mats +#if TILE_LAYOUT + {"[]=", tile, {0}}, +#endif +#if MONOCLE_LAYOUT + {"[M]", monocle, {0}}, +#endif +#if BSTACK_LAYOUT + {"TTT", bstack, {0}}, +#endif +#if BSTACKHORIZ_LAYOUT + {"===", bstackhoriz, {0}}, +#endif +#if CENTEREDMASTER_LAYOUT + {"|M|", centeredmaster, {0}}, +#endif +#if CENTEREDFLOATINGMASTER_LAYOUT + {">M>", centeredfloatingmaster, {0}}, +#endif +#if COLUMNS_LAYOUT + {"|||", col, {0}}, +#endif +#if DECK_LAYOUT + {"[D]", deck, {0}}, +#endif +#if FIBONACCI_SPIRAL_LAYOUT + {"(@)", spiral, {0}}, +#endif +#if FIBONACCI_DWINDLE_LAYOUT + {"[\\]", dwindle, {0}}, +#endif +#if GRIDMODE_LAYOUT + {"HHH", grid, {0}}, +#endif +#if HORIZGRID_LAYOUT + {"---", horizgrid, {0}}, +#endif +#if GAPPLESSGRID_LAYOUT + {":::", gaplessgrid, {0}}, +#endif +#if NROWGRID_LAYOUT + {"###", nrowgrid, {0}}, +#endif +}; +#else +static const Layout layouts[] = { +/* symbol arrange function */ +#if TILE_LAYOUT + {"[]=", tile}, /* first entry is default */ +#endif + {"><>", NULL}, /* no layout function means floating behavior */ +#if MONOCLE_LAYOUT + {"[M]", monocle}, +#endif +#if BSTACK_LAYOUT + {"TTT", bstack}, +#endif +#if BSTACKHORIZ_LAYOUT + {"===", bstackhoriz}, +#endif +#if CENTEREDMASTER_LAYOUT + {"|M|", centeredmaster}, +#endif +#if CENTEREDFLOATINGMASTER_LAYOUT + {">M>", centeredfloatingmaster}, +#endif +#if COLUMNS_LAYOUT + {"|||", col}, +#endif +#if DECK_LAYOUT + {"[D]", deck}, +#endif +#if FIBONACCI_SPIRAL_LAYOUT + {"(@)", spiral}, +#endif +#if FIBONACCI_DWINDLE_LAYOUT + {"[\\]", dwindle}, +#endif +#if GRIDMODE_LAYOUT + {"HHH", grid}, +#endif +#if HORIZGRID_LAYOUT + {"---", horizgrid}, +#endif +#if GAPPLESSGRID_LAYOUT + {":::", gaplessgrid}, +#endif +#if NROWGRID_LAYOUT + {"###", nrowgrid}, +#endif +}; +#endif // FLEXTILE_DELUXE_LAYOUT + +#if XKB_PATCH +/* xkb frontend */ +static const char *xkb_layouts[] = { + "en", + "ru", +}; +#endif // XKB_PATCH + +/* key definitions */ +#define MODKEY Mod1Mask +#if COMBO_PATCH && SWAPTAGS_PATCH && TAGOTHERMONITOR_PATCH +#define TAGKEYS(KEY, TAG) \ + {MODKEY, KEY, comboview, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \ + {MODKEY | ShiftMask, KEY, combotag, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask | ShiftMask, KEY, swaptags, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask | ControlMask, KEY, tagprevmon, {.ui = 1 << TAG}}, +#elif COMBO_PATCH && SWAPTAGS_PATCH +#define TAGKEYS(KEY, TAG) \ + {MODKEY, KEY, comboview, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \ + {MODKEY | ShiftMask, KEY, combotag, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask | ShiftMask, KEY, swaptags, {.ui = 1 << TAG}}, +#elif COMBO_PATCH && TAGOTHERMONITOR_PATCH +#define TAGKEYS(KEY, TAG) \ + {MODKEY, KEY, comboview, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \ + {MODKEY | ShiftMask, KEY, combotag, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask | ControlMask, KEY, tagprevmon, {.ui = 1 << TAG}}, +#elif COMBO_PATCH +#define TAGKEYS(KEY, TAG) \ + {MODKEY, KEY, comboview, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \ + {MODKEY | ShiftMask, KEY, combotag, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, +#elif SWAPTAGS_PATCH && TAGOTHERMONITOR_PATCH +#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}}, \ + {MODKEY | Mod4Mask | ShiftMask, KEY, swaptags, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask | ControlMask, KEY, tagprevmon, {.ui = 1 << TAG}}, +#elif SWAPTAGS_PATCH +#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}}, \ + {MODKEY | Mod4Mask | ShiftMask, KEY, swaptags, {.ui = 1 << TAG}}, +#elif TAGOTHERMONITOR_PATCH +#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}}, \ + {MODKEY | Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG}}, \ + {MODKEY | Mod4Mask | ControlMask, KEY, tagprevmon, {.ui = 1 << TAG}}, +#else +#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}}, +#endif // COMBO_PATCH / SWAPTAGS_PATCH / TAGOTHERMONITOR_PATCH + +#if STACKER_PATCH +#define STACKKEYS(MOD, ACTION) \ + {MOD, XK_j, ACTION##stack, {.i = INC(+1)}}, \ + {MOD, XK_k, ACTION##stack, {.i = INC(-1)}}, \ + {MOD, XK_s, ACTION##stack, {.i = PREVSEL}}, \ + {MOD, XK_w, ACTION##stack, {.i = 0}}, \ + {MOD, XK_e, ACTION##stack, {.i = 1}}, \ + {MOD, XK_a, ACTION##stack, {.i = 2}}, \ + {MOD, XK_z, ACTION##stack, {.i = -1}}, +#endif // STACKER_PATCH + +#if BAR_HOLDBAR_PATCH +#define HOLDKEY 0 // replace 0 with the keysym to activate holdbar +#endif // BAR_HOLDBAR_PATCH + +/* commands */ +#if !NODMENU_PATCH +static char dmenumon[2] = + "0"; /* component of dmenucmd, manipulated in spawn() */ +#endif // NODMENU_PATCH +static const char *dmenucmd[] = {"dmenu_run", +#if !NODMENU_PATCH + "-m", + dmenumon, +#endif // NODMENU_PATCH + "-fn", + dmenufont, + "-nb", + normbgcolor, + "-nf", + normfgcolor, + "-sb", + selbgcolor, + "-sf", + selfgcolor, +#if BAR_DMENUMATCHTOP_PATCH + topbar ? NULL : "-b", +#endif // BAR_DMENUMATCHTOP_PATCH + NULL}; +static const char *termcmd[] = {"st", NULL}; + +#if BAR_STATUSCMD_PATCH +#if BAR_DWMBLOCKS_PATCH +/* This defines the name of the executable that handles the bar (used for + * signalling purposes) */ +#define STATUSBAR "dwmblocks" +#else +/* commands spawned when clicking statusbar, the mouse button pressed is + * exported as BUTTON */ +static const StatusCmd statuscmds[] = { + {"notify-send Volume$BUTTON", 1}, + {"notify-send CPU$BUTTON", 2}, + {"notify-send Battery$BUTTON", 3}, +}; +/* test the above with: xsetroot -name "$(printf '\x01Volume |\x02 CPU |\x03 + * Battery')" */ +static const char *statuscmd[] = {"/bin/sh", "-c", NULL, NULL}; +#endif // BAR_DWMBLOCKS_PATCH +#endif // BAR_STATUSCMD_PATCH + +#if ON_EMPTY_KEYS_PATCH +static const char *firefoxcmd[] = {"firefox", NULL}; +static const Key on_empty_keys[] = { + /* modifier key function argument */ + {0, XK_f, spawn, {.v = firefoxcmd}}, +}; +#endif // ON_EMPTY_KEYS_PATCH + +#if XRESOURCES_PATCH +/* + * Xresources preferences to load at startup. + * + * Name Type Address + * ------------------------------------------------ + * "nmaster" INTEGER &nmaster + * "mfact" FLOAT &mfact + * "color1" STRING &color1 + * + * In the Xresources file setting resources shoud be prefixed with "dwm.", e.g. + * + * dwm.nmaster: 1 + * dwm.mfact: 0.50 + * dwm.color1: #FA6EFA + * + * Note that the const qualifier must be removed from the variables if you plan + * on overriding them with values from Xresources. While resources can be + * reloaded using the xrdb function some changes may only take effect following + * a restart. + */ +ResourcePref resources[] = { + /* Resource name Type Address */ + {"normfgcolor", STRING, &normfgcolor}, + {"normbgcolor", STRING, &normbgcolor}, + {"normbordercolor", STRING, &normbordercolor}, + {"normfloatcolor", STRING, &normfloatcolor}, + {"selfgcolor", STRING, &selfgcolor}, + {"selbgcolor", STRING, &selbgcolor}, + {"selbordercolor", STRING, &selbordercolor}, + {"selfloatcolor", STRING, &selfloatcolor}, + {"titlenormfgcolor", STRING, &titlenormfgcolor}, + {"titlenormbgcolor", STRING, &titlenormbgcolor}, + {"titlenormbordercolor", STRING, &titlenormbordercolor}, + {"titlenormfloatcolor", STRING, &titlenormfloatcolor}, + {"titleselfgcolor", STRING, &titleselfgcolor}, + {"titleselbgcolor", STRING, &titleselbgcolor}, + {"titleselbordercolor", STRING, &titleselbordercolor}, + {"titleselfloatcolor", STRING, &titleselfloatcolor}, + {"tagsnormfgcolor", STRING, &tagsnormfgcolor}, + {"tagsnormbgcolor", STRING, &tagsnormbgcolor}, + {"tagsnormbordercolor", STRING, &tagsnormbordercolor}, + {"tagsnormfloatcolor", STRING, &tagsnormfloatcolor}, + {"tagsselfgcolor", STRING, &tagsselfgcolor}, + {"tagsselbgcolor", STRING, &tagsselbgcolor}, + {"tagsselbordercolor", STRING, &tagsselbordercolor}, + {"tagsselfloatcolor", STRING, &tagsselfloatcolor}, + {"hidnormfgcolor", STRING, &hidnormfgcolor}, + {"hidnormbgcolor", STRING, &hidnormbgcolor}, + {"hidselfgcolor", STRING, &hidselfgcolor}, + {"hidselbgcolor", STRING, &hidselbgcolor}, + {"urgfgcolor", STRING, &urgfgcolor}, + {"urgbgcolor", STRING, &urgbgcolor}, + {"urgbordercolor", STRING, &urgbordercolor}, + {"urgfloatcolor", STRING, &urgfloatcolor}, +#if RENAMED_SCRATCHPADS_PATCH + {"scratchselfgcolor", STRING, &scratchselfgcolor}, + {"scratchselbgcolor", STRING, &scratchselbgcolor}, + {"scratchselbordercolor", STRING, &scratchselbordercolor}, + {"scratchselfloatcolor", STRING, &scratchselfloatcolor}, + {"scratchnormfgcolor", STRING, &scratchnormfgcolor}, + {"scratchnormbgcolor", STRING, &scratchnormbgcolor}, + {"scratchnormbordercolor", STRING, &scratchnormbordercolor}, + {"scratchnormfloatcolor", STRING, &scratchnormfloatcolor}, +#endif // RENAMED_SCRATCHPADS_PATCH +#if BAR_FLEXWINTITLE_PATCH + {"normTTBbgcolor", STRING, &normTTBbgcolor}, + {"normLTRbgcolor", STRING, &normLTRbgcolor}, + {"normMONObgcolor", STRING, &normMONObgcolor}, + {"normGRIDbgcolor", STRING, &normGRIDbgcolor}, + {"normGRD1bgcolor", STRING, &normGRD1bgcolor}, + {"normGRD2bgcolor", STRING, &normGRD2bgcolor}, + {"normGRDMbgcolor", STRING, &normGRDMbgcolor}, + {"normHGRDbgcolor", STRING, &normHGRDbgcolor}, + {"normDWDLbgcolor", STRING, &normDWDLbgcolor}, + {"normSPRLbgcolor", STRING, &normSPRLbgcolor}, + {"normfloatbgcolor", STRING, &normfloatbgcolor}, + {"actTTBbgcolor", STRING, &actTTBbgcolor}, + {"actLTRbgcolor", STRING, &actLTRbgcolor}, + {"actMONObgcolor", STRING, &actMONObgcolor}, + {"actGRIDbgcolor", STRING, &actGRIDbgcolor}, + {"actGRD1bgcolor", STRING, &actGRD1bgcolor}, + {"actGRD2bgcolor", STRING, &actGRD2bgcolor}, + {"actGRDMbgcolor", STRING, &actGRDMbgcolor}, + {"actHGRDbgcolor", STRING, &actHGRDbgcolor}, + {"actDWDLbgcolor", STRING, &actDWDLbgcolor}, + {"actSPRLbgcolor", STRING, &actSPRLbgcolor}, + {"actfloatbgcolor", STRING, &actfloatbgcolor}, + {"selTTBbgcolor", STRING, &selTTBbgcolor}, + {"selLTRbgcolor", STRING, &selLTRbgcolor}, + {"selMONObgcolor", STRING, &selMONObgcolor}, + {"selGRIDbgcolor", STRING, &selGRIDbgcolor}, + {"selGRD1bgcolor", STRING, &selGRD1bgcolor}, + {"selGRD2bgcolor", STRING, &selGRD2bgcolor}, + {"selGRDMbgcolor", STRING, &selGRDMbgcolor}, + {"selHGRDbgcolor", STRING, &selHGRDbgcolor}, + {"selDWDLbgcolor", STRING, &selDWDLbgcolor}, + {"selSPRLbgcolor", STRING, &selSPRLbgcolor}, + {"selfloatbgcolor", STRING, &selfloatbgcolor}, +#endif // BAR_FLEXWINTITLE_PATCH +#if BAR_LTSYMBOL_SCHEME_PATCH + {"ltsymbolfgcolor", STRING, <symbolfgcolor}, + {"ltsymbolbgcolor", STRING, <symbolbgcolor}, +#endif // BAR_LTSYMBOL_SCHEME_PATCH +}; +#endif // XRESOURCES_PATCH + +static const Key keys[] = { +/* modifier key function argument + */ +#if KEYMODES_PATCH + {MODKEY, XK_Escape, setkeymode, {.ui = COMMANDMODE}}, +#endif // KEYMODES_PATCH + {MODKEY, XK_r, spawn, {.v = dmenucmd}}, + {MODKEY, XK_Return, spawn, {.v = termcmd}}, +#if RIODRAW_PATCH + {MODKEY | ControlMask, XK_p, riospawnsync, {.v = dmenucmd}}, + {MODKEY | ControlMask, XK_Return, riospawn, {.v = termcmd}}, + {MODKEY, XK_s, rioresize, {0}}, +#endif // RIODRAW_PATCH + {MODKEY, XK_b, togglebar, {0}}, +#if TOGGLETOPBAR_PATCH + {MODKEY | ShiftMask, XK_b, toggletopbar, {0}}, +#endif // TOGGLETOPBAR_PATCH +#if TAB_PATCH + {MODKEY | ControlMask, XK_b, tabmode, {-1}}, +#endif // TAB_PATCH +#if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH + {MODKEY | ControlMask, XK_space, focusmaster, {0}}, +#endif // FOCUSMASTER_PATCH / FOCUSMASTER_RETURN_PATCH +#if STACKER_PATCH + STACKKEYS(MODKEY, focus) STACKKEYS(MODKEY | ShiftMask, push) +#else + {MODKEY, XK_j, focusstack, {.i = +1}}, + {MODKEY, XK_k, focusstack, {.i = -1}}, +#endif // STACKER_PATCH +#if FOCUSDIR_PATCH + {MODKEY, XK_Left, focusdir, {.i = 0}}, // left + {MODKEY, XK_Right, focusdir, {.i = 1}}, // right + {MODKEY, XK_Up, focusdir, {.i = 2}}, // up + {MODKEY, XK_Down, focusdir, {.i = 3}}, // down +#endif // FOCUSDIR_PATCH +#if PLACEDIR_PATCH + {MODKEY | ControlMask, XK_Left, placedir, {.i = 0}}, // left + {MODKEY | ControlMask, XK_Right, placedir, {.i = 1}}, // right + {MODKEY | ControlMask, XK_Up, placedir, {.i = 2}}, // up + {MODKEY | ControlMask, XK_Down, placedir, {.i = 3}}, // down +#endif // PLACEDIR_PATCH +#if SWAPFOCUS_PATCH && PERTAG_PATCH + {MODKEY, XK_s, swapfocus, {.i = -1}}, +#endif // SWAPFOCUS_PATCH +#if SWITCHCOL_PATCH + {MODKEY, XK_v, switchcol, {0}}, +#endif // SWITCHCOL_PATCH +#if ROTATESTACK_PATCH + {MODKEY | Mod4Mask, XK_j, rotatestack, {.i = +1}}, + {MODKEY | Mod4Mask, XK_k, rotatestack, {.i = -1}}, +#endif // ROTATESTACK_PATCH +#if INPLACEROTATE_PATCH + {MODKEY | Mod4Mask, XK_j, inplacerotate, {.i = +2}}, // same as rotatestack + {MODKEY | Mod4Mask, XK_k, inplacerotate, {.i = -2}}, // same as reotatestack + {MODKEY | Mod4Mask | ShiftMask, XK_j, inplacerotate, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_k, inplacerotate, {.i = -1}}, +#endif // INPLACEROTATE_PATCH +#if PUSH_PATCH || PUSH_NO_MASTER_PATCH + {MODKEY | ControlMask, XK_j, pushdown, {0}}, + {MODKEY | ControlMask, XK_k, pushup, {0}}, +#endif // PUSH_PATCH / PUSH_NO_MASTER_PATCH + {MODKEY, XK_i, incnmaster, {.i = +1}}, + {MODKEY, XK_d, incnmaster, {.i = -1}}, +#if FLEXTILE_DELUXE_LAYOUT + {MODKEY | ControlMask, XK_i, incnstack, {.i = +1}}, + {MODKEY | ControlMask, XK_u, incnstack, {.i = -1}}, +#endif // FLEXTILE_DELUXE_LAYOUT + {MODKEY, XK_h, setmfact, {.f = -0.05}}, + {MODKEY, XK_l, setmfact, {.f = +0.05}}, +#if CFACTS_PATCH + {MODKEY | ShiftMask, XK_h, setcfact, {.f = +0.25}}, + {MODKEY | ShiftMask, XK_l, setcfact, {.f = -0.25}}, + {MODKEY | ShiftMask, XK_o, setcfact, {0}}, +#endif // CFACTS_PATCH +#if ASPECTRESIZE_PATCH + {MODKEY | ControlMask | ShiftMask, XK_e, aspectresize, {.i = +24}}, + {MODKEY | ControlMask | ShiftMask, XK_r, aspectresize, {.i = -24}}, +#endif // ASPECTRESIZE_PATCH +#if MOVERESIZE_PATCH + {MODKEY | Mod4Mask, XK_Down, moveresize, {.v = "0x 25y 0w 0h"}}, + {MODKEY | Mod4Mask, XK_Up, moveresize, {.v = "0x -25y 0w 0h"}}, + {MODKEY | Mod4Mask, XK_Right, moveresize, {.v = "25x 0y 0w 0h"}}, + {MODKEY | Mod4Mask, XK_Left, moveresize, {.v = "-25x 0y 0w 0h"}}, + {MODKEY | Mod4Mask | ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h"}}, + {MODKEY | Mod4Mask | ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h"}}, + {MODKEY | Mod4Mask | ShiftMask, + XK_Right, + moveresize, + {.v = "0x 0y 25w 0h"}}, + {MODKEY | Mod4Mask | ShiftMask, + XK_Left, + moveresize, + {.v = "0x 0y -25w 0h"}}, +#endif // MOVERESIZE_PATCH +#if MOVESTACK_PATCH + {MODKEY | ShiftMask, XK_j, movestack, {.i = +1}}, + {MODKEY | ShiftMask, XK_k, movestack, {.i = -1}}, +#endif // MOVESTACK_PATCH +#if TRANSFER_PATCH + {MODKEY, XK_x, transfer, {0}}, +#endif // TRANSFER_PATCH +#if TRANSFER_ALL_PATCH + {MODKEY | ControlMask, XK_x, transferall, {0}}, +#endif // TRANSFER_ALL_PATCH +#if REORGANIZETAGS_PATCH + {MODKEY | ControlMask, XK_r, reorganizetags, {0}}, +#endif // REORGANIZETAGS_PATCH +#if DISTRIBUTETAGS_PATCH + {MODKEY | ControlMask, XK_d, distributetags, {0}}, +#endif // DISTRIBUTETAGS_PATCH +#if INSETS_PATCH + {MODKEY | ShiftMask | ControlMask, + XK_a, + updateinset, + {.v = &default_inset}}, +#endif // INSETS_PATCH + {MODKEY | ShftMask, XK_Return, zoom, {0}}, +#if VANITYGAPS_PATCH + {MODKEY | Mod4Mask, XK_u, incrgaps, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_u, incrgaps, {.i = -1}}, + {MODKEY | Mod4Mask, XK_i, incrigaps, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_i, incrigaps, {.i = -1}}, + {MODKEY | Mod4Mask, XK_o, incrogaps, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_o, incrogaps, {.i = -1}}, + {MODKEY | Mod4Mask, XK_6, incrihgaps, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_6, incrihgaps, {.i = -1}}, + {MODKEY | Mod4Mask, XK_7, incrivgaps, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_7, incrivgaps, {.i = -1}}, + {MODKEY | Mod4Mask, XK_8, incrohgaps, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_8, incrohgaps, {.i = -1}}, + {MODKEY | Mod4Mask, XK_9, incrovgaps, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_9, incrovgaps, {.i = -1}}, + {MODKEY | Mod4Mask, XK_0, togglegaps, {0}}, + {MODKEY | Mod4Mask | ShiftMask, XK_0, defaultgaps, {0}}, +#endif // VANITYGAPS_PATCH +#if ALT_TAB_PATCH + {Mod1Mask, XK_Tab, alttabstart, {0}}, +#else + {MODKEY, XK_Tab, view, {0}}, +#endif // ALT_TAB_PATCH +#if SHIFTTAG_PATCH + {MODKEY | ShiftMask, + XK_Left, + shifttag, + {.i = -1}}, // note keybinding conflict with focusadjacenttag tagtoleft + {MODKEY | ShiftMask, + XK_Right, + shifttag, + {.i = +1}}, // note keybinding conflict with focusadjacenttag tagtoright +#endif // SHIFTTAG_PATCH +#if SHIFTTAGCLIENTS_PATCH + {MODKEY | ShiftMask | ControlMask, XK_Left, shifttagclients, {.i = -1}}, + {MODKEY | ShiftMask | ControlMask, XK_Right, shifttagclients, {.i = +1}}, +#endif // SHIFTTAGCLIENTS_PATCH +#if SHIFTVIEW_PATCH + {MODKEY | ShiftMask, XK_Tab, shiftview, {.i = -1}}, + {MODKEY | ShiftMask, XK_backslash, shiftview, {.i = +1}}, +#endif // SHIFTVIEW_PATCH +#if SHIFTVIEW_CLIENTS_PATCH + {MODKEY | Mod4Mask, XK_Tab, shiftviewclients, {.i = -1}}, + {MODKEY | Mod4Mask, XK_backslash, shiftviewclients, {.i = +1}}, +#endif // SHIFTVIEW_CLIENTS_PATCH +#if SHIFTBOTH_PATCH + {MODKEY | ControlMask, + XK_Left, + shiftboth, + {.i = -1}}, // note keybinding conflict with focusadjacenttag + // tagandviewtoleft placedir + {MODKEY | ControlMask, + XK_Right, + shiftboth, + {.i = +1}}, // note keybinding conflict with focusadjacenttag + // tagandviewtoright placedir +#endif // SHIFTBOTH_PATCH +#if SHIFTSWAPTAGS_PATCH && SWAPTAGS_PATCH + {MODKEY | Mod4Mask | ShiftMask, XK_Left, shiftswaptags, {.i = -1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_Right, shiftswaptags, {.i = +1}}, +#endif // SHIFTSWAPTAGS_PATCH +#if BAR_WINTITLEACTIONS_PATCH + {MODKEY | ControlMask, XK_z, showhideclient, {0}}, + {MODKEY | ControlMask, XK_s, unhideall, {0}}, +#endif // BAR_WINTITLEACTIONS_PATCH + {MODKEY, XK_s, killclient, {0}}, +#if KILLUNSEL_PATCH + {MODKEY | ShiftMask, XK_x, killunsel, {0}}, +#endif // KILLUNSEL_PATCH +#if SELFRESTART_PATCH + {MODKEY | ShiftMask, XK_r, self_restart, {0}}, +#endif // SELFRESTART_PATCH + {MODKEY | ShiftMask, XK_q, quit, {0}}, +#if RESTARTSIG_PATCH + {MODKEY | ControlMask | ShiftMask, XK_q, quit, {1}}, +#endif // RESTARTSIG_PATCH +#if FOCUSURGENT_PATCH + {MODKEY, XK_u, focusurgent, {0}}, +#endif // FOCUSURGENT_PATCH +#if BAR_HOLDBAR_PATCH + {0, HOLDKEY, holdbar, {0}}, +#endif // BAR_HOLDBAR_PATCH +#if WINVIEW_PATCH + {MODKEY, XK_o, winview, {0}}, +#endif // WINVIEW_PATCH +#if XRDB_PATCH || XRESOURCES_PATCH + {MODKEY | ShiftMask, XK_F5, xrdb, {.v = NULL}}, +#endif // XRDB_PATCH | XRESOURCES_PATCH + {MODKEY, XK_t, setlayout, {.v = &layouts[0]}}, + {MODKEY, XK_f, setlayout, {.v = &layouts[1]}}, + {MODKEY, XK_m, setlayout, {.v = &layouts[2]}}, +#if COLUMNS_LAYOUT + {MODKEY, XK_c, setlayout, {.v = &layouts[3]}}, +#endif // COLUMNS_LAYOUT +#if FLEXTILE_DELUXE_LAYOUT + {MODKEY | ControlMask, + XK_t, + rotatelayoutaxis, + {.i = +1}}, /* flextile, 1 = layout axis */ + {MODKEY | ControlMask, + XK_Tab, + rotatelayoutaxis, + {.i = +2}}, /* flextile, 2 = master axis */ + {MODKEY | ControlMask | ShiftMask, + XK_Tab, + rotatelayoutaxis, + {.i = +3}}, /* flextile, 3 = stack axis */ + {MODKEY | ControlMask | Mod1Mask, + XK_Tab, + rotatelayoutaxis, + {.i = +4}}, /* flextile, 4 = secondary stack axis */ + {MODKEY | Mod5Mask, + XK_t, + rotatelayoutaxis, + {.i = -1}}, /* flextile, 1 = layout axis */ + {MODKEY | Mod5Mask, + XK_Tab, + rotatelayoutaxis, + {.i = -2}}, /* flextile, 2 = master axis */ + {MODKEY | Mod5Mask | ShiftMask, + XK_Tab, + rotatelayoutaxis, + {.i = -3}}, /* flextile, 3 = stack axis */ + {MODKEY | Mod5Mask | Mod1Mask, + XK_Tab, + rotatelayoutaxis, + {.i = -4}}, /* flextile, 4 = secondary stack axis */ + {MODKEY | ControlMask, + XK_Return, + mirrorlayout, + {0}}, /* flextile, flip master and stack areas */ +#endif // FLEXTILE_DELUXE_LAYOUT + {MODKEY, XK_space, setlayout, {0}}, + {MODKEY | ShiftMask, XK_space, togglefloating, {0}}, +#if ALWAYSONTOP_PATCH + {MODKEY | ShiftMask, XK_space, togglealwaysontop, {0}}, +#endif // ALWAYSONTOP_PATCH +#if MAXIMIZE_PATCH + {MODKEY | ControlMask | ShiftMask, XK_h, togglehorizontalmax, {0}}, + {MODKEY | ControlMask | ShiftMask, XK_l, togglehorizontalmax, {0}}, + {MODKEY | ControlMask | ShiftMask, XK_j, toggleverticalmax, {0}}, + {MODKEY | ControlMask | ShiftMask, XK_k, toggleverticalmax, {0}}, + {MODKEY | ControlMask, XK_m, togglemax, {0}}, +#endif // MAXIMIZE_PATCH +#if NO_MOD_BUTTONS_PATCH + {MODKEY | ShiftMask, XK_Escape, togglenomodbuttons, {0}}, +#endif // NO_MOD_BUTTONS_PATCH +#if RENAMED_SCRATCHPADS_PATCH + {MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd}}, + {MODKEY | ControlMask, XK_grave, setscratch, {.v = scratchpadcmd}}, + {MODKEY | ShiftMask, XK_grave, removescratch, {.v = scratchpadcmd}}, +#elif SCRATCHPADS_PATCH + {MODKEY, XK_grave, togglescratch, {.ui = 0}}, + {MODKEY | ControlMask, XK_grave, setscratch, {.ui = 0}}, + {MODKEY | ShiftMask, XK_grave, removescratch, {.ui = 0}}, +#endif // SCRATCHPADS_PATCH | RENAMED_SCRATCHPADS_PATCH +#if UNFLOATVISIBLE_PATCH + {MODKEY | Mod4Mask, XK_space, unfloatvisible, {0}}, + {MODKEY | ShiftMask, XK_t, unfloatvisible, {.v = &layouts[0]}}, +#endif // UNFLOATVISIBLE_PATCH +#if TOGGLEFULLSCREEN_PATCH + {MODKEY, XK_y, togglefullscreen, {0}}, +#endif // TOGGLEFULLSCREEN_PATCH +#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + {MODKEY | ShiftMask, XK_y, togglefakefullscreen, {0}}, +#endif // FAKEFULLSCREEN_CLIENT_PATCH +#if FULLSCREEN_PATCH + {MODKEY | ShiftMask, XK_f, fullscreen, {0}}, +#endif // FULLSCREEN_PATCH +#if STICKY_PATCH + {MODKEY | ShiftMask, XK_s, togglesticky, {0}}, +#endif // STICKY_PATCH +#if SCRATCHPAD_ALT_1_PATCH + {MODKEY, XK_minus, scratchpad_show, {0}}, + {MODKEY | ShiftMask, XK_minus, scratchpad_hide, {0}}, + {MODKEY, XK_equal, scratchpad_remove, {0}}, +#elif SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + {MODKEY, XK_0, view, {.ui = ~SPTAGMASK}}, + {MODKEY | ShiftMask, XK_0, tag, {.ui = ~SPTAGMASK}}, +#else + {MODKEY, XK_0, view, {.ui = ~0}}, + {MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}}, +#endif // SCRATCHPAD_ALT_1_PATCH + {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}}, +#if FOCUSADJACENTTAG_PATCH + {MODKEY, + XK_Left, + viewtoleft, + {0}}, // note keybinding conflict with focusdir + {MODKEY, + XK_Right, + viewtoright, + {0}}, // note keybinding conflict with focusdir + {MODKEY | ShiftMask, + XK_Left, + tagtoleft, + {0}}, // note keybinding conflict with shifttag + {MODKEY | ShiftMask, + XK_Right, + tagtoright, + {0}}, // note keybinding conflict with shifttag + {MODKEY | ControlMask, + XK_Left, + tagandviewtoleft, + {0}}, // note keybinding conflict with placedir + {MODKEY | ControlMask, + XK_Right, + tagandviewtoright, + {0}}, // note keybinding conflict with placedir +#endif // FOCUSADJACENTTAG_PATCH +#if TAGALL_PATCH + {MODKEY | ShiftMask, XK_F1, tagall, {.v = "F1"}}, + {MODKEY | ShiftMask, XK_F2, tagall, {.v = "F2"}}, + {MODKEY | ShiftMask, XK_F3, tagall, {.v = "F3"}}, + {MODKEY | ShiftMask, XK_F4, tagall, {.v = "F4"}}, + {MODKEY | ShiftMask, XK_F5, tagall, {.v = "F5"}}, + {MODKEY | ShiftMask, XK_F6, tagall, {.v = "F6"}}, + {MODKEY | ShiftMask, XK_F7, tagall, {.v = "F7"}}, + {MODKEY | ShiftMask, XK_F8, tagall, {.v = "F8"}}, + {MODKEY | ShiftMask, XK_F9, tagall, {.v = "F9"}}, + {MODKEY | ControlMask, XK_F1, tagall, {.v = "1"}}, + {MODKEY | ControlMask, XK_F2, tagall, {.v = "2"}}, + {MODKEY | ControlMask, XK_F3, tagall, {.v = "3"}}, + {MODKEY | ControlMask, XK_F4, tagall, {.v = "4"}}, + {MODKEY | ControlMask, XK_F5, tagall, {.v = "5"}}, + {MODKEY | ControlMask, XK_F6, tagall, {.v = "6"}}, + {MODKEY | ControlMask, XK_F7, tagall, {.v = "7"}}, + {MODKEY | ControlMask, XK_F8, tagall, {.v = "8"}}, + {MODKEY | ControlMask, XK_F9, tagall, {.v = "9"}}, +#endif // TAGALL_PATCH +#if TAGALLMON_PATCH + {MODKEY | Mod4Mask | ShiftMask, XK_comma, tagallmon, {.i = +1}}, + {MODKEY | Mod4Mask | ShiftMask, XK_period, tagallmon, {.i = -1}}, +#endif // TAGALLMON_PATCH +#if TAGSWAPMON_PATCH + {MODKEY | Mod4Mask | ControlMask, XK_comma, tagswapmon, {.i = +1}}, + {MODKEY | Mod4Mask | ControlMask, XK_period, tagswapmon, {.i = -1}}, +#endif // TAGSWAPMON_PATCH +#if BAR_ALTERNATIVE_TAGS_PATCH + {MODKEY, XK_n, togglealttag, {0}}, +#endif // BAR_ALTERNATIVE_TAGS_PATCH +#if NAMETAG_PATCH + {MODKEY | ShiftMask, XK_n, nametag, {0}}, +#endif // NAMETAG_PATCH +#if BAR_TAGGRID_PATCH + {MODKEY | ControlMask, + XK_Up, + switchtag, + {.ui = SWITCHTAG_UP | SWITCHTAG_VIEW}}, + {MODKEY | ControlMask, + XK_Down, + switchtag, + {.ui = SWITCHTAG_DOWN | SWITCHTAG_VIEW}}, + {MODKEY | ControlMask, + XK_Right, + switchtag, + {.ui = SWITCHTAG_RIGHT | + SWITCHTAG_VIEW}}, // note keybinding conflict with placedir + {MODKEY | ControlMask, + XK_Left, + switchtag, + {.ui = SWITCHTAG_LEFT | + SWITCHTAG_VIEW}}, // note keybinding conflict with placedir + {MODKEY | Mod4Mask, + XK_Up, + switchtag, + {.ui = SWITCHTAG_UP | SWITCHTAG_TAG | SWITCHTAG_VIEW}}, + {MODKEY | Mod4Mask, + XK_Down, + switchtag, + {.ui = SWITCHTAG_DOWN | SWITCHTAG_TAG | SWITCHTAG_VIEW}}, + {MODKEY | Mod4Mask, + XK_Right, + switchtag, + {.ui = SWITCHTAG_RIGHT | SWITCHTAG_TAG | SWITCHTAG_VIEW}}, + {MODKEY | Mod4Mask, + XK_Left, + switchtag, + {.ui = SWITCHTAG_LEFT | SWITCHTAG_TAG | SWITCHTAG_VIEW}}, +#endif // BAR_TAGGRID_PATCH +#if MOVECENTER_PATCH + {MODKEY, XK_x, movecenter, {0}}, // note keybinding conflict with killunsel +#endif // MOVECENTER_PATCH +#if MOVEPLACE_PATCH + {MODKEY, XK_KP_7, moveplace, {.ui = WIN_NW}}, /* XK_KP_Home, */ + {MODKEY, XK_KP_8, moveplace, {.ui = WIN_N}}, /* XK_KP_Up, */ + {MODKEY, XK_KP_9, moveplace, {.ui = WIN_NE}}, /* XK_KP_Prior, */ + {MODKEY, XK_KP_4, moveplace, {.ui = WIN_W}}, /* XK_KP_Left, */ + {MODKEY, XK_KP_5, moveplace, {.ui = WIN_C}}, /* XK_KP_Begin, */ + {MODKEY, XK_KP_6, moveplace, {.ui = WIN_E}}, /* XK_KP_Right, */ + {MODKEY, XK_KP_1, moveplace, {.ui = WIN_SW}}, /* XK_KP_End, */ + {MODKEY, XK_KP_2, moveplace, {.ui = WIN_S}}, /* XK_KP_Down, */ + {MODKEY, XK_KP_3, moveplace, {.ui = WIN_SE}}, /* XK_KP_Next, */ +#endif // MOVEPLACE_PATCH +#if EXRESIZE_PATCH + {MODKEY, XK_KP_7, explace, {.ui = EX_NW}}, /* XK_KP_Home, */ + {MODKEY, XK_KP_8, explace, {.ui = EX_N}}, /* XK_KP_Up, */ + {MODKEY, XK_KP_9, explace, {.ui = EX_NE}}, /* XK_KP_Prior, */ + {MODKEY, XK_KP_4, explace, {.ui = EX_W}}, /* XK_KP_Left, */ + {MODKEY, XK_KP_5, explace, {.ui = EX_C}}, /* XK_KP_Begin, */ + {MODKEY, XK_KP_6, explace, {.ui = EX_E}}, /* XK_KP_Right, */ + {MODKEY, XK_KP_1, explace, {.ui = EX_SW}}, /* XK_KP_End, */ + {MODKEY, XK_KP_2, explace, {.ui = EX_S}}, /* XK_KP_Down, */ + {MODKEY, XK_KP_3, explace, {.ui = EX_SE}}, /* XK_KP_Next, */ + + {MODKEY | ShiftMask, + XK_KP_8, + exresize, + {.v = (int[]){0, 25}}}, /* XK_KP_Up, */ + {MODKEY | ShiftMask, + XK_KP_2, + exresize, + {.v = (int[]){0, -25}}}, /* XK_KP_Down, */ + {MODKEY | ShiftMask, + XK_KP_6, + exresize, + {.v = (int[]){25, 0}}}, /* XK_KP_Right, */ + {MODKEY | ShiftMask, + XK_KP_4, + exresize, + {.v = (int[]){-25, 0}}}, /* XK_KP_Left, */ + {MODKEY | ShiftMask, + XK_KP_5, + exresize, + {.v = (int[]){25, 25}}}, /* XK_KP_Begin, */ + {MODKEY | ShiftMask | ControlMask, + XK_KP_5, + exresize, + {.v = (int[]){-25, -25}}}, /* XK_KP_Begin, */ + + {MODKEY | ControlMask, + XK_KP_6, + togglehorizontalexpand, + {.i = +1}}, /* XK_KP_Right, */ + {MODKEY | ControlMask, + XK_KP_3, + togglehorizontalexpand, + {.i = 0}}, /* XK_KP_Next, */ + {MODKEY | ControlMask, + XK_KP_4, + togglehorizontalexpand, + {.i = -1}}, /* XK_KP_Left, */ + {MODKEY | ControlMask, + XK_KP_8, + toggleverticalexpand, + {.i = +1}}, /* XK_KP_Up, */ + {MODKEY | ControlMask, + XK_KP_1, + toggleverticalexpand, + {.i = 0}}, /* XK_KP_End, */ + {MODKEY | ControlMask, + XK_KP_2, + toggleverticalexpand, + {.i = -1}}, /* XK_KP_Down, */ + {MODKEY | ControlMask, + XK_KP_9, + togglemaximize, + {.i = -1}}, /* XK_KP_Prior, */ + {MODKEY | ControlMask, + XK_KP_7, + togglemaximize, + {.i = +1}}, /* XK_KP_Home, */ + {MODKEY | ControlMask, + XK_KP_5, + togglemaximize, + {.i = 0}}, /* XK_KP_Begin, */ +#endif // EXRESIZE_PATCH +#if FLOATPOS_PATCH + /* Note that due to key limitations the below example kybindings are defined + * with a Mod3Mask, which is not always readily available. Refer to the + * patch wiki for more details. */ + /* Client position is limited to monitor window area */ + {Mod3Mask, XK_u, floatpos, {.v = "-26x -26y"}}, // ↖ + {Mod3Mask, XK_i, floatpos, {.v = " 0x -26y"}}, // ↑ + {Mod3Mask, XK_o, floatpos, {.v = " 26x -26y"}}, // ↗ + {Mod3Mask, XK_j, floatpos, {.v = "-26x 0y"}}, // ← + {Mod3Mask, XK_l, floatpos, {.v = " 26x 0y"}}, // → + {Mod3Mask, XK_m, floatpos, {.v = "-26x 26y"}}, // ↙ + {Mod3Mask, XK_comma, floatpos, {.v = " 0x 26y"}}, // ↓ + {Mod3Mask, XK_period, floatpos, {.v = " 26x 26y"}}, // ↘ + /* Absolute positioning (allows moving windows between monitors) */ + {Mod3Mask | ControlMask, XK_u, floatpos, {.v = "-26a -26a"}}, // ↖ + {Mod3Mask | ControlMask, XK_i, floatpos, {.v = " 0a -26a"}}, // ↑ + {Mod3Mask | ControlMask, XK_o, floatpos, {.v = " 26a -26a"}}, // ↗ + {Mod3Mask | ControlMask, XK_j, floatpos, {.v = "-26a 0a"}}, // ← + {Mod3Mask | ControlMask, XK_l, floatpos, {.v = " 26a 0a"}}, // → + {Mod3Mask | ControlMask, XK_m, floatpos, {.v = "-26a 26a"}}, // ↙ + {Mod3Mask | ControlMask, XK_comma, floatpos, {.v = " 0a 26a"}}, // ↓ + {Mod3Mask | ControlMask, XK_period, floatpos, {.v = " 26a 26a"}}, // ↘ + /* Resize client, client center position is fixed which means that client + expands in all directions */ + {Mod3Mask | ShiftMask, XK_u, floatpos, {.v = "-26w -26h"}}, // ↖ + {Mod3Mask | ShiftMask, XK_i, floatpos, {.v = " 0w -26h"}}, // ↑ + {Mod3Mask | ShiftMask, XK_o, floatpos, {.v = " 26w -26h"}}, // ↗ + {Mod3Mask | ShiftMask, XK_j, floatpos, {.v = "-26w 0h"}}, // ← + {Mod3Mask | ShiftMask, XK_k, floatpos, {.v = "800W 800H"}}, // · + {Mod3Mask | ShiftMask, XK_l, floatpos, {.v = " 26w 0h"}}, // → + {Mod3Mask | ShiftMask, XK_m, floatpos, {.v = "-26w 26h"}}, // ↙ + {Mod3Mask | ShiftMask, XK_comma, floatpos, {.v = " 0w 26h"}}, // ↓ + {Mod3Mask | ShiftMask, XK_period, floatpos, {.v = " 26w 26h"}}, // ↘ + /* Client is positioned in a floating grid, movement is relative to client's + current position */ + {Mod3Mask | Mod1Mask, XK_u, floatpos, {.v = "-1p -1p"}}, // ↖ + {Mod3Mask | Mod1Mask, XK_i, floatpos, {.v = " 0p -1p"}}, // ↑ + {Mod3Mask | Mod1Mask, XK_o, floatpos, {.v = " 1p -1p"}}, // ↗ + {Mod3Mask | Mod1Mask, XK_j, floatpos, {.v = "-1p 0p"}}, // ← + {Mod3Mask | Mod1Mask, XK_k, floatpos, {.v = " 0p 0p"}}, // · + {Mod3Mask | Mod1Mask, XK_l, floatpos, {.v = " 1p 0p"}}, // → + {Mod3Mask | Mod1Mask, XK_m, floatpos, {.v = "-1p 1p"}}, // ↙ + {Mod3Mask | Mod1Mask, XK_comma, floatpos, {.v = " 0p 1p"}}, // ↓ + {Mod3Mask | Mod1Mask, XK_period, floatpos, {.v = " 1p 1p"}}, // ↘ +#endif // FLOATPOS_PATCH +#if SETBORDERPX_PATCH + {MODKEY | ControlMask, XK_minus, setborderpx, {.i = -1}}, + {MODKEY | ControlMask, XK_plus, setborderpx, {.i = +1}}, + {MODKEY | ControlMask, XK_numbersign, setborderpx, {.i = 0}}, +#endif // SETBORDERPX_PATCH +#if CYCLELAYOUTS_PATCH + {MODKEY | ControlMask, XK_comma, cyclelayout, {.i = -1}}, + {MODKEY | ControlMask, XK_period, cyclelayout, {.i = +1}}, +#endif // CYCLELAYOUTS_PATCH +#if MPDCONTROL_PATCH + {MODKEY, XK_F1, mpdchange, {.i = -1}}, + {MODKEY, XK_F2, mpdchange, {.i = +1}}, + {MODKEY, XK_Escape, mpdcontrol, {0}}, +#endif // MPDCONTROL_PATCH + 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)}; + +#if KEYMODES_PATCH +static const Key cmdkeys[] = { + /* modifier keys function argument */ + {0, XK_Escape, clearcmd, {0}}, + {ControlMask, XK_c, clearcmd, {0}}, + {0, XK_i, setkeymode, {.ui = INSERTMODE}}, +}; + +static const Command commands[] = { + /* modifier (4 keys) keysyms (4 keys) function + argument */ + {{ControlMask, ShiftMask, 0, 0}, + {XK_w, XK_h, 0, 0}, + setlayout, + {.v = &layouts[0]}}, + {{ControlMask, 0, 0, 0}, {XK_w, XK_o, 0, 0}, setlayout, {.v = &layouts[2]}}, + {{ControlMask, ShiftMask, 0, 0}, {XK_w, XK_o, 0, 0}, onlyclient, {0}}, + {{ControlMask, 0, 0, 0}, {XK_w, XK_v, 0, 0}, setlayout, {.v = &layouts[0]}}, + {{ControlMask, 0, 0, 0}, {XK_w, XK_less, 0, 0}, setmfact, {.f = -0.05}}, + {{ControlMask, ShiftMask, 0, 0}, + {XK_w, XK_less, 0, 0}, + setmfact, + {.f = +0.05}}, + {{ControlMask, ShiftMask, 0, 0}, + {XK_w, XK_0, 0, 0}, + setmfact, + {.f = +1.50}}, + {{ShiftMask, 0, 0, 0}, {XK_period, XK_e, 0, 0}, spawn, {.v = dmenucmd}}, + {{ShiftMask, 0, 0, 0}, {XK_period, XK_o, 0, 0}, spawn, {.v = dmenucmd}}, + {{ShiftMask, 0, 0, 0}, {XK_period, XK_q, XK_Return, 0}, quit, {0}}, + {{ShiftMask, 0, 0, 0}, {XK_period, XK_b, XK_d, XK_Return}, killclient, {0}}, + {{ShiftMask, 0, 0, 0}, + {XK_period, XK_b, XK_n, XK_Return}, + focusstack, + {.i = +1}}, + {{ShiftMask, 0, ShiftMask, 0}, + {XK_period, XK_b, XK_n, XK_Return}, + focusstack, + {.i = -1}}, +}; +#endif // KEYMODES_PATCH + +/* button definitions */ +#if STATUSBUTTON_PATCH +/* click can be ClkButton, ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + * ClkClientWin, or ClkRootWin */ +#else +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + * ClkClientWin, or ClkRootWin */ +#endif // +static const Button buttons[] = { +/* click event mask button function argument + */ +#if BAR_STATUSBUTTON_PATCH + {ClkButton, 0, Button1, spawn, {.v = dmenucmd}}, +#endif // BAR_STATUSBUTTON_PATCH + {ClkLtSymbol, 0, Button1, setlayout, {0}}, +#if BAR_LAYOUTMENU_PATCH + {ClkLtSymbol, 0, Button3, layoutmenu, {0}}, +#else + {ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}}, +#endif // BAR_LAYOUTMENU_PATCH +#if BAR_WINTITLEACTIONS_PATCH + {ClkWinTitle, 0, Button1, togglewin, {0}}, + {ClkWinTitle, 0, Button3, showhideclient, {0}}, +#endif // BAR_WINTITLEACTIONS_PATCH + {ClkWinTitle, 0, Button2, zoom, {0}}, +#if BAR_STATUSCMD_PATCH && BAR_DWMBLOCKS_PATCH + {ClkStatusText, 0, Button1, sigstatusbar, {.i = 1}}, + {ClkStatusText, 0, Button2, sigstatusbar, {.i = 2}}, + {ClkStatusText, 0, Button3, sigstatusbar, {.i = 3}}, +#elif BAR_STATUSCMD_PATCH + {ClkStatusText, 0, Button1, spawn, {.v = statuscmd}}, + {ClkStatusText, 0, Button2, spawn, {.v = statuscmd}}, + {ClkStatusText, 0, Button3, spawn, {.v = statuscmd}}, +#else + {ClkStatusText, 0, Button2, spawn, {.v = termcmd}}, +#endif // BAR_STATUSCMD_PATCH +#if PLACEMOUSE_PATCH + /* placemouse options, choose which feels more natural: + * 0 - tiled position is relative to mouse cursor + * 1 - tiled postiion is relative to window center + * 2 - mouse pointer warps to window center + * + * The moveorplace uses movemouse or placemouse depending on the floating + * state of the selected client. Set up individual keybindings for the two + * if you want to control these separately (i.e. to retain the feature to + * move a tiled window into a floating position). + */ + {ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1}}, +#else + {ClkClientWin, MODKEY, Button1, movemouse, {0}}, +#endif // PLACEMOUSE_PATCH + {ClkClientWin, MODKEY, Button2, togglefloating, {0}}, + {ClkClientWin, MODKEY, Button3, resizemouse, {0}}, +#if TAPRESIZE_PATCH + {ClkClientWin, MODKEY, Button4, resizemousescroll, {.v = &scrollargs[0]}}, + {ClkClientWin, MODKEY, Button5, resizemousescroll, {.v = &scrollargs[1]}}, + {ClkClientWin, MODKEY, Button6, resizemousescroll, {.v = &scrollargs[2]}}, + {ClkClientWin, MODKEY, Button7, resizemousescroll, {.v = &scrollargs[3]}}, +#endif // TAPRESIZE_PATCH +#if DRAGCFACT_PATCH && CFACTS_PATCH + {ClkClientWin, MODKEY | ShiftMask, Button3, dragcfact, {0}}, +#endif // DRAGCFACT_PATCH +#if DRAGMFACT_PATCH + {ClkClientWin, MODKEY | ShiftMask, Button1, dragmfact, {0}}, +#endif // DRAGMFACT_PATCH + {ClkTagBar, 0, Button1, view, {0}}, + {ClkTagBar, 0, Button3, toggleview, {0}}, + {ClkTagBar, MODKEY, Button1, tag, {0}}, + {ClkTagBar, MODKEY, Button3, toggletag, {0}}, +#if TAB_PATCH + {ClkTabBar, 0, Button1, focuswin, {0}}, +#endif // TAB_PATCH +}; + +#if DWMC_PATCH +/* signal definitions */ +/* signum must be greater than 0 */ +/* trigger signals using `xsetroot -name "fsignal: [ ]"` + */ +static const Signal signals[] = { + /* signum function */ + {"focusstack", focusstack}, + {"setmfact", setmfact}, + {"togglebar", togglebar}, +#if TOGGLETOPBAR_PATCH + {"toggletopbar", toggletopbar}, +#endif // TOGGLETOPBAR_PATCH + {"incnmaster", incnmaster}, + {"togglefloating", togglefloating}, + {"focusmon", focusmon}, +#if STACKER_PATCH + {"pushstack", pushstack}, +#endif // STACKER_PATCH +#if FLOATPOS_PATCH + {"floatpos", floatpos}, +#endif // FLOATPOS_PATCH +#if FOCUSURGENT_PATCH + {"focusurgent", focusurgent}, +#endif // FOCUSURGENT_PATCH +#if FOCUSADJACENTTAG_PATCH + {"viewtoleft", viewtoleft}, + {"viewtoright", viewtoright}, + {"tagtoleft", tagtoleft}, + {"tagtoright", tagtoright}, + {"tagandviewtoleft", tagandviewtoleft}, + {"tagandviewtoright", tagandviewtoright}, +#endif // FOCUSADJACENTTAG_PATCH +#if SWAPFOCUS_PATCH && PERTAG_PATCH + {"swapfocus", swapfocus}, +#endif // SWAPFOCUS_PATCH +#if SWITCHCOL_PATCH + {"switchcol", switchcol}, +#endif // SWITCHCOL_PATCH +#if ROTATESTACK_PATCH + {"rotatestack", rotatestack}, +#endif // ROTATESTACK_PATCH +#if INPLACEROTATE_PATCH + {"inplacerotate", inplacerotate}, +#endif // INPLACEROTATE_PATCH +#if PUSH_PATCH || PUSH_NO_MASTER_PATCH + {"pushdown", pushdown}, + {"pushup", pushup}, +#endif // PUSH_PATCH / PUSH_NO_MASTER_PATCH +#if FLEXTILE_DELUXE_LAYOUT + {"incnstack", incnstack}, + {"rotatelayoutaxis", rotatelayoutaxis}, + {"setlayoutaxisex", setlayoutaxisex}, + {"mirrorlayout", mirrorlayout}, +#endif // FLEXTILE_DELUXE_LAYOUT +#if CFACTS_PATCH + {"setcfact", setcfact}, +#endif // CFACTS_PATCH +#if MOVECENTER_PATCH + {"movecenter", movecenter}, +#endif // MOVECENTER_PATCH +#if MOVEPLACE_PATCH + {"moveplace", moveplace}, +#endif // MOVEPLACE_PATCH +#if NAMETAG_PATCH + {"nametag", nametag}, +#endif // NAMETAG_PATCH +#if EXRESIZE_PATCH + {"explace", explace}, + {"togglehorizontalexpand", togglehorizontalexpand}, + {"toggleverticalexpand", toggleverticalexpand}, + {"togglemaximize", togglemaximize}, +#endif // EXRESIZE_PATCH +#if KEYMODES_PATCH + {"setkeymode", setkeymode}, +#endif // KEYMODES_PATCH +#if TRANSFER_PATCH + {"transfer", transfer}, +#endif // TRANSFER_PATCH +#if TRANSFER_ALL_PATCH + {"transferall", transferall}, +#endif // TRANSFER_ALL_PATCH + {"tagmon", tagmon}, + {"zoom", zoom}, +#if VANITYGAPS_PATCH + {"incrgaps", incrgaps}, + {"incrigaps", incrigaps}, + {"incrogaps", incrogaps}, + {"incrihgaps", incrihgaps}, + {"incrivgaps", incrivgaps}, + {"incrohgaps", incrohgaps}, + {"incrovgaps", incrovgaps}, + {"togglegaps", togglegaps}, + {"defaultgaps", defaultgaps}, + {"setgaps", setgapsex}, +#endif // VANITYGAPS_PATCH + {"view", view}, + {"viewall", viewallex}, + {"viewex", viewex}, + {"toggleview", toggleview}, +#if BAR_WINTITLEACTIONS_PATCH + {"showhideclient", showhideclient}, +#endif // BAR_WINTITLEACTIONS_PATCH +#if SHIFTBOTH_PATCH + {"shiftboth", shiftboth}, +#endif // SHIFTBOTH_PATCH +#if SHIFTTAG_PATCH + {"shifttag", shifttag}, +#endif // SHIFTTAG_PATCH +#if SHIFTTAGCLIENTS_PATCH + {"shifttagclients", shifttagclients}, +#endif // SHIFTTAGCLIENTS_PATCH +#if SHIFTVIEW_PATCH + {"shiftview", shiftview}, +#endif // SHIFTVIEW_PATCH +#if SHIFTVIEW_CLIENTS_PATCH + {"shiftviewclients", shiftviewclients}, +#endif // SHIFTVIEW_CLIENTS_PATCH +#if SHIFTSWAPTAGS_PATCH && SWAPTAGS_PATCH + {"shiftswaptags", shiftswaptags}, +#endif // SHIFTSWAPTAGS_PATCH +#if SELFRESTART_PATCH + {"self_restart", self_restart}, +#endif // SELFRESTART_PATCH +#if BAR_TAGGRID_PATCH + {"switchtag", switchtag}, +#endif // BAR_TAGGRID_PATCH +#if STICKY_PATCH + {"togglesticky", togglesticky}, +#endif // STICKY_PATCH +#if SETBORDERPX_PATCH + {"setborderpx", setborderpx}, +#endif // SETBORDERPX_PATCH +#if CYCLELAYOUTS_PATCH + {"cyclelayout", cyclelayout}, +#endif // CYCLELAYOUTS_PATCH +#if MPDCONTROL_PATCH + {"mpdchange", mpdchange}, + {"mpdcontrol", mpdcontrol}, +#endif // MPDCONTROL_PATCH + {"toggleviewex", toggleviewex}, + {"tag", tag}, + {"tagall", tagallex}, + {"tagex", tagex}, + {"toggletag", toggletag}, + {"toggletagex", toggletagex}, +#if TAGALLMON_PATCH + {"tagallmon", tagallmon}, +#endif // TAGALLMON_PATCH +#if TAGSWAPMON_PATCH + {"tagswapmon", tagswapmon}, +#endif // TAGSWAPMON_PATCH +#if BAR_ALTERNATIVE_TAGS_PATCH + {"togglealttag", togglealttag}, +#endif // BAR_ALTERNATIVE_TAGS_PATCH +#if TOGGLEFULLSCREEN_PATCH + {"togglefullscreen", togglefullscreen}, +#endif // TOGGLEFULLSCREEN_PATCH +#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + {"togglefakefullscreen", togglefakefullscreen}, +#endif // FAKEFULLSCREEN_CLIENT_PATCH +#if FULLSCREEN_PATCH + {"fullscreen", fullscreen}, +#endif // FULLSCREEN_PATCH +#if MAXIMIZE_PATCH + {"togglehorizontalmax", togglehorizontalmax}, + {"toggleverticalmax", toggleverticalmax}, + {"togglemax", togglemax}, +#endif // MAXIMIZE_PATCH +#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + {"togglescratch", togglescratch}, +#endif // SCRATCHPADS_PATCH +#if UNFLOATVISIBLE_PATCH + {"unfloatvisible", unfloatvisible}, +#endif // UNFLOATVISIBLE_PATCH + {"killclient", killclient}, +#if WINVIEW_PATCH + {"winview", winview}, +#endif // WINVIEW_PATCH +#if XRDB_PATCH || XRESOURCES_PATCH + {"xrdb", xrdb}, +#endif // XRDB_PATCH | XRESOURCES_PATCH +#if TAGOTHERMONITOR_PATCH + {"tagnextmonex", tagnextmonex}, + {"tagprevmonex", tagprevmonex}, +#endif // TAGOTHERMONITOR_PATCH + {"quit", quit}, + {"setlayout", setlayout}, + {"setlayoutex", setlayoutex}, +}; +#elif FSIGNAL_PATCH +/* signal definitions */ +/* signum must be greater than 0 */ +/* trigger signals using `xsetroot -name "fsignal:"` */ +static Signal signals[] = { + /* signum function argument */ + {1, setlayout, {.v = 0}}, +}; +#endif // DWMC_PATCH + +#if IPC_PATCH +static const char *ipcsockpath = "/tmp/dwm.sock"; +static IPCCommand ipccommands[] = { + IPCCOMMAND(focusmon, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(focusstack, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(incnmaster, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(killclient, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(quit, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(setlayoutsafe, 1, {ARG_TYPE_PTR}), + IPCCOMMAND(setmfact, 1, {ARG_TYPE_FLOAT}), + IPCCOMMAND(setstatus, 1, {ARG_TYPE_STR}), + IPCCOMMAND(tag, 1, {ARG_TYPE_UINT}), + IPCCOMMAND(tagmon, 1, {ARG_TYPE_UINT}), + IPCCOMMAND(togglebar, 1, {ARG_TYPE_NONE}), +#if TOGGLETOPBAR_PATCH + IPCCOMMAND(toggletopbar, 1, {ARG_TYPE_NONE}), +#endif // TOGGLETOPBAR_PATCH + IPCCOMMAND(togglefloating, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(toggletag, 1, {ARG_TYPE_UINT}), + IPCCOMMAND(toggleview, 1, {ARG_TYPE_UINT}), + IPCCOMMAND(view, 1, {ARG_TYPE_UINT}), + IPCCOMMAND(zoom, 1, {ARG_TYPE_NONE}), +#if BAR_ALTERNATIVE_TAGS_PATCH + IPCCOMMAND(togglealttag, 1, {ARG_TYPE_NONE}), +#endif // BAR_ALTERNATIVE_TAGS_PATCH +#if BAR_TAGGRID_PATCH + IPCCOMMAND(switchtag, 1, {ARG_TYPE_UINT}), +#endif // BAR_TAGGRID_PATCH +#if CFACTS_PATCH + IPCCOMMAND(setcfact, 1, {ARG_TYPE_FLOAT}), +#endif // CFACTS_PATCH +#if CYCLELAYOUTS_PATCH + IPCCOMMAND(cyclelayout, 1, {ARG_TYPE_SINT}), +#endif // CYCLELAYOUTS_PATCH +#if EXRESIZE_PATCH + IPCCOMMAND(explace, 1, {ARG_TYPE_UINT}), + IPCCOMMAND(togglehorizontalexpand, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(toggleverticalexpand, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(togglemaximize, 1, {ARG_TYPE_SINT}), +#endif // EXRESIZE_PATCH +#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + IPCCOMMAND(togglefakefullscreen, 1, {ARG_TYPE_NONE}), +#endif // FAKEFULLSCREEN_CLIENT_PATCH +#if FLOATPOS_PATCH + IPCCOMMAND(floatpos, 1, {ARG_TYPE_STR}), +#endif // FLOATPOS_PATCH +#if FULLSCREEN_PATCH + IPCCOMMAND(fullscreen, 1, {ARG_TYPE_NONE}), +#endif // FULLSCREEN_PATCH +#if FLEXTILE_DELUXE_LAYOUT + IPCCOMMAND(incnstack, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(rotatelayoutaxis, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(setlayoutaxisex, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(mirrorlayout, 1, {ARG_TYPE_NONE}), +#endif // FLEXTILE_DELUXE_LAYOUT +#if FOCUSURGENT_PATCH + IPCCOMMAND(focusurgent, 1, {ARG_TYPE_NONE}), +#endif // FOCUSURGENT_PATCH +#if FOCUSADJACENTTAG_PATCH + IPCCOMMAND(viewtoleft, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(viewtoright, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(tagtoleft, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(tagtoright, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(tagandviewtoleft, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(tagandviewtoright, 1, {ARG_TYPE_NONE}), +#endif // FOCUSADJACENTTAG_PATCH +#if INPLACEROTATE_PATCH + IPCCOMMAND(inplacerotate, 1, {ARG_TYPE_SINT}), +#endif // INPLACEROTATE_PATCH +#if KEYMODES_PATCH + IPCCOMMAND(setkeymode, 1, {ARG_TYPE_UINT}), +#endif // KEYMODES_PATCH +#if MAXIMIZE_PATCH + IPCCOMMAND(togglehorizontalmax, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(toggleverticalmax, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(togglemax, 1, {ARG_TYPE_NONE}), +#endif // MAXIMIZE_PATCH +#if MPDCONTROL_PATCH + IPCCOMMAND(mpdchange, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(mpdcontrol, 1, {ARG_TYPE_NONE}), +#endif // MPDCONTROL_PATCH +#if MOVECENTER_PATCH + IPCCOMMAND(movecenter, 1, {ARG_TYPE_NONE}), +#endif // MOVECENTER_PATCH +#if MOVEPLACE_PATCH + IPCCOMMAND(moveplace, 1, {ARG_TYPE_UINT}), +#endif // MOVEPLACE_PATCH +#if MOVERESIZE_PATCH + IPCCOMMAND(moveresize, 1, {ARG_TYPE_STR}), +#endif // MOVERESIZE_PATCH +#if NAMETAG_PATCH + IPCCOMMAND(nametag, 1, {ARG_TYPE_NONE}), +#endif // NAMETAG_PATCH +#if RIODRAW_PATCH + IPCCOMMAND(rioresize, 1, {ARG_TYPE_NONE}), +#endif // RIODRAW_PATCH +#if PUSH_PATCH || PUSH_NO_MASTER_PATCH + IPCCOMMAND(pushdown, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(pushup, 1, {ARG_TYPE_NONE}), +#endif // PUSH_PATCH / PUSH_NO_MASTER_PATCH +#if ROTATESTACK_PATCH + IPCCOMMAND(rotatestack, 1, {ARG_TYPE_SINT}), +#endif // ROTATESTACK_PATCH +#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + IPCCOMMAND(togglescratch, 1, {ARG_TYPE_UINT}), +#endif // SCRATCHPADS_PATCH +#if SELFRESTART_PATCH + IPCCOMMAND(self_restart, 1, {ARG_TYPE_NONE}), +#endif // SELFRESTART_PATCH +#if SETBORDERPX_PATCH + IPCCOMMAND(setborderpx, 1, {ARG_TYPE_SINT}), +#endif // SETBORDERPX_PATCH +#if BAR_WINTITLEACTIONS_PATCH + IPCCOMMAND(showhideclient, 1, {ARG_TYPE_NONE}), +#endif // BAR_WINTITLEACTIONS_PATCH +#if SHIFTBOTH_PATCH + IPCCOMMAND(shiftboth, 1, {ARG_TYPE_SINT}), +#endif // SHIFTBOTH_PATCH +#if SHIFTTAG_PATCH + IPCCOMMAND(shifttag, 1, {ARG_TYPE_SINT}), +#endif // SHIFTTAG_PATCH +#if SHIFTTAGCLIENTS_PATCH + IPCCOMMAND(shifttagclients, 1, {ARG_TYPE_SINT}), +#endif // SHIFTVIEWCLIENTS_PATCH +#if SHIFTVIEW_PATCH + IPCCOMMAND(shiftview, 1, {ARG_TYPE_SINT}), +#endif // SHIFTVIEW_PATCH +#if SHIFTVIEW_CLIENTS_PATCH + IPCCOMMAND(shiftviewclients, 1, {ARG_TYPE_SINT}), +#endif // SHIFTVIEW_CLIENTS_PATCH +#if SHIFTSWAPTAGS_PATCH && SWAPTAGS_PATCH + IPCCOMMAND(shiftswaptags, 1, {ARG_TYPE_SINT}), +#endif // SHIFTSWAPTAGS_PATCH +#if STACKER_PATCH + IPCCOMMAND(pushstack, 1, {ARG_TYPE_SINT}), +#endif // STACKER_PATCH +#if STICKY_PATCH + IPCCOMMAND(togglesticky, 1, {ARG_TYPE_NONE}), +#endif // STICKY_PATCH +#if SWAPFOCUS_PATCH && PERTAG_PATCH + IPCCOMMAND(swapfocus, 1, {ARG_TYPE_SINT}), +#endif // SWAPFOCUS_PATCH +#if SWITCHCOL_PATCH + IPCCOMMAND(switchcol, 1, {ARG_TYPE_NONE}), +#endif // SWITCHCOL_PATCH +#if TAGALLMON_PATCH + IPCCOMMAND(tagallmon, 1, {ARG_TYPE_SINT}), +#endif // TAGALLMON_PATCH +#if TAGOTHERMONITOR_PATCH + IPCCOMMAND(tagnextmonex, 1, {ARG_TYPE_UINT}), + IPCCOMMAND(tagprevmonex, 1, {ARG_TYPE_UINT}), +#endif // TAGOTHERMONITOR_PATCH +#if TAGSWAPMON_PATCH + IPCCOMMAND(tagswapmon, 1, {ARG_TYPE_SINT}), +#endif // TAGSWAPMON_PATCH +#if TOGGLEFULLSCREEN_PATCH + IPCCOMMAND(togglefullscreen, 1, {ARG_TYPE_NONE}), +#endif // TOGGLEFULLSCREEN_PATCH +#if TRANSFER_PATCH + IPCCOMMAND(transfer, 1, {ARG_TYPE_NONE}), +#endif // TRANSFER_PATCH +#if TRANSFER_ALL_PATCH + IPCCOMMAND(transferall, 1, {ARG_TYPE_NONE}), +#endif // TRANSFER_ALL_PATCH +#if UNFLOATVISIBLE_PATCH + IPCCOMMAND(unfloatvisible, 1, {ARG_TYPE_NONE}), +#endif // UNFLOATVISIBLE_PATCH +#if VANITYGAPS_PATCH + IPCCOMMAND(incrgaps, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(incrigaps, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(incrogaps, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(incrihgaps, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(incrivgaps, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(incrohgaps, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(incrovgaps, 1, {ARG_TYPE_SINT}), + IPCCOMMAND(togglegaps, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(defaultgaps, 1, {ARG_TYPE_NONE}), + IPCCOMMAND(setgapsex, 1, {ARG_TYPE_SINT}), +#endif // VANITYGAPS_PATCH +#if WINVIEW_PATCH + IPCCOMMAND(winview, 1, {ARG_TYPE_NONE}), +#endif // WINVIEW_PATCH +#if XRDB_PATCH || XRESOURCES_PATCH + IPCCOMMAND(xrdb, 1, {ARG_TYPE_NONE}), +#endif // XRDB_PATCH | XRESOURCES_PATCH +}; +#endif // IPC_PATCH diff --git a/dwm/config.mk b/dwm/config.mk new file mode 100755 index 0000000..e2d98fb --- /dev/null +++ b/dwm/config.mk @@ -0,0 +1,76 @@ +# dwm version +VERSION = 6.8 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/include +X11LIB = /usr/lib + +# FreeBSD (uncomment) +#X11INC = /usr/local/include +#X11LIB = /usr/local/lib + +# Xinerama, comment if you don't want it +#XINERAMALIBS = -lXinerama +#XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +# FreeBSD (uncomment) +#FREETYPEINC = /usr/local/include/freetype2 +# OpenBSD (uncomment) +#FREETYPEINC = ${X11INC}/freetype2 +# OpenBSD - Uncomment this for the swallow patch / SWALLOW_PATCH +#KVMLIB = -lkvm + +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) +XRENDER = -lXrender + +# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH +#MPDCLIENT = -lmpdclient + +# Uncomment for the pango patch / BAR_PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -lyajl +#YAJLINC = -I/usr/include/yajl + +# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH +#XEXTLIB = -lXext + +# Uncomment this for the swallow patch / SWALLOW_PATCH +#XCBLIBS = -lX11-xcb -lxcb -lxcb-res + +# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH +#IMLIB2LIBS = -lImlib2 + +# Uncomment for the banish patch / BANISH_PATCH (for mouse related features) +#XILIB = `pkg-config --libs xi xfixes` + +# Uncomment for the bidi patch +#BDINC = `pkg-config --cflags fribidi` +#BDLIBS = `pkg-config --libs fribidi` + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} ${BDINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} $(BDLIBS) $(XILIB) + +# 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-unused-function -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/drw.c b/dwm/drw.c new file mode 100755 index 0000000..8a479fb --- /dev/null +++ b/dwm/drw.c @@ -0,0 +1,775 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "patches.h" +#include "drw.h" +#include "util.h" + +#if BIDI_PATCH +#include + +static char fribidi_text[BUFSIZ] = ""; + +static void +apply_fribidi(const char *str) +{ + FriBidiStrIndex len = strlen(str); + FriBidiChar logical[BUFSIZ]; + FriBidiChar visual[BUFSIZ]; + FriBidiParType base = FRIBIDI_PAR_ON; + FriBidiCharSet charset; + + fribidi_text[0] = 0; + if (len > 0) { + charset = fribidi_parse_charset("UTF-8"); + len = fribidi_charset_to_unicode(charset, str, len, logical); + fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL); + len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text); + } +} +#endif + +#if !BAR_PANGO_PATCH +#define UTF_INVALID 0xFFFD +#endif // BAR_PANGO_PATCH + +#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH +Clr transcheme[3]; +#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH + +#if !BAR_PANGO_PATCH +static 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; +} +#endif // BAR_PANGO_PATCH + +Drw * +#if BAR_ALPHA_PATCH +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) +#else +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +#endif // BAR_ALPHA_PATCH +{ + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; + drw->screen = screen; + drw->root = root; + drw->w = w; + drw->h = h; + + #if BAR_ALPHA_PATCH + drw->visual = visual; + drw->depth = depth; + drw->cmap = cmap; + drw->drawable = XCreatePixmap(dpy, root, w, h, depth); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, visual), 0, NULL); + #endif // BAR_WINICON_PATCH + drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); + #else + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); + #endif // BAR_WINICON_PATCH + drw->gc = XCreateGC(dpy, root, 0, NULL); + #endif // BAR_ALPHA_PATCH + 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 BAR_WINICON_PATCH + if (drw->picture) + XRenderFreePicture(drw->dpy, drw->picture); + #endif // BAR_WINICON_PATCH + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + #if BAR_ALPHA_PATCH + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, drw->visual), 0, NULL); + #endif // BAR_WINICON_PATCH + #else // !BAR_ALPHA_PATCH + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL); + #endif // BAR_WINICON_PATCH + #endif // BAR_ALPHA_PATCH +} + +void +drw_free(Drw *drw) +{ + #if BAR_WINICON_PATCH + XRenderFreePicture(drw->dpy, drw->picture); + #endif // BAR_WINICON_PATCH + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); + free(drw); +} + +#if BAR_PANGO_PATCH +/* This function is an implementation detail. Library users should use + * drw_font_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname) +{ + Fnt *font; + PangoFontMap *fontmap; + PangoContext *context; + PangoFontDescription *desc; + PangoFontMetrics *metrics; + + if (!fontname) { + die("no font specified."); + } + + font = ecalloc(1, sizeof(Fnt)); + font->dpy = drw->dpy; + + fontmap = pango_xft_get_font_map(drw->dpy, drw->screen); + context = pango_font_map_create_context(fontmap); + desc = pango_font_description_from_string(fontname); + font->layout = pango_layout_new(context); + pango_layout_set_font_description(font->layout, desc); + + metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us")); + font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); + g_object_unref(context); + + return font; +} +#else +/* This function is an implementation detail. Library users should use + * drw_fontset_create instead. + */ +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."); + } + + #if BAR_NO_COLOR_EMOJI_PATCH + /* Do not allow using color fonts. This is a workaround for a BadLength + * error from Xft with color glyphs. Modelled on the Xterm workaround. See + * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + * https://lists.suckless.org/dev/1701/30932.html + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 + * and lots more all over the internet. + */ + FcBool iscol; + if (FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + XftFontClose(drw->dpy, xfont); + return NULL; + } + #endif // BAR_NO_COLOR_EMOJI_PATCH + + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->h = xfont->ascent + xfont->descent; + font->dpy = drw->dpy; + + return font; +} +#endif // BAR_PANGO_PATCH + +static void +xfont_free(Fnt *font) +{ + if (!font) + return; + #if BAR_PANGO_PATCH + if (font->layout) + g_object_unref(font->layout); + #else + if (font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); + #endif // BAR_PANGO_PATCH + free(font); +} + +#if BAR_PANGO_PATCH +Fnt* +drw_font_create(Drw* drw, const char font[]) +{ + Fnt *fnt = NULL; + + if (!drw || !font) + return NULL; + + fnt = xfont_create(drw, font); + + return (drw->fonts = fnt); +} +#else +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + 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); +} +#endif // BAR_PANGO_PATCH + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + #if !BAR_PANGO_PATCH + drw_fontset_free(font->next); + #endif // BAR_PANGO_PATCH + xfont_free(font); + } +} + +void +drw_clr_create( + Drw *drw, + Clr *dest, + const char *clrname + #if BAR_ALPHA_PATCH + , unsigned int alpha + #endif // BAR_ALPHA_PATCH +) { + if (!drw || !dest || !clrname) + return; + + #if BAR_ALPHA_PATCH + if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, + clrname, dest)) + #if DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH + fprintf(stderr, "warning, cannot allocate color '%s'", clrname); + #else + die("error, cannot allocate color '%s'", clrname); + #endif // DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH + + dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); + #else + if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), + clrname, dest)) + #if DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH + fprintf(stderr, "warning, cannot allocate color '%s'", clrname); + #else + die("error, cannot allocate color '%s'", clrname); + #endif // DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH + + #if NO_TRANSPARENT_BORDERS_PATCH + dest->pixel |= 0xff << 24; + #endif // NO_TRANSPARENT_BORDERS_PATCH + #endif // BAR_ALPHA_PATCH +} + +/* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ +Clr * +drw_scm_create( + Drw *drw, + char *clrnames[], + #if BAR_ALPHA_PATCH + const unsigned int alphas[], + #endif // BAR_ALPHA_PATCH + 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++) + #if BAR_ALPHA_PATCH + drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); + #else + drw_clr_create(drw, &ret[i], clrnames[i]); + #endif // BAR_ALPHA_PATCH + return ret; +} + +#if !BAR_PANGO_PATCH +void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} +#endif // BAR_PANGO_PATCH + +void +drw_setscheme(Drw *drw, Clr *scm) +{ + if (drw) + drw->scheme = scm; +} + +#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH +void +drw_settrans(Drw *drw, Clr *psc, Clr *nsc) +{ + if (drw) { + transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColBorder]; + drw->scheme = transcheme; + } +} +#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) +{ + 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); +} + +#if BIDI_PATCH +int +_drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) +#else +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) +#endif // BIDI_PATCH +{ +#if BAR_PANGO_PATCH + char buf[1024]; + int i, ty, th; + unsigned int ew, eh; + XftDraw *d = NULL; + size_t len; + int render = x || y || w || h; + + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + if (w < lpad) + return x + w; + #if BAR_ALPHA_PATCH + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + #else + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + #endif // BAR_ALPHA_PATCH + x += lpad; + w -= lpad; + } + + len = strlen(text); + + if (len) { + drw_font_getexts(drw->fonts, text, len, &ew, &eh, markup); + th = eh; + /* shorten text if necessary */ + for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) { + drw_font_getexts(drw->fonts, text, len, &ew, &eh, markup); + if (eh > th) + th = eh; + } + + if (len) { + memcpy(buf, text, len); + buf[len] = '\0'; + if (len < strlen(text)) + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ + + if (render) { + ty = y + (h - th) / 2; + if (markup) + pango_layout_set_markup(drw->fonts->layout, buf, len); + else + pango_layout_set_text(drw->fonts->layout, buf, len); + pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg], + drw->fonts->layout, x * PANGO_SCALE, ty * PANGO_SCALE); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(drw->fonts->layout, NULL); + } + x += ew; + w -= ew; + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +#else + int 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; + #if BAR_ALPHA_PATCH + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + #else + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + #endif // BAR_ALPHA_PATCH + x += lpad; + w -= lpad; + } + + usedfont = drw->fonts; + if (!ellipsis_width && render) + ellipsis_width = drw_fontset_getwidth(drw, "...", markup); + if (!invalid_width && render) + invalid_width = drw_fontset_getwidth(drw, invalid, markup); + 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, markup); + x += invalid_width; + w -= invalid_width; + } + if (render && overflow) + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert, markup); + + 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); + #if BAR_NO_COLOR_EMOJI_PATCH + FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); + #endif // BAR_NO_COLOR_EMOJI_PATCH + + 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); +#endif // BAR_PANGO_PATCH +} + +#if BIDI_PATCH +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) +{ + apply_fribidi(text); + return _drw_text(drw, x, y, w, h, lpad, fribidi_text, invert, markup); +} +#endif // BIDI_PATCH + +#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH +void +drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash) +{ + if (!drw || !drw->scheme) + return; + + /* direction=1 draws right arrow */ + x = direction ? x : x + w; + w = direction ? w : -w; + /* slash=1 draws slash instead of arrow */ + unsigned int hh = slash ? (direction ? 0 : h) : h/2; + + XPoint points[] = { + {x , y }, + {x + w, y + hh }, + {x , y + h }, + }; + + XPoint bg[] = { + {x , y }, + {x + w, y }, + {x + w, y + h}, + {x , y + h}, + }; + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin); + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel); + XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin); +} +#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH + +void +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ + 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, Bool markup) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup); +} + +#if BAR_PANGO_PATCH +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup) +{ + if (!font || !text) + return; + + PangoRectangle r; + if (markup) + pango_layout_set_markup(font->layout, text, len); + else + pango_layout_set_text(font->layout, text, len); + pango_layout_get_extents(font->layout, 0, &r); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(font->layout, NULL); + if (w) + *w = r.width / PANGO_SCALE; + if (h) + *h = r.height / PANGO_SCALE; +} +#else +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; +} +#endif // BAR_PANGO_PATCH + +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/drw.h b/dwm/drw.h new file mode 100755 index 0000000..ec24e02 --- /dev/null +++ b/dwm/drw.h @@ -0,0 +1,106 @@ +/* See LICENSE file for copyright and license details. */ + +#if BAR_PANGO_PATCH +#include +#include +#endif // BAR_PANGO_PATCH + +typedef struct { + Cursor cursor; +} Cur; + +typedef struct Fnt { + Display *dpy; + unsigned int h; + #if BAR_PANGO_PATCH + PangoLayout *layout; + #else + XftFont *xfont; + FcPattern *pattern; + struct Fnt *next; + #endif // BAR_PANGO_PATCH +} Fnt; + +enum { ColFg, ColBg, ColBorder, ColFloat, ColCount }; /* Clr scheme index */ +typedef XftColor Clr; + +typedef struct { + unsigned int w, h; + Display *dpy; + int screen; + Window root; + #if BAR_ALPHA_PATCH + Visual *visual; + unsigned int depth; + Colormap cmap; + #endif // BAR_ALPHA_PATCH + Drawable drawable; + #if BAR_WINICON_PATCH + Picture picture; + #endif // BAR_WINICON_PATCH + GC gc; + Clr *scheme; + Fnt *fonts; +} Drw; + +/* Drawable abstraction */ +#if BAR_ALPHA_PATCH +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap); +#else +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +#endif // BAR_ALPHA_PATCH +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); + +/* Fnt abstraction */ +#if BAR_PANGO_PATCH +Fnt *drw_font_create(Drw* drw, const char font[]); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup); +#else +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); +#endif // BAR_PANGO_PATCH +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text, Bool markup); + +/* Colorscheme abstraction */ +void drw_clr_create( + Drw *drw, + Clr *dest, + const char *clrname + #if BAR_ALPHA_PATCH + , unsigned int alpha + #endif // BAR_ALPHA_PATCH +); +Clr *drw_scm_create( + Drw *drw, + char *clrnames[], + #if BAR_ALPHA_PATCH + const unsigned int alphas[], + #endif // BAR_ALPHA_PATCH + size_t clrcount +); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); + +/* Drawing context manipulation */ +#if !BAR_PANGO_PATCH +void drw_setfontset(Drw *drw, Fnt *set); +#endif // BAR_PANGO_PATCH +void drw_setscheme(Drw *drw, Clr *scm); +#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH +void drw_settrans(Drw *drw, Clr *psc, Clr *nsc); +#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup); +#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH +void drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash); +#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH + +/* Map functions */ +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); + diff --git a/dwm/dwm.1 b/dwm/dwm.1 new file mode 100755 index 0000000..ddc8321 --- /dev/null +++ b/dwm/dwm.1 @@ -0,0 +1,176 @@ +.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.c b/dwm/dwm.c new file mode 100755 index 0000000..0df5669 --- /dev/null +++ b/dwm/dwm.c @@ -0,0 +1,5512 @@ +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include + +#include "patches.h" +#include "drw.h" +#include "util.h" + +#if BAR_FLEXWINTITLE_PATCH +#ifndef FLEXTILE_DELUXE_LAYOUT +#define FLEXTILE_DELUXE_LAYOUT 1 +#endif +#endif + +#if BAR_PANGO_PATCH +#include +#endif // BAR_PANGO_PATCH + +#if RESTARTSIG_PATCH +#include +#endif // RESTARTSIG_PATCH + +#if XKB_PATCH +#include +#endif // XKB_PATCH + +#if SPAWNCMD_PATCH +#include +#include +#include +#define SPAWN_CWD_DELIM " []{}()<>\"':" +#endif // SPAWNCMD_PATCH + +/* macros */ +#define Button6 6 +#define Button7 7 +#define Button8 8 +#define Button9 9 +#define NUMTAGS 9 +#define NUMVIEWHIST NUMTAGS +#define BARRULES 20 +#if TAB_PATCH +#define MAXTABS 50 +#endif // TAB_PATCH +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#if BAR_ANYBAR_PATCH +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \ + * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my))) +#else +#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))) +#endif // BAR_ANYBAR_PATCH +#if ATTACHASIDE_PATCH && STICKY_PATCH +#define ISVISIBLEONTAG(C, T) ((C->tags & T) || C->issticky) +#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) +#elif ATTACHASIDE_PATCH +#define ISVISIBLEONTAG(C, T) ((C->tags & T)) +#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) +#elif STICKY_PATCH +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) +#else +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#endif // ATTACHASIDE_PATCH +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define WTYPE "_NET_WM_WINDOW_TYPE_" +#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH +#define TOTALTAGS (NUMTAGS + LENGTH(scratchpads)) +#define TAGMASK ((1 << TOTALTAGS) - 1) +#define SPTAG(i) ((1 << NUMTAGS) << (i)) +#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << NUMTAGS) +#else +#define TAGMASK ((1 << NUMTAGS) - 1) +#endif // SCRATCHPADS_PATCH +#define TEXTWM(X) (drw_fontset_getwidth(drw, (X), True) + lrpad) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X), False) + lrpad) +#define HIDDEN(C) ((getstate(C->win) == IconicState)) + +/* enums */ +enum { + #if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH + CurResizeBR, + CurResizeBL, + CurResizeTR, + CurResizeTL, + #endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH + #if DRAGMFACT_PATCH + CurResizeHorzArrow, + CurResizeVertArrow, + #endif // DRAGMFACT_PATCH + #if DRAGCFACT_PATCH + CurIronCross, + #endif // DRAGCFACT_PATCH + CurNormal, + CurResize, + CurMove, + CurLast +}; /* cursor */ + +enum { + SchemeNorm, + SchemeSel, + SchemeTitleNorm, + SchemeTitleSel, + SchemeTagsNorm, + SchemeTagsSel, + SchemeHidNorm, + SchemeHidSel, + SchemeUrg, + #if BAR_LTSYMBOL_SCHEME_PATCH + SchemeLtSymbol, + #endif // BAR_LTSYMBOL_SCHEME_PATCH + #if RENAMED_SCRATCHPADS_PATCH + SchemeScratchSel, + SchemeScratchNorm, + #endif // RENAMED_SCRATCHPADS_PATCH + #if BAR_FLEXWINTITLE_PATCH + SchemeFlexActTTB, + SchemeFlexActLTR, + SchemeFlexActMONO, + SchemeFlexActGRID, + SchemeFlexActGRD1, + SchemeFlexActGRD2, + SchemeFlexActGRDM, + SchemeFlexActHGRD, + SchemeFlexActDWDL, + SchemeFlexActSPRL, + SchemeFlexInaTTB, + SchemeFlexInaLTR, + SchemeFlexInaMONO, + SchemeFlexInaGRID, + SchemeFlexInaGRD1, + SchemeFlexInaGRD2, + SchemeFlexInaGRDM, + SchemeFlexInaHGRD, + SchemeFlexInaDWDL, + SchemeFlexInaSPRL, + SchemeFlexSelTTB, + SchemeFlexSelLTR, + SchemeFlexSelMONO, + SchemeFlexSelGRID, + SchemeFlexSelGRD1, + SchemeFlexSelGRD2, + SchemeFlexSelGRDM, + SchemeFlexSelHGRD, + SchemeFlexSelDWDL, + SchemeFlexSelSPRL, + SchemeFlexActFloat, + SchemeFlexInaFloat, + SchemeFlexSelFloat, + #endif // BAR_FLEXWINTITLE_PATCH +}; /* color schemes */ + +enum { + NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + #if BAR_WINICON_PATCH + NetWMIcon, + #endif // BAR_WINICON_PATCH + #if BAR_SYSTRAY_PATCH + NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, + NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz, + #endif // BAR_SYSTRAY_PATCH + #if BAR_EWMHTAGS_PATCH + NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop, + #endif // BAR_EWMHTAGS_PATCH + NetClientList, + #if NET_CLIENT_LIST_STACKING_PATCH + NetClientListStacking, + #endif // NET_CLIENT_LIST_STACKING_PATCH + NetLast +}; /* EWMH atoms */ + +enum { + WMProtocols, + WMDelete, + WMState, + WMTakeFocus, + #if WINDOWROLERULE_PATCH + WMWindowRole, + #endif // WINDOWROLERULE_PATCH + WMLast +}; /* default atoms */ + +#if SEAMLESS_RESTART_PATCH +enum { + ClientFields, + ClientTags, + ClientLast +}; /* dwm client atoms */ +#endif // SEAMLESS_RESTART_PATCH + +enum { + #if BAR_STATUSBUTTON_PATCH + ClkButton, + #endif // BAR_STATUSBUTTON_PATCH + #if TAB_PATCH + ClkTabBar, + #endif // TAB_PATCH + ClkTagBar, + ClkLtSymbol, + ClkStatusText, + ClkWinTitle, + ClkClientWin, + ClkRootWin, + #if XKB_PATCH + ClkXKB, + #endif // XKB_PATCH + ClkLast +}; /* clicks */ + +enum { + BAR_ALIGN_LEFT, + BAR_ALIGN_CENTER, + BAR_ALIGN_RIGHT, + BAR_ALIGN_LEFT_LEFT, + BAR_ALIGN_LEFT_RIGHT, + BAR_ALIGN_LEFT_CENTER, + BAR_ALIGN_NONE, + BAR_ALIGN_RIGHT_LEFT, + BAR_ALIGN_RIGHT_RIGHT, + BAR_ALIGN_RIGHT_CENTER, + BAR_ALIGN_LAST +}; /* bar alignment */ + +#if IPC_PATCH +typedef struct TagState TagState; +struct TagState { + int selected; + int occupied; + int urgent; +}; + +typedef struct ClientState ClientState; +struct ClientState { + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; +}; +#endif // IPC_PATCH + +typedef union { + #if IPC_PATCH + long i; + unsigned long ui; + #else + int i; + unsigned int ui; + #endif // IPC_PATCH + float f; + const void *v; +} Arg; + +typedef struct Monitor Monitor; +typedef struct Bar Bar; +struct Bar { + Window win; + Monitor *mon; + Bar *next; + int idx; + int showbar; + int topbar; + int external; + int borderpx; + int borderscheme; + int bx, by, bw, bh; /* bar geometry */ + int w[BARRULES]; // width, array length == barrules, then use r index for lookup purposes + int x[BARRULES]; // x position, array length == ^ +}; + +typedef struct { + int x; + int y; + int h; + int w; +} BarArg; + +typedef struct { + int monitor; + int bar; + int alignment; // see bar alignment enum + int (*widthfunc)(Bar *bar, BarArg *a); + int (*drawfunc)(Bar *bar, BarArg *a); + int (*clickfunc)(Bar *bar, Arg *arg, BarArg *a); + int (*hoverfunc)(Bar *bar, BarArg *a, XMotionEvent *ev); + char *name; // for debugging + int x, w; // position, width for internal use +} BarRule; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + +#if XKB_PATCH +typedef struct XkbInfo XkbInfo; +struct XkbInfo { + XkbInfo *next; + XkbInfo *prev; + int group; + Window w; +}; +#endif // XKB_PATCH + +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + #if CFACTS_PATCH + float cfact; + #endif // CFACTS_PATCH + int x, y, w, h; + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ + #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH + #if SEAMLESS_RESTART_PATCH + unsigned int idx; + #endif // SEAMLESS_RESTART_PATCH + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; + #if SWITCHTAG_PATCH + unsigned int switchtag; + #endif // SWITCHTAG_PATCH + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + #if ALWAYSONTOP_PATCH + int alwaysontop; + #endif // ALWAYSONTOP_PATCH + #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + int fakefullscreen; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #if GAMES_PATCH + int isgame; + #endif // GAMES_PATCH + #if EXRESIZE_PATCH + unsigned char expandmask; + int expandx1, expandy1, expandx2, expandy2; + #if !MAXIMIZE_PATCH + int wasfloating; + #endif // MAXIMIZE_PATCH + #endif // EXRESIZE_PATCH + #if MAXIMIZE_PATCH + int ismax, wasfloating; + #endif // MAXIMIZE_PATCH + #if AUTORESIZE_PATCH + int needresize; + #endif // AUTORESIZE_PATCH + #if CENTER_PATCH + int iscentered; + #endif // CENTER_PATCH + #if ISPERMANENT_PATCH + int ispermanent; + #endif // ISPERMANENT_PATCH + #if PLACEMOUSE_PATCH + int beingmoved; + #endif // PLACEMOUSE_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + int isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH + #if SWALLOW_PATCH + int isterminal, noswallow; + pid_t pid; + #endif // SWALLOW_PATCH + #if STEAM_PATCH + int issteam; + #endif // STEAM_PATCH + #if STICKY_PATCH + int issticky; + #endif // STICKY_PATCH + Client *next; + Client *snext; + #if SWALLOW_PATCH + Client *swallowing; + #endif // SWALLOW_PATCH + Monitor *mon; + Window win; + #if IPC_PATCH + ClientState prevstate; + #endif // IPC_PATCH + #if RENAMED_SCRATCHPADS_PATCH + char scratchkey; + #endif // RENAMED_SCRATCHPADS_PATCH + #if XKB_PATCH + XkbInfo *xkb; + #endif // XKB_PATCH + #if BAR_WINICON_PATCH + unsigned int icw, ich; + Picture icon; + #endif // BAR_WINICON_PATCH +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +#if FLEXTILE_DELUXE_LAYOUT +typedef struct { + int nmaster; + int nstack; + int layout; + int masteraxis; // master stack area + int stack1axis; // primary stack area + int stack2axis; // secondary stack area, e.g. centered master + void (*symbolfunc)(Monitor *, unsigned int); +} LayoutPreset; +#endif // FLEXTILE_DELUXE_LAYOUT + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); + #if FLEXTILE_DELUXE_LAYOUT + LayoutPreset preset; + #endif // FLEXTILE_DELUXE_LAYOUT +} Layout; + +#if INSETS_PATCH +typedef struct { + int x; + int y; + int w; + int h; +} Inset; +#endif // INSETS_PATCH + +#if PERTAG_PATCH +typedef struct Pertag Pertag; +#endif // PERTAG_PATCH +struct Monitor { + char ltsymbol[16]; + float mfact; + #if FLEXTILE_DELUXE_LAYOUT + int ltaxis[4]; + int nstack; + #endif // FLEXTILE_DELUXE_LAYOUT + int nmaster; + int num; + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + #if TAB_PATCH + int ty; /* tab bar geometry */ + #endif // TAB_PATCH + #if VANITYGAPS_PATCH + int gappih; /* horizontal gap between windows */ + int gappiv; /* vertical gap between windows */ + int gappoh; /* horizontal outer gaps */ + int gappov; /* vertical outer gaps */ + #if PERMON_VANITYGAPS_PATCH + int enablegaps; /* whether gaps are enabled */ + #endif // PERMON_VANITYGAPS_PATCH + #endif // VANITYGAPS_PATCH + #if SETBORDERPX_PATCH + int borderpx; + #endif // SETBORDERPX_PATCH + unsigned int seltags; + unsigned int sellt; + #if VIEW_HISTORY_PATCH + unsigned int tagset[NUMVIEWHIST]; + #else + unsigned int tagset[2]; + #endif // VIEW_HISTORY_PATCH + int showbar; + #if TAB_PATCH + int showtab; + int toptab; + Window tabwin; + int ntabs; + int tab_widths[MAXTABS]; + #endif // TAB_PATCH + Client *clients; + Client *sel; + Client *stack; + #if FOCUSMASTER_RETURN_PATCH + Client *tagmarked[32]; + #endif // FOCUSMASTER_RETURN_PATCH + Monitor *next; + Bar *bar; + const Layout *lt[2]; + #if BAR_ALTERNATIVE_TAGS_PATCH + unsigned int alttag; + #endif // BAR_ALTERNATIVE_TAGS_PATCH + #if PERTAG_PATCH + Pertag *pertag; + #endif // PERTAG_PATCH + #if INSETS_PATCH + Inset inset; + #endif // INSETS_PATCH + #if BAR_TAGLABELS_PATCH + char taglabel[NUMTAGS][64]; + #endif // BAR_TAGLABELS_PATCH + #if IPC_PATCH + char lastltsymbol[16]; + TagState tagstate; + Client *lastsel; + const Layout *lastlt; + #endif // IPC_PATCH + #if BAR_TAGPREVIEW_PATCH + Window tagwin; + int previewshow; + Pixmap tagmap[NUMTAGS]; + #endif // BAR_TAGPREVIEW_PATCH +}; + +typedef struct { + const char *class; + #if WINDOWROLERULE_PATCH + const char *role; + #endif // WINDOWROLERULE_PATCH + const char *instance; + const char *title; + const char *wintype; + unsigned int tags; + #if SWITCHTAG_PATCH + int switchtag; + #endif // SWITCHTAG_PATCH + #if CENTER_PATCH + int iscentered; + #endif // CENTER_PATCH + int isfloating; + #if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + int isfakefullscreen; + #endif // SELECTIVEFAKEFULLSCREEN_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + int isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH + #if ISPERMANENT_PATCH + int ispermanent; + #endif // ISPERMANENT_PATCH + #if SWALLOW_PATCH + int isterminal; + int noswallow; + #endif // SWALLOW_PATCH + #if FLOATPOS_PATCH + const char *floatpos; + #endif // FLOATPOS_PATCH + int monitor; + #if RENAMED_SCRATCHPADS_PATCH + const char scratchkey; + #endif // RENAMED_SCRATCHPADS_PATCH + #if UNMANAGED_PATCH + int unmanaged; + #endif // UNMANAGED_PATCH + #if XKB_PATCH + int xkb_layout; + #endif // XKB_PATCH + #if BORDER_RULE_PATCH + int bw; + #endif // BORDER_RULE_PATCH + #if GAMES_PATCH + int isgame; + #endif // GAMES_PATCH +} Rule; + +#if BORDER_RULE_PATCH && XKB_PATCH +#define RULE(...) { .monitor = -1, .xkb_layout = -1, .bw = -1, __VA_ARGS__ }, +#elif XKB_PATCH +#define RULE(...) { .monitor = -1, .xkb_layout = -1, __VA_ARGS__ }, +#elif BORDER_RULE_PATCH +#define RULE(...) { .monitor = -1, .bw = -1, __VA_ARGS__ }, +#else +#define RULE(...) { .monitor = -1, __VA_ARGS__ }, +#endif // XKB_PATCH + +/* Cross patch compatibility rule macro helper macros */ +#define FLOATING , .isfloating = 1 +#if CENTER_PATCH +#define CENTERED , .iscentered = 1 +#else +#define CENTERED +#endif // CENTER_PATCH +#if ISPERMANENT_PATCH +#define PERMANENT , .ispermanent = 1 +#else +#define PERMANENT +#endif // ISPERMANENT_PATCH +#if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH +#define FAKEFULLSCREEN , .isfakefullscreen = 1 +#else +#define FAKEFULLSCREEN +#endif // SELECTIVEFAKEFULLSCREEN_PATCH +#if SWALLOW_PATCH +#define NOSWALLOW , .noswallow = 1 +#define TERMINAL , .isterminal = 1 +#else +#define NOSWALLOW +#define TERMINAL +#endif // SWALLOW_PATCH +#if SWITCHTAG_PATCH +#define SWITCHTAG , .switchtag = 1 +#else +#define SWITCHTAG +#endif // SWITCHTAG_PATCH + +#if MONITOR_RULES_PATCH +typedef struct { + int monitor; + #if PERTAG_PATCH + int tag; + #endif // PERTAG_PATCH + int layout; + float mfact; + int nmaster; + int showbar; + int topbar; +} MonitorRule; +#endif // MONITOR_RULES_PATCH + +/* 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 drawbarwin(Bar *bar); +#if !FOCUSONCLICK_PATCH +static void enternotify(XEvent *e); +#endif // FOCUSONCLICK_PATCH +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +#if !STACKER_PATCH +static void focusstack(const Arg *arg); +#endif // STACKER_PATCH +static Atom getatomprop(Client *c, Atom prop, Atom req); +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); +#if KEYMODES_PATCH +static void grabdefkeys(void); +#else +static void grabkeys(void); +#endif // KEYMODES_PATCH +static void incnmaster(const Arg *arg); +#if KEYMODES_PATCH +static void keydefpress(XEvent *e); +#else +static void keypress(XEvent *e); +#endif // KEYMODES_PATCH +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 motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +#if NOBORDER_PATCH +static int noborder(Client *c); +#endif // NOBORDER_PATCH +#if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH +static void pop(Client *c); +#endif // !ZOOMSWAP_PATCH / TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH +static void propertynotify(XEvent *e); +static void quit(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); +#if BAR_SYSTRAY_PATCH +static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); +#else +static int sendevent(Client *c, Atom proto); +#endif // BAR_SYSTRAY_PATCH +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); +#if COOL_AUTOSTART_PATCH +static void sigchld(int unused); +#endif // COOL_AUTOSTART_PATCH +static void showhide(Client *c); +static void spawn(const Arg *arg); +#if RIODRAW_PATCH +static pid_t spawncmd(const Arg *arg); +#endif // RIODRAW_PATCH +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +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, Client *nextfocus); +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 updatewmhints(Client *c); +static void view(const Arg *arg); +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); + +/* bar functions */ + +#include "patch/include.h" + +/* variables */ +static const char broken[] = "broken"; +#if BAR_PANGO_PATCH || BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH +static char stext[1024]; +#else +static char stext[512]; +#endif // BAR_PANGO_PATCH | BAR_STATUS2D_PATCH +#if BAR_EXTRASTATUS_PATCH || BAR_STATUSCMD_PATCH +#if BAR_STATUS2D_PATCH +static char rawstext[1024]; +#else +static char rawstext[512]; +#endif // BAR_STATUS2D_PATCH +#endif // BAR_EXTRASTATUS_PATCH | BAR_STATUSCMD_PATCH +#if BAR_EXTRASTATUS_PATCH +#if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH +static char estext[1024]; +#else +static char estext[512]; +#endif // BAR_STATUS2D_PATCH +#if BAR_STATUSCMD_PATCH +static char rawestext[1024]; +#endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH +#endif // BAR_EXTRASTATUS_PATCH + +#if XKB_PATCH +static int xkbEventType = 0; +#endif // XKB_PATCH +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh; /* bar geometry */ +#if UNMANAGED_PATCH +static int unmanaged = 0; /* whether the window manager should manage the new window or not */ +#endif // UNMANAGED_PATCH +static int lrpad; /* sum of left and right padding for text */ +/* Some clients (e.g. alacritty) helpfully send configure requests with a new size or position + * when they detect that they have been moved to another monitor. This can cause visual glitches + * when moving (or resizing) client windows from one monitor to another. This variable is used + * internally to ignore such configure requests while movemouse or resizemouse are being used. */ +static int ignoreconfigurerequests = 0; +#if WARP_PATCH +static int force_warp = 0; // force warp in some situations, e.g. killclient +static int ignore_warp = 0; // force skip warp in some situations, e.g. dragmfact, dragcfact +#endif // WARP_PATCH +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +#if RIODRAW_PATCH +static int riodimensions[4] = { -1, -1, -1, -1 }; +static pid_t riopid = 0; +#endif // RIODRAW_PATCH +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + #if COMBO_PATCH || BAR_HOLDBAR_PATCH + [ButtonRelease] = keyrelease, + #endif // COMBO_PATCH / BAR_HOLDBAR_PATCH + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + #if !FOCUSONCLICK_PATCH + [EnterNotify] = enternotify, + #endif // FOCUSONCLICK_PATCH + [Expose] = expose, + #if BANISH_PATCH + [GenericEvent] = genericevent, + #endif // BANISH_PATCH + [FocusIn] = focusin, + [KeyPress] = keypress, + #if COMBO_PATCH || BAR_HOLDBAR_PATCH + [KeyRelease] = keyrelease, + #endif // COMBO_PATCH / BAR_HOLDBAR_PATCH + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + #if BAR_SYSTRAY_PATCH + [ResizeRequest] = resizerequest, + #endif // BAR_SYSTRAY_PATCH + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +#if BAR_SYSTRAY_PATCH +static Atom xatom[XLast]; +#endif // BAR_SYSTRAY_PATCH +#if SEAMLESS_RESTART_PATCH +static Atom clientatom[ClientLast]; +#endif // SEAMLESS_RESTART_PATCH +#if ON_EMPTY_KEYS_PATCH +static int isempty = 0; +#endif // ON_EMPTY_KEYS_PATCH +#if RESTARTSIG_PATCH +static volatile sig_atomic_t running = 1; +#else +static int running = 1; +#endif // RESTARTSIG_PATCH +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" + +#include "patch/include.c" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +#if SCRATCHPAD_ALT_1_PATCH +struct NumTags { char limitexceeded[NUMTAGS > 30 ? -1 : 1]; }; +#else +struct NumTags { char limitexceeded[NUMTAGS > 31 ? -1 : 1]; }; +#endif // SCRATCHPAD_ALT_1_PATCH + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + Atom wintype; + #if WINDOWROLERULE_PATCH + char role[64]; + #endif // WINDOWROLERULE_PATCH + unsigned int i; + #if SWITCHTAG_PATCH + unsigned int newtagset; + #endif // SWITCHTAG_PATCH + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + #if SWALLOW_PATCH + c->noswallow = -1; + #endif // SWALLOW_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + c->isfreesize = 1; + #endif // SIZEHINTS_ISFREESIZE_PATCH + c->isfloating = 0; + c->tags = 0; + #if RENAMED_SCRATCHPADS_PATCH + c->scratchkey = 0; + #endif // RENAMED_SCRATCHPADS_PATCH + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM); + #if WINDOWROLERULE_PATCH + gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role)); + #endif // WINDOWROLERULE_PATCH + + #if STEAM_PATCH + if (strstr(class, "Steam") || strstr(class, "steam_app_")) + c->issteam = 1; + #endif // STEAM_PATCH + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + #if WINDOWROLERULE_PATCH + && (!r->role || strstr(role, r->role)) + #endif // WINDOWROLERULE_PATCH + && (!r->instance || strstr(instance, r->instance)) + && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False))) + { + #if CENTER_PATCH + c->iscentered = r->iscentered; + #endif // CENTER_PATCH + #if BORDER_RULE_PATCH + if (r->bw != -1) + c->bw = r->bw; + #endif // BORDER_RULE_PATCH + #if ISPERMANENT_PATCH + c->ispermanent = r->ispermanent; + #endif // ISPERMANENT_PATCH + #if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + c->fakefullscreen = r->isfakefullscreen; + #endif // SELECTIVEFAKEFULLSCREEN_PATCH + #if GAMES_PATCH + c->isgame = r->isgame; + #endif // GAMES_PATCH + #if SWALLOW_PATCH + c->isterminal = r->isterminal; + c->noswallow = r->noswallow; + #endif // SWALLOW_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + c->isfreesize = r->isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH + c->isfloating = r->isfloating; + c->tags |= r->tags; + #if RENAMED_SCRATCHPADS_PATCH + c->scratchkey = r->scratchkey; + #elif SCRATCHPADS_PATCH + if ((r->tags & SPTAGMASK) && r->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + #endif // SCRATCHPADS_PATCH + #if UNMANAGED_PATCH + unmanaged = r->unmanaged; + #endif // UNMANAGED_PATCH + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + #if FLOATPOS_PATCH + if (c->isfloating && r->floatpos) { + #if CENTER_PATCH + c->iscentered = 0; + #endif // CENTER_PATCH + setfloatpos(c, r->floatpos); + } + #endif // FLOATPOS_PATCH + + #if SWITCHTAG_PATCH + #if SWALLOW_PATCH + if (r->switchtag && ( + c->noswallow > 0 || + !termforwin(c) || + !(c->isfloating && swallowfloating && c->noswallow < 0))) + #else + if (r->switchtag) + #endif // SWALLOW_PATCH + { + unfocus(selmon->sel, 1, NULL); + selmon = c->mon; + if (r->switchtag == 2 || r->switchtag == 4) + newtagset = c->mon->tagset[c->mon->seltags] ^ c->tags; + else + newtagset = c->tags; + + /* Switch to the client's tag, but only if that tag is not already shown */ + if (newtagset && !(c->tags & c->mon->tagset[c->mon->seltags])) { + if (r->switchtag == 3 || r->switchtag == 4) + c->switchtag = c->mon->tagset[c->mon->seltags]; + if (r->switchtag == 1 || r->switchtag == 3) { + view(&((Arg) { .ui = newtagset })); + } else { + #if TAGSYNC_PATCH + for (m = mons; m; m = m->next) + m->tagset[m->seltags] = newtagset; + arrange(NULL); + #else + c->mon->tagset[c->mon->seltags] = newtagset; + arrange(c->mon); + #endif // TAGSYNC_PATCH + } + } + } + #endif // SWITCHTAG_PATCH + #if XKB_PATCH + if (r->xkb_layout > -1) + c->xkb->group = r->xkb_layout; + #endif // XKB_PATCH + #if ONLY_ONE_RULE_MATCH_PATCH + break; + #endif // ONLY_ONE_RULE_MATCH_PATCH + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + #if EMPTYVIEW_PATCH + if (c->tags & TAGMASK) c->tags = c->tags & TAGMASK; + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + else if (c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags] & ~SPTAGMASK; + #elif SCRATCHPAD_ALT_1_PATCH + else if (c->tags != SCRATCHPAD_MASK && c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags]; + #else + else if (c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags]; + #endif // SCRATCHPADS_PATCH + else c->tags = 1; + #elif SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK); + #elif SCRATCHPAD_ALT_1_PATCH + if (c->tags != SCRATCHPAD_MASK) + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; + #else + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; + #endif // EMPTYVIEW_PATCH +} + +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) +{ + #if BAR_PADDING_SMART_PATCH + updatebarpos(selmon); + for (Bar *bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #endif // BAR_PADDING_SMART_PATCH + #if TAB_PATCH + updatebarpos(m); + XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); + #endif // TAB_PATCH + 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) +{ + int click, i, r; + #if TAB_PATCH + int x; + #endif // TAB_PATCH + Arg arg = {0}; + Client *c; + Monitor *m; + Bar *bar; + XButtonPressedEvent *ev = &e->xbutton; + const BarRule *br; + BarArg carg = { 0, 0, 0, 0 }; + click = ClkRootWin; + + #if BAR_STATUSCMD_PATCH && !BAR_DWMBLOCKS_PATCH + *lastbutton = '0' + ev->button; + #endif // BAR_STATUSCMD_PATCH | BAR_DWMBLOCKS_PATCH + + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon + #if FOCUSONCLICK_PATCH + && (focusonwheel || (ev->button != Button4 && ev->button != Button5)) + #endif // FOCUSONCLICK_PATCH + ) { + unfocus(selmon->sel, 1, NULL); + selmon = m; + focus(NULL); + } + + #if BANISH_PATCH + c = wintoclient(ev->window); + + if (!c && cursor_hidden) { + c = recttoclient(mouse_x, mouse_y, 1, 1, 1); + showcursor(NULL); + } + + if (c) { + #if FOCUSONCLICK_PATCH + if (focusonwheel || (ev->button != Button4 && ev->button != Button5)) + focus(c); + #else + focus(c); + restack(selmon); + #endif // FOCUSONCLICK_PATCH + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + #endif // BANISH_PATCH + + for (bar = selmon->bar; bar; bar = bar->next) { + if (ev->window == bar->win) { + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) { + carg.x = ev->x - bar->x[r]; + carg.y = ev->y - bar->borderpx; + carg.w = bar->w[r]; + carg.h = bar->bh - 2 * bar->borderpx; + click = br->clickfunc(bar, &arg, &carg); + if (click < 0) + return; + break; + } + } + break; + } + } + + #if TAB_PATCH + if (ev->window == selmon->tabwin) { + for (i = 0, x = 0, c = selmon->clients; c; c = c->next) { + if (!ISVISIBLE(c) || HIDDEN(c)) + continue; + x += selmon->tab_widths[i]; + if (ev->x > x) + ++i; + else + break; + if (i >= m->ntabs) + break; + } + if (c) { + click = ClkTabBar; + arg.ui = i; + } + } + #endif // TAB_PATCH + + #if !BANISH_PATCH + if (click == ClkRootWin && (c = wintoclient(ev->window))) { + #if FOCUSONCLICK_PATCH + if (focusonwheel || (ev->button != Button4 && ev->button != Button5)) + focus(c); + #else + focus(c); + restack(selmon); + #endif // FOCUSONCLICK_PATCH + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + #endif // BANISH_PATCH + + 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 + #if TAB_PATCH + || click == ClkTabBar + #endif // TAB_PATCH + #if BAR_WINTITLEACTIONS_PATCH + || click == ClkWinTitle + #endif // BAR_WINTITLEACTIONS_PATCH + ) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg + ); + } + } + + #if BANISH_PATCH + last_button_press = now(); + #endif // BANISH_PATCH +} + +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) +{ + Monitor *m; + Layout foo = { "", NULL }; + size_t i; + + #if ALT_TAB_PATCH + alttabend(); + #endif // ALT_TAB_PATCH + + #if SEAMLESS_RESTART_PATCH + for (m = mons; m; m = m->next) + persistmonitorstate(m); + #endif // SEAMLESS_RESTART_PATCH + + #if COOL_AUTOSTART_PATCH + /* kill child processes */ + for (i = 0; i < autostart_len; i++) { + if (0 < autostart_pids[i]) { + kill(autostart_pids[i], SIGTERM); + waitpid(autostart_pids[i], NULL, 0); + } + } + #endif // COOL_AUTOSTART_PATCH + + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + #if BAR_SYSTRAY_PATCH + if (showsystray && systray) { + while (systray->icons) + removesystrayicon(systray->icons); + if (systray->win) { + XUnmapWindow(dpy, systray->win); + XDestroyWindow(dpy, systray->win); + } + free(systray); + } + #endif // BAR_SYSTRAY_PATCH + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + #if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH + for (i = 0; i < LENGTH(colors) + 1; i++) + #else + for (i = 0; i < LENGTH(colors); i++) + #endif // BAR_STATUS2D_PATCH + free(scheme[i]); + free(scheme); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + + #if IPC_PATCH + ipc_cleanup(); + + if (close(epoll_fd) < 0) + fprintf(stderr, "Failed to close epoll file descriptor\n"); + #endif // IPC_PATCH +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + Bar *bar; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + for (bar = mon->bar; bar; bar = mon->bar) { + if (!bar->external) { + XUnmapWindow(dpy, bar->win); + XDestroyWindow(dpy, bar->win); + } + mon->bar = bar->next; + #if BAR_SYSTRAY_PATCH + if (systray && bar == systray->bar) + systray->bar = NULL; + #endif // BAR_SYSTRAY_PATCH + free(bar); + } + #if TAB_PATCH + XUnmapWindow(dpy, mon->tabwin); + XDestroyWindow(dpy, mon->tabwin); + #endif // TAB_PATCH + #if PERTAG_PATCH + free(mon->pertag); + #endif // PERTAG_PATCH + #if BAR_TAGPREVIEW_PATCH + for (size_t i = 0; i < NUMTAGS; i++) + if (mon->tagmap[i]) + XFreePixmap(dpy, mon->tagmap[i]); + XUnmapWindow(dpy, mon->tagwin); + XDestroyWindow(dpy, mon->tagwin); + #endif // BAR_TAGPREVIEW_PATCH + free(mon); +} + +void +clientmessage(XEvent *e) +{ + #if BAR_SYSTRAY_PATCH + XWindowAttributes wa; + XSetWindowAttributes swa; + #endif // BAR_SYSTRAY_PATCH + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + #if FOCUSONNETACTIVE_PATCH + unsigned int i; + #endif // FOCUSONNETACTIVE_PATCH + + #if BAR_SYSTRAY_PATCH + if (showsystray && systray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { + /* add systray icons */ + if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { + if (!(c = (Client *)calloc(1, sizeof(Client)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Client)); + if (!(c->win = cme->data.l[2])) { + free(c); + return; + } + + c->mon = selmon; + c->next = systray->icons; + systray->icons = c; + XGetWindowAttributes(dpy, c->win, &wa); + c->x = c->oldx = c->y = c->oldy = 0; + c->w = c->oldw = wa.width; + c->h = c->oldh = wa.height; + c->oldbw = wa.border_width; + c->bw = 0; + c->isfloating = True; + /* reuse tags field as mapped status */ + c->tags = 1; + updatesizehints(c); + updatesystrayicongeom(c, wa.width, wa.height); + XAddToSaveSet(dpy, c->win); + XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); + XClassHint ch = {"dwmsystray", "dwmsystray"}; + XSetClassHint(dpy, c->win, &ch); + XReparentWindow(dpy, c->win, systray->win, 0, 0); + /* use parents background color */ + swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); + XSync(dpy, False); + setclientstate(c, NormalState); + } + return; + } + #endif // BAR_SYSTRAY_PATCH + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) { + #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + if (c->fakefullscreen == 2 && c->isfullscreen) + c->fakefullscreen = 3; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ + #if !FAKEFULLSCREEN_PATCH + && !c->isfullscreen + #endif // !FAKEFULLSCREEN_PATCH + ))); + } + } else if (cme->message_type == netatom[NetActiveWindow]) { + #if FOCUSONNETACTIVE_PATCH + if (c->tags & c->mon->tagset[c->mon->seltags]) + focus(c); + else { + for (i = 0; i < NUMTAGS && !((1 << i) & c->tags); i++); + if (i < NUMTAGS) { + if (c != selmon->sel) + unfocus(selmon->sel, 0, NULL); + selmon = c->mon; + if (((1 << i) & TAGMASK) != selmon->tagset[selmon->seltags]) + view(&((Arg) { .ui = 1 << i })); + focus(c); + restack(selmon); + } + } + #else + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + #endif // FOCUSONNETACTIVE_PATCH + } +} + +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; + + #if NOBORDER_PATCH + if (noborder(c)) { + ce.width += c->bw * 2; + ce.height += c->bw * 2; + ce.border_width = 0; + } + #endif // NOBORDER_PATCH + + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Bar *bar; + #if !FAKEFULLSCREEN_PATCH + Client *c; + #endif // !FAKEFULLSCREEN_PATCH + 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, sh); + updatebars(); + for (m = mons; m; m = m->next) { + #if !FAKEFULLSCREEN_PATCH + for (c = m->clients; c; c = c->next) + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && c->fakefullscreen != 1) + #else + if (c->isfullscreen) + #endif // FAKEFULLSCREEN_CLIENT_PATCH + resizeclient(c, m->mx, m->my, m->mw, m->mh); + #endif // !FAKEFULLSCREEN_PATCH + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #if BAR_TAGPREVIEW_PATCH + createpreview(m); + #endif // BAR_TAGPREVIEW_PATCH + } + arrange(NULL); + focus(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + #if BAR_ANYBAR_PATCH + Bar *bar; + #endif // BAR_ANYBAR_PATCH + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if (ignoreconfigurerequests) + return; + + 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 STEAM_PATCH + if (!c->issteam) { + 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; + } + } + #else + 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; + } + #endif // STEAM_PATCH + 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); + #if AUTORESIZE_PATCH + else + c->needresize = 1; + #endif // AUTORESIZE_PATCH + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + #if BAR_ANYBAR_PATCH + m = wintomon(ev->window); + for (bar = m->bar; bar; bar = bar->next) { + if (bar->win == ev->window) { + wc.y = bar->by; + wc.x = bar->bx; + } + } + #endif // BAR_ANYBAR_PATCH + 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, *mon; + int i, n, mi, max_bars = 2, istopbar = topbar; + #if MONITOR_RULES_PATCH + int layout; + #endif // MONITOR_RULES_PATCH + + const BarRule *br; + Bar *bar; + #if MONITOR_RULES_PATCH + int j; + const MonitorRule *mr; + #endif // MONITOR_RULES_PATCH + + m = ecalloc(1, sizeof(Monitor)); + #if !EMPTYVIEW_PATCH + #if VIEW_HISTORY_PATCH + for (i = 0; i < LENGTH(m->tagset); i++) + m->tagset[i] = 1; + #else + m->tagset[0] = m->tagset[1] = 1; + #endif // VIEW_HISTORY_PATCH + #endif // EMPTYVIEW_PATCH + m->mfact = mfact; + m->nmaster = nmaster; + #if FLEXTILE_DELUXE_LAYOUT + m->nstack = nstack; + #endif // FLEXTILE_DELUXE_LAYOUT + m->showbar = showbar; + #if TAB_PATCH + m->showtab = showtab; + m->toptab = toptab; + m->ntabs = 0; + #endif // TAB_PATCH + #if SETBORDERPX_PATCH + m->borderpx = borderpx; + #endif // SETBORDERPX_PATCH + #if VANITYGAPS_PATCH + m->gappih = gappih; + m->gappiv = gappiv; + m->gappoh = gappoh; + m->gappov = gappov; + #endif // VANITYGAPS_PATCH + for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index + m->num = mi; + #if MONITOR_RULES_PATCH + for (j = 0; j < LENGTH(monrules); j++) { + mr = &monrules[j]; + if ((mr->monitor == -1 || mr->monitor == m->num) + #if PERTAG_PATCH + && (mr->tag <= 0 || (m->tagset[0] & (1 << (mr->tag - 1)))) + #endif // PERTAG_PATCH + ) { + layout = MAX(mr->layout, 0); + layout = MIN(layout, LENGTH(layouts) - 1); + m->lt[0] = &layouts[layout]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[layout].symbol, sizeof m->ltsymbol); + + if (mr->mfact > -1) + m->mfact = mr->mfact; + if (mr->nmaster > -1) + m->nmaster = mr->nmaster; + if (mr->showbar > -1) + m->showbar = mr->showbar; + if (mr->topbar > -1) + istopbar = mr->topbar; + break; + } + } + #else + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + #endif // MONITOR_RULES_PATCH + + /* Derive the number of bars for this monitor based on bar rules */ + for (n = -1, i = 0; i < LENGTH(barrules); i++) { + br = &barrules[i]; + if (br->monitor == 'A' || br->monitor == -1 || br->monitor == m->num) + n = MAX(br->bar, n); + } + + m->bar = NULL; + for (i = 0; i <= n && i < max_bars; i++) { + bar = ecalloc(1, sizeof(Bar)); + bar->mon = m; + bar->idx = i; + bar->next = m->bar; + bar->topbar = istopbar; + m->bar = bar; + istopbar = !istopbar; + bar->showbar = 1; + bar->external = 0; + #if BAR_BORDER_PATCH + bar->borderpx = (barborderpx ? barborderpx : borderpx); + #else + bar->borderpx = 0; + #endif // BAR_BORDER_PATCH + bar->bh = bh + bar->borderpx * 2; + bar->borderscheme = SchemeNorm; + } + + #if FLEXTILE_DELUXE_LAYOUT + m->ltaxis[LAYOUT] = m->lt[0]->preset.layout; + m->ltaxis[MASTER] = m->lt[0]->preset.masteraxis; + m->ltaxis[STACK] = m->lt[0]->preset.stack1axis; + m->ltaxis[STACK2] = m->lt[0]->preset.stack2axis; + #endif // FLEXTILE_DELUXE_LAYOUT + + #if PERTAG_PATCH + if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); + m->pertag->curtag = 1; + for (i = 0; i <= NUMTAGS; i++) { + #if FLEXTILE_DELUXE_LAYOUT + m->pertag->nstacks[i] = m->nstack; + #endif // FLEXTILE_DELUXE_LAYOUT + + #if !MONITOR_RULES_PATCH + /* init nmaster */ + m->pertag->nmasters[i] = m->nmaster; + + /* init mfacts */ + m->pertag->mfacts[i] = m->mfact; + + #if PERTAGBAR_PATCH + /* init showbar */ + m->pertag->showbars[i] = m->showbar; + #endif // PERTAGBAR_PATCH + #endif // MONITOR_RULES_PATCH + + #if ZOOMSWAP_PATCH + m->pertag->prevzooms[i] = NULL; + #endif // ZOOMSWAP_PATCH + + /* init layouts */ + #if MONITOR_RULES_PATCH + for (j = 0; j < LENGTH(monrules); j++) { + mr = &monrules[j]; + if ((mr->monitor == -1 || mr->monitor == m->num) && (mr->tag == -1 || mr->tag == i)) { + layout = MAX(mr->layout, 0); + layout = MIN(layout, LENGTH(layouts) - 1); + m->pertag->ltidxs[i][0] = &layouts[layout]; + m->pertag->ltidxs[i][1] = m->lt[0]; + m->pertag->nmasters[i] = (mr->nmaster > -1 ? mr->nmaster : m->nmaster); + m->pertag->mfacts[i] = (mr->mfact > -1 ? mr->mfact : m->mfact); + #if PERTAGBAR_PATCH + m->pertag->showbars[i] = (mr->showbar > -1 ? mr->showbar : m->showbar); + #endif // PERTAGBAR_PATCH + #if FLEXTILE_DELUXE_LAYOUT + m->pertag->ltaxis[i][LAYOUT] = m->pertag->ltidxs[i][0]->preset.layout; + m->pertag->ltaxis[i][MASTER] = m->pertag->ltidxs[i][0]->preset.masteraxis; + m->pertag->ltaxis[i][STACK] = m->pertag->ltidxs[i][0]->preset.stack1axis; + m->pertag->ltaxis[i][STACK2] = m->pertag->ltidxs[i][0]->preset.stack2axis; + #endif // FLEXTILE_DELUXE_LAYOUT + break; + } + } + #else + m->pertag->ltidxs[i][0] = m->lt[0]; + m->pertag->ltidxs[i][1] = m->lt[1]; + #if FLEXTILE_DELUXE_LAYOUT + /* init flextile axes */ + m->pertag->ltaxis[i][LAYOUT] = m->ltaxis[LAYOUT]; + m->pertag->ltaxis[i][MASTER] = m->ltaxis[MASTER]; + m->pertag->ltaxis[i][STACK] = m->ltaxis[STACK]; + m->pertag->ltaxis[i][STACK2] = m->ltaxis[STACK2]; + #endif // FLEXTILE_DELUXE_LAYOUT + #endif // MONITOR_RULES_PATCH + m->pertag->sellts[i] = m->sellt; + + #if PERTAG_VANITYGAPS_PATCH && VANITYGAPS_PATCH + m->pertag->enablegaps[i] = 1; + m->pertag->gaps[i] = + ((gappoh & 0xFF) << 0) | ((gappov & 0xFF) << 8) | ((gappih & 0xFF) << 16) | ((gappiv & 0xFF) << 24); + #endif // PERTAG_VANITYGAPS_PATCH | VANITYGAPS_PATCH + } + #endif // PERTAG_PATCH + + #if PERMON_VANITYGAPS_PATCH + m->enablegaps = 1; + #endif // PERMON_VANITYGAPS_PATCH + + #if SEAMLESS_RESTART_PATCH + restoremonitorstate(m); + #endif // SEAMLESS_RESTART_PATCH + + #if INSETS_PATCH + m->inset = default_inset; + #endif // INSETS_PATCH + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + #if BAR_ANYBAR_PATCH + Monitor *m; + Bar *bar; + #endif // BAR_ANYBAR_PATCH + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); + #if SWALLOW_PATCH + else if ((c = swallowingclient(ev->window))) + unmanage(c->swallowing, 1); + #endif // SWALLOW_PATCH + #if BAR_SYSTRAY_PATCH + else if (showsystray && (c = wintosystrayicon(ev->window))) { + removesystrayicon(c); + drawbarwin(systray->bar); + } + #endif // BAR_SYSTRAY_PATCH + #if BAR_ANYBAR_PATCH + else { + m = wintomon(ev->window); + for (bar = m->bar; bar; bar = bar->next) { + if (bar->win == ev->window) { + unmanagealtbar(ev->window); + break; + } + } + } + #endif // BAR_ANYBAR_PATCH +} + +void +detach(Client *c) +{ + Client **tc; + #if SEAMLESS_RESTART_PATCH + c->idx = 0; + #endif // SEAMLESS_RESTART_PATCH + #if FOCUSMASTER_RETURN_PATCH + for (int i = 1; i < NUMTAGS; i++) + if (c == c->mon->tagmarked[i]) + c->mon->tagmarked[i] = NULL; + #endif // FOCUSMASTER_RETURN_PATCH + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; + c->next = NULL; +} + +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; + } + c->snext = NULL; +} + +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) +{ + Bar *bar; + + #if !BAR_FLEXWINTITLE_PATCH + if (m->showbar) + #endif // BAR_FLEXWINTITLE_PATCH + for (bar = m->bar; bar; bar = bar->next) + drawbarwin(bar); +} + +void +drawbars(void) +{ + Monitor *m; + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +drawbarwin(Bar *bar) +{ + if (!bar || !bar->win || bar->external) + return; + int r, w, total_drawn = 0; + int rx, lx, rw, lw; // bar size, split between left and right if a center module is added + const BarRule *br; + + if (bar->borderpx) { + #if BAR_BORDER_COLBG_PATCH + XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBg].pixel); + #else + XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBorder].pixel); + #endif // BAR_BORDER_COLBG_PATCH + XFillRectangle(drw->dpy, drw->drawable, drw->gc, 0, 0, bar->bw, bar->bh); + } + + BarArg warg = { 0 }; + BarArg darg = { 0 }; + warg.h = bar->bh - 2 * bar->borderpx; + + rw = lw = bar->bw - 2 * bar->borderpx; + rx = lx = bar->borderpx; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, lx, bar->borderpx, lw, bar->bh - 2 * bar->borderpx, 1, 1); + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || !br->widthfunc || (br->monitor == 'A' && bar->mon != selmon)) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + drw_setscheme(drw, scheme[SchemeNorm]); + warg.w = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw); + + w = br->widthfunc(bar, &warg); + w = MIN(warg.w, w); + + if (lw <= 0) { // if left is exhausted then switch to right side, and vice versa + lw = rw; + lx = rx; + } else if (rw <= 0) { + rw = lw; + rx = lx; + } + + switch(br->alignment) { + default: + case BAR_ALIGN_NONE: + case BAR_ALIGN_LEFT_LEFT: + case BAR_ALIGN_LEFT: + bar->x[r] = lx; + if (lx == rx) { + rx += w; + rw -= w; + } + lx += w; + lw -= w; + break; + case BAR_ALIGN_LEFT_RIGHT: + case BAR_ALIGN_RIGHT: + bar->x[r] = lx + lw - w; + if (lx == rx) + rw -= w; + lw -= w; + break; + case BAR_ALIGN_LEFT_CENTER: + case BAR_ALIGN_CENTER: + bar->x[r] = lx + lw / 2 - w / 2; + if (lx == rx) { + rw = rx + rw - bar->x[r] - w; + rx = bar->x[r] + w; + } + lw = bar->x[r] - lx; + break; + case BAR_ALIGN_RIGHT_LEFT: + bar->x[r] = rx; + if (lx == rx) { + lx += w; + lw -= w; + } + rx += w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_RIGHT: + bar->x[r] = rx + rw - w; + if (lx == rx) + lw -= w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_CENTER: + bar->x[r] = rx + rw / 2 - w / 2; + if (lx == rx) { + lw = lx + lw - bar->x[r] + w; + lx = bar->x[r] + w; + } + rw = bar->x[r] - rx; + break; + } + bar->w[r] = w; + darg.x = bar->x[r]; + darg.y = bar->borderpx; + darg.h = bar->bh - 2 * bar->borderpx; + darg.w = bar->w[r]; + if (br->drawfunc) + total_drawn += br->drawfunc(bar, &darg); + } + + if (total_drawn == 0 && bar->showbar) { + bar->showbar = 0; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(bar->mon); + } + else if (total_drawn > 0 && !bar->showbar) { + bar->showbar = 1; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); + arrange(bar->mon); + } else + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); +} + +#if !FOCUSONCLICK_PATCH +void +enternotify(XEvent *e) +{ + Client *c; + #if LOSEFULLSCREEN_PATCH + Client *sel; + #endif // LOSEFULLSCREEN_PATCH + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + #if BANISH_PATCH + if (cursor_hidden) + return; + #endif // BANISH_PATCH + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + #if LOSEFULLSCREEN_PATCH + sel = selmon->sel; + selmon = m; + unfocus(sel, 1, c); + #else + unfocus(selmon->sel, 1, c); + selmon = m; + #endif // LOSEFULLSCREEN_PATCH + } else if (!c || c == selmon->sel) + return; + focus(c); +} +#endif // FOCUSONCLICK_PATCH + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) { + drawbar(m); + #if TAB_PATCH + drawtabs(); + #endif // TAB_PATCH + } +} + +void +focus(Client *c) +{ + #if FOCUSFOLLOWMOUSE_PATCH + if (!c || !ISVISIBLE(c)) + c = getpointerclient(); + #endif // FOCUSFOLLOWMOUSE_PATCH + #if STICKY_PATCH + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && (!ISVISIBLE(c) || c->issticky); c = c->snext); + #endif // STICKY_PATCH + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0, c); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + #if !BAR_FLEXWINTITLE_PATCH + #if RENAMED_SCRATCHPADS_PATCH + if (c->scratchkey != 0 && c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColFloat].pixel); + else if (c->scratchkey != 0) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColBorder].pixel); + else if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + #else + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + #endif // RENAMED_SCRATCHPADS_PATCH + #endif // BAR_FLEXWINTITLE_PATCH + setfocus(c); + } else { + #if NODMENU_PATCH + XSetInputFocus(dpy, selmon->bar && selmon->bar->win ? selmon->bar->win : root, RevertToPointerRoot, CurrentTime); + #else + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + #endif // NODMENU_PATCH + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); + + #if ON_EMPTY_KEYS_PATCH + if ((isempty && selmon->sel) || (!isempty && !selmon->sel)) { + isempty = !isempty; + grabkeys(); + } + #endif // ON_EMPTY_KEYS_PATCH +} + +/* 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 LOSEFULLSCREEN_PATCH + Client *sel; + #endif // LOSEFULLSCREEN_PATCH + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + #if LOSEFULLSCREEN_PATCH + sel = selmon->sel; + selmon = m; + unfocus(sel, 0, NULL); + #else + unfocus(selmon->sel, 0, NULL); + selmon = m; + #endif // LOSEFULLSCREEN_PATCH + focus(NULL); + #if WARP_PATCH + warp(selmon->sel); + #endif // WARP_PATCH +} + +#if !STACKER_PATCH +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + #if LOSEFULLSCREEN_PATCH + if (!selmon->sel) + return; + #elif FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + if (!selmon->sel || (selmon->sel->isfullscreen && !selmon->sel->fakefullscreen)) + return; + #else + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) + return; + #endif // LOSEFULLSCREEN_PATCH + #if BAR_WINTITLEACTIONS_PATCH + if (arg->i > 0) { + for (c = selmon->sel->next; c && (!ISVISIBLE(c) || (arg->i == 1 && HIDDEN(c))); c = c->next); + if (!c) + for (c = selmon->clients; c && (!ISVISIBLE(c) || (arg->i == 1 && HIDDEN(c))); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i) && !(arg->i == -1 && HIDDEN(i))) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i) && !(arg->i == -1 && HIDDEN(i))) + c = i; + } + #else + 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; + } + #endif // BAR_WINTITLEACTIONS_PATCH + if (c) { + focus(c); + restack(selmon); + } +} +#endif // STACKER_PATCH + +Atom +getatomprop(Client *c, Atom prop, Atom req) +{ + int di; + unsigned long nitems, dl; + unsigned char *p = NULL; + Atom da, atom = None; + + #if BAR_SYSTRAY_PATCH + if (prop == xatom[XembedInfo]) + req = xatom[XembedInfo]; + #endif // BAR_SYSTRAY_PATCH + + /* FIXME getatomprop should return the number of items and a pointer to + * the stored data instead of this workaround */ + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, + &da, &di, &nitems, &dl, &p) == Success && p) { + if (nitems > 0) + atom = *(Atom *)p; + #if BAR_SYSTRAY_PATCH + if (da == xatom[XembedInfo] && dl == 2) + atom = ((Atom *)p)[1]; + #endif // BAR_SYSTRAY_PATCH + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + #if BANISH_PATCH + if (cursor_hidden) { + *x = mouse_x; + *y = mouse_y; + return 1; + } + #endif // BANISH_PATCH + + 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 + #if NO_MOD_BUTTONS_PATCH + && (nomodbuttons || buttons[i].mask != 0) + #endif // NO_MOD_BUTTONS_PATCH + ) + 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 +#if KEYMODES_PATCH +grabdefkeys(void) +#else +grabkeys(void) +#endif // KEYMODES_PATCH +{ + 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); + #if ON_EMPTY_KEYS_PATCH + if (!selmon->sel) + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(on_empty_keys); i++) + /* skip modifier codes, we do that ourselves */ + if (on_empty_keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + on_empty_keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); + #endif // ON_EMPTY_KEYS_PATCH + XFree(syms); + } +} + +void +incnmaster(const Arg *arg) +{ + #if PERTAG_PATCH + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + #else + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + #endif // PERTAG_PATCH + 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 +#if KEYMODES_PATCH +keydefpress(XEvent *e) +#else +keypress(XEvent *e) +#endif // KEYMODES_PATCH +{ + unsigned int i; + int keysyms_return; + KeySym* keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XGetKeyboardMapping(dpy, (KeyCode)ev->keycode, 1, &keysyms_return); + 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)); + #if ON_EMPTY_KEYS_PATCH + if (!selmon->sel) + for (i = 0; i < LENGTH(on_empty_keys); i++) + if (*keysym == on_empty_keys[i].keysym + && CLEANMASK(on_empty_keys[i].mod) == CLEANMASK(ev->state) + && on_empty_keys[i].func) + on_empty_keys[i].func(&(on_empty_keys[i].arg)); + #endif // ON_EMPTY_KEYS_PATCH + XFree(keysym); +} + +void +killclient(const Arg *arg) +{ + #if ISPERMANENT_PATCH + if (!selmon->sel || selmon->sel->ispermanent) + #else + if (!selmon->sel) + #endif // ISPERMANENT_PATCH + return; + #if BAR_SYSTRAY_PATCH + if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0, 0, 0)) + #else + if (!sendevent(selmon->sel, wmatom[WMDelete])) + #endif // BAR_SYSTRAY_PATCH + { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + #if WARP_PATCH + force_warp = 1; + #endif // WARP_PATCH + } + #if SWAPFOCUS_PATCH && PERTAG_PATCH + selmon->pertag->prevclient[selmon->pertag->curtag] = NULL; + #endif // SWAPFOCUS_PATCH +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL; + #if SWALLOW_PATCH + Client *term = NULL; + #endif // SWALLOW_PATCH + #if SEAMLESS_RESTART_PATCH + int settings_restored; + #endif // SEAMLESS_RESTART_PATCH + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + #if SWALLOW_PATCH + c->pid = winpid(w); + #endif // SWALLOW_PATCH + /* geometry */ + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + c->sfx = c->sfy = c->sfw = c->sfh = -9999; + #endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH + 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; + #if CFACTS_PATCH + c->cfact = 1.0; + #endif // CFACTS_PATCH + #if SEAMLESS_RESTART_PATCH + settings_restored = restoreclientstate(c); + #endif // SEAMLESS_RESTART_PATCH + #if BAR_WINICON_PATCH + updateicon(c); + #endif // BAR_WINICON_PATCH + updatetitle(c); + + #if XKB_PATCH + /* Setting current xkb state must be before applyrules */ + if (!(c->xkb = findxkb(c->win))) + c->xkb = createxkb(c->win); + #endif // XKB_PATCH + + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + #if SETBORDERPX_PATCH + c->bw = c->mon->borderpx; + #else + c->bw = borderpx; + #endif // SETBORDERPX_PATCH + #if CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH + c->x = t->x + WIDTH(t) / 2 - WIDTH(c) / 2; + c->y = t->y + HEIGHT(t) / 2 - HEIGHT(c) / 2; + #elif CENTER_PATCH && CENTER_TRANSIENT_WINDOWS_PATCH + c->iscentered = 1; + #elif CENTER_TRANSIENT_WINDOWS_PATCH + c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; + c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + #elif CENTER_PATCH + if (c->x == c->mon->wx && c->y == c->mon->wy) + c->iscentered = 1; + #endif // CENTER_TRANSIENT_WINDOWS_PATCH | CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH | CENTER_PATCH + } else { + #if SEAMLESS_RESTART_PATCH + if (!settings_restored || c->mon == NULL) { + c->mon = selmon; + settings_restored = 0; + } + #else + c->mon = selmon; + #endif // SEAMLESS_RESTART_PATCH + #if CENTER_PATCH + if (c->x == c->mon->wx && c->y == c->mon->wy) + c->iscentered = 1; + #endif // CENTER_PATCH + #if SETBORDERPX_PATCH + c->bw = c->mon->borderpx; + #else + c->bw = borderpx; + #endif // SETBORDERPX_PATCH + #if SEAMLESS_RESTART_PATCH + if (!settings_restored) + applyrules(c); + #else + applyrules(c); + #endif // SEAMLESS_RESTART_PATCH + #if SWALLOW_PATCH + term = termforwin(c); + if (term) + c->mon = term->mon; + #endif // SWALLOW_PATCH + } + + #if UNMANAGED_PATCH + if (unmanaged) { + XMapWindow(dpy, c->win); + if (unmanaged == 1) + XRaiseWindow(dpy, c->win); + else if (unmanaged == 2) + XLowerWindow(dpy, c->win); + + updatewmhints(c); + if (!c->neverfocus) + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + #if BAR_SYSTRAY_PATCH + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); + #else + sendevent(c, wmatom[WMTakeFocus]); + #endif // BAR_SYSTRAY_PATCH + + free(c); + unmanaged = 0; + return; + } + #endif // UNMANAGED_PATCH + + 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); + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + #if !BAR_FLEXWINTITLE_PATCH + if (c->isfloating) + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + #endif // BAR_FLEXWINTITLE_PATCH + configure(c); /* propagates border_width, if size doesn't change */ + updatesizehints(c); + updatewmhints(c); + #if DECORATION_HINTS_PATCH + updatemotifhints(c); + #endif // DECORATION_HINTS_PATCH + + #if CENTER_PATCH && SAVEFLOATS_PATCH || CENTER_PATCH && EXRESIZE_PATCH + if (c->iscentered) { + c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; + c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + } + #elif CENTER_PATCH + if (c->iscentered) { + c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; + c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + } + #elif ALWAYSCENTER_PATCH && SAVEFLOATS_PATCH || ALWAYSCENTER_PATCH && EXRESIZE_PATCH + c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; + c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + #elif ALWAYSCENTER_PATCH + c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; + c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + #endif // CENTER_PATCH / ALWAYSCENTER_PATCH / SAVEFLOATS_PATCH + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + if (c->sfw == -9999) { + c->sfw = c->w; + c->sfh = c->h; + } + #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH + + if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + #if MAXIMIZE_PATCH + c->wasfloating = 0; + c->ismax = 0; + #elif EXRESIZE_PATCH + c->wasfloating = 0; + #endif // MAXIMIZE_PATCH / EXRESIZE_PATCH + + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) { + XRaiseWindow(dpy, c->win); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + } + #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH + attachx(c); + #else + attach(c); + #endif + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + #if NET_CLIENT_LIST_STACKING_PATCH + XChangeProperty(dpy, root, netatom[NetClientListStacking], XA_WINDOW, 32, PropModePrepend, + (unsigned char *) &(c->win), 1); + #endif // NET_CLIENT_LIST_STACKING_PATCH + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + + #if BAR_WINTITLEACTIONS_PATCH + if (!HIDDEN(c)) + setclientstate(c, NormalState); + #else + setclientstate(c, NormalState); + #endif // BAR_WINTITLEACTIONS_PATCH + if (c->mon == selmon) + unfocus(selmon->sel, 0, c); + c->mon->sel = c; + #if SWALLOW_PATCH + if (!(term && swallow(term, c))) { + #if RIODRAW_PATCH + if (riopid && (!riodraw_matchpid || isdescprocess(riopid, c->pid))) { + if (riodimensions[3] != -1) + rioposition(c, riodimensions[0], riodimensions[1], riodimensions[2], riodimensions[3]); + else { + killclient(&((Arg) { .v = c })); + return; + } + } + #endif // RIODRAW_PATCH + arrange(c->mon); + #if BAR_WINTITLEACTIONS_PATCH + if (!HIDDEN(c)) + XMapWindow(dpy, c->win); + #else + XMapWindow(dpy, c->win); + #endif // BAR_WINTITLEACTIONS_PATCH + } + #else + #if RIODRAW_PATCH + if (riopid) { + if (riodimensions[3] != -1) + rioposition(c, riodimensions[0], riodimensions[1], riodimensions[2], riodimensions[3]); + else { + killclient(&((Arg) { .v = c })); + return; + } + } + #endif // RIODRAW_PATCH + arrange(c->mon); + #if BAR_WINTITLEACTIONS_PATCH + if (!HIDDEN(c)) + XMapWindow(dpy, c->win); + #else + XMapWindow(dpy, c->win); + #endif // BAR_WINTITLEACTIONS_PATCH + #endif // SWALLOW_PATCH + focus(NULL); + + #if BAR_EWMHTAGS_PATCH + setfloatinghint(c); + #endif // BAR_EWMHTAGS_PATCH +} + +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 BAR_SYSTRAY_PATCH + Client *i; + if (showsystray && systray && (i = wintosystrayicon(ev->window))) { + sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); + drawbarwin(systray->bar); + } + #endif // BAR_SYSTRAY_PATCH + + if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) + return; + #if BAR_ANYBAR_PATCH + if (wmclasscontains(ev->window, altbarclass, "")) + managealtbar(ev->window, &wa); + else + #endif // BAR_ANYBAR_PATCH + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +motionnotify(XEvent *e) +{ + #if !FOCUSONCLICK_PATCH + static Monitor *mon = NULL; + Monitor *m; + #if LOSEFULLSCREEN_PATCH + Client *sel; + #endif // LOSEFULLSCREEN_PATCH + #endif // FOCUSONCLICK_PATCH + Bar *bar; + XMotionEvent *ev = &e->xmotion; + + if ((bar = wintobar(ev->window))) { + barhover(e, bar); + return; + } + + #if BAR_TAGPREVIEW_PATCH + if (selmon->previewshow != 0) + hidetagpreview(selmon); + #endif // BAR_TAGPREVIEW_PATCH + + #if !FOCUSONCLICK_PATCH + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + #if LOSEFULLSCREEN_PATCH + sel = selmon->sel; + selmon = m; + unfocus(sel, 1, NULL); + #else + unfocus(selmon->sel, 1, NULL); + selmon = m; + #endif // LOSEFULLSCREEN_PATCH + focus(NULL); + } + mon = m; + #endif // FOCUSONCLICK_PATCH +} + +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 !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + if (c->isfullscreen && c->fakefullscreen != 1) /* no support moving fullscreen windows by mouse */ + return; + #else + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // FAKEFULLSCREEN_PATCH + restack(selmon); + nx = ocx = c->x; + ny = ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + ignoreconfigurerequests = 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 / refreshrate)) + 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)) { + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + c->sfx = -9999; // disable savefloats when using movemouse + #endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH + 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) { + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + #endif // SCRATCHPADS_PATCH + sendmon(c, m); + selmon = m; + focus(NULL); + } + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + /* save last known float coordinates */ + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + c->sfx = nx; + c->sfy = ny; + } + #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH + ignoreconfigurerequests = 0; +} + +Client * +nexttiled(Client *c) +{ + #if BAR_WINTITLEACTIONS_PATCH + for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next); + #else + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + #endif // BAR_WINTITLEACTIONS_PATCH + return c; +} + +#if NOBORDER_PATCH +int +noborder(Client *c) +{ + int monocle_layout = 0; + + #if MONOCLE_LAYOUT + if (&monocle == c->mon->lt[c->mon->sellt]->arrange) + monocle_layout = 1; + #endif // MONOCLE_LAYOUT + + #if DECK_LAYOUT + if (&deck == c->mon->lt[c->mon->sellt]->arrange && c->mon->nmaster == 0) + monocle_layout = 1; + #endif // DECK_LAYOUT + + #if FLEXTILE_DELUXE_LAYOUT + if (&flextile == c->mon->lt[c->mon->sellt]->arrange && ( + (c->mon->ltaxis[LAYOUT] == NO_SPLIT && c->mon->ltaxis[MASTER] == MONOCLE) || + (c->mon->ltaxis[STACK] == MONOCLE && c->mon->nmaster == 0) + )) { + monocle_layout = 1; + } + #endif //FLEXTILE_DELUXE_LAYOUT + + if (!monocle_layout && (nexttiled(c->mon->clients) != c || nexttiled(c->next))) + return 0; + + if (c->isfloating) + return 0; + + if (!c->mon->lt[c->mon->sellt]->arrange) + return 0; + + #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + if (c->fakefullscreen != 1 && c->isfullscreen) + return 0; + #elif !FAKEFULLSCREEN_PATCH + if (c->isfullscreen) + return 0; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + + return 1; +} +#endif // NOBORDER_PATCH + +#if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH +void +pop(Client *c) +{ + #if FOCUSMASTER_RETURN_PATCH + int i; + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + i++; + + c->mon->tagmarked[i] = nexttiled(c->mon->clients); + #endif // FOCUSMASTER_RETURN_PATCH + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} +#endif // !ZOOMSWAP_PATCH / TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + #if BAR_SYSTRAY_PATCH + if (showsystray && (c = wintosystrayicon(ev->window))) { + if (ev->atom == XA_WM_NORMAL_HINTS) { + updatesizehints(c); + updatesystrayicongeom(c, c->w, c->h); + } + else + updatesystrayiconstate(c, ev); + drawbarwin(systray->bar); + } + #endif // BAR_SYSTRAY_PATCH + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { + #if DWMC_PATCH || FSIGNAL_PATCH + if (!fake_signal()) + updatestatus(); + #else + updatestatus(); + #endif // DWMC_PATCH / FSIGNAL_PATCH + } 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); + if (c->isurgent) + drawbars(); + #if TAB_PATCH + drawtabs(); + #endif // TAB_PATCH + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + #if TAB_PATCH + drawtab(c->mon); + #endif // TAB_PATCH + } + #if DECORATION_HINTS_PATCH + if (ev->atom == motifatom) + updatemotifhints(c); + #endif // DECORATION_HINTS_PATCH + #if BAR_WINICON_PATCH + else if (ev->atom == netatom[NetWMIcon]) { + updateicon(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + #endif // BAR_WINICON_PATCH + } +} + +void +quit(const Arg *arg) +{ + #if RESTARTSIG_PATCH + restart = arg->i; + #endif // RESTARTSIG_PATCH + #if ONLYQUITONEMPTY_PATCH + Monitor *m; + Client *c; + unsigned int n = 0; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next, n++); + + #if RESTARTSIG_PATCH + if (restart || n <= quit_empty_window_count) + #else + if (n <= quit_empty_window_count) + #endif // RESTARTSIG_PATCH + running = 0; + else + fprintf(stderr, "[dwm] not exiting (n=%d)\n", n); + + #else // !ONLYQUITONEMPTY_PATCH + running = 0; + #endif // ONLYQUITONEMPTY_PATCH +} + +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; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + #if EXRESIZE_PATCH + c->expandmask = 0; + #endif // EXRESIZE_PATCH + wc.border_width = c->bw; + #if ROUNDED_CORNERS_PATCH + drawroundedcorners(c); + #endif // ROUNDED_CORNERS_PATCH + #if NOBORDER_PATCH + if (noborder(c)) { + wc.width += c->bw * 2; + wc.height += c->bw * 2; + wc.border_width = 0; + } + #endif // NOBORDER_PATCH + 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, nx, ny; + #if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH + int opx, opy, och, ocw; + int horizcorner, vertcorner; + unsigned int dui; + Window dummy; + #endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */ + return; + #else + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // !FAKEFULLSCREEN_PATCH + restack(selmon); + nx = ocx = c->x; + ny = ocy = c->y; + nh = c->h; + nw = c->w; + #if RESIZEPOINT_PATCH + och = c->h; + ocw = c->w; + #elif RESIZECORNERS_PATCH + och = c->y + c->h; + ocw = c->x + c->w; + #endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH + #if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH + if (!XQueryPointer(dpy, c->win, &dummy, &dummy, &opx, &opy, &nx, &ny, &dui)) + return; + horizcorner = nx < c->w / 2; + vertcorner = ny < c->h / 2; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[horizcorner | (vertcorner << 1)]->cursor, CurrentTime) != GrabSuccess) + return; + #if RESIZECORNERS_PATCH + XWarpPointer (dpy, None, c->win, 0, 0, 0, 0, + horizcorner ? (-c->bw) : (c->w + c->bw - 1), + vertcorner ? (-c->bw) : (c->h + c->bw - 1)); + #endif // RESIZECORNERS_PATCH + #else + 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); + #endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH + ignoreconfigurerequests = 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 / refreshrate)) + continue; + lasttime = ev.xmotion.time; + + #if RESIZEPOINT_PATCH + nx = horizcorner ? (ocx + ev.xmotion.x - opx) : c->x; + ny = vertcorner ? (ocy + ev.xmotion.y - opy) : c->y; + nw = MAX(horizcorner ? (ocx + ocw - nx) : (ocw + (ev.xmotion.x - opx)), 1); + nh = MAX(vertcorner ? (ocy + och - ny) : (och + (ev.xmotion.y - opy)), 1); + #elif RESIZECORNERS_PATCH + nx = horizcorner ? ev.xmotion.x : c->x; + ny = vertcorner ? ev.xmotion.y : c->y; + nw = MAX(horizcorner ? (ocw - nx) : (ev.xmotion.x - ocx - 2 * c->bw + 1), 1); + nh = MAX(vertcorner ? (och - ny) : (ev.xmotion.y - ocy - 2 * c->bw + 1), 1); + #else + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + #endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH + 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)) { + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + c->sfx = -9999; // disable savefloats when using resizemouse + #endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH + togglefloating(NULL); + } + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + resize(c, nx, ny, nw, nh, 1); + } + break; + } + } while (ev.type != ButtonRelease); + + #if !RESIZEPOINT_PATCH + #if RESIZECORNERS_PATCH + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, + horizcorner ? (-c->bw) : (c->w + c->bw - 1), + vertcorner ? (-c->bw) : (c->h + c->bw - 1)); + #else + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + #endif // RESIZECORNERS_PATCH + #endif // RESIZEPOINT_PATCH + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + #endif // SCRATCHPADS_PATCH + sendmon(c, m); + selmon = m; + focus(NULL); + } + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + /* save last known float dimensions */ + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + c->sfx = nx; + c->sfy = ny; + c->sfw = nw; + c->sfh = nh; + } + #endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH + ignoreconfigurerequests = 0; +} + +void +restack(Monitor *m) +{ + Client *c, *f = NULL; + XEvent ev; + XWindowChanges wc; + #if WARP_PATCH && FLEXTILE_DELUXE_LAYOUT + int n; + #endif // WARP_PATCH + #if ALWAYSONTOP_PATCH + Monitor *mon; + #endif // ALWAYSONTOP_PATCH + + drawbar(m); + #if TAB_PATCH + drawtab(m); + #endif // TAB_PATCH + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + + #if ALWAYSONTOP_PATCH + /* raise the aot windows */ + for (mon = mons; mon; mon = mon->next) { + for (c = mon->clients; c; c = c->next) { + if (c->alwaysontop) { + XRaiseWindow(dpy, c->win); + } + } + } + #endif // ALWAYSONTOP_PATCH + + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + if (m->bar) { + wc.sibling = m->bar->win; + } else { + for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client + if (f) + wc.sibling = f->win; + } + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c) && c != f) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + #if WARP_PATCH && FLEXTILE_DELUXE_LAYOUT || WARP_PATCH && MONOCLE_LAYOUT + #if FLEXTILE_DELUXE_LAYOUT + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // FLEXTILE_DELUXE_LAYOUT + if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && ( + #if MONOCLE_LAYOUT && FLEXTILE_DELUXE_LAYOUT + (m->lt[m->sellt]->arrange != &monocle + && !(m->ltaxis[MASTER] == MONOCLE && (abs(m->ltaxis[LAYOUT] == NO_SPLIT || !m->nmaster || n <= m->nmaster)))) + #elif MONOCLE_LAYOUT + m->lt[m->sellt]->arrange != &monocle + #else + !(m->ltaxis[MASTER] == MONOCLE && (abs(m->ltaxis[LAYOUT] == NO_SPLIT || !m->nmaster || n <= m->nmaster))) + #endif // FLEXTILE_DELUXE_LAYOUT + || m->sel->isfloating) + ) + warp(m->sel); + #endif // WARP_PATCH +} + +#if IPC_PATCH +void +run(void) +{ + int event_count = 0; + const int MAX_EVENTS = 10; + struct epoll_event events[MAX_EVENTS]; + + XSync(dpy, False); + + /* main event loop */ + while (running) { + event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); + + for (int i = 0; i < event_count; i++) { + int event_fd = events[i].data.fd; + DEBUG("Got event from fd %d\n", event_fd); + + if (event_fd == dpy_fd) { + // -1 means EPOLLHUP + if (handlexevent(events + i) == -1) + return; + } else if (event_fd == ipc_get_sock_fd()) { + ipc_handle_socket_epoll_event(events + i); + } else if (ipc_is_client_registered(event_fd)) { + if (ipc_handle_client_epoll_event(events + i, mons, &lastselmon, selmon, + NUMTAGS, layouts, LENGTH(layouts)) < 0) { + fprintf(stderr, "Error handling IPC event on fd %d\n", event_fd); + } + } else { + fprintf(stderr, "Got event from unknown fd %d, ptr %p, u32 %d, u64 %lu", + event_fd, events[i].data.ptr, events[i].data.u32, + events[i].data.u64); + fprintf(stderr, " with events %d\n", events[i].events); + } + } + } +} +#elif RESTARTSIG_PATCH +void +run(void) +{ + XEvent ev; + XSync(dpy, False); + /* main event loop */ + while (running) { + struct pollfd pfd = { + .fd = ConnectionNumber(dpy), + .events = POLLIN, + }; + int pending = XPending(dpy) > 0 || poll(&pfd, 1, -1) > 0; + + if (!running) + break; + if (!pending) + continue; + + XNextEvent(dpy, &ev); + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ + } +} +#else +void +run(void) +{ + XEvent ev; + /* main event loop */ + XSync(dpy, False); + while (running && !XNextEvent(dpy, &ev)) { + + #if XKB_PATCH + /* Unfortunately the xkbEventType is not constant hence it can't be part of the + * normal event handler below */ + if (ev.type == xkbEventType) { + xkbeventnotify(&ev); + continue; + } + #endif // XKB_PATCH + + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ + } +} +#endif // IPC_PATCH | RESTARTSIG_PATCH + +void +scan(void) +{ + #if SWALLOW_PATCH + scanner = 1; + char swin[256]; + #endif // SWALLOW_PATCH + 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 BAR_ANYBAR_PATCH + if (wmclasscontains(wins[i], altbarclass, "")) + managealtbar(wins[i], &wa); + else + #endif // BAR_ANYBAR_PATCH + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + #if SWALLOW_PATCH + else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) + manage(wins[i], &wa); + #endif // SWALLOW_PATCH + } + 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); + } + XFree(wins); + } + #if SWALLOW_PATCH + scanner = 0; + #endif // SWALLOW_PATCH +} + +void +sendmon(Client *c, Monitor *m) +{ + #if EXRESIZE_PATCH + Monitor *oldm = selmon; + #endif // EXRESIZE_PATCH + if (c->mon == m) + return; + #if SENDMON_KEEPFOCUS_PATCH && !EXRESIZE_PATCH + int hadfocus = (c == selmon->sel); + #endif // SENDMON_KEEPFOCUS_PATCH + unfocus(c, 1, NULL); + detach(c); + detachstack(c); + #if SENDMON_KEEPFOCUS_PATCH && !EXRESIZE_PATCH + arrange(c->mon); + #endif // SENDMON_KEEPFOCUS_PATCH + c->mon = m; + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + if (!(c->tags & SPTAGMASK)) + #endif // SCRATCHPADS_PATCH + #if EMPTYVIEW_PATCH + c->tags = (m->tagset[m->seltags] ? m->tagset[m->seltags] : 1); + #else + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + #endif // EMPTYVIEW_PATCH + #if SENDMON_CENTER_PATCH + c->x = m->mx + (m->mw - WIDTH(c)) / 2; + c->y = m->my + (m->mh - HEIGHT(c)) / 2; + #if SAVEFLOATS_PATCH + c->sfx = m->mx + (m->mw - c->sfw - 2 * c->bw) / 2; + c->sfy = m->my + (m->mh - c->sfh - 2 * c->bw) / 2; + #endif // SAVEFLOATS_PATCH + #endif // SENDMON_CENTER_PATCH + #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH + attachx(c); + #else + attach(c); + #endif + attachstack(c); + #if EXRESIZE_PATCH + if (oldm != m) + arrange(oldm); + arrange(m); + focus(c); + restack(m); + #elif SENDMON_KEEPFOCUS_PATCH + arrange(m); + if (hadfocus) { + focus(c); + restack(m); + } else { + focus(NULL); + } + #else + arrange(NULL); + focus(NULL); + #endif // EXRESIZE_PATCH / SENDMON_KEEPFOCUS_PATCH + #if SWITCHTAG_PATCH + if (c->switchtag) + c->switchtag = 0; + #endif // SWITCHTAG_PATCH +} + +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 +#if BAR_SYSTRAY_PATCH +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) +#else +sendevent(Client *c, Atom proto) +#endif // BAR_SYSTRAY_PATCH +{ + int n; + Atom *protocols; + #if BAR_SYSTRAY_PATCH + Atom mt; + #endif // BAR_SYSTRAY_PATCH + int exists = 0; + XEvent ev; + + #if BAR_SYSTRAY_PATCH + if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { + mt = wmatom[WMProtocols]; + if (XGetWMProtocols(dpy, w, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + } else { + exists = True; + mt = proto; + } + #else + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + #endif // BAR_SYSTRAY_PATCH + + if (exists) { + #if BAR_SYSTRAY_PATCH + ev.type = ClientMessage; + ev.xclient.window = w; + ev.xclient.message_type = mt; + ev.xclient.format = 32; + ev.xclient.data.l[0] = d0; + ev.xclient.data.l[1] = d1; + ev.xclient.data.l[2] = d2; + ev.xclient.data.l[3] = d3; + ev.xclient.data.l[4] = d4; + XSendEvent(dpy, w, False, mask, &ev); + #else + 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); + #endif // BAR_SYSTRAY_PATCH + } + 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); + #if XKB_PATCH + XkbLockGroup(dpy, XkbUseCoreKbd, c->xkb->group); + #endif // XKB_PATCH + } + + #if GAMES_PATCH + if (c->isgame && c->isfullscreen) + unminimize(c); + #endif // GAMES_PATCH + + #if BAR_SYSTRAY_PATCH + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); + #else + sendevent(c, wmatom[WMTakeFocus]); + #endif // BAR_SYSTRAY_PATCH +} + +#if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH +void +setfullscreen(Client *c, int fullscreen) +{ + XEvent ev; + int savestate = 0, restorestate = 0; + + if ((c->fakefullscreen == 0 && fullscreen && !c->isfullscreen) // normal fullscreen + || (c->fakefullscreen == 2 && fullscreen)) // fake fullscreen --> actual fullscreen + savestate = 1; // go actual fullscreen + else if ((c->fakefullscreen == 0 && !fullscreen && c->isfullscreen) // normal fullscreen exit + || (c->fakefullscreen >= 2 && !fullscreen)) // fullscreen exit --> fake fullscreen + restorestate = 1; // go back into tiled + + /* If leaving fullscreen and the window was previously fake fullscreen (2), then restore + * that while staying in fullscreen. The exception to this is if we are in said state, but + * the client itself disables fullscreen (3) then we let the client go out of fullscreen + * while keeping fake fullscreen enabled (as otherwise there will be a mismatch between the + * client and the window manager's perception of the client's fullscreen state). */ + if (c->fakefullscreen == 2 && !fullscreen && c->isfullscreen) { + c->fakefullscreen = 1; + c->isfullscreen = 1; + fullscreen = 1; + } else if (c->fakefullscreen == 3) // client exiting actual fullscreen + c->fakefullscreen = 1; + + if (fullscreen != c->isfullscreen) { // only send property change if necessary + if (fullscreen) + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + else + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + } + + c->isfullscreen = fullscreen; + + /* Some clients, e.g. firefox, will send a client message informing the window manager + * that it is going into fullscreen after receiving the above signal. This has the side + * effect of this function (setfullscreen) sometimes being called twice when toggling + * fullscreen on and off via the window manager as opposed to the application itself. + * To protect against obscure issues where the client settings are stored or restored + * when they are not supposed to we add an additional bit-lock on the old state so that + * settings can only be stored and restored in that precise order. */ + if (savestate && !(c->oldstate & (1 << 1))) { + c->oldbw = c->bw; + c->oldstate = c->isfloating | (1 << 1); + 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 (restorestate && (c->oldstate & (1 << 1))) { + c->bw = c->oldbw; + c->isfloating = c->oldstate = c->oldstate & 1; + 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); + restack(c->mon); + } else + resizeclient(c, c->x, c->y, c->w, c->h); + + /* Exception: if the client was in actual fullscreen and we exit out to fake fullscreen + * mode, then the focus would sometimes drift to whichever window is under the mouse cursor + * at the time. To avoid this we ask X for all EnterNotify events and just ignore them. + */ + if (!c->isfullscreen) + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} +#else +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; + #if !FAKEFULLSCREEN_PATCH + c->oldbw = c->bw; + c->oldstate = c->isfloating; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + #endif // !FAKEFULLSCREEN_PATCH + } else if (!fullscreen && c->isfullscreen){ + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; + #if !FAKEFULLSCREEN_PATCH + c->bw = c->oldbw; + c->isfloating = c->oldstate; + 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); + #endif // !FAKEFULLSCREEN_PATCH + } + #if FAKEFULLSCREEN_PATCH + resizeclient(c, c->x, c->y, c->w, c->h); + #endif // FAKEFULLSCREEN_PATCH +} +#endif // FAKEFULLSCREEN_CLIENT_PATCH + +void +setlayout(const Arg *arg) +{ + #if !TOGGLELAYOUT_PATCH + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { + #endif // TOGGLELAYOUT_PATCH + #if PERTAG_PATCH + selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + #else + selmon->sellt ^= 1; + #endif // PERTAG_PATCH + #if EXRESIZE_PATCH + if (!selmon->lt[selmon->sellt]->arrange) { + for (Client *c = selmon->clients ; c ; c = c->next) { + if (!c->isfloating) { + /*restore last known float dimensions*/ + resize(c, selmon->mx + c->sfx, selmon->my + c->sfy, + c->sfw, c->sfh, False); + } + } + } + #endif // EXRESIZE_PATCH + #if !TOGGLELAYOUT_PATCH + } + #endif // TOGGLELAYOUT_PATCH + #if TOGGLELAYOUT_PATCH + if (arg && arg->v && arg->v != selmon->lt[selmon->sellt ^ 1]) + #else + if (arg && arg->v) + #endif // TOGGLELAYOUT_PATCH + #if PERTAG_PATCH + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + #else + selmon->lt[selmon->sellt] = (Layout *)arg->v; + #endif // PERTAG_PATCH + + #if FLEXTILE_DELUXE_LAYOUT + if (selmon->lt[selmon->sellt]->preset.nmaster && selmon->lt[selmon->sellt]->preset.nmaster != -1) + selmon->nmaster = selmon->lt[selmon->sellt]->preset.nmaster; + if (selmon->lt[selmon->sellt]->preset.nstack && selmon->lt[selmon->sellt]->preset.nstack != -1) + selmon->nstack = selmon->lt[selmon->sellt]->preset.nstack; + + selmon->ltaxis[LAYOUT] = selmon->lt[selmon->sellt]->preset.layout; + selmon->ltaxis[MASTER] = selmon->lt[selmon->sellt]->preset.masteraxis; + selmon->ltaxis[STACK] = selmon->lt[selmon->sellt]->preset.stack1axis; + selmon->ltaxis[STACK2] = selmon->lt[selmon->sellt]->preset.stack2axis; + + #if PERTAG_PATCH + selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT] = selmon->ltaxis[LAYOUT]; + selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER] = selmon->ltaxis[MASTER]; + selmon->pertag->ltaxis[selmon->pertag->curtag][STACK] = selmon->ltaxis[STACK]; + selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2] = selmon->ltaxis[STACK2]; + #endif // PERTAG_PATCH + #endif // FLEXTILE_DELUXE_LAYOUT + 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; + #if PERTAG_PATCH + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + #else + selmon->mfact = f; + #endif // PERTAG_PATCH + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + #if XKB_PATCH + XkbStateRec xkbstate; + #endif // XKB_PATCH + Atom utf8string; + #if COOL_AUTOSTART_PATCH + /* clean up any zombies immediately */ + sigchld(0); + #else + 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); + #endif // COOL_AUTOSTART_PATCH + + #if RESTARTSIG_PATCH + signal(SIGHUP, sighup); + signal(SIGTERM, sigterm); + #endif // RESTARTSIG_PATCH + + /* the one line of bloat that would have saved a lot of time for a lot of people */ + putenv("_JAVA_AWT_WM_NONREPARENTING=1"); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + #if BAR_ALPHA_PATCH + xinitvisual(); + drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); + #else + drw = drw_create(dpy, screen, root, sw, sh); + #endif // BAR_ALPHA_PATCH + #if BAR_PANGO_PATCH + if (!drw_font_create(drw, font)) + #else + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + #endif // BAR_PANGO_PATCH + die("no fonts could be loaded."); + #if BAR_STATUSPADDING_PATCH + lrpad = drw->fonts->h + horizpadbar; + bh = drw->fonts->h + vertpadbar; + #else + lrpad = drw->fonts->h; + #if BAR_HEIGHT_PATCH + bh = bar_height ? bar_height : drw->fonts->h + 2; + #else + bh = drw->fonts->h + 2; + #endif // BAR_HEIGHT_PATCH + #endif // BAR_STATUSPADDING_PATCH + #if TAB_PATCH + th = bh; + #endif // TAB_PATCH + 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); + #if WINDOWROLERULE_PATCH + wmatom[WMWindowRole] = XInternAtom(dpy, "WM_WINDOW_ROLE", False); + #endif // WINDOWROLERULE_PATCH + #if SEAMLESS_RESTART_PATCH + clientatom[ClientFields] = XInternAtom(dpy, "_DWM_CLIENT_FIELDS", False); + clientatom[ClientTags] = XInternAtom(dpy, "_DWM_CLIENT_TAGS", False); + #endif // SEAMLESS_RESTART_PATCH + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + #if BAR_SYSTRAY_PATCH + netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); + netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); + netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); + netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); + netatom[NetSystemTrayVisual] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_VISUAL", False); + netatom[NetWMWindowTypeDock] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); + xatom[Manager] = XInternAtom(dpy, "MANAGER", False); + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); + #endif // BAR_SYSTRAY_PATCH + #if BAR_EWMHTAGS_PATCH + netatom[NetDesktopViewport] = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False); + netatom[NetNumberOfDesktops] = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False); + netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False); + netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False); + #endif // BAR_EWMHTAGS_PATCH + #if BAR_WINICON_PATCH + netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); + #endif // BAR_WINICON_PATCH + 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[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + #if NET_CLIENT_LIST_STACKING_PATCH + netatom[NetClientListStacking] = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False); + #endif // NET_CLIENT_LIST_STACKING_PATCH + #if DECORATION_HINTS_PATCH + motifatom = XInternAtom(dpy, "_MOTIF_WM_HINTS", False); + #endif // DECORATION_HINTS_PATCH + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + #if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH + cursor[CurResizeBR] = drw_cur_create(drw, XC_bottom_right_corner); + cursor[CurResizeBL] = drw_cur_create(drw, XC_bottom_left_corner); + cursor[CurResizeTR] = drw_cur_create(drw, XC_top_right_corner); + cursor[CurResizeTL] = drw_cur_create(drw, XC_top_left_corner); + #endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH + #if DRAGMFACT_PATCH + cursor[CurResizeHorzArrow] = drw_cur_create(drw, XC_sb_h_double_arrow); + cursor[CurResizeVertArrow] = drw_cur_create(drw, XC_sb_v_double_arrow); + #endif // DRAGMFACT_PATCH + #if DRAGCFACT_PATCH + cursor[CurIronCross] = drw_cur_create(drw, XC_iron_cross); + #endif // DRAGCFACT_PATCH + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + #if BAR_VTCOLORS_PATCH + get_vt_colors(); + if (get_luminance(colors[SchemeTagsNorm][ColBg]) > 50) { + strcpy(colors[SchemeTitleNorm][ColBg], title_bg_light); + strcpy(colors[SchemeTitleSel][ColBg], title_bg_light); + } else { + strcpy(colors[SchemeTitleNorm][ColBg], title_bg_dark); + strcpy(colors[SchemeTitleSel][ColBg], title_bg_dark); + } + #endif // BAR_VTCOLORS_PATCH + #if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH + scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *)); + #if BAR_ALPHA_PATCH + scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], alphas[0], ColCount); + #else + scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], ColCount); + #endif // BAR_ALPHA_PATCH + #else + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + #endif // BAR_STATUS2D_PATCH + for (i = 0; i < LENGTH(colors); i++) + #if BAR_ALPHA_PATCH + scheme[i] = drw_scm_create(drw, colors[i], alphas[i], ColCount); + #else + scheme[i] = drw_scm_create(drw, colors[i], ColCount); + #endif // BAR_ALPHA_PATCH + #if BAR_POWERLINE_STATUS_PATCH + statusscheme = ecalloc(LENGTH(statuscolors), sizeof(Clr *)); + for (i = 0; i < LENGTH(statuscolors); i++) + #if BAR_ALPHA_PATCH + statusscheme[i] = drw_scm_create(drw, statuscolors[i], alphas[0], ColCount); + #else + statusscheme[i] = drw_scm_create(drw, statuscolors[i], ColCount); + #endif // BAR_ALPHA_PATCH + #endif // BAR_POWERLINE_STATUS_PATCH + + 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); + #if LG3D_PATCH + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "LG3D", 4); + #else + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + #endif // LG3D_PATCH + 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); + #if BAR_EWMHTAGS_PATCH + setnumdesktops(); + setcurrentdesktop(); + setdesktopnames(); + setviewport(); + #endif // BAR_EWMHTAGS_PATCH + XDeleteProperty(dpy, root, netatom[NetClientList]); + #if NET_CLIENT_LIST_STACKING_PATCH + XDeleteProperty(dpy, root, netatom[NetClientListStacking]); + #endif // NET_CLIENT_LIST_STACKING_PATCH + /* 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); + + #if XKB_PATCH + /* get xkb extension info, events and current state */ + if (!XkbQueryExtension(dpy, NULL, &xkbEventType, NULL, NULL, NULL)) + fputs("warning: can not query xkb extension\n", stderr); + XkbSelectEventDetails(dpy, XkbUseCoreKbd, XkbStateNotify, + XkbAllStateComponentsMask, XkbGroupStateMask); + XkbGetState(dpy, XkbUseCoreKbd, &xkbstate); + xkbGlobal.group = xkbstate.locked_group; + #endif // XKB_PATCH + + #if BANISH_PATCH + if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &i, &i)) { + fprintf(stderr, "Warning: XInput is not available."); + } + /* Tell XInput to send us all RawMotion events. */ + unsigned char mask_bytes[XIMaskLen(XI_LASTEVENT)]; + memset(mask_bytes, 0, sizeof(mask_bytes)); + XISetMask(mask_bytes, XI_RawMotion); + XISetMask(mask_bytes, XI_RawKeyRelease); + XISetMask(mask_bytes, XI_RawTouchBegin); + XISetMask(mask_bytes, XI_RawTouchEnd); + XISetMask(mask_bytes, XI_RawTouchUpdate); + + XIEventMask mask; + mask.deviceid = XIAllMasterDevices; + mask.mask_len = sizeof(mask_bytes); + mask.mask = mask_bytes; + XISelectEvents(dpy, root, &mask, 1); + #endif // BANISH_PATCH + + grabkeys(); + focus(NULL); + #if IPC_PATCH + setupepoll(); + #endif // IPC_PATCH + #if BAR_ANYBAR_PATCH + if (usealtbar) + spawnbar(); + #endif // BAR_ANYBAR_PATCH +} + + +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)) { + #if !RENAMED_SCRATCHPADS_PATCH + #if SCRATCHPADS_PATCH && SCRATCHPADS_KEEP_POSITION_AND_SIZE_PATCH + if ( + (c->tags & SPTAGMASK) && + c->isfloating && + ( + c->x < c->mon->mx || + c->x > c->mon->mx + c->mon->mw || + c->y < c->mon->my || + c->y > c->mon->my + c->mon->mh + ) + ) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + #elif SCRATCHPADS_PATCH + if ((c->tags & SPTAGMASK) && c->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + #endif // SCRATCHPADS_KEEP_POSITION_AND_SIZE_PATCH | SCRATCHPADS_PATCH + #endif // RENAMED_SCRATCHPADS_PATCH + /* show clients top down */ + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) { + XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh); + resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0); + showhide(c->snext); + return; + } + #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH + #if AUTORESIZE_PATCH + if (c->needresize) { + c->needresize = 0; + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else { + XMoveWindow(dpy, c->win, c->x, c->y); + } + #else + XMoveWindow(dpy, c->win, c->x, c->y); + #endif // AUTORESIZE_PATCH + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) + #if !FAKEFULLSCREEN_PATCH + && !c->isfullscreen + #endif // !FAKEFULLSCREEN_PATCH + ) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + #if RENAMED_SCRATCHPADS_PATCH && RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH + /* optional: auto-hide scratchpads when moving to other tags */ + if (c->scratchkey != 0 && !(c->tags & c->mon->tagset[c->mon->seltags])) + c->tags = 0; + #endif // RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +#if COOL_AUTOSTART_PATCH +void +sigchld(int unused) +{ + pid_t pid; + + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); + + while (0 < (pid = waitpid(-1, NULL, WNOHANG))) { + pid_t *p, *lim; + + if (!(p = autostart_pids)) + continue; + lim = &p[autostart_len]; + + for (; p < lim; p++) { + if (*p == pid) { + *p = -1; + break; + } + } + } +} +#endif // COOL_AUTOSTART_PATCH + +#if RIODRAW_PATCH +void +spawn(const Arg *arg) +{ + spawncmd(arg); +} + +pid_t +spawncmd(const Arg *arg) +#else +void +spawn(const Arg *arg) +#endif // RIODRAW_PATCH +{ + struct sigaction sa; + + #if RIODRAW_PATCH + pid_t pid; + #endif // RIODRAW_PATCH + #if !NODMENU_PATCH + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + #endif // NODMENU_PATCH + + #if RIODRAW_PATCH + if ((pid = fork()) == 0) + #else + if (fork() == 0) + #endif // RIODRAW_PATCH + { + if (dpy) + close(ConnectionNumber(dpy)); + + #if BAR_STATUSCMD_PATCH && !BAR_DWMBLOCKS_PATCH + if (arg->v == statuscmd) { + for (int i = 0; i < LENGTH(statuscmds); i++) { + if (statuscmdn == statuscmds[i].id) { + statuscmd[2] = statuscmds[i].cmd; + setenv("BUTTON", lastbutton, 1); + break; + } + } + if (!statuscmd[2]) + exit(EXIT_SUCCESS); + } + #endif // BAR_STATUSCMD_PATCH | BAR_DWMBLOCKS_PATCH + #if SPAWNCMD_PATCH + if (selmon->sel) { + const char* const home = getenv("HOME"); + assert(home && strchr(home, '/')); + const size_t homelen = strlen(home); + char *cwd, *pathbuf = NULL; + struct stat statbuf; + + cwd = strtok(selmon->sel->name, SPAWN_CWD_DELIM); + /* NOTE: strtok() alters selmon->sel->name in-place, + * but that does not matter because we are going to + * exec() below anyway; nothing else will use it */ + while (cwd) { + if (*cwd == '~') { /* replace ~ with $HOME */ + if (!(pathbuf = malloc(homelen + strlen(cwd)))) /* ~ counts for NULL term */ + die("fatal: could not malloc() %u bytes\n", homelen + strlen(cwd)); + strcpy(strcpy(pathbuf, home) + homelen, cwd + 1); + cwd = pathbuf; + } + + if (strchr(cwd, '/') && !stat(cwd, &statbuf)) { + if (!S_ISDIR(statbuf.st_mode)) + cwd = dirname(cwd); + + if (!chdir(cwd)) + break; + } + + cwd = strtok(NULL, SPAWN_CWD_DELIM); + } + + free(pathbuf); + } + #endif // SPAWNCMD_PATCH + 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]); + } + #if RIODRAW_PATCH + return pid; + #endif // RIODRAW_PATCH +} + +void +tag(const Arg *arg) +{ + #if SWAPFOCUS_PATCH && PERTAG_PATCH + unsigned int tagmask, tagindex; + #endif // SWAPFOCUS_PATCH + + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + #if SWITCHTAG_PATCH + if (selmon->sel->switchtag) + selmon->sel->switchtag = 0; + #endif // SWITCHTAG_PATCH + arrange(selmon); + focus(NULL); + #if SWAPFOCUS_PATCH && PERTAG_PATCH + selmon->pertag->prevclient[selmon->pertag->curtag] = NULL; + for (tagmask = arg->ui & TAGMASK, tagindex = 1; tagmask!=0; tagmask >>= 1, tagindex++) + if (tagmask & 1) + selmon->pertag->prevclient[tagindex] = NULL; + #endif // SWAPFOCUS_PATCH + #if VIEWONTAG_PATCH + if ((arg->ui & TAGMASK) != selmon->tagset[selmon->seltags]) + view(arg); + #endif // VIEWONTAG_PATCH + } +} + +void +tagmon(const Arg *arg) +{ + Client *c = selmon->sel; + Monitor *dest; + #if SEAMLESS_RESTART_PATCH && SAVEFLOATS_PATCH + int restored; + #endif // SEAMLESS_RESTART_PATCH | SAVEFLOATS_PATCH + if (!c || !mons->next) + return; + dest = dirtomon(arg->i); + #if SEAMLESS_RESTART_PATCH && SAVEFLOATS_PATCH + savewindowfloatposition(c, c->mon); + restored = restorewindowfloatposition(c, dest); + if (restored && (!dest->lt[dest->sellt]->arrange || c->isfloating)) { + XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh); + resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 1); + } + #endif // SEAMLESS_RESTART_PATCH | SAVEFLOATS_PATCH + #if TAGMONFIXFS_PATCH + if (c->isfullscreen) { + c->isfullscreen = 0; + sendmon(c, dest); + c->isfullscreen = 1; + #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + if (c->fakefullscreen != 1) { + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } + #elif !FAKEFULLSCREEN_PATCH + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + #endif // FAKEFULLSCREEN_CLIENT_PATCH + } else + sendmon(c, dest); + #else + sendmon(c, dest); + #endif // TAGMONFIXFS_PATCH +} + +void +togglebar(const Arg *arg) +{ + Bar *bar; + #if BAR_HOLDBAR_PATCH && PERTAG_PATCH && PERTAGBAR_PATCH + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = (selmon->showbar == 2 ? 1 : !selmon->showbar); + #elif BAR_HOLDBAR_PATCH + selmon->showbar = (selmon->showbar == 2 ? 1 : !selmon->showbar); + #elif PERTAG_PATCH && PERTAGBAR_PATCH + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; + #else + selmon->showbar = !selmon->showbar; + #endif // BAR_HOLDBAR_PATCH | PERTAG_PATCH + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #if BAR_SYSTRAY_PATCH + if (!selmon->showbar && systray) + XMoveWindow(dpy, systray->win, -32000, -32000); + #endif // BAR_SYSTRAY_PATCH + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + Client *c = selmon->sel; + if (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && c->fakefullscreen != 1) /* no support for fullscreen windows */ + return; + #else + if (c->isfullscreen) /* no support for fullscreen windows */ + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // !FAKEFULLSCREEN_PATCH + c->isfloating = !c->isfloating || c->isfixed; + #if !BAR_FLEXWINTITLE_PATCH + #if RENAMED_SCRATCHPADS_PATCH + if (c->scratchkey != 0 && c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColFloat].pixel); + else if (c->scratchkey != 0) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColBorder].pixel); + else if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + #else + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + #endif // RENAMED_SCRATCHPADS_PATCH + #endif // BAR_FLEXWINTITLE_PATCH + if (c->isfloating) { + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + if (c->sfx != -9999) { + /* restore last known float dimensions */ + resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0); + } else + #endif // SAVEFLOATS_PATCH // EXRESIZE_PATCH + resize(c, c->x, c->y, c->w, c->h, 0); + #if SAVEFLOATS_PATCH || EXRESIZE_PATCH + } else { + /* save last known float dimensions */ + c->sfx = c->x; + c->sfy = c->y; + c->sfw = c->w; + c->sfh = c->h; + #if ALWAYSONTOP_PATCH + c->alwaysontop = 0; + #endif // ALWAYSONTOP_PATCH + #elif ALWAYSONTOP_PATCH + } else { + c->alwaysontop = 0; + #endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH | ALWAYSONTOP_PATCH + } + arrange(c->mon); + + #if BAR_EWMHTAGS_PATCH + setfloatinghint(c); + #endif // BAR_EWMHTAGS_PATCH +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + #if SWAPFOCUS_PATCH && PERTAG_PATCH + unsigned int tagmask, tagindex; + #endif // SWAPFOCUS_PATCH + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + arrange(selmon); + focus(NULL); + #if SWAPFOCUS_PATCH && PERTAG_PATCH + for (tagmask = arg->ui & TAGMASK, tagindex = 1; tagmask!=0; tagmask >>= 1, tagindex++) + if (tagmask & 1) + selmon->pertag->prevclient[tagindex] = NULL; + #endif // SWAPFOCUS_PATCH + } + #if BAR_EWMHTAGS_PATCH + updatecurrentdesktop(); + #endif // BAR_EWMHTAGS_PATCH +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);; + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH + #if PERTAG_PATCH + int i; + #endif // PERTAG_PATCH + + #if TAGINTOSTACK_ALLMASTER_PATCH + Client *const selected = selmon->sel; + + // clients in the master area should be the same after we add a new tag + Client **const masters = calloc(selmon->nmaster, sizeof(Client *)); + if (!masters) { + die("fatal: could not calloc() %u bytes \n", selmon->nmaster * sizeof(Client *)); + } + // collect (from last to first) references to all clients in the master area + Client *c; + size_t j; + for (c = nexttiled(selmon->clients), j = 0; c && j < selmon->nmaster; c = nexttiled(c->next), ++j) + masters[selmon->nmaster - (j + 1)] = c; + // put the master clients at the front of the list + // > go from the 'last' master to the 'first' + for (j = 0; j < selmon->nmaster; ++j) + if (masters[j]) + pop(masters[j]); + free(masters); + + // we also want to be sure not to mutate the focus + focus(selected); + #elif TAGINTOSTACK_ONEMASTER_PATCH + // the first visible client should be the same after we add a new tag + // we also want to be sure not to mutate the focus + Client *const c = nexttiled(selmon->clients); + if (c) { + Client * const selected = selmon->sel; + pop(c); + focus(selected); + } + #endif // TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH + + #if !EMPTYVIEW_PATCH + if (newtagset) { + #endif // EMPTYVIEW_PATCH + #if BAR_TAGPREVIEW_PATCH + tagpreviewswitchtag(); + #endif // BAR_TAGPREVIEW_PATCH + selmon->tagset[selmon->seltags] = newtagset; + + #if PERTAG_PATCH + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + if (newtagset == ~SPTAGMASK) + #else + if (newtagset == ~0) + #endif // SCRATCHPADS_PATCH + { + selmon->pertag->curtag = 0; + } + /* test if the user did not select the same tag */ + if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { + for (i = 0; !(newtagset & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + + /* apply settings for this view */ + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + #if PERTAGBAR_PATCH + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + #endif // PERTAGBAR_PATCH + #endif // PERTAG_PATCH + #if !TAGSYNC_PATCH + arrange(selmon); + focus(NULL); + #endif // TAGSYNC_PATCH + #if !EMPTYVIEW_PATCH + } + #endif // EMPTYVIEW_PATCH + #if TAGSYNC_PATCH + } + selmon = origselmon; + #if !EMPTYVIEW_PATCH + if (newtagset) { + #endif // EMPTYVIEW_PATCH + arrange(NULL); + focus(NULL); + #if !EMPTYVIEW_PATCH + } + #endif // EMPTYVIEW_PATCH + #endif // TAGSYNC_PATCH + #if BAR_EWMHTAGS_PATCH + updatecurrentdesktop(); + #endif // BAR_EWMHTAGS_PATCH +} + +void +unfocus(Client *c, int setfocus, Client *nextfocus) +{ + if (!c) + return; + + #if SWAPFOCUS_PATCH && PERTAG_PATCH + selmon->pertag->prevclient[selmon->pertag->curtag] = c; + #endif // SWAPFOCUS_PATCH + #if GAMES_PATCH + if (c->isgame && c->isfullscreen) { + minimize(c); + } + #endif // GAMES_PATCH + #if GAMES_PATCH && LOSEFULLSCREEN_PATCH + else + #endif // GAMES_PATCH | LOSEFULLSCREEN_PATCH + #if LOSEFULLSCREEN_PATCH + if (c->isfullscreen && ISVISIBLE(c) && c->mon == selmon && nextfocus && !nextfocus->isfloating) { + #if RENAMED_SCRATCHPADS_PATCH && RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->scratchkey != 0 && c->fakefullscreen != 1) + togglescratch(&((Arg) {.v = (const char*[]){ &c->scratchkey, NULL } })); + #else + if (c->scratchkey != 0) + togglescratch(&((Arg) {.v = (const char*[]){ &c->scratchkey, NULL } })); + #endif // FAKEFULLSCREEN_CLIENT_PATCH + else + #endif // RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->fakefullscreen != 1) + setfullscreen(c, 0); + #else + setfullscreen(c, 0); + #endif // #if FAKEFULLSCREEN_CLIENT_PATCH + } + #endif // LOSEFULLSCREEN_PATCH + grabbuttons(c, 0); + #if !BAR_FLEXWINTITLE_PATCH + #if RENAMED_SCRATCHPADS_PATCH + if (c->scratchkey != 0 && c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColFloat].pixel); + else if (c->scratchkey != 0) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColBorder].pixel); + else if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + #else + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + #endif // RENAMED_SCRATCHPADS_PATCH + #endif // BAR_FLEXWINTITLE_PATCH + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m; + #if SWITCHTAG_PATCH + unsigned int switchtag = c->switchtag; + #endif // SWITCHTAG_PATCH + XWindowChanges wc; + #if XKB_PATCH + XkbInfo *xkb; + #endif // XKB_PATCH + + #if ZOOMSWAP_PATCH + /* Make sure to clear any previous zoom references to the client being removed. */ + #if PERTAG_PATCH + int i; + for (m = mons; m; m = m->next) { + for (i = 0; i <= NUMTAGS; i++) { + if (m->pertag->prevzooms[i] == c) { + m->pertag->prevzooms[i] = NULL; + } + } + } + #else + if (c == prevzoom) + prevzoom = NULL; + #endif // PERTAG_PATCH + #endif // ZOOMSWAP_PATCH + m = c->mon; + + #if SWALLOW_PATCH + if (c->swallowing) { + unswallow(c); + return; + } + + Client *s = swallowingclient(c->win); + if (s) { + free(s->swallowing); + s->swallowing = NULL; + arrange(m); + focus(NULL); + return; + } + #endif // SWALLOW_PATCH + + detach(c); + detachstack(c); + #if BAR_WINICON_PATCH + freeicon(c); + #endif // BAR_WINICON_PATCH + 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); + if (!HIDDEN(c)) + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + #if XKB_PATCH + else { + xkb = findxkb(c->win); + if (xkb != NULL) { + if (xkb->prev) + xkb->prev->next = xkb->next; + if (xkb->next) + xkb->next->prev = xkb->prev; + free(xkb); + } + } + #endif // XKB_PATCH + + #if SCRATCHPAD_ALT_1_PATCH + if (scratchpad_last_showed == c) + scratchpad_last_showed = NULL; + #endif // SCRATCHPAD_ALT_1_PATCH + + free(c); + #if SWALLOW_PATCH + if (s) + return; + #endif // SWALLOW_PATCH + arrange(m); + focus(NULL); + updateclientlist(); + #if SWITCHTAG_PATCH + if (switchtag && ((switchtag & TAGMASK) != selmon->tagset[selmon->seltags])) + view(&((Arg) { .ui = switchtag })); + #endif // SWITCHTAG_PATCH +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + #if BAR_ANYBAR_PATCH + Monitor *m; + Bar *bar; + #endif // BAR_ANYBAR_PATCH + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + #if BAR_SYSTRAY_PATCH + } else if (showsystray && (c = wintosystrayicon(ev->window))) { + /* KLUDGE! sometimes icons occasionally unmap their windows, but do + * _not_ destroy them. We map those windows back */ + XMapRaised(dpy, c->win); + removesystrayicon(c); + drawbarwin(systray->bar); + #endif // BAR_SYSTRAY_PATCH + } + #if BAR_ANYBAR_PATCH + else { + m = wintomon(ev->window); + for (bar = m->bar; bar; bar = bar->next) { + if (bar->win == ev->window) { + unmanagealtbar(ev->window); + break; + } + } + } + #endif // BAR_ANYBAR_PATCH +} + +void +updatebars(void) +{ + Bar *bar; + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + #if BAR_ALPHA_PATCH + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + #else + .background_pixmap = ParentRelative, + #endif // BAR_ALPHA_PATCH + #if BAR_TAGPREVIEW_PATCH + .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask + #else + .event_mask = ButtonPressMask|ExposureMask + #endif // BAR_TAGPREVIEW_PATCH + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + for (bar = m->bar; bar; bar = bar->next) { + if (bar->external) + continue; + if (!bar->win) { + #if BAR_ALPHA_PATCH + bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + #else + bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + #endif // BAR_ALPHA_PATCH + XDefineCursor(dpy, bar->win, cursor[CurNormal]->cursor); + XMapRaised(dpy, bar->win); + XSetClassHint(dpy, bar->win, &ch); + } + } + #if TAB_PATCH + if (!m->tabwin) { + #if BAR_ALPHA_PATCH + m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + #else + m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + #endif // BAR_ALPHA_PATCH + XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->tabwin); + } + #endif // TAB_PATCH + } +} + +void +updatebarpos(Monitor *m) +{ + #if TAB_PATCH + Client *c; + int nvis = 0; + #endif // TAB_PATCH + + m->wx = m->mx; + m->wy = m->my; + m->ww = m->mw; + m->wh = m->mh; + Bar *bar; + int y_pad = 0; + int x_pad = 0; + #if BAR_PADDING_VANITYGAPS_PATCH && VANITYGAPS_PATCH + #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH + if (!selmon || selmon->pertag->enablegaps[selmon->pertag->curtag]) + #elif PERMON_VANITYGAPS_PATCH + if (!selmon || selmon->enablegaps) + #else + if (enablegaps) + #endif // PERTAG_VANITYGAPS_PATCH + { + #if BAR_PADDING_SMART_PATCH + unsigned int n; Client *c; + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n > 1) { + y_pad = gappoh; + x_pad = gappov; + } + #else + y_pad = gappoh; + x_pad = gappov; + #endif // BAR_PADDING_SMART_PATCH + } + #elif BAR_PADDING_PATCH + #if BAR_PADDING_SMART_PATCH + unsigned int n; Client *c; + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n > 1) { + y_pad = vertpad; + x_pad = sidepad; + } + #else + y_pad = vertpad; + x_pad = sidepad; + #endif // BAR_PADDING_SMART_PATCH + #endif // BAR_PADDING_PATCH | BAR_PADDING_VANITYGAPS_PATCH + + #if INSETS_PATCH + // Custom insets + Inset inset = m->inset; + m->wx += inset.x; + m->wy += inset.y; + m->ww -= inset.w + inset.x; + m->wh -= inset.h + inset.y; + #endif // INSETS_PATCH + + for (bar = m->bar; bar; bar = bar->next) { + bar->bx = m->wx + x_pad; + #if BAR_ANYBAR_PATCH && !BAR_ANYBAR_MANAGE_WIDTH_PATCH + if (bar->external) + continue; + #endif // BAR_ANYBAR_PATCH | BAR_ANYBAR_MANAGE_WIDTH_PATCH + bar->bw = m->ww - 2 * x_pad; + } + + for (bar = m->bar; bar; bar = bar->next) + if (!m->showbar || !bar->showbar) + bar->by = -bar->bh - y_pad; + + #if TAB_PATCH + for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c) && !HIDDEN(c)) + ++nvis; + } + + if (m->showtab == showtab_always + || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))) { + m->wh -= th; + m->ty = m->toptab ? m->wy : m->wy + m->wh; + if (m->toptab) + m->wy += th; + } else { + m->ty = -th; + } + #endif // TAB_PATCH + + if (!m->showbar) + return; + for (bar = m->bar; bar; bar = bar->next) { + if (!bar->showbar) + continue; + #if BAR_HOLDBAR_PATCH + if (m->showbar == 2) { + bar->by = (bar->topbar ? m->wy : m->wy + m->wh - bar->bh); + continue; + } + #endif // BAR_HOLDBAR_PATCH + if (bar->topbar) + m->wy = m->wy + bar->bh + y_pad; + m->wh -= y_pad + bar->bh; + bar->by = (bar->topbar ? m->wy - bar->bh : m->wy + m->wh); + } +} + +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); + + #if NET_CLIENT_LIST_STACKING_PATCH + XDeleteProperty(dpy, root, netatom[NetClientListStacking]); + for (m = mons; m; m = m->next) + for (c = m->stack; c; c = c->snext) + XChangeProperty(dpy, root, netatom[NetClientListStacking], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + #endif // NET_CLIENT_LIST_STACKING_PATCH +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + #if SORTSCREENS_PATCH + sortscreens(unique, nn); + #endif // SORTSCREENS_PATCH + /* 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 */ + #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH + size.flags = 0; + #else + size.flags = PSize; + #endif // SIZEHINTS_PATCH | SIZEHINTS_RULED_PATCH | SIZEHINTS_ISFREESIZE_PATCH + 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; + #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + if ((size.flags & PSize) && c->isfreesize) + #else + if (size.flags & PSize) + #endif // SIZEHINTS_ISFREESIZE_PATCH + { + c->basew = size.base_width; + c->baseh = size.base_height; + c->isfloating = 1; + } + #if SIZEHINTS_RULED_PATCH + checkfloatingrules(c); + #endif // SIZEHINTS_RULED_PATCH + #endif // SIZEHINTS_PATCH + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; +} + +void +updatestatus(void) +{ + Monitor *m; + #if BAR_EXTRASTATUS_PATCH + if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) { + strcpy(stext, "dwm-"VERSION); + estext[0] = '\0'; + } else { + char *e = strchr(rawstext, statussep); + if (e) { + *e = '\0'; e++; + #if BAR_STATUSCMD_PATCH + strncpy(rawestext, e, sizeof(estext) - 1); + copyvalidchars(estext, rawestext); + #else + strncpy(estext, e, sizeof(estext) - 1); + #endif // BAR_STATUSCMD_PATCH + } else { + estext[0] = '\0'; + } + #if BAR_STATUSCMD_PATCH + copyvalidchars(stext, rawstext); + #else + strncpy(stext, rawstext, sizeof(stext) - 1); + #endif // BAR_STATUSCMD_PATCH + } + #elif BAR_STATUSCMD_PATCH + if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) + strcpy(stext, "dwm-"VERSION); + else + copyvalidchars(stext, rawstext); + #else + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + #endif // BAR_EXTRASTATUS_PATCH | BAR_STATUSCMD_PATCH + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +updatetitle(Client *c) +{ + #if IPC_PATCH + char oldname[sizeof(c->name)]; + strcpy(oldname, c->name); + #endif // IPC_PATCH + + 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); + + #if IPC_PATCH + for (Monitor *m = mons; m; m = m->next) { + if (m->sel == c && strcmp(oldname, c->name) != 0) + ipc_focused_title_change_event(m->num, c->win, oldname, c->name); + } + #endif // IPC_PATCH +} + +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 (c->isurgent) { + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel); + } + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH + #if EMPTYVIEW_PATCH + if (arg->ui && (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + #else + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + #endif // EMPTYVIEW_PATCH + { + #if TOGGLETAG_PATCH + view(&((Arg) { .ui = 0 })); + #endif // TOGGLETAG_PATCH + return; + } + #if BAR_TAGPREVIEW_PATCH + tagpreviewswitchtag(); + #endif // BAR_TAGPREVIEW_PATCH + #if VIEW_HISTORY_PATCH + if (!arg->ui) { + selmon->seltags += 1; + if (selmon->seltags == LENGTH(selmon->tagset)) + selmon->seltags = 0; + } else { + if (selmon->seltags == 0) + selmon->seltags = LENGTH(selmon->tagset) - 1; + else + selmon->seltags -= 1; + } + #else + selmon->seltags ^= 1; /* toggle sel tagset */ + #endif // VIEW_HISTORY_PATCH + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + #if PERTAG_PATCH + pertagview(arg); + #endif // PERTAG_PATCH + #if TAGSYNC_PATCH + } + selmon = origselmon; + #endif // TAGSYNC_PATCH + #if TAGSYNC_PATCH + arrange(NULL); + #else + arrange(selmon); + #endif // TAGSYNC_PATCH + focus(NULL); + #if BAR_EWMHTAGS_PATCH + updatecurrentdesktop(); + #endif // BAR_EWMHTAGS_PATCH +} + +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; + Bar *bar; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (w == bar->win) + 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 FOCUSMASTER_RETURN_PATCH && ZOOMSWAP_PATCH + int i; + #endif // FOCUSMASTER_RETURN_PATCH + if (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + #if ZOOMSWAP_PATCH + Client *at = NULL, *cold, *cprevious = NULL, *p; + #endif // ZOOMSWAP_PATCH + + #if ZOOMFLOATING_PATCH + if (c && c->isfloating) + togglefloating(&((Arg) { .v = c })); + #endif // ZOOMFLOATING_PATCH + + #if SWAPFOCUS_PATCH && PERTAG_PATCH + c->mon->pertag->prevclient[c->mon->pertag->curtag] = nexttiled(c->mon->clients); + #endif // SWAPFOCUS_PATCH + + if (!c->mon->lt[c->mon->sellt]->arrange || !c || c->isfloating) + return; + + #if ZOOMSWAP_PATCH + if (c == nexttiled(c->mon->clients)) { + #if PERTAG_PATCH + p = c->mon->pertag->prevzooms[c->mon->pertag->curtag]; + #else + p = prevzoom; + #endif // PERTAG_PATCH + at = findbefore(p); + if (at) + cprevious = nexttiled(at->next); + if (!cprevious || cprevious != p) { + #if PERTAG_PATCH + c->mon->pertag->prevzooms[c->mon->pertag->curtag] = NULL; + #else + prevzoom = NULL; + #endif // PERTAG_PATCH + #if SWAPFOCUS_PATCH && PERTAG_PATCH + if (!c || !(c = c->mon->pertag->prevclient[c->mon->pertag->curtag] = nexttiled(c->next))) + #else + if (!c || !(c = nexttiled(c->next))) + #endif // SWAPFOCUS_PATCH + return; + } else + #if SWAPFOCUS_PATCH && PERTAG_PATCH + c = c->mon->pertag->prevclient[c->mon->pertag->curtag] = cprevious; + #else + c = cprevious; + #endif // SWAPFOCUS_PATCH + } + + cold = nexttiled(c->mon->clients); + if (c != cold && !at) + at = findbefore(c); + #if FOCUSMASTER_RETURN_PATCH + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + i++; + + c->mon->tagmarked[i] = cold; + #endif // FOCUSMASTER_RETURN_PATCH + detach(c); + attach(c); + /* swap windows instead of pushing the previous one down */ + if (c != cold && at) { + #if PERTAG_PATCH + c->mon->pertag->prevzooms[c->mon->pertag->curtag] = cold; + #else + prevzoom = cold; + #endif // PERTAG_PATCH + if (cold && at != cold) { + detach(cold); + cold->next = at->next; + at->next = cold; + } + } + focus(c); + arrange(c->mon); + #elif SWAPFOCUS_PATCH && PERTAG_PATCH + if (c == nexttiled(c->mon->clients) && !(c = c->mon->pertag->prevclient[c->mon->pertag->curtag] = nexttiled(c->next))) + return; + pop(c); + #else + if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) + return; + pop(c); + #endif // ZOOMSWAP_PATCH +} + +int +main(int argc, char *argv[]) +{ + #if CMDCUSTOMIZE_PATCH + for (int i=1;isel && m->sel->snext) { + alttabn++; + if (alttabn >= ntabs) + alttabn = 0; /* reset alttabn */ + + focus(altsnext[alttabn]); + restack(m); + } + + /* redraw tab */ + XRaiseWindow(dpy, alttabwin); + drawalttab(ntabs, 0, m); +} + +void +alttabend() +{ + Monitor *m = selmon; + Client *buff; + int i; + + if (!isalt) + return; + + /* Move all clients between first and choosen position, + * one down in stack and put choosen client to the first position + * so they remain in right order for the next time that alt-tab is used + */ + if (ntabs > 1) { + if (alttabn != 0) { /* if user picked original client do nothing */ + buff = altsnext[alttabn]; + if (alttabn > 1) + for (i = alttabn; i > 0; i--) + altsnext[i] = altsnext[i - 1]; + else /* swap them if there are just 2 clients */ + altsnext[alttabn] = altsnext[0]; + altsnext[0] = buff; + } + + /* restack clients */ + for (i = ntabs - 1; i >= 0; i--) { + focus(altsnext[i]); + restack(m); + } + + free(altsnext); /* free list of clients */ + } + + /* destroy the window */ + isalt = 0; + ntabs = 0; + XUnmapWindow(dpy, alttabwin); + XDestroyWindow(dpy, alttabwin); +} + +void +drawalttab(int nwins, int first, Monitor *m) +{ + Client *c; + int i, h; + int y = 0; + int px = m->mx; + int py = m->my; + + if (first) { + XSetWindowAttributes wa = { + .override_redirect = True, + #if BAR_ALPHA_PATCH + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + #else + .background_pixmap = ParentRelative, + #endif // BAR_ALPHA_PATCH + .event_mask = ButtonPressMask|ExposureMask + }; + + /* decide position of tabwin */ + if (tabposx == 1) + px = m->mx + (m->mw / 2) - (maxwtab / 2); + else if (tabposx == 2) + px = m->mx + m->mw - maxwtab; + + if (tabposy == 1) + py = m->my + (m->mh / 2) - (maxhtab / 2); + else if (tabposy == 2) + py = m->my + m->mh - maxhtab; + + h = maxhtab; + + #if BAR_ALPHA_PATCH + alttabwin = XCreateWindow(dpy, root, px, py, maxwtab, maxhtab, 2, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + #else + alttabwin = XCreateWindow(dpy, root, px, py, maxwtab, maxhtab, 2, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + #endif // BAR_ALPHA_PATCH + + XDefineCursor(dpy, alttabwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, alttabwin); + } + + h = maxhtab / ntabs; + for (i = 0; i < ntabs; i++) { /* draw all clients into tabwin */ + c = altsnext[i]; + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + drw_setscheme(drw, scheme[c == m->sel ? SchemeSel : SchemeNorm]); + drw_text(drw, 0, y, maxwtab, h, 0, c->name, 0, 0); + y += h; + } + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_map(drw, alttabwin, 0, 0, maxwtab, maxhtab); +} + +void +alttabstart(const Arg *arg) +{ + Client *c; + Monitor *m = selmon; + int grabbed; + int i; + + altsnext = NULL; + if (alttabwin) + alttabend(); + + if (isalt == 1) { + alttabend(); + return; + } + + isalt = 1; + alttabn = 0; + ntabs = 0; + + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + ++ntabs; + } + + if (!ntabs) { + alttabend(); + return; + } + + altsnext = (Client **) malloc(ntabs * sizeof(Client *)); + + for (i = 0, c = m->stack; c; c = c->snext) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + altsnext[i] = c; + i++; + } + + drawalttab(ntabs, 1, m); + + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; + + /* grab keyboard (take all input from keyboard) */ + grabbed = 1; + for (i = 0; i < 1000; i++) { + if (XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) + break; + nanosleep(&ts, NULL); + if (i == 1000 - 1) + grabbed = 0; + } + + XEvent event; + alttab(); + + if (grabbed == 0) { + alttabend(); + return; + } + + while (grabbed) { + XNextEvent(dpy, &event); + if (event.type == KeyPress || event.type == KeyRelease) { + if (event.type == KeyRelease && event.xkey.keycode == tabmodkey) /* if mod key is released break cycle */ + break; + + if (event.type == KeyPress) { + if (event.xkey.keycode == tabcyclekey) { /* if tab is pressed move to the next window */ + alttab(); + } + } + } + } + + c = m->sel; + alttabend(); + + XUngrabKeyboard(dpy, CurrentTime); + focus(c); + restack(m); +} diff --git a/dwm/patch/alttab.h b/dwm/patch/alttab.h new file mode 100755 index 0000000..07fed28 --- /dev/null +++ b/dwm/patch/alttab.h @@ -0,0 +1,5 @@ +#include + +static void drawalttab(int nwins, int first, Monitor *m); +static void alttabstart(const Arg *arg); +static void alttabend(); diff --git a/dwm/patch/alwaysontop.c b/dwm/patch/alwaysontop.c new file mode 100755 index 0000000..38801f0 --- /dev/null +++ b/dwm/patch/alwaysontop.c @@ -0,0 +1,20 @@ +void +togglealwaysontop(const Arg *arg) +{ + Client *c = selmon->sel; + + if (!c) + return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && !c->fakefullscreen) + return; + #else + if (c->isfullscreen) + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // FAKEFULLSCREEN_PATCH + + c->alwaysontop = !c->alwaysontop; + restack(selmon); +} diff --git a/dwm/patch/alwaysontop.h b/dwm/patch/alwaysontop.h new file mode 100755 index 0000000..34bdbd1 --- /dev/null +++ b/dwm/patch/alwaysontop.h @@ -0,0 +1 @@ +static void togglealwaysontop(const Arg *arg); diff --git a/dwm/patch/aspectresize.c b/dwm/patch/aspectresize.c new file mode 100755 index 0000000..cdd5afd --- /dev/null +++ b/dwm/patch/aspectresize.c @@ -0,0 +1,25 @@ +void +aspectresize(const Arg *arg) +{ + /* only floating windows can be moved */ + Client *c; + c = selmon->sel; + float ratio; + int w, h,nw, nh; + + if (!c || !arg) + return; + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) + return; + + ratio = (float)c->w / (float)c->h; + h = arg->i; + w = (int)(ratio * h); + + nw = c->w + w; + nh = c->h + h; + + XRaiseWindow(dpy, c->win); + resize(c, c->x, c->y, nw, nh, True); +} + diff --git a/dwm/patch/aspectresize.h b/dwm/patch/aspectresize.h new file mode 100755 index 0000000..4ac7cbb --- /dev/null +++ b/dwm/patch/aspectresize.h @@ -0,0 +1,2 @@ +static void aspectresize(const Arg *arg); + diff --git a/dwm/patch/attachx.c b/dwm/patch/attachx.c new file mode 100755 index 0000000..0ce908a --- /dev/null +++ b/dwm/patch/attachx.c @@ -0,0 +1,59 @@ +void +attachx(Client *c) +{ + #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH + Client *at; + #endif // ATTACHABOVE_PATCH | ATTACHASIDE_PATCH | ATTACHBOTTOM_PATCH | SEAMLESS_RESTART_PATCH + + #if SEAMLESS_RESTART_PATCH + if (c->idx > 0) { /* then the client has a designated position in the client list */ + for (at = c->mon->clients; at; at = at->next) { + if (c->idx < at->idx) { + c->next = at; + c->mon->clients = c; + return; + } else if (at->idx <= c->idx && (!at->next || c->idx <= at->next->idx)) { + c->next = at->next; + at->next = c; + return; + } + } + } + #endif // SEAMLESS_RESTART_PATCH + + #if ATTACHABOVE_PATCH + if (!(c->mon->sel == NULL || c->mon->sel == c->mon->clients || c->mon->sel->isfloating)) { + for (at = c->mon->clients; at->next != c->mon->sel; at = at->next); + c->next = at->next; + at->next = c; + return; + } + #elif ATTACHASIDE_PATCH + unsigned int n; + for (at = c->mon->clients, n = 0; at; at = at->next) + if (!at->isfloating && ISVISIBLEONTAG(at, c->tags)) + if (++n >= c->mon->nmaster) + break; + + if (at && c->mon->nmaster) { + c->next = at->next; + at->next = c; + return; + } + #elif ATTACHBELOW_PATCH + if (!(c->mon->sel == NULL || c->mon->sel == c || c->mon->sel->isfloating)) { + c->next = c->mon->sel->next; + c->mon->sel->next = c; + return; + } + #elif ATTACHBOTTOM_PATCH + for (at = c->mon->clients; at && at->next; at = at->next); + if (at) { + at->next = c; + c->next = NULL; + return; + } + #endif + attach(c); // master (default) +} + diff --git a/dwm/patch/attachx.h b/dwm/patch/attachx.h new file mode 100755 index 0000000..e522d27 --- /dev/null +++ b/dwm/patch/attachx.h @@ -0,0 +1,2 @@ +static void attachx(Client *c); + diff --git a/dwm/patch/autostart.c b/dwm/patch/autostart.c new file mode 100755 index 0000000..6053f1f --- /dev/null +++ b/dwm/patch/autostart.c @@ -0,0 +1,76 @@ +void +runautostart(void) +{ + char *pathpfx; + char *path; + char *xdgdatahome; + char *home; + struct stat sb; + + if ((home = getenv("HOME")) == NULL) + /* this is almost impossible */ + return; + + /* if $XDG_DATA_HOME is set and not empty, use $XDG_DATA_HOME/dwm, + * otherwise use ~/.local/share/dwm as autostart script directory + */ + xdgdatahome = getenv("XDG_DATA_HOME"); + if (xdgdatahome != NULL && *xdgdatahome != '\0') { + /* space for path segments, separators and nul */ + pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2); + + if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) { + free(pathpfx); + return; + } + } else { + /* space for path segments, separators and nul */ + pathpfx = ecalloc(1, strlen(home) + strlen(localshare) + + strlen(dwmdir) + 3); + + if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) { + free(pathpfx); + return; + } + } + + /* check if the autostart script directory exists */ + if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) { + /* the XDG conformant path does not exist or is no directory + * so we try ~/.dwm instead + */ + char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3); + if(pathpfx_new == NULL) { + free(pathpfx); + return; + } + pathpfx = pathpfx_new; + + if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) { + free(pathpfx); + return; + } + } + + /* try the blocking script first */ + path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2); + if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) { + free(path); + free(pathpfx); + } + + if (access(path, X_OK) == 0) + system(path); + + /* now the non-blocking script */ + if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) { + free(path); + free(pathpfx); + } + + if (access(path, X_OK) == 0) + system(strcat(path, " &")); + + free(pathpfx); + free(path); +} diff --git a/dwm/patch/autostart.h b/dwm/patch/autostart.h new file mode 100755 index 0000000..db29377 --- /dev/null +++ b/dwm/patch/autostart.h @@ -0,0 +1,2 @@ +static void runautostart(void); + diff --git a/dwm/patch/banish.c b/dwm/patch/banish.c new file mode 100755 index 0000000..60806ab --- /dev/null +++ b/dwm/patch/banish.c @@ -0,0 +1,71 @@ +static int cursor_hidden = 0; +/* mouse_x and mouse_y are used to store the actual co-ordinates of the mouse cursor when + * hidden. These can be manipulated freely, e.g. when using the warp patch, to set a new + * cursor position for when the cursor is to be revealed again. */ +static int mouse_x = 0; +static int mouse_y = 0; +static int xi_opcode; +static unsigned long long last_button_press = 0; + +void +genericevent(XEvent *e) +{ + if (e->xcookie.extension != xi_opcode) + return; + + if (!XGetEventData(dpy, &e->xcookie)) + return; + + switch (e->xcookie.evtype) { + case XI_RawMotion: + if (cursor_hidden) + showcursor(NULL); + break; + case XI_RawTouchBegin: + case XI_RawTouchEnd: + case XI_RawTouchUpdate: + if (!cursor_hidden) + hidecursor(NULL); + break; + case XI_RawKeyRelease: + if (now() - last_button_press > 2000 && !cursor_hidden) { + hidecursor(NULL); + } + break; + } + + XFreeEventData(dpy, &e->xcookie); +} + +void +hidecursor(const Arg *arg) +{ + if (cursor_hidden) + return; + + XFixesHideCursor(dpy, root); + if (getrootptr(&mouse_x, &mouse_y)) { + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->mx + selmon->mw, selmon->my); + } + + cursor_hidden = 1; +} + +unsigned long long +now(void) { + struct timespec currentTime; + clock_gettime(CLOCK_REALTIME, ¤tTime); + return currentTime.tv_sec * 1000LL + currentTime.tv_nsec / 1000000LL; +} + +void +showcursor(const Arg *arg) +{ + if (!cursor_hidden) + return; + + XWarpPointer(dpy, None, root, 0, 0, 0, 0, mouse_x, mouse_y); + XFixesShowCursor(dpy, root); + + cursor_hidden = 0; +} diff --git a/dwm/patch/banish.h b/dwm/patch/banish.h new file mode 100755 index 0000000..d26563b --- /dev/null +++ b/dwm/patch/banish.h @@ -0,0 +1,8 @@ +#include +#include +#include + +static void genericevent(XEvent *e); +static void hidecursor(const Arg *arg); +static unsigned long long now(void); +static void showcursor(const Arg *arg); diff --git a/dwm/patch/bar.c b/dwm/patch/bar.c new file mode 100755 index 0000000..65e1a69 --- /dev/null +++ b/dwm/patch/bar.c @@ -0,0 +1,39 @@ +void +barhover(XEvent *e, Bar *bar) +{ + const BarRule *br; + Monitor *m = bar->mon; + XMotionEvent *ev = &e->xmotion; + BarArg barg = { 0, 0, 0, 0 }; + int r; + + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->hoverfunc == NULL) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + if (bar->x[r] > ev->x || ev->x > bar->x[r] + bar->w[r]) + continue; + + barg.x = ev->x - bar->x[r]; + barg.y = ev->y - bar->borderpx; + barg.w = bar->w[r]; + barg.h = bar->bh - 2 * bar->borderpx; + + br->hoverfunc(bar, &barg, ev); + break; + } +} + +Bar * +wintobar(Window win) +{ + Monitor *m; + Bar *bar; + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (bar->win == win) + return bar; + return NULL; +} diff --git a/dwm/patch/bar.h b/dwm/patch/bar.h new file mode 100755 index 0000000..3e006dc --- /dev/null +++ b/dwm/patch/bar.h @@ -0,0 +1,2 @@ +static void barhover(XEvent *e, Bar *bar); +static Bar *wintobar(Window win); diff --git a/dwm/patch/bar_alpha.c b/dwm/patch/bar_alpha.c new file mode 100755 index 0000000..465f6f2 --- /dev/null +++ b/dwm/patch/bar_alpha.c @@ -0,0 +1,43 @@ + +static int useargb = 0; +static Visual *visual; +static int depth; +static Colormap cmap; + +void +xinitvisual() +{ + XVisualInfo *infos; + XRenderPictFormat *fmt; + int nitems; + int i; + + XVisualInfo tpl = { + .screen = screen, + .depth = 32, + .class = TrueColor + }; + long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; + + infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); + visual = NULL; + for (i = 0; i < nitems; i ++) { + fmt = XRenderFindVisualFormat(dpy, infos[i].visual); + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { + visual = infos[i].visual; + depth = infos[i].depth; + cmap = XCreateColormap(dpy, root, visual, AllocNone); + useargb = 1; + break; + } + } + + XFree(infos); + + if (!visual) { + visual = DefaultVisual(dpy, screen); + depth = DefaultDepth(dpy, screen); + cmap = DefaultColormap(dpy, screen); + } +} + diff --git a/dwm/patch/bar_alpha.h b/dwm/patch/bar_alpha.h new file mode 100755 index 0000000..1c2a012 --- /dev/null +++ b/dwm/patch/bar_alpha.h @@ -0,0 +1,4 @@ +#define OPAQUE 0xffU + +static void xinitvisual(); + diff --git a/dwm/patch/bar_alternativetags.c b/dwm/patch/bar_alternativetags.c new file mode 100755 index 0000000..bc800f2 --- /dev/null +++ b/dwm/patch/bar_alternativetags.c @@ -0,0 +1,7 @@ +void +togglealttag() +{ + selmon->alttag = !selmon->alttag; + drawbar(selmon); +} + diff --git a/dwm/patch/bar_alternativetags.h b/dwm/patch/bar_alternativetags.h new file mode 100755 index 0000000..0f7a25a --- /dev/null +++ b/dwm/patch/bar_alternativetags.h @@ -0,0 +1,2 @@ +static void togglealttag(); + diff --git a/dwm/patch/bar_anybar.c b/dwm/patch/bar_anybar.c new file mode 100755 index 0000000..d9bdb27 --- /dev/null +++ b/dwm/patch/bar_anybar.c @@ -0,0 +1,94 @@ +void +managealtbar(Window win, XWindowAttributes *wa) +{ + Monitor *m; + Bar *bar; + int i = 0; + if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) + return; + for (bar = m->bar; bar && bar->win && bar->next; bar = bar->next); // find last bar + if (!bar) { + bar = m->bar = ecalloc(1, sizeof(Bar)); + bar->topbar = topbar; + } else if (bar && bar->win) { + i = bar->idx + 1; + bar->next = ecalloc(1, sizeof(Bar)); + #if BAR_ANYBAR_TOP_AND_BOTTOM_BARS_PATCH + bar->next->topbar = !bar->topbar; + #else + bar->next->topbar = topbar; + #endif // BAR_ANYBAR_TOP_AND_BOTTOM_BARS_PATCH + bar = bar->next; + } + bar->external = 1; + bar->showbar = 1; + bar->mon = m; + bar->idx = i; + bar->borderpx = 0; + bar->win = win; + bar->bw = wa->width; + bar->bh = wa->height; + updatebarpos(m); + arrange(m); + XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + XMapWindow(dpy, win); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(selmon); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &win, 1); +} + +void +spawnbar() +{ + if (*altbarcmd) + system(altbarcmd); +} + +void +unmanagealtbar(Window w) +{ + Monitor *m = wintomon(w); + Bar *bar, *next, *prev = NULL; + + if (!m) + return; + + for (bar = m->bar; bar && bar->win; bar = next) { + next = bar->next; + if (bar->win == w) { + if (prev) + prev->next = next; + else + m->bar = next; + free(bar); + break; + } + prev = bar; + } + updatebarpos(m); + arrange(m); +} + +int +wmclasscontains(Window win, const char *class, const char *name) +{ + XClassHint ch = { NULL, NULL }; + int res = 1; + + if (XGetClassHint(dpy, win, &ch)) { + if (ch.res_name && strstr(ch.res_name, name) == NULL) + res = 0; + if (ch.res_class && strstr(ch.res_class, class) == NULL) + res = 0; + } else + res = 0; + + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + + return res; +} + diff --git a/dwm/patch/bar_anybar.h b/dwm/patch/bar_anybar.h new file mode 100755 index 0000000..980f5e2 --- /dev/null +++ b/dwm/patch/bar_anybar.h @@ -0,0 +1,5 @@ +static void managealtbar(Window win, XWindowAttributes *wa); +static void spawnbar(); +static void unmanagealtbar(Window w); +static int wmclasscontains(Window win, const char *class, const char *name); + diff --git a/dwm/patch/bar_awesomebar.c b/dwm/patch/bar_awesomebar.c new file mode 100755 index 0000000..c6fe8f1 --- /dev/null +++ b/dwm/patch/bar_awesomebar.c @@ -0,0 +1,123 @@ +int +width_awesomebar(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_awesomebar(Bar *bar, BarArg *a) +{ + int n = 0, scm, remainder = 0, tabw, tpad, tx, tw; + unsigned int i; + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + #if BAR_WINICON_PATCH + int ipad; + #endif // BAR_WINICON_PATCH + #if BAR_TITLE_LEFT_PAD_PATCH && BAR_TITLE_RIGHT_PAD_PATCH + int x = a->x + lrpad / 2, w = a->w - lrpad; + #elif BAR_TITLE_LEFT_PAD_PATCH + int x = a->x + lrpad / 2, w = a->w - lrpad / 2; + #elif BAR_TITLE_RIGHT_PAD_PATCH + int x = a->x, w = a->w - lrpad / 2; + #else + int x = a->x, w = a->w; + #endif // BAR_TITLE_LEFT_PAD_PATCH | BAR_TITLE_RIGHT_PAD_PATCH + + Client *c; + for (c = bar->mon->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + + if (n > 0) { + remainder = w % n; + tabw = w / n; + for (i = 0, c = bar->mon->clients; c; c = c->next, i++) { + if (!ISVISIBLE(c)) + continue; + if (bar->mon->sel == c && HIDDEN(c)) + scm = SchemeHidSel; + else if (HIDDEN(c)) + scm = SchemeHidNorm; + else if (bar->mon->sel == c) + scm = SchemeTitleSel; + else + scm = SchemeTitleNorm; + + tpad = lrpad / 2; + #if BAR_CENTEREDWINDOWNAME_PATCH + cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + #if BAR_WINICON_PATCH + ipad = c->icon ? c->icw + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + + tx = x; + tw = tabw; + + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + if (TEXTW(c->name) + ipad < tabw) + cpad = (tabw - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH + if (TEXTW(c->name) < tabw) + cpad = (tabw - TEXTW(c->name)) / 2; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + drw_setscheme(drw, scheme[scm]); + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, tx, a->y, tw, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + + #if BAR_WINICON_PATCH + if (ipad) { + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); + tx += ipad; + tw -= ipad; + } + #endif // BAR_WINICON_PATCH + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + + drawstateindicator(c->mon, c, 1, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, 0, 0, c->isfixed); + x += tabw + (i < remainder ? 1 : 0); + } + } + return n; +} + +int +click_awesomebar(Bar *bar, Arg *arg, BarArg *a) +{ + int x = 0, n = 0; + Client *c; + + for (c = bar->mon->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + + c = bar->mon->clients; + + do { + if (!c || !ISVISIBLE(c)) + continue; + else + x += (1.0 / (double)n) * a->w; + } while (c && a->x > x && (c = c->next)); + + if (c) { + arg->v = c; + return ClkWinTitle; + } + return -1; +} + diff --git a/dwm/patch/bar_awesomebar.h b/dwm/patch/bar_awesomebar.h new file mode 100755 index 0000000..5ea51f6 --- /dev/null +++ b/dwm/patch/bar_awesomebar.h @@ -0,0 +1,4 @@ +static int width_awesomebar(Bar *bar, BarArg *a); +static int draw_awesomebar(Bar *bar, BarArg *a); +static int click_awesomebar(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/bar_dwmblocks.c b/dwm/patch/bar_dwmblocks.c new file mode 100755 index 0000000..fe7880b --- /dev/null +++ b/dwm/patch/bar_dwmblocks.c @@ -0,0 +1,51 @@ +static int statussig; +pid_t statuspid = -1; + +pid_t +getstatusbarpid() +{ + char buf[32], *str = buf, *c; + FILE *fp; + + if (statuspid > 0) { + snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid); + if ((fp = fopen(buf, "r"))) { + fgets(buf, sizeof(buf), fp); + while ((c = strchr(str, '/'))) + str = c + 1; + fclose(fp); + if (!strcmp(str, STATUSBAR)) + return statuspid; + } + } + if (!(fp = popen("pgrep -o "STATUSBAR, "r"))) + return -1; + fgets(buf, sizeof(buf), fp); + pclose(fp); + return strtol(buf, NULL, 10); +} + +void +sigstatusbar(const Arg *arg) +{ + union sigval sv; + + if (!statussig) + return; + if ((statuspid = getstatusbarpid()) <= 0) + return; + + #if BAR_DWMBLOCKS_SIGUSR1_PATCH + sv.sival_int = (statussig << 8) | arg->i; + if (sigqueue(statuspid, SIGUSR1, sv) == -1) { + if (errno == ESRCH) { + if (!getstatusbarpid()) + sigqueue(statuspid, SIGUSR1, sv); + } + } + #else + sv.sival_int = arg->i; + sigqueue(statuspid, SIGRTMIN+statussig, sv); + #endif // BAR_DWMBLOCKS_SIGUSR1_PATCH +} + diff --git a/dwm/patch/bar_dwmblocks.h b/dwm/patch/bar_dwmblocks.h new file mode 100755 index 0000000..4db9467 --- /dev/null +++ b/dwm/patch/bar_dwmblocks.h @@ -0,0 +1,3 @@ +static int getstatusbarpid(); +static void sigstatusbar(const Arg *arg); + diff --git a/dwm/patch/bar_ewmhtags.c b/dwm/patch/bar_ewmhtags.c new file mode 100755 index 0000000..46ee5e4 --- /dev/null +++ b/dwm/patch/bar_ewmhtags.c @@ -0,0 +1,52 @@ +void +setcurrentdesktop(void) +{ + long data[] = { 0 }; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +void +setdesktopnames(void) +{ + int i; + XTextProperty text; + char *tags[NUMTAGS]; + for (i = 0; i < NUMTAGS; i++) + tags[i] = tagicon(selmon, i); + Xutf8TextListToTextProperty(dpy, tags, NUMTAGS, XUTF8StringStyle, &text); + XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]); +} + +void +setfloatinghint(Client *c) +{ + Atom target = XInternAtom(dpy, "_IS_FLOATING", 0); + unsigned int floating[1] = {c->isfloating}; + XChangeProperty(dpy, c->win, target, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)floating, 1); +} + +void +setnumdesktops(void) +{ + long data[] = { NUMTAGS }; + XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +void +setviewport(void) +{ + long data[] = { 0, 0 }; + XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2); +} + +void +updatecurrentdesktop(void) +{ + long rawdata[] = { selmon->tagset[selmon->seltags] }; + int i = 0; + while (*rawdata >> (i + 1)) { + i++; + } + long data[] = { i }; + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} diff --git a/dwm/patch/bar_ewmhtags.h b/dwm/patch/bar_ewmhtags.h new file mode 100755 index 0000000..4d6a74b --- /dev/null +++ b/dwm/patch/bar_ewmhtags.h @@ -0,0 +1,7 @@ +static void setcurrentdesktop(void); +static void setdesktopnames(void); +static void setfloatinghint(Client *c); +static void setnumdesktops(void); +static void setviewport(void); +static void updatecurrentdesktop(void); + diff --git a/dwm/patch/bar_fancybar.c b/dwm/patch/bar_fancybar.c new file mode 100755 index 0000000..40a1883 --- /dev/null +++ b/dwm/patch/bar_fancybar.c @@ -0,0 +1,103 @@ +int +width_fancybar(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_fancybar(Bar *bar, BarArg *a) +{ + int tabw, mw, ew = 0, n = 0, tx, tw; + #if BAR_WINICON_PATCH + int ipad; + #endif // BAR_WINICON_PATCH + unsigned int i; + Client *c; + Monitor *m = bar->mon; + + #if BAR_TITLE_LEFT_PAD_PATCH && BAR_TITLE_RIGHT_PAD_PATCH + int x = a->x + lrpad / 2, w = a->w - lrpad; + #elif BAR_TITLE_LEFT_PAD_PATCH + int x = a->x + lrpad / 2, w = a->w - lrpad / 2; + #elif BAR_TITLE_RIGHT_PAD_PATCH + int x = a->x, w = a->w - lrpad / 2; + #else + int x = a->x, w = a->w; + #endif // BAR_TITLE_LEFT_PAD_PATCH | BAR_TITLE_RIGHT_PAD_PATCH + + for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c)) + n++; + } + + if (n > 0) { + tabw = TEXTW(m->sel->name); + #if BAR_WINICON_PATCH + if (m->sel->icon) + tabw += m->sel->icw + ICONSPACING; + #endif // BAR_WINICON_PATCH + mw = (tabw >= w || n == 1) ? 0 : (w - tabw) / (n - 1); + + i = 0; + + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c) || c == m->sel) + continue; + tabw = TEXTW(c->name); + #if BAR_WINICON_PATCH + if (c->icon) + tabw += c->icw + ICONSPACING; + #endif // BAR_WINICON_PATCH + if (tabw < mw) + ew += (mw - tabw); + else + i++; + } + + if (i > 0) + mw += ew / i; + + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + tabw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); + #if BAR_WINICON_PATCH + ipad = c->icon ? c->icw + ICONSPACING : 0; + tabw += ipad; + #endif // BAR_WINICON_PATCH + tx = x; + tw = tabw; + drw_setscheme(drw, scheme[m->sel == c ? SchemeTitleSel : SchemeTitleNorm]); + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, tx, a->y, tw, a->h); + + if (tabw <= 0) /* trap special handling of 0 in drw_text */ + continue; + + tx += lrpad / 2; + tw -= lrpad; + + #if BAR_WINICON_PATCH + if (ipad) { + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); + tx += ipad; + tw -= ipad; + } + #endif // BAR_WINICON_PATCH + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(c->mon, c, 1, x, a->y, tabw, a->h, 0, 0, c->isfixed); + x += tabw; + w -= tabw; + } + } + return n; +} + +int +click_fancybar(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkWinTitle; +} + diff --git a/dwm/patch/bar_fancybar.h b/dwm/patch/bar_fancybar.h new file mode 100755 index 0000000..473cca3 --- /dev/null +++ b/dwm/patch/bar_fancybar.h @@ -0,0 +1,4 @@ +static int width_fancybar(Bar *bar, BarArg *a); +static int draw_fancybar(Bar *bar, BarArg *a); +static int click_fancybar(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/bar_flexwintitle.c b/dwm/patch/bar_flexwintitle.c new file mode 100755 index 0000000..c8cd4b6 --- /dev/null +++ b/dwm/patch/bar_flexwintitle.c @@ -0,0 +1,482 @@ +/* Flexwintitle properties, you can override these in your config.h if you want. */ +#ifndef FLEXWINTITLE_BORDERS +#define FLEXWINTITLE_BORDERS 1 // 0 = off, 1 = on +#endif +#ifndef FLEXWINTITLE_SHOWFLOATING +#define FLEXWINTITLE_SHOWFLOATING 0 // whether to show titles for floating windows, hidden clients are always shown +#endif +#ifndef FLEXWINTITLE_MASTERWEIGHT +#define FLEXWINTITLE_MASTERWEIGHT 9 // master weight compared to stack, hidden and floating window titles +#endif +#ifndef FLEXWINTITLE_STACKWEIGHT +#define FLEXWINTITLE_STACKWEIGHT 3 // stack weight compared to master, hidden and floating window titles +#endif +#ifndef FLEXWINTITLE_HIDDENWEIGHT +#define FLEXWINTITLE_HIDDENWEIGHT 1 // hidden window title weight +#endif +#ifndef FLEXWINTITLE_FLOATWEIGHT +#define FLEXWINTITLE_FLOATWEIGHT 1 // floating window title weight, set to 0 to not show floating windows +#endif + +#define SCHEMEFOR(c) getschemefor(m, c, groupactive == c) + +enum { GRP_NOSELECTION, GRP_MASTER, GRP_STACK1, GRP_STACK2, GRP_FLOAT, GRP_HIDDEN }; + +int +width_flexwintitle(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_flexwintitle(Bar *bar, BarArg *a) +{ + drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1); + return flextitlecalculate(bar->mon, a->x, a->w, -1, flextitledraw, NULL, a); +} + +int +click_flexwintitle(Bar *bar, Arg *arg, BarArg *a) +{ + flextitlecalculate(bar->mon, 0, a->w, a->x, flextitleclick, arg, a); + return ClkWinTitle; +} + +Client * +flextitledrawarea(Monitor *m, Client *c, int x, int r, int w, int max_clients, int scheme, int draw_tiled, int draw_hidden, int draw_floating, + int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg) +{ + int i; + for (i = 0; c && i < max_clients; c = c->next) { + if ( + ISVISIBLE(c) && + ( + (draw_tiled && !c->isfloating && !HIDDEN(c)) || + (draw_floating && c->isfloating && !HIDDEN(c)) || + (draw_hidden && HIDDEN(c)) + ) + ) { + tabfn(m, c, passx, x, w + (i < r ? 1 : 0), scheme, arg, barg); + x += w + (i < r ? 1 : 0); + i++; + } + } + return c; +} + +int +getschemefor(Monitor *m, int group, int activegroup) +{ + switch (group) { + case GRP_NOSELECTION: + case GRP_MASTER: + case GRP_STACK1: + case GRP_STACK2: + #if BSTACK_LAYOUT + if (m->lt[m->sellt]->arrange == &bstack) + return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); + #endif // BSTACK_LAYOUT + #if BSTACKHORIZ_LAYOUT + if (m->lt[m->sellt]->arrange == &bstackhoriz) { + if (group == GRP_MASTER) + return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); + else + return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); + } + #endif // BSTACKHORIZ_LAYOUT + #if CENTEREDMASTER_LAYOUT + if (m->lt[m->sellt]->arrange == ¢eredmaster) + return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); + #endif // CENTEREDMASTER_LAYOUT + #if CENTEREDFLOATINGMASTER_LAYOUT + if (m->lt[m->sellt]->arrange == ¢eredfloatingmaster) + return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); + #endif // CENTEREDFLOATINGMASTER_LAYOUT + #if COLUMNS_LAYOUT + if (m->lt[m->sellt]->arrange == &col) { + if (group == GRP_MASTER) + return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); + else + return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); + } + #endif // COLUMNS_LAYOUT + #if DECK_LAYOUT + if (m->lt[m->sellt]->arrange == &deck) { + if (group == GRP_MASTER) + return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); + else + return (activegroup ? SchemeFlexActMONO : SchemeFlexInaMONO); + } + #endif // DECK_LAYOUT + #if FIBONACCI_DWINDLE_LAYOUT + if (m->lt[m->sellt]->arrange == &dwindle) + return (activegroup ? SchemeFlexActDWDL : SchemeFlexInaDWDL); + #endif // FIBONACCI_DWINDLE_LAYOUT + #if FIBONACCI_SPIRAL_LAYOUT + if (m->lt[m->sellt]->arrange == &spiral) + return (activegroup ? SchemeFlexActSPRL : SchemeFlexInaSPRL); + #endif // FIBONACCI_SPIRAL_LAYOUT + #if FLEXTILE_DELUXE_LAYOUT + if (m->lt[m->sellt]->arrange == &flextile) + return (activegroup ? SchemeFlexActTTB + m->ltaxis[group] : SchemeFlexInaTTB + m->ltaxis[group]); + #endif // FLEXTILE_DELUXE_LAYOUT + #if GAPPLESSGRID_LAYOUT + if (m->lt[m->sellt]->arrange == &gaplessgrid) + return (activegroup ? SchemeFlexActGRID : SchemeFlexInaGRID); + #endif // GAPPLESSGRID_LAYOUT + #if GRIDMODE_LAYOUT + if (m->lt[m->sellt]->arrange == &grid) + return (activegroup ? SchemeFlexActGRDM : SchemeFlexInaGRDM); + #endif // GRIDMODE_LAYOUT + #if HORIZGRID_LAYOUT + if (m->lt[m->sellt]->arrange == &horizgrid) + return (activegroup ? SchemeFlexActHGRD : SchemeFlexInaHGRD); + #endif // HORIZGRID_LAYOUT + #if NROWGRID_LAYOUT + if (m->lt[m->sellt]->arrange == &nrowgrid) + return (activegroup ? SchemeFlexActGRD1 : SchemeFlexInaGRD1); + #endif // NROWGRID_LAYOUT + #if TILE_LAYOUT + if (m->lt[m->sellt]->arrange == &tile) + return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); + #endif // TILE_LAYOUT + #if MONOCLE_LAYOUT + if (m->lt[m->sellt]->arrange == &monocle) + return (activegroup ? SchemeFlexActMONO : SchemeFlexInaMONO); + #endif // MONOCLE_LAYOUT + return SchemeTitleNorm; + case GRP_HIDDEN: + return SchemeHidNorm; + case GRP_FLOAT: + return (activegroup ? SchemeFlexActFloat : SchemeFlexInaFloat); + } + return SchemeTitleNorm; +} + +int +getselschemefor(int scheme) +{ + if (scheme == SchemeFlexActFloat || scheme == SchemeFlexInaFloat) + return SchemeFlexSelFloat; + if (scheme >= SchemeFlexInaTTB) + return scheme + SchemeFlexInaTTB - SchemeFlexActTTB; + if (scheme >= SchemeFlexActTTB) + return scheme + SchemeFlexSelTTB - SchemeFlexActTTB; + return SchemeTitleSel; +} + +void +flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Arg *arg, BarArg *a) +{ + if (!c) + return; + int i, nclienttags = 0, nviewtags = 0; + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icw + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + + int clientscheme = ( + #if RENAMED_SCRATCHPADS_PATCH + c->scratchkey != 0 && c == selmon->sel + ? SchemeScratchSel + : c->scratchkey != 0 + ? SchemeScratchNorm + : + #endif // RENAMED_SCRATCHPADS_PATCH + c == selmon->sel && HIDDEN(c) + ? SchemeHidSel + : HIDDEN(c) + ? SchemeHidNorm + : c == selmon->sel + ? getselschemefor(tabscheme) + : c->isurgent + ? SchemeUrg + : tabscheme + ); + + drw_setscheme(drw, scheme[clientscheme]); + XSetWindowBorder(dpy, c->win, scheme[clientscheme][ColBorder].pixel); + + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) < w) + cpad = (w - TEXTW(c->name)) / 2; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + + #if BAR_WINICON_PATCH + if (ipad) { + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); + tx += ipad; + tw -= ipad; + } + #endif // BAR_WINICON_PATCH + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(m, c, 1, x + 2, a->y, w, a->h, 0, 0, 0); + + if (FLEXWINTITLE_BORDERS) { + XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); + } + + /* Optional tags icons */ + for (i = 0; i < NUMTAGS; i++) { + if ((m->tagset[m->seltags] >> i) & 1) + nviewtags++; + if ((c->tags >> i) & 1) + nclienttags++; + } + + if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) + drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); +} + +#ifndef HIDDEN +#define HIDDEN(C) 0 +#endif + +void +flextitleclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg) +{ + if (passx >= x && passx <= x + w) + arg->v = c; +} + +int +flextitlecalculate( + Monitor *m, int offx, int tabw, int passx, + void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), + Arg *arg, BarArg *barg +) { + Client *c; + int n, center = 0, mirror = 0, fixed = 0; // layout configuration + int clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, clientsnhidden = 0; + int i, w, r, num = 0, den, fulllayout = 0; + int clientsnstack2 = 0; + int groupactive = 0; + int selidx = 0; + int dualstack = 0; + int rw, rr; + + int mas_x = offx, st1_x = offx, st2_x = offx, hid_x = offx, flt_x = offx; + int mas_w, st1_w, st2_w, hid_w; + + for (i = 0, c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) { + if (FLEXWINTITLE_HIDDENWEIGHT) + clientsnhidden++; + continue; + } + + if (c->isfloating) { + if (FLEXWINTITLE_FLOATWEIGHT) + clientsnfloating++; + continue; + } + + if (m->sel == c) + selidx = i; + + if (i < m->nmaster) + clientsnmaster++; + #if FLEXTILE_DELUXE_LAYOUT + else if (m->nstack) { + if (clientsnstack < m->nstack) + clientsnstack++; + else + clientsnstack2++; + } + #endif // FLEXTILE_DELUXE_LAYOUT + else if ((i - m->nmaster) % 2) + clientsnstack2++; + else + clientsnstack++; + i++; + } + + if (!m->sel) + groupactive = GRP_NOSELECTION; + else if (HIDDEN(m->sel)) + groupactive = GRP_HIDDEN; + else if (m->sel->isfloating) + groupactive = GRP_FLOAT; + else if (selidx < clientsnmaster) + groupactive = GRP_MASTER; + else if (selidx < clientsnmaster + clientsnstack) + groupactive = GRP_STACK1; + else if (selidx < clientsnmaster + clientsnstack + clientsnstack2) + groupactive = GRP_STACK2; + + n = clientsnmaster + clientsnstack + clientsnstack2 + clientsnfloating + clientsnhidden; + if (n == 0) + return 0; + #if FLEXTILE_DELUXE_LAYOUT + else if (m->lt[m->sellt]->arrange == &flextile) { + int layout = m->ltaxis[LAYOUT]; + if (layout < 0) { + mirror = 1; + layout *= -1; + } + if (layout > FLOATING_MASTER) { + layout -= FLOATING_MASTER; + fixed = 1; + } + + if (layout == SPLIT_HORIZONTAL_DUAL_STACK || layout == SPLIT_HORIZONTAL_DUAL_STACK_FIXED) + dualstack = 1; + else if (layout == SPLIT_CENTERED_VERTICAL && (fixed || n - m->nmaster > 1)) + center = 1; + else if (layout == FLOATING_MASTER) + center = 1; + else if (layout == SPLIT_CENTERED_HORIZONTAL) { + if (fixed || n - m->nmaster > 1) + center = 1; + } + } + #endif // FLEXTILE_DELUXE_LAYOUT + #if CENTEREDMASTER_LAYOUT + else if (m->lt[m->sellt]->arrange == ¢eredmaster && (fixed || n - m->nmaster > 1)) + center = 1; + #endif // CENTEREDMASTER_LAYOUT + #if CENTEREDFLOATINGMASTER_LAYOUT + else if (m->lt[m->sellt]->arrange == ¢eredfloatingmaster) + center = 1; + #endif // CENTEREDFLOATINGMASTER_LAYOUT + + /* Certain layouts have no master / stack areas */ + if (!m->lt[m->sellt]->arrange // floating layout + || (!n || (!fixed && m->nmaster && n <= m->nmaster)) // no master + #if MONOCLE_LAYOUT + || m->lt[m->sellt]->arrange == &monocle + #endif // MONOCLE_LAYOUT + #if GRIDMODE_LAYOUT + || m->lt[m->sellt]->arrange == &grid + #endif // GRIDMODE_LAYOUT + #if HORIZGRID_LAYOUT + || m->lt[m->sellt]->arrange == &horizgrid + #endif // HORIZGRID_LAYOUT + #if GAPPLESSGRID_LAYOUT + || m->lt[m->sellt]->arrange == &gaplessgrid + #endif // GAPPLESSGRID_LAYOUT + #if NROWGRID_LAYOUT + || m->lt[m->sellt]->arrange == &nrowgrid + #endif // NROWGRID_LAYOUT + #if FLEXTILE_DELUXE_LAYOUT + || (m->lt[m->sellt]->arrange == &flextile && m->ltaxis[LAYOUT] == NO_SPLIT) + #endif // FLEXTILE_DELUXE_LAYOUT + ) + fulllayout = 1; + + num = tabw; + c = m->clients; + + /* floating mode */ + if ((fulllayout && FLEXWINTITLE_FLOATWEIGHT > 0) || clientsnmaster + clientsnstack == 0 || !m->lt[m->sellt]->arrange) { + den = clientsnmaster + clientsnstack + clientsnstack2 + clientsnfloating + clientsnhidden; + w = num / den; + r = num % den; // rest + c = flextitledrawarea(m, c, mas_x, r, w, den, !m->lt[m->sellt]->arrange ? SchemeFlexActFloat : SCHEMEFOR(GRP_MASTER), 1, FLEXWINTITLE_HIDDENWEIGHT, FLEXWINTITLE_FLOATWEIGHT, passx, tabfn, arg, barg); // floating + /* no master and stack mode, e.g. monocole, grid layouts, fibonacci */ + } else if (fulllayout) { + den = clientsnmaster + clientsnstack + clientsnstack2 + clientsnhidden; + w = num / den; + r = num % den; // rest + c = flextitledrawarea(m, c, mas_x, r, w, den, SCHEMEFOR(GRP_MASTER), 1, FLEXWINTITLE_HIDDENWEIGHT, 0, passx, tabfn, arg, barg); // full + /* tiled mode */ + } else { + den = clientsnmaster * FLEXWINTITLE_MASTERWEIGHT + (clientsnstack + clientsnstack2) * FLEXWINTITLE_STACKWEIGHT + clientsnfloating * FLEXWINTITLE_FLOATWEIGHT + clientsnhidden * FLEXWINTITLE_HIDDENWEIGHT; + w = num / den; // weight width per client + r = num % den; // weight rest width + rw = r / n; // rest incr per client + rr = r % n; // rest rest + #if FLEXTILE_DELUXE_LAYOUT + if ((!center && !dualstack) || (center && n <= m->nmaster + (m->nstack ? m->nstack : 1))) + #else + if ((!center && !dualstack) || (center && n <= m->nmaster + 1)) + #endif // FLEXTILE_DELUXE_LAYOUT + { + clientsnstack += clientsnstack2; + clientsnstack2 = 0; + if (groupactive == GRP_STACK2) + groupactive = GRP_STACK1; + } + + mas_w = clientsnmaster * rw + w * clientsnmaster * FLEXWINTITLE_MASTERWEIGHT + (rr > 0 ? MIN(rr, clientsnmaster) : 0); + rr -= clientsnmaster; + st1_w = clientsnstack * (rw + w * FLEXWINTITLE_STACKWEIGHT) + (rr > 0 ? MIN(rr, clientsnstack) : 0); + rr -= clientsnstack; + st2_w = clientsnstack2 * (rw + w * FLEXWINTITLE_STACKWEIGHT) + (rr > 0 ? MIN(rr, clientsnstack2) : 0); + rr -= clientsnstack2; + hid_w = clientsnhidden * (rw + w * FLEXWINTITLE_HIDDENWEIGHT) + (rr > 0 ? MIN(rr, clientsnhidden) : 0); + rr -= clientsnhidden; + rr = r % n; + + if (mirror) { + if (center && clientsnstack2) { + mas_x = st1_x + st1_w; + st2_x = mas_x + mas_w; + hid_x = st2_x + st2_w; + } else { + if (clientsnstack2) { + st2_x = st1_x + st1_w; + mas_x = st2_x + st2_w; + } else + mas_x = st1_x + st1_w; + hid_x = mas_x + mas_w; + } + } else { + if (center && clientsnstack2) { + mas_x = st2_x + st2_w; + st1_x = mas_x + mas_w; + hid_x = st1_x + st1_w; + } else { + st1_x = mas_x + mas_w; + if (clientsnstack2) { + st2_x = st1_x + st1_w; + hid_x = st2_x + st2_w; + } else + hid_x = st1_x + st1_w; + } + } + + flt_x = hid_x + hid_w; + c = flextitledrawarea(m, c, mas_x, rr, w * FLEXWINTITLE_MASTERWEIGHT + rw, clientsnmaster, SCHEMEFOR(GRP_MASTER), 1, 0, 0, passx, tabfn, arg, barg); // master + rr -= clientsnmaster; + c = flextitledrawarea(m, c, st1_x, rr, w * FLEXWINTITLE_STACKWEIGHT + rw, clientsnstack, SCHEMEFOR(GRP_STACK1), 1, 0, 0, passx, tabfn, arg, barg); // stack1 + rr -= clientsnstack; + if (clientsnstack2) { + c = flextitledrawarea(m, c, st2_x, rr, w * FLEXWINTITLE_STACKWEIGHT + rw, clientsnstack2, SCHEMEFOR(GRP_STACK2), 1, 0, 0, passx, tabfn, arg, barg); // stack2 + rr -= clientsnstack2; + } + c = flextitledrawarea(m, m->clients, hid_x, rr, w * FLEXWINTITLE_HIDDENWEIGHT + rw, clientsnhidden, SCHEMEFOR(GRP_HIDDEN), 0, 1, 0, passx, tabfn, arg, barg); // hidden + rr -= clientsnhidden; + c = flextitledrawarea(m, m->clients, flt_x, rr, w * FLEXWINTITLE_FLOATWEIGHT + rw, clientsnfloating, SCHEMEFOR(GRP_FLOAT), 0, 0, 1, passx, tabfn, arg, barg); // floating + } + return 1; +} + diff --git a/dwm/patch/bar_flexwintitle.h b/dwm/patch/bar_flexwintitle.h new file mode 100755 index 0000000..f4c6612 --- /dev/null +++ b/dwm/patch/bar_flexwintitle.h @@ -0,0 +1,11 @@ +static int width_flexwintitle(Bar *bar, BarArg *a); +static int draw_flexwintitle(Bar *bar, BarArg *a); +static int click_flexwintitle(Bar *bar, Arg *arg, BarArg *a); + +static void flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg); +static void flextitleclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg); +static int flextitlecalculate(Monitor *m, int offx, int w, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg); +static int getschemefor(Monitor *m, int group, int activegroup); +static int getselschemefor(int scheme); +static Client *flextitledrawarea(Monitor *m, Client *c, int x, int r, int w, int max_clients, int tabscheme, int draw_tiled, int draw_hidden, int draw_floating, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg); + diff --git a/dwm/patch/bar_holdbar.c b/dwm/patch/bar_holdbar.c new file mode 100755 index 0000000..7597a38 --- /dev/null +++ b/dwm/patch/bar_holdbar.c @@ -0,0 +1,43 @@ +void +holdbar(const Arg *arg) +{ + if (selmon->showbar) + return; + Bar *bar; + selmon->showbar = 2; + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + drawbar(selmon); +} + +void +keyrelease(XEvent *e) +{ + Bar *bar; + if (XEventsQueued(dpy, QueuedAfterReading)) { + XEvent ne; + XPeekEvent(dpy, &ne); + + if (ne.type == KeyPress && ne.xkey.time == e->xkey.time && + ne.xkey.keycode == e->xkey.keycode) { + XNextEvent(dpy, &ne); + return; + } + } + if (e->xkey.keycode == XKeysymToKeycode(dpy, HOLDKEY) && selmon->showbar == 2) { + selmon->showbar = 0; + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #if BAR_SYSTRAY_PATCH + if (!selmon->showbar && systray) + XMoveWindow(dpy, systray->win, -32000, -32000); + #endif // BAR_SYSTRAY_PATCH + arrange(selmon); + } + #if COMBO_PATCH + combo = 0; + #endif // COMBO_PATCH +} + diff --git a/dwm/patch/bar_holdbar.h b/dwm/patch/bar_holdbar.h new file mode 100755 index 0000000..bcde089 --- /dev/null +++ b/dwm/patch/bar_holdbar.h @@ -0,0 +1,3 @@ +static void keyrelease(XEvent *e); +static void holdbar(const Arg *arg); + diff --git a/dwm/patch/bar_indicators.c b/dwm/patch/bar_indicators.c new file mode 100755 index 0000000..712d4fc --- /dev/null +++ b/dwm/patch/bar_indicators.c @@ -0,0 +1,115 @@ +/* Indicator properties, you can override these in your config.h if you want. */ +#ifndef TAGSINDICATOR +#define TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on +#endif +#ifndef TAGSPX +#define TAGSPX 5 // # pixels for tag grid boxes +#endif +#ifndef TAGSROWS +#define TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3) +#endif + +void +drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type) +{ + int i, boxw, boxs, indn = 0; + if (!(occ & 1 << tag) || type == INDICATOR_NONE) + return; + + boxs = drw->fonts->h / 9; + boxw = drw->fonts->h / 6 + 2; + if (filled == -1) + filled = m == selmon && m->sel && m->sel->tags & 1 << tag; + + switch (type) { + default: + case INDICATOR_TOP_LEFT_SQUARE: + drw_rect(drw, x + boxs, y + boxs, boxw, boxw, filled, invert); + break; + case INDICATOR_TOP_LEFT_LARGER_SQUARE: + drw_rect(drw, x + boxs + 2, y + boxs+1, boxw+1, boxw+1, filled, invert); + break; + case INDICATOR_TOP_BAR: + drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), boxw/2, filled, invert); + break; + case INDICATOR_TOP_BAR_SLIM: + drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), 1, 0, invert); + break; + case INDICATOR_BOTTOM_BAR: + drw_rect(drw, x + boxw, y + h - boxw/2, w - ( 2 * boxw + 1), boxw/2, filled, invert); + break; + case INDICATOR_BOTTOM_BAR_SLIM: + drw_rect(drw, x + boxw, y + h - 1, w - ( 2 * boxw + 1), 1, 0, invert); + break; + case INDICATOR_BOX: + drw_rect(drw, x + boxw, y, w - 2 * boxw, h, 0, invert); + break; + case INDICATOR_BOX_WIDER: + drw_rect(drw, x + boxw/2, y, w - boxw, h, 0, invert); + break; + case INDICATOR_BOX_FULL: + drw_rect(drw, x, y, w - 2, h, 0, invert); + break; + case INDICATOR_CLIENT_DOTS: + for (c = m->clients; c; c = c->next) { + if (c->tags & (1 << tag)) { + drw_rect(drw, x, 1 + (indn * 2), m->sel == c ? 6 : 1, 1, 1, invert); + indn++; + } + if (h <= 1 + (indn * 2)) { + indn = 0; + x += 2; + } + } + break; + case INDICATOR_RIGHT_TAGS: + if (!c) + break; + for (i = 0; i < NUMTAGS; i++) { + drw_rect(drw, + ( x + w - 2 - ((NUMTAGS / TAGSROWS) * TAGSPX) + - (i % (NUMTAGS/TAGSROWS)) + ((i % (NUMTAGS / TAGSROWS)) * TAGSPX) + ), + ( y + 2 + ((i / (NUMTAGS/TAGSROWS)) * TAGSPX) + - ((i / (NUMTAGS/TAGSROWS))) + ), + TAGSPX, TAGSPX, (c->tags >> i) & 1, 0 + ); + } + break; + case INDICATOR_PLUS_AND_LARGER_SQUARE: + boxs += 2; + boxw += 2; + /* falls through */ + case INDICATOR_PLUS_AND_SQUARE: + drw_rect(drw, x + boxs, y + boxs, boxw % 2 ? boxw : boxw + 1, boxw % 2 ? boxw : boxw + 1, filled, invert); + /* falls through */ + case INDICATOR_PLUS: + if (!(boxw % 2)) + boxw += 1; + drw_rect(drw, x + boxs + boxw / 2, y + boxs, 1, boxw, filled, invert); // | + drw_rect(drw, x + boxs, y + boxs + boxw / 2, boxw + 1, 1, filled, invert); // ‒ + break; + } +} + +void +drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert) +{ + #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + if (c->fakefullscreen && c->isfloating) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatfakefsindicatortype); + else if (c->fakefullscreen) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, fakefsindicatortype); + else + #endif // FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfloating) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatindicatortype); + else + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, tiledindicatortype); + #if ALWAYSONTOP_PATCH + if (c->isfloating && c->alwaysontop) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, aotindicatortype); + #endif // ALWAYSONTOP_PATCH +} + diff --git a/dwm/patch/bar_indicators.h b/dwm/patch/bar_indicators.h new file mode 100755 index 0000000..c66e4f0 --- /dev/null +++ b/dwm/patch/bar_indicators.h @@ -0,0 +1,21 @@ +enum { + INDICATOR_NONE, + INDICATOR_TOP_LEFT_SQUARE, + INDICATOR_TOP_LEFT_LARGER_SQUARE, + INDICATOR_TOP_BAR, + INDICATOR_TOP_BAR_SLIM, + INDICATOR_BOTTOM_BAR, + INDICATOR_BOTTOM_BAR_SLIM, + INDICATOR_BOX, + INDICATOR_BOX_WIDER, + INDICATOR_BOX_FULL, + INDICATOR_CLIENT_DOTS, + INDICATOR_RIGHT_TAGS, + INDICATOR_PLUS, + INDICATOR_PLUS_AND_SQUARE, + INDICATOR_PLUS_AND_LARGER_SQUARE, +}; + +static void drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type); +static void drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert); + diff --git a/dwm/patch/bar_launcher.c b/dwm/patch/bar_launcher.c new file mode 100755 index 0000000..a06096d --- /dev/null +++ b/dwm/patch/bar_launcher.c @@ -0,0 +1,81 @@ +#if BAR_STATUS2D_PATCH +int +width_launcher(Bar *bar, BarArg *a) +{ + int i, x = 0; + + for (i = 0; i < LENGTH(launchers); i++) { + x += status2dtextlength(launchers[i].name) + lrpad; + } + return x; +} + +int +draw_launcher(Bar *bar, BarArg *a) +{ + int i, w = 0;; + + for (i = 0; i < LENGTH(launchers); i++) { + w = status2dtextlength(launchers[i].name); + drawstatusbar(a, launchers[i].name); + a->x += w + lrpad; + } + + return a->x ; +} + +int +click_launcher(Bar *bar, Arg *arg, BarArg *a) +{ + int i, x = 0; + + for (i = 0; i < LENGTH(launchers); i++) { + x += status2dtextlength(launchers[i].name) + lrpad; + if (a->x < x) { + spawn(&launchers[i].command); + break; + } + } + return -1; +} +#else +int +width_launcher(Bar *bar, BarArg *a) +{ + int i, x = 0; + + for (i = 0; i < LENGTH(launchers); i++) { + x += TEXTW(launchers[i].name); + } + return x; +} + +int +draw_launcher(Bar *bar, BarArg *a) +{ + int i, x = 0, w = 0;; + + for (i = 0; i < LENGTH(launchers); i++) { + w = TEXTW(launchers[i].name); + drw_text(drw, x, 0, w, bh, lrpad / 2, launchers[i].name, 0, True); + x += w; + } + + return x; +} + +int +click_launcher(Bar *bar, Arg *arg, BarArg *a) +{ + int i, x = 0; + + for (i = 0; i < LENGTH(launchers); i++) { + x += TEXTW(launchers[i].name); + if (a->x < x) { + spawn(&launchers[i].command); + break; + } + } + return -1; +} +#endif // BAR_STATUS2D_PATCH \ No newline at end of file diff --git a/dwm/patch/bar_launcher.h b/dwm/patch/bar_launcher.h new file mode 100755 index 0000000..c2b3259 --- /dev/null +++ b/dwm/patch/bar_launcher.h @@ -0,0 +1,8 @@ +typedef struct { + char* name; + const Arg command; +} Launcher; + +static int width_launcher(Bar *bar, BarArg *a); +static int draw_launcher(Bar *bar, BarArg *a); +static int click_launcher(Bar *bar, Arg *arg, BarArg *a); diff --git a/dwm/patch/bar_layoutmenu.c b/dwm/patch/bar_layoutmenu.c new file mode 100755 index 0000000..bab4e47 --- /dev/null +++ b/dwm/patch/bar_layoutmenu.c @@ -0,0 +1,18 @@ +void +layoutmenu(const Arg *arg) { + FILE *p; + char c[3], *s; + int i; + + if (!(p = popen(layoutmenu_cmd, "r"))) + return; + s = fgets(c, sizeof(c), p); + pclose(p); + + if (!s || *s == '\0' || c[0] == '\0') + return; + + i = atoi(c); + setlayout(&((Arg) { .v = &layouts[i] })); +} + diff --git a/dwm/patch/bar_layoutmenu.h b/dwm/patch/bar_layoutmenu.h new file mode 100755 index 0000000..d05455c --- /dev/null +++ b/dwm/patch/bar_layoutmenu.h @@ -0,0 +1,2 @@ +static void layoutmenu(const Arg *arg); + diff --git a/dwm/patch/bar_ltsymbol.c b/dwm/patch/bar_ltsymbol.c new file mode 100755 index 0000000..fe5ce86 --- /dev/null +++ b/dwm/patch/bar_ltsymbol.c @@ -0,0 +1,20 @@ +int +width_ltsymbol(Bar *bar, BarArg *a) +{ + return TEXTW(bar->mon->ltsymbol); +} + +int +draw_ltsymbol(Bar *bar, BarArg *a) +{ + #if BAR_LTSYMBOL_SCHEME_PATCH + drw_setscheme(drw, scheme[SchemeLtSymbol]); + #endif // BAR_LTSYMBOL_SCHEME_PATCH + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, bar->mon->ltsymbol, 0, False); +} + +int +click_ltsymbol(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkLtSymbol; +} diff --git a/dwm/patch/bar_ltsymbol.h b/dwm/patch/bar_ltsymbol.h new file mode 100755 index 0000000..4188584 --- /dev/null +++ b/dwm/patch/bar_ltsymbol.h @@ -0,0 +1,3 @@ +static int width_ltsymbol(Bar *bar, BarArg *a); +static int draw_ltsymbol(Bar *bar, BarArg *a); +static int click_ltsymbol(Bar *bar, Arg *arg, BarArg *a); diff --git a/dwm/patch/bar_powerline_status.c b/dwm/patch/bar_powerline_status.c new file mode 100755 index 0000000..a09487f --- /dev/null +++ b/dwm/patch/bar_powerline_status.c @@ -0,0 +1,122 @@ +static Clr **statusscheme; + +int +width_pwrl_status(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return widthpowerlinestatus(rawstext); + #else + return widthpowerlinestatus(stext); + #endif // BAR_STATUSCMD_PATCH +} + +#if BAR_EXTRASTATUS_PATCH +int +width_pwrl_status_es(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return widthpowerlinestatus(rawestext); + #else + return widthpowerlinestatus(estext); + #endif // BAR_STATUSCMD_PATCH +} +#endif // BAR_EXTRASTATUS_PATCH + +int +draw_pwrl_status(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return drawpowerlinestatus(a->x + a->w, rawstext, a); + #else + return drawpowerlinestatus(a->x + a->w, stext, a); + #endif // BAR_STATUSCMD_PATCH +} + +#if BAR_EXTRASTATUS_PATCH +int +draw_pwrl_status_es(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return drawpowerlinestatus(a->x + a->w, rawestext, a); + #else + return drawpowerlinestatus(a->x + a->w, estext, a); + #endif // BAR_STATUSCMD_PATCH +} +#endif // BAR_EXTRASTATUS_PATCH + +int +click_pwrl_status(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkStatusText; +} + +int +widthpowerlinestatus(char *stext) +{ + char status[512]; + int w = 0, i, n = strlen(stext); + int plw = drw->fonts->h / 2 + 1; + char *bs, bp = '|'; + strcpy(status, stext); + + for (i = n, bs = &status[n-1]; i >= 0; i--, bs--) { + if (*bs == '<' || *bs == '/' || *bs == '\\' || *bs == '>' || *bs == '|') { /* block start */ + if (bp != '|') + w += plw; + w += TEXTW(bs+2); + bp = *bs; + *bs = 0; + } + } + if (bp != '|') + w += plw * 2; + + return w; +} + +int +drawpowerlinestatus(int xpos, char *stext, BarArg *barg) +{ + char status[512]; + int i, n = strlen(stext), cn = 0; + int x = xpos, w = 0; + int plw = drw->fonts->h / 2 + 1; + char *bs, bp = '|'; + Clr *prevscheme = statusscheme[0], *nxtscheme; + strcpy(status, stext); + + for (i = n, bs = &status[n-1]; i >= 0; i--, bs--) { + if (*bs == '<' || *bs == '/' || *bs == '\\' || *bs == '>' || *bs == '|') { /* block start */ + cn = ((int) *(bs+1)) - 1; + + if (cn < LENGTH(statuscolors)) { + drw_settrans(drw, prevscheme, (nxtscheme = statusscheme[cn])); + } else { + drw_settrans(drw, prevscheme, (nxtscheme = statusscheme[0])); + } + + if (bp != '|') { + drw_arrow(drw, x - plw, barg->y, plw, barg->h, bp == '\\' || bp == '>' ? 1 : 0, bp == '<' ? 0 : 1); + x -= plw; + } + + drw_setscheme(drw, nxtscheme); + w = TEXTW(bs+2); + drw_text(drw, x - w, barg->y, w, barg->h, lrpad / 2, bs+2, 0, False); + x -= w; + + bp = *bs; + *bs = 0; + prevscheme = nxtscheme; + } + } + if (bp != '|') { + drw_settrans(drw, prevscheme, scheme[SchemeNorm]); + drw_arrow(drw, x - plw, barg->y, plw, barg->h, bp == '\\' || bp == '>' ? 1 : 0, bp == '<' ? 0 : 1); + drw_rect(drw, x - 2 * plw, barg->y, plw, barg->h, 1, 1); + x -= plw * 2; + } + + return xpos - x; +} + diff --git a/dwm/patch/bar_powerline_status.h b/dwm/patch/bar_powerline_status.h new file mode 100755 index 0000000..46b78e0 --- /dev/null +++ b/dwm/patch/bar_powerline_status.h @@ -0,0 +1,12 @@ +static int width_pwrl_status(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int width_pwrl_status_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +static int draw_pwrl_status(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int draw_pwrl_status_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +static int click_pwrl_status(Bar *bar, Arg *arg, BarArg *a); +static int drawpowerlinestatus(int x, char *stext, BarArg *a); +static int widthpowerlinestatus(char *stext); + diff --git a/dwm/patch/bar_powerline_tags.c b/dwm/patch/bar_powerline_tags.c new file mode 100755 index 0000000..86fe0a1 --- /dev/null +++ b/dwm/patch/bar_powerline_tags.c @@ -0,0 +1,166 @@ +int +width_pwrl_tags(Bar *bar, BarArg *a) +{ + int w, i; + int plw = drw->fonts->h / 2 + 1; + #if BAR_HIDEVACANTTAGS_PATCH + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + + for (w = 0, i = 0; i < NUMTAGS; i++) { + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + w += TEXTW(tagicon(bar->mon, i)) + plw; + } + return w + lrpad; +} + +int +draw_pwrl_tags(Bar *bar, BarArg *a) +{ + int x, w; + int invert; + int plw = drw->fonts->h / 2 + 1; + unsigned int i, occ = 0, urg = 0; + char *icon; + Client *c; + Clr *prevscheme, *nxtscheme; + + for (c = bar->mon->clients; c; c = c->next) { + #if BAR_HIDEVACANTTAGS_PATCH + occ |= c->tags == 255 ? 0 : c->tags; + #else + occ |= c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + if (c->isurgent) + urg |= c->tags; + } + x = a->x; + prevscheme = scheme[SchemeNorm]; + for (i = 0; i < NUMTAGS; i++) { + #if BAR_HIDEVACANTTAGS_PATCH + /* do not draw vacant tags */ + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + + icon = tagicon(bar->mon, i); + invert = 0; + w = TEXTW(icon); + if (urg & 1 << i) { + drw_settrans(drw, prevscheme, (nxtscheme = scheme[bar->mon->tagset[bar->mon->seltags] & 1 << i ? SchemeSel : SchemeUrg])); + } else { + drw_settrans(drw, prevscheme, (nxtscheme = scheme[bar->mon->tagset[bar->mon->seltags] & 1 << i ? SchemeSel : SchemeNorm])); + } + #if BAR_POWERLINE_TAGS_SLASH_PATCH + drw_arrow(drw, x, a->y, plw, a->h, 1, 1); + #else + drw_arrow(drw, x, a->y, plw, a->h, 1, 0); + #endif // BAR_POWERLINE_TAGS_SLASH_PATCH + x += plw; + drw_setscheme(drw, nxtscheme); + drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False); + drawindicator(bar->mon, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + x += w; + prevscheme = nxtscheme; + } + nxtscheme = scheme[SchemeNorm]; + + drw_settrans(drw, prevscheme, nxtscheme); + #if BAR_POWERLINE_TAGS_SLASH_PATCH + drw_arrow(drw, x, a->y, plw, a->h, 1, 1); + #else + drw_arrow(drw, x, a->y, plw, a->h, 1, 0); + #endif // BAR_POWERLINE_TAGS_SLASH_PATCH + return 1; +} + +int +click_pwrl_tags(Bar *bar, Arg *arg, BarArg *a) +{ + int i = 0, x = lrpad / 2; + int plw = drw->fonts->h / 2 + 1; + #if BAR_HIDEVACANTTAGS_PATCH + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + + do { + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + x += TEXTW(tagicon(bar->mon, i)) + plw; + } while (a->x >= x && ++i < NUMTAGS); + if (i < NUMTAGS) { + arg->ui = 1 << i; + } + #if BAR_TAGPREVIEW_PATCH + if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + return ClkTagBar; +} + +int +hover_pwrl_tags(Bar *bar, BarArg *a, XMotionEvent *ev) +{ + #if BAR_TAGPREVIEW_PATCH + int i = 0, x = lrpad / 2; + int px, py; + int plw = drw->fonts->h / 2 + 1; + Monitor *m = bar->mon; + #if VANITYGAPS_PATCH + int ov = gappov; + int oh = gappoh; + #else + int ov = 0; + int oh = 0; + #endif // VANITYGAPS_PATCH + + #if BAR_HIDEVACANTTAGS_PATCH + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + + do { + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + x += TEXTW(tagicon(bar->mon, i)) + plw; + } while (a->x >= x && ++i < NUMTAGS); + + if (i < NUMTAGS) { + if ((i + 1) != selmon->previewshow && !(selmon->tagset[selmon->seltags] & 1 << i)) { + if (bar->by > m->my + m->mh / 2) // bottom bar + py = bar->by - m->mh / scalepreview - oh; + else // top bar + py = bar->by + bar->bh + oh; + px = bar->bx + ev->x - m->mw / scalepreview / 2; + if (px + m->mw / scalepreview > m->mx + m->mw) + px = m->wx + m->ww - m->mw / scalepreview - ov; + else if (px < bar->bx) + px = m->wx + ov; + selmon->previewshow = i + 1; + showtagpreview(i, px, py); + } else if (selmon->tagset[selmon->seltags] & 1 << i) { + hidetagpreview(selmon); + } + } else if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + + return 1; +} diff --git a/dwm/patch/bar_powerline_tags.h b/dwm/patch/bar_powerline_tags.h new file mode 100755 index 0000000..b0838a6 --- /dev/null +++ b/dwm/patch/bar_powerline_tags.h @@ -0,0 +1,4 @@ +static int width_pwrl_tags(Bar *bar, BarArg *a); +static int draw_pwrl_tags(Bar *bar, BarArg *a); +static int click_pwrl_tags(Bar *bar, Arg *arg, BarArg *a); +static int hover_pwrl_tags(Bar *bar, BarArg *a, XMotionEvent *ev); diff --git a/dwm/patch/bar_status.c b/dwm/patch/bar_status.c new file mode 100755 index 0000000..715b6d2 --- /dev/null +++ b/dwm/patch/bar_status.c @@ -0,0 +1,34 @@ +int +width_status(Bar *bar, BarArg *a) +{ + return TEXTWM(stext); +} + +#if BAR_EXTRASTATUS_PATCH +int +width_status_es(Bar *bar, BarArg *a) +{ + return TEXTWM(estext) - lrpad; +} +#endif // BAR_EXTRASTATUS_PATCH + +int +draw_status(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, stext, 0, True); +} + +#if BAR_EXTRASTATUS_PATCH +int +draw_status_es(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, 0, estext, 0, True); +} +#endif // BAR_EXTRASTATUS_PATCH + +int +click_status(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkStatusText; +} + diff --git a/dwm/patch/bar_status.h b/dwm/patch/bar_status.h new file mode 100755 index 0000000..4bf5e58 --- /dev/null +++ b/dwm/patch/bar_status.h @@ -0,0 +1,10 @@ +static int width_status(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int width_status_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +static int draw_status(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int draw_status_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +static int click_status(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/bar_status2d.c b/dwm/patch/bar_status2d.c new file mode 100755 index 0000000..4f8234e --- /dev/null +++ b/dwm/patch/bar_status2d.c @@ -0,0 +1,263 @@ +#if BAR_STATUS2D_XRDB_TERMCOLORS_PATCH +static char termcol0[] = "#000000"; /* black */ +static char termcol1[] = "#ff0000"; /* red */ +static char termcol2[] = "#33ff00"; /* green */ +static char termcol3[] = "#ff0099"; /* yellow */ +static char termcol4[] = "#0066ff"; /* blue */ +static char termcol5[] = "#cc00ff"; /* magenta */ +static char termcol6[] = "#00ffff"; /* cyan */ +static char termcol7[] = "#d0d0d0"; /* white */ +static char termcol8[] = "#808080"; /* black */ +static char termcol9[] = "#ff0000"; /* red */ +static char termcol10[] = "#33ff00"; /* green */ +static char termcol11[] = "#ff0099"; /* yellow */ +static char termcol12[] = "#0066ff"; /* blue */ +static char termcol13[] = "#cc00ff"; /* magenta */ +static char termcol14[] = "#00ffff"; /* cyan */ +static char termcol15[] = "#ffffff"; /* white */ +static char *termcolor[] = { + termcol0, termcol1, termcol2, termcol3, termcol4, termcol5, termcol6, termcol7, + termcol8, termcol9, termcol10, termcol11, termcol12, termcol13, termcol14, termcol15, +}; +#endif // BAR_STATUS2D_XRDB_TERMCOLORS_PATCH + +int +width_status2d(Bar *bar, BarArg *a) +{ + #if BAR_EXTRASTATUS_PATCH || BAR_STATUSCMD_PATCH + return status2dtextlength(rawstext); + #else + return status2dtextlength(stext); + #endif // #if BAR_EXTRASTATUS_PATCH | BAR_STATUSCMD_PATCH +} + +#if BAR_EXTRASTATUS_PATCH +int +width_status2d_es(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return status2dtextlength(rawestext); + #else + return status2dtextlength(estext); + #endif // BAR_STATUSCMD_PATCH +} +#endif // BAR_EXTRASTATUS_PATCH + +int +draw_status2d(Bar *bar, BarArg *a) +{ + #if BAR_EXTRASTATUS_PATCH || BAR_STATUSCMD_PATCH + return drawstatusbar(a, rawstext); + #else + return drawstatusbar(a, stext); + #endif // #if BAR_EXTRASTATUS_PATCH | BAR_STATUSCMD_PATCH +} + +#if BAR_EXTRASTATUS_PATCH +int +draw_status2d_es(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return drawstatusbar(a, rawestext); + #else + return drawstatusbar(a, estext); + #endif // BAR_STATUSCMD_PATCH +} +#endif // BAR_EXTRASTATUS_PATCH + +#if !BAR_STATUSCMD_PATCH +int +click_status2d(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkStatusText; +} +#endif // BAR_STATUSCMD_PATCH + +int +drawstatusbar(BarArg *a, char* stext) +{ + int i, w, len; + int x = a->x; + int y = a->y; + short isCode = 0; + char *text; + char *p; + Clr oldbg, oldfg; + len = strlen(stext); + if (!(text = (char*) malloc(sizeof(char)*(len + 1)))) + die("malloc"); + p = text; + #if BAR_STATUSCMD_PATCH + copyvalidchars(text, stext); + #else + memcpy(text, stext, len); + #endif // BAR_STATUSCMD_PATCH + text[len] = '\0'; + + drw_setscheme(drw, scheme[LENGTH(colors)]); + drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; + drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; + + /* process status text */ + i = -1; + while (text[++i]) { + if (text[i] == '^' && !isCode) { + isCode = 1; + + text[i] = '\0'; + w = TEXTWM(text) - lrpad; + drw_text(drw, x, y, w, bh, 0, text, 0, True); + + x += w; + + /* process code */ + while (text[++i] != '^') { + if (text[i] == 'c') { + char buf[8]; + if (i + 7 >= len) { + i += 7; + len = 0; + break; + } + memcpy(buf, (char*)text+i+1, 7); + buf[7] = '\0'; + #if BAR_ALPHA_PATCH && BAR_STATUS2D_NO_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColFg], buf, 0xff); + #elif BAR_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColFg], buf, alphas[SchemeNorm][ColFg]); + #else + drw_clr_create(drw, &drw->scheme[ColFg], buf); + #endif // BAR_ALPHA_PATCH + i += 7; + } else if (text[i] == 'b') { + char buf[8]; + if (i + 7 >= len) { + i += 7; + len = 0; + break; + } + memcpy(buf, (char*)text+i+1, 7); + buf[7] = '\0'; + #if BAR_ALPHA_PATCH && BAR_STATUS2D_NO_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColBg], buf, 0xff); + #elif BAR_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColBg], buf, alphas[SchemeNorm][ColBg]); + #else + drw_clr_create(drw, &drw->scheme[ColBg], buf); + #endif // BAR_ALPHA_PATCH + i += 7; + #if BAR_STATUS2D_XRDB_TERMCOLORS_PATCH + } else if (text[i] == 'C') { + int c = atoi(text + ++i) % 16; + #if BAR_ALPHA_PATCH && BAR_STATUS2D_NO_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColFg], termcolor[c], 0xff); + #elif BAR_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColFg], termcolor[c], alphas[SchemeNorm][ColBg]); + #else + drw_clr_create(drw, &drw->scheme[ColFg], termcolor[c]); + #endif // BAR_ALPHA_PATCH + } else if (text[i] == 'B') { + int c = atoi(text + ++i) % 16; + #if BAR_ALPHA_PATCH && BAR_STATUS2D_NO_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColBg], termcolor[c], 0xff); + #elif BAR_ALPHA_PATCH + drw_clr_create(drw, &drw->scheme[ColBg], termcolor[c], alphas[SchemeNorm][ColBg]); + #else + drw_clr_create(drw, &drw->scheme[ColBg], termcolor[c]); + #endif // BAR_ALPHA_PATCH + #endif // BAR_STATUS2D_XRDB_TERMCOLORS_PATCH + } else if (text[i] == 'd') { + drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; + drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; + } else if (text[i] == 'w') { + Clr swp; + swp = drw->scheme[ColFg]; + drw->scheme[ColFg] = drw->scheme[ColBg]; + drw->scheme[ColBg] = swp; + } else if (text[i] == 'v') { + oldfg = drw->scheme[ColFg]; + oldbg = drw->scheme[ColBg]; + } else if (text[i] == 't') { + drw->scheme[ColFg] = oldfg; + drw->scheme[ColBg] = oldbg; + } else if (text[i] == 'r') { + int rx = atoi(text + ++i); + while (text[++i] != ','); + int ry = atoi(text + ++i); + while (text[++i] != ','); + int rw = atoi(text + ++i); + while (text[++i] != ','); + int rh = atoi(text + ++i); + + if (ry < 0) + ry = 0; + if (rx < 0) + rx = 0; + + drw_rect(drw, rx + x, y + ry, rw, rh, 1, 0); + } else if (text[i] == 'f') { + x += atoi(text + ++i); + } + } + + text = text + i + 1; + len -= i + 1; + i = -1; + isCode = 0; + if (len <= 0) + break; + } + } + if (!isCode && len > 0) { + w = TEXTWM(text) - lrpad; + drw_text(drw, x, y, w, bh, 0, text, 0, True); + x += w; + } + free(p); + + drw_setscheme(drw, scheme[SchemeNorm]); + return 1; +} + +int +status2dtextlength(char* stext) +{ + int i, w, len; + short isCode = 0; + char *text; + char *p; + + len = strlen(stext) + 1; + if (!(text = (char*) malloc(sizeof(char)*len))) + die("malloc"); + p = text; + #if BAR_STATUSCMD_PATCH + copyvalidchars(text, stext); + #else + memcpy(text, stext, len); + #endif // BAR_STATUSCMD_PATCH + + /* compute width of the status text */ + w = 0; + i = -1; + while (text[++i]) { + if (text[i] == '^') { + if (!isCode) { + isCode = 1; + text[i] = '\0'; + w += TEXTWM(text) - lrpad; + text[i] = '^'; + if (text[++i] == 'f') + w += atoi(text + ++i); + } else { + isCode = 0; + text = text + i + 1; + i = -1; + } + } + } + if (!isCode) + w += TEXTWM(text) - lrpad; + free(p); + return w; +} diff --git a/dwm/patch/bar_status2d.h b/dwm/patch/bar_status2d.h new file mode 100755 index 0000000..8e088fb --- /dev/null +++ b/dwm/patch/bar_status2d.h @@ -0,0 +1,14 @@ +static int width_status2d(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int width_status2d_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +static int draw_status2d(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int draw_status2d_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +#if !BAR_STATUSCMD_PATCH +static int click_status2d(Bar *bar, Arg *arg, BarArg *a); +#endif // BAR_STATUSCMD_PATCH +static int drawstatusbar(BarArg *a, char *text); +static int status2dtextlength(char *stext); + diff --git a/dwm/patch/bar_statusbutton.c b/dwm/patch/bar_statusbutton.c new file mode 100755 index 0000000..5e43fe0 --- /dev/null +++ b/dwm/patch/bar_statusbutton.c @@ -0,0 +1,18 @@ +int +width_stbutton(Bar *bar, BarArg *a) +{ + return TEXTW(buttonbar); +} + +int +draw_stbutton(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, buttonbar, 0, False); +} + +int +click_stbutton(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkButton; +} + diff --git a/dwm/patch/bar_statusbutton.h b/dwm/patch/bar_statusbutton.h new file mode 100755 index 0000000..ed5beb5 --- /dev/null +++ b/dwm/patch/bar_statusbutton.h @@ -0,0 +1,4 @@ +static int width_stbutton(Bar *bar, BarArg *a); +static int draw_stbutton(Bar *bar, BarArg *a); +static int click_stbutton(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/bar_statuscmd.c b/dwm/patch/bar_statuscmd.c new file mode 100755 index 0000000..8a6393d --- /dev/null +++ b/dwm/patch/bar_statuscmd.c @@ -0,0 +1,79 @@ +#if !BAR_DWMBLOCKS_PATCH +static const char statusexport[] = "export BUTTON=-;"; +static int statuscmdn; +static char lastbutton[] = "-"; +#endif // BAR_DWMBLOCKS_PATCH + +int +click_statuscmd(Bar *bar, Arg *arg, BarArg *a) +{ + return click_statuscmd_text(arg, a->x, rawstext); +} + +#if BAR_EXTRASTATUS_PATCH +int +click_statuscmd_es(Bar *bar, Arg *arg, BarArg *a) +{ + return click_statuscmd_text(arg, a->x, rawestext); +} +#endif // BAR_EXTRASTATUS_PATCH + +int +click_statuscmd_text(Arg *arg, int rel_x, char *text) +{ + int i = -1; + int x = 0; + char ch; + #if BAR_DWMBLOCKS_PATCH + statussig = -1; + #else + statuscmdn = 0; + #endif // BAR_DWMBLOCKS_PATCH + while (text[++i]) { + if ((unsigned char)text[i] < ' ') { + #if BAR_STATUSCOLORS_PATCH + if (text[i] < 17) + continue; + #endif // BAR_STATUSCOLORS_PATCH + ch = text[i]; + text[i] = '\0'; + #if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH + x += status2dtextlength(text); + #else + x += TEXTWM(text) - lrpad; + #endif // BAR_STATUS2D_PATCH + text[i] = ch; + text += i+1; + i = -1; + #if BAR_DWMBLOCKS_PATCH + if (x >= rel_x && statussig != -1) + break; + statussig = ch; + #else + if (x >= rel_x) + break; + if (ch <= LENGTH(statuscmds)) + statuscmdn = ch; + #endif // BAR_DWMBLOCKS_PATCH + } + } + #if BAR_DWMBLOCKS_PATCH + if (statussig == -1) + statussig = 0; + #endif // BAR_DWMBLOCKS_PATCH + return ClkStatusText; +} + +void +copyvalidchars(char *text, char *rawtext) +{ + int i = -1, j = 0; + + while (rawtext[++i]) { + if ((unsigned char)rawtext[i] >= ' ') { + text[j++] = rawtext[i]; + } + } + text[j] = '\0'; +} + diff --git a/dwm/patch/bar_statuscmd.h b/dwm/patch/bar_statuscmd.h new file mode 100755 index 0000000..a4c4d24 --- /dev/null +++ b/dwm/patch/bar_statuscmd.h @@ -0,0 +1,12 @@ +static int click_statuscmd(Bar *bar, Arg *arg, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int click_statuscmd_es(Bar *bar, Arg *arg, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +static int click_statuscmd_text(Arg *arg, int rel_x, char *text); +static void copyvalidchars(char *text, char *rawtext); + +typedef struct { + const char *cmd; + int id; +} StatusCmd; + diff --git a/dwm/patch/bar_statuscolors.c b/dwm/patch/bar_statuscolors.c new file mode 100755 index 0000000..7ecb049 --- /dev/null +++ b/dwm/patch/bar_statuscolors.c @@ -0,0 +1,102 @@ +int +width_statuscolors(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return textw_wosc(rawstext); + #else + return textw_wosc(stext); + #endif // BAR_STATUSCMD_PATCH +} + +#if BAR_EXTRASTATUS_PATCH +int +width_statuscolors_es(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return textw_wosc(rawestext); + #else + return textw_wosc(estext); + #endif // BAR_STATUSCMD_PATCH +} +#endif // BAR_EXTRASTATUS_PATCH + +int +draw_statuscolors(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return draw_wosc(bar, a, rawstext); + #else + return draw_wosc(bar, a, stext); + #endif // BAR_STATUSCMD_PATCH +} + +#if BAR_EXTRASTATUS_PATCH +int +draw_statuscolors_es(Bar *bar, BarArg *a) +{ + #if BAR_STATUSCMD_PATCH + return draw_wosc(bar, a, rawestext); + #else + return draw_wosc(bar, a, estext); + #endif // BAR_STATUSCMD_PATCH +} +#endif // BAR_EXTRASTATUS_PATCH + +#if !BAR_STATUSCMD_PATCH +int +click_statuscolors(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkStatusText; +} +#endif // BAR_STATUSCMD_PATCH + +int +textw_wosc(char *s) +{ + char *ts = s; + char *tp = s; + int sw = 0; + char ctmp; + while (1) { + if ((unsigned int)*ts > LENGTH(colors)) { + ts++; + continue; + } + ctmp = *ts; + *ts = '\0'; + sw += drw_fontset_getwidth(drw, tp, True); + *ts = ctmp; + if (ctmp == '\0') + break; + tp = ++ts; + } + + return sw; +} + +int +draw_wosc(Bar *bar, BarArg *a, char *s) +{ + char *ts = s; + char *tp = s; + int tx = 0; + char ctmp; + + while (1) { + if ((unsigned int)*ts > LENGTH(colors)) { + ts++; + continue; + } + ctmp = *ts; + *ts = '\0'; + drw_text(drw, a->x + tx, a->y, a->w - tx, a->h, 0, tp, 0, True); + tx += TEXTW(tp) - lrpad; + if (ctmp == '\0') + break; + drw_setscheme(drw, scheme[(unsigned int)(ctmp-1)]); + *ts = ctmp; + tp = ++ts; + } + + return 1; +} \ No newline at end of file diff --git a/dwm/patch/bar_statuscolors.h b/dwm/patch/bar_statuscolors.h new file mode 100755 index 0000000..f4880a6 --- /dev/null +++ b/dwm/patch/bar_statuscolors.h @@ -0,0 +1,13 @@ +static int width_statuscolors(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int width_statuscolors_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +static int draw_statuscolors(Bar *bar, BarArg *a); +#if BAR_EXTRASTATUS_PATCH +static int draw_statuscolors_es(Bar *bar, BarArg *a); +#endif // BAR_EXTRASTATUS_PATCH +#if !BAR_STATUSCMD_PATCH +static int click_statuscolors(Bar *bar, Arg *arg, BarArg *a); +#endif // BAR_STATUSCMD_PATCH +static int textw_wosc(char *s); +static int draw_wosc(Bar *bar, BarArg *a, char *s); \ No newline at end of file diff --git a/dwm/patch/bar_systray.c b/dwm/patch/bar_systray.c new file mode 100755 index 0000000..5d18e7c --- /dev/null +++ b/dwm/patch/bar_systray.c @@ -0,0 +1,208 @@ +static Systray *systray = NULL; +static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; + +int +width_systray(Bar *bar, BarArg *a) +{ + unsigned int w = 0; + Client *i; + if (!systray) + return 1; + if (showsystray) { + for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next); + if (!w) + XMoveWindow(dpy, systray->win, -systray->h, bar->by); + } + return w ? w + lrpad - systrayspacing : 0; +} + +int +draw_systray(Bar *bar, BarArg *a) +{ + if (!showsystray) + return 0; + + XSetWindowAttributes wa; + XWindowChanges wc; + Client *i; + unsigned int w; + + if (!systray) { + /* init systray */ + if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); + + wa.override_redirect = True; + wa.event_mask = ButtonPressMask|ExposureMask; + wa.border_pixel = 0; + systray->h = MIN(a->h, drw->fonts->h); + #if BAR_ALPHA_PATCH + wa.background_pixel = 0; + wa.colormap = cmap; + systray->win = XCreateWindow(dpy, root, bar->bx + a->x + lrpad / 2, -systray->h, MAX(a->w + 40, 1), systray->h, 0, depth, + InputOutput, visual, + CWOverrideRedirect|CWBorderPixel|CWBackPixel|CWColormap|CWEventMask, &wa); // CWBackPixmap + #else + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + systray->win = XCreateSimpleWindow(dpy, root, bar->bx + a->x + lrpad / 2, -systray->h, MIN(a->w, 1), systray->h, 0, 0, scheme[SchemeNorm][ColBg].pixel); + XChangeWindowAttributes(dpy, systray->win, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &wa); + #endif // BAR_ALPHA_PATCH + + XSelectInput(dpy, systray->win, SubstructureNotifyMask); + XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&systrayorientation, 1); + #if BAR_ALPHA_PATCH + XChangeProperty(dpy, systray->win, netatom[NetSystemTrayVisual], XA_VISUALID, 32, + PropModeReplace, (unsigned char *)&visual->visualid, 1); + #endif // BAR_ALPHA_PATCH + XChangeProperty(dpy, systray->win, netatom[NetWMWindowType], XA_ATOM, 32, + PropModeReplace, (unsigned char *)&netatom[NetWMWindowTypeDock], 1); + XMapRaised(dpy, systray->win); + XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); + if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { + sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); + XSync(dpy, False); + } else { + fprintf(stderr, "dwm: unable to obtain system tray.\n"); + free(systray); + systray = NULL; + return 0; + } + } + + systray->bar = bar; + + wc.stack_mode = Above; + wc.sibling = bar->win; + XConfigureWindow(dpy, systray->win, CWSibling|CWStackMode, &wc); + + drw_setscheme(drw, scheme[SchemeNorm]); + for (w = 0, i = systray->icons; i; i = i->next) { + #if BAR_ALPHA_PATCH + wa.background_pixel = 0; + #else + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + #endif // BAR_ALPHA_PATCH + XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); + XMapRaised(dpy, i->win); + i->x = w; + XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); + w += i->w; + if (i->next) + w += systrayspacing; + if (i->mon != bar->mon) + i->mon = bar->mon; + } + + #if !BAR_ALPHA_PATCH + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + XChangeWindowAttributes(dpy, systray->win, CWBackPixel, &wa); + XClearWindow(dpy, systray->win); + #endif // BAR_ALPHA_PATCH + + XMoveResizeWindow(dpy, systray->win, bar->bx + a->x + lrpad / 2, (w ? bar->by + a->y + (a->h - systray->h) / 2: -systray->h), MAX(w, 1), systray->h); + return w; +} + +int +click_systray(Bar *bar, Arg *arg, BarArg *a) +{ + return -1; +} + +void +removesystrayicon(Client *i) +{ + Client **ii; + + if (!showsystray || !i) + return; + for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); + if (ii) + *ii = i->next; + XReparentWindow(dpy, i->win, root, 0, 0); + free(i); + drawbarwin(systray->bar); +} + +void +resizerequest(XEvent *e) +{ + XResizeRequestEvent *ev = &e->xresizerequest; + Client *i; + + if ((i = wintosystrayicon(ev->window))) { + updatesystrayicongeom(i, ev->width, ev->height); + drawbarwin(systray->bar); + } +} + +void +updatesystrayicongeom(Client *i, int w, int h) +{ + if (!systray) + return; + + int icon_height = systray->h; + if (i) { + i->h = icon_height; + if (w == h) + i->w = icon_height; + else if (h == icon_height) + i->w = w; + else + i->w = (int) ((float)icon_height * ((float)w / (float)h)); + applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); + /* force icons into the systray dimensions if they don't want to */ + if (i->h > icon_height) { + if (i->w == i->h) + i->w = icon_height; + else + i->w = (int) ((float)icon_height * ((float)i->w / (float)i->h)); + i->h = icon_height; + } + if (i->w > 2 * icon_height) + i->w = icon_height; + } +} + +void +updatesystrayiconstate(Client *i, XPropertyEvent *ev) +{ + long flags; + int code = 0; + + if (!showsystray || !systray || !i || ev->atom != xatom[XembedInfo] || + !(flags = getatomprop(i, xatom[XembedInfo], xatom[XembedInfo]))) + return; + + if (flags & XEMBED_MAPPED && !i->tags) { + i->tags = 1; + code = XEMBED_WINDOW_ACTIVATE; + XMapRaised(dpy, i->win); + setclientstate(i, NormalState); + } + else if (!(flags & XEMBED_MAPPED) && i->tags) { + i->tags = 0; + code = XEMBED_WINDOW_DEACTIVATE; + XUnmapWindow(dpy, i->win); + setclientstate(i, WithdrawnState); + } + else + return; + sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, + systray->win, XEMBED_EMBEDDED_VERSION); +} + +Client * +wintosystrayicon(Window w) +{ + if (!systray) + return NULL; + Client *i = NULL; + if (!showsystray || !w) + return i; + for (i = systray->icons; i && i->win != w; i = i->next); + return i; +} + diff --git a/dwm/patch/bar_systray.h b/dwm/patch/bar_systray.h new file mode 100755 index 0000000..092a6ff --- /dev/null +++ b/dwm/patch/bar_systray.h @@ -0,0 +1,41 @@ +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 + +/* XEMBED messages */ +#define XEMBED_EMBEDDED_NOTIFY 0 +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_FOCUS_IN 4 +#define XEMBED_MODALITY_ON 10 + +#define XEMBED_MAPPED (1 << 0) +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_WINDOW_DEACTIVATE 2 + +#define VERSION_MAJOR 0 +#define VERSION_MINOR 0 +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR + +/* enums */ +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ + +typedef struct Systray Systray; +struct Systray { + Window win; + Client *icons; + Bar *bar; + int h; +}; + +/* bar integration */ +static int width_systray(Bar *bar, BarArg *a); +static int draw_systray(Bar *bar, BarArg *a); +static int click_systray(Bar *bar, Arg *arg, BarArg *a); + +/* function declarations */ +static void removesystrayicon(Client *i); +static void resizerequest(XEvent *e); +static void updatesystrayicongeom(Client *i, int w, int h); +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); +static Client *wintosystrayicon(Window w); + + diff --git a/dwm/patch/bar_tabgroups.c b/dwm/patch/bar_tabgroups.c new file mode 100755 index 0000000..b61a0db --- /dev/null +++ b/dwm/patch/bar_tabgroups.c @@ -0,0 +1,258 @@ +/* Bartabgroups properties, you can override these in your config.h if you want. */ +#ifndef BARTAB_BORDERS +#define BARTAB_BORDERS 1 // 0 = off, 1 = on +#endif +#ifndef BARTAB_SHOWFLOATING +#define BARTAB_SHOWFLOATING 0 // whether to show titles for floating windows, hidden clients are always shown +#endif +#ifndef BARTAB_STACKWEIGHT +#define BARTAB_STACKWEIGHT 1 // stack weight compared to hidden and floating window titles +#endif +#ifndef BARTAB_HIDDENWEIGHT +#define BARTAB_HIDDENWEIGHT 1 // hidden window title weight +#endif +#ifndef BARTAB_FLOATWEIGHT +#define BARTAB_FLOATWEIGHT 1 // floating window title weight, set to 0 to not show floating windows +#endif + +int +width_bartabgroups(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_bartabgroups(Bar *bar, BarArg *a) +{ + drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1); + return bartabcalculate(bar->mon, a->x, a->w, -1, bartabdraw, NULL, a); +} + +int +click_bartabgroups(Bar *bar, Arg *arg, BarArg *a) +{ + bartabcalculate(bar->mon, 0, a->w, a->x, bartabclick, arg, a); + return ClkWinTitle; +} + +void +bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *a) +{ + if (!c) + return; + int i, nclienttags = 0, nviewtags = 0; + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icw + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + + drw_setscheme(drw, scheme[ + m->sel == c + #ifdef HIDDEN + && HIDDEN(c) + ? SchemeHidSel + : HIDDEN(c) + ? SchemeHidNorm + : m->sel == c + #endif + ? SchemeSel + : groupactive + ? SchemeTitleSel + : SchemeTitleNorm + ]); + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) < w) + cpad = (w - TEXTW(c->name)) / 2; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + + #if BAR_WINICON_PATCH + if (ipad) { + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); + tx += ipad; + tw -= ipad; + } + #endif // BAR_WINICON_PATCH + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + + drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed); + + if (BARTAB_BORDERS) { + XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); + } + /* Optional tags icons */ + for (i = 0; i < NUMTAGS; i++) { + if ((m->tagset[m->seltags] >> i) & 1) + nviewtags++; + if ((c->tags >> i) & 1) + nclienttags++; + } + + if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) + drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); +} + +#ifndef HIDDEN +#define HIDDEN(C) 0 +#endif + +void +bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg) +{ + if (passx >= x && passx <= x + w) + arg->v = c; +} + +int +bartabcalculate( + Monitor *m, int offx, int tabw, int passx, + void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), + Arg *arg, BarArg *barg +) { + Client *c; + int + i, clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, clientsnhidden = 0, + masteractive = 0, fulllayout = 0, + x = offx, w, r, num = 0, den, tgactive; + + for (i = 0; i < LENGTH(bartabmonfns); i++) + if (m ->lt[m->sellt]->arrange == bartabmonfns[i]) { + fulllayout = 1; + break; + } + + for (i = 0, c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) { + clientsnhidden++; + continue; + } + if (c->isfloating) { + clientsnfloating++; + continue; + } + if (m->sel == c) + masteractive = i < m->nmaster; + if (i < m->nmaster) + clientsnmaster++; + else + clientsnstack++; + i++; + } + + if (clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden == 0) + return 0; + + tgactive = 1; + num = tabw; + /* floating mode */ + if ((fulllayout && BARTAB_FLOATWEIGHT) || clientsnmaster + clientsnstack == 0 || !m->lt[m->sellt]->arrange) { + den = clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden; + r = num % den; + w = num / den; + for (c = m->clients, i = 0; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg); + x += w + (i < r ? 1 : 0); + i++; + } + /* no master and stack mode, e.g. monocole, grid layouts, fibonacci */ + } else if (fulllayout) { + den = clientsnmaster + clientsnstack + clientsnhidden; + r = num % den; + w = num / den; + for (c = m->clients, i = 0; c; c = c->next) { + if (!ISVISIBLE(c) || (c->isfloating && !HIDDEN(c))) + continue; + tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg); + x += w + (i < r ? 1 : 0); + i++; + } + /* tiled mode */ + } else { + den = clientsnmaster; + c = m->clients; + i = 0; + if (den) { + if (clientsnstack + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden) { + tgactive = masteractive; + num = tabw * m->mfact; + } + r = num % den; + w = num / den; + for (; c && i < m->nmaster; c = c->next) { // tiled master + if (!ISVISIBLE(c) || c->isfloating || HIDDEN(c)) + continue; + tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg); + x += w + (i < r ? 1 : 0); + i++; + } + tgactive = !tgactive; + num = tabw - num; + } + + den = clientsnstack * BARTAB_STACKWEIGHT + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden * BARTAB_HIDDENWEIGHT; + if (!den) + return 1; + + r = num % den; + w = num / den; + #if BARTAB_STACKWEIGHT + for (; c; c = c->next) { // tiled stack + if (!ISVISIBLE(c) || HIDDEN(c) || c->isfloating) + continue; + tabfn(m, c, passx, x, w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg); + x += w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0); + i++; + } + #endif // BARTAB_STACKWEIGHT + + #if BARTAB_HIDDENWEIGHT + for (c = m->clients; c; c = c->next) { // hidden windows + if (!ISVISIBLE(c) || !HIDDEN(c)) + continue; + tabfn(m, c, passx, x, w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg); + x += w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0); + i++; + } + #endif // BARTAB_HIDDENWEIGHT + + #if BARTAB_FLOATWEIGHT + for (c = m->clients; c; c = c->next) { // floating windows + if (!ISVISIBLE(c) || HIDDEN(c) || !c->isfloating) + continue; + tabfn(m, c, passx, x, w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg); + x += w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0); + i++; + } + #endif // BARTAB_FLOATWEIGHT + } + return 1; +} + diff --git a/dwm/patch/bar_tabgroups.h b/dwm/patch/bar_tabgroups.h new file mode 100755 index 0000000..75a8512 --- /dev/null +++ b/dwm/patch/bar_tabgroups.h @@ -0,0 +1,8 @@ +static int width_bartabgroups(Bar *bar, BarArg *a); +static int draw_bartabgroups(Bar *bar, BarArg *a); +static int click_bartabgroups(Bar *bar, Arg *arg, BarArg *a); + +static void bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg); +static void bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg); +static int bartabcalculate(Monitor *m, int offx, int w, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg); + diff --git a/dwm/patch/bar_taggrid.c b/dwm/patch/bar_taggrid.c new file mode 100755 index 0000000..675c8de --- /dev/null +++ b/dwm/patch/bar_taggrid.c @@ -0,0 +1,150 @@ +int +width_taggrid(Bar *bar, BarArg *a) +{ + return (a->h / 2) * (NUMTAGS / tagrows + ((NUMTAGS % tagrows > 0) ? 1 : 0)) + lrpad; +} + +int +draw_taggrid(Bar *bar, BarArg *a) +{ + unsigned int x, y, h, max_x = 0, columns, occ = 0; + int invert, i,j, k; + Client *c; + + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags; + + max_x = x = a->x + lrpad / 2; + h = a->h / tagrows - 1; + y = a->y; + columns = NUMTAGS / tagrows + ((NUMTAGS % tagrows > 0) ? 1 : 0); + + /* Firstly we will fill the borders of squares */ + XSetForeground(drw->dpy, drw->gc, scheme[SchemeTagsNorm][ColBg].pixel); + XFillRectangle(dpy, drw->drawable, drw->gc, x, y, h*columns + 1, a->h); + + /* We will draw NUMTAGS squares in tagraws raws. */ + for (j = 0, i = 0; j < tagrows; j++) { + x = a->x + lrpad / 2; + for (k = 0; k < columns; k++, i++) { + if (i < NUMTAGS) { + invert = bar->mon->tagset[bar->mon->seltags] & 1 << i ? 0 : 1; + + /* Select active color for current square */ + XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeTagsSel][ColBg].pixel : + scheme[SchemeTagsNorm][ColFg].pixel); + XFillRectangle(dpy, drw->drawable, drw->gc, x+1, y+1, h-1, h-1); + + /* Mark square if tag has client */ + if (occ & 1 << i) { + XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeTagsSel][ColFg].pixel : + scheme[SchemeTagsNorm][ColBg].pixel); + XFillRectangle(dpy, drw->drawable, drw->gc, x + 1, y + 1, + h / 2, h / 2); + } + } else { + XSetForeground(drw->dpy, drw->gc, scheme[SchemeTagsNorm][ColBg].pixel); + XFillRectangle(dpy, drw->drawable, drw->gc, x+1, y+1, h-1, h); + } + x += h; + if (x > max_x) { + max_x = x; + } + } + y += h; + } + return 1; +} + +int +click_taggrid(Bar *bar, Arg *arg, BarArg *a) +{ + unsigned int i, h, columns; + + h = a->h / tagrows - 1; + columns = NUMTAGS / tagrows + ((NUMTAGS % tagrows > 0) ? 1 : 0); + i = (a->x - lrpad / 2) / h + columns * (a->y / h); + if (i >= NUMTAGS) { + i = NUMTAGS - 1; + } + arg->ui = 1 << i; + return ClkTagBar; +} + +void +switchtag(const Arg *arg) +{ + unsigned int columns; + unsigned int new_tagset = 0; + unsigned int pos, i; + int col, row; + Arg new_arg; + + columns = NUMTAGS / tagrows + ((NUMTAGS % tagrows > 0) ? 1 : 0); + + for (i = 0; i < NUMTAGS; ++i) { + if (!(selmon->tagset[selmon->seltags] & 1 << i)) { + continue; + } + pos = i; + row = pos / columns; + col = pos % columns; + if (arg->ui & SWITCHTAG_UP) { /* UP */ + row --; + if (row < 0) { + row = tagrows - 1; + } + do { + pos = row * columns + col; + row --; + } while (pos >= NUMTAGS); + } + if (arg->ui & SWITCHTAG_DOWN) { /* DOWN */ + row ++; + if (row >= tagrows) { + row = 0; + } + pos = row * columns + col; + if (pos >= NUMTAGS) { + row = 0; + } + pos = row * columns + col; + } + if (arg->ui & SWITCHTAG_LEFT) { /* LEFT */ + col --; + if (col < 0) { + col = columns - 1; + } + do { + pos = row * columns + col; + col --; + } while (pos >= NUMTAGS); + } + if (arg->ui & SWITCHTAG_RIGHT) { /* RIGHT */ + col ++; + if (col >= columns) { + col = 0; + } + pos = row * columns + col; + if (pos >= NUMTAGS) { + col = 0; + pos = row * columns + col; + } + } + new_tagset |= 1 << pos; + } + new_arg.ui = new_tagset; + if (arg->ui & SWITCHTAG_TOGGLETAG) { + toggletag(&new_arg); + } + if (arg->ui & SWITCHTAG_TAG) { + tag(&new_arg); + } + if (arg->ui & SWITCHTAG_VIEW) { + view (&new_arg); + } + if (arg->ui & SWITCHTAG_TOGGLEVIEW) { + toggleview (&new_arg); + } +} + diff --git a/dwm/patch/bar_taggrid.h b/dwm/patch/bar_taggrid.h new file mode 100755 index 0000000..dfc60de --- /dev/null +++ b/dwm/patch/bar_taggrid.h @@ -0,0 +1,5 @@ +static int width_taggrid(Bar *bar, BarArg *a); +static int draw_taggrid(Bar *bar, BarArg *a); +static int click_taggrid(Bar *bar, Arg *arg, BarArg *a); +static void switchtag(const Arg *arg); + diff --git a/dwm/patch/bar_tagicons.c b/dwm/patch/bar_tagicons.c new file mode 100755 index 0000000..fa1b96c --- /dev/null +++ b/dwm/patch/bar_tagicons.c @@ -0,0 +1,21 @@ +char * +tagicon(Monitor *m, int tag) +{ + #if BAR_ALTTAGSDECORATION_PATCH + Client *c; + #endif // BAR_ALTTAGSDECORATION_PATCH + int tagindex = tag + NUMTAGS * m->num; + if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS])) + tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]); + #if BAR_ALTTAGSDECORATION_PATCH + for (c = m->clients; c && (!(c->tags & 1 << tag) || HIDDEN(c)); c = c->next); + if (c) + return tagicons[ALT_TAGS_DECORATION][tagindex]; + #endif // BAR_ALTTAGSDECORATION_PATCH + #if BAR_ALTERNATIVE_TAGS_PATCH + if (m->alttag) + return tagicons[ALTERNATIVE_TAGS][tagindex]; + #endif // BAR_ALTERNATIVE_TAGS_PATCH + return tagicons[DEFAULT_TAGS][tagindex]; +} + diff --git a/dwm/patch/bar_tagicons.h b/dwm/patch/bar_tagicons.h new file mode 100755 index 0000000..16fad2a --- /dev/null +++ b/dwm/patch/bar_tagicons.h @@ -0,0 +1,8 @@ +enum { + DEFAULT_TAGS, + ALTERNATIVE_TAGS, + ALT_TAGS_DECORATION, +}; + +static char * tagicon(Monitor *m, int tag); + diff --git a/dwm/patch/bar_taglabels.c b/dwm/patch/bar_taglabels.c new file mode 100755 index 0000000..a616319 --- /dev/null +++ b/dwm/patch/bar_taglabels.c @@ -0,0 +1,141 @@ +int +width_taglabels(Bar *bar, BarArg *a) +{ + int w, i; + Client *c; + Monitor *m = bar->mon; + char *icon; + unsigned int occ = 0; + + for (c = m->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + + for (w = 0, i = 0; i < NUMTAGS; i++) { + m->taglabel[i][0] = '\0'; + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + icon = tagicon(m, i); + XClassHint ch = { NULL, NULL }; + for (c = m->clients; c; c = c->next) { + if (c->tags & (1 << i)) { + XGetClassHint(dpy, c->win, &ch); + break; + } + } + if (ch.res_class) { + if (lcaselbl) + ch.res_class[0] = tolower(ch.res_class[0]); + snprintf(m->taglabel[i], 64, ptagf, icon, ch.res_class); + } else + snprintf(m->taglabel[i], 64, etagf, icon); + + w += TEXTW(m->taglabel[i]); + } + return w; +} + +int +draw_taglabels(Bar *bar, BarArg *a) +{ + int invert = 0; + int w, x = a->x; + unsigned int i, occ = 0, urg = 0; + Client *c; + Monitor *m = bar->mon; + + for (c = m->clients; c; c = c->next) + if (c->isurgent) + urg |= c->tags; + + for (i = 0; i < NUMTAGS; i++) { + /* do not draw vacant tags */ + if (!m->taglabel[i][0]) + continue; + drw_setscheme(drw, scheme[ + m->tagset[m->seltags] & 1 << i + ? SchemeTagsSel + : urg & 1 << i + ? SchemeUrg + : SchemeTagsNorm + ]); + w = TEXTW(m->taglabel[i]); + drw_text(drw, x, a->y, w, a->h, lrpad / 2, m->taglabel[i], invert, False); + drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + #if BAR_UNDERLINETAGS_PATCH + if (ulineall || m->tagset[m->seltags] & 1 << i) + drw_rect(drw, x + ulinepad, a->y + bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0); + #endif // BAR_UNDERLINETAGS_PATCH + x += w; + } + + return 1; +} + +int +click_taglabels(Bar *bar, Arg *arg, BarArg *a) +{ + int i = 0, x = lrpad / 2; + Monitor *m = bar->mon; + + do { + if (!m->taglabel[i][0]) + continue; + x += TEXTW(m->taglabel[i]); + } while (a->x >= x && ++i < NUMTAGS); + if (i < NUMTAGS) { + arg->ui = 1 << i; + } + #if BAR_TAGPREVIEW_PATCH + if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + return ClkTagBar; +} + +int +hover_taglabels(Bar *bar, BarArg *a, XMotionEvent *ev) +{ + #if BAR_TAGPREVIEW_PATCH + int i = 0, x = lrpad / 2; + int px, py; + Monitor *m = bar->mon; + #if VANITYGAPS_PATCH + int ov = gappov; + int oh = gappoh; + #else + int ov = 0; + int oh = 0; + #endif // VANITYGAPS_PATCH + + do { + if (!m->taglabel[i][0]) + continue; + x += TEXTW(m->taglabel[i]); + } while (a->x >= x && ++i < NUMTAGS); + + if (i < NUMTAGS) { + if ((i + 1) != selmon->previewshow && !(selmon->tagset[selmon->seltags] & 1 << i)) { + if (bar->by > m->my + m->mh / 2) // bottom bar + py = bar->by - m->mh / scalepreview - oh; + else // top bar + py = bar->by + bar->bh + oh; + px = bar->bx + ev->x - m->mw / scalepreview / 2; + if (px + m->mw / scalepreview > m->mx + m->mw) + px = m->wx + m->ww - m->mw / scalepreview - ov; + else if (px < bar->bx) + px = m->wx + ov; + selmon->previewshow = i + 1; + showtagpreview(i, px, py); + } else if (selmon->tagset[selmon->seltags] & 1 << i) { + hidetagpreview(selmon); + } + } else if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + + return 1; +} diff --git a/dwm/patch/bar_taglabels.h b/dwm/patch/bar_taglabels.h new file mode 100755 index 0000000..61b5aa0 --- /dev/null +++ b/dwm/patch/bar_taglabels.h @@ -0,0 +1,6 @@ +#include /* for making tab label lowercase, very tiny standard library */ + +static int width_taglabels(Bar *bar, BarArg *a); +static int draw_taglabels(Bar *bar, BarArg *a); +static int click_taglabels(Bar *bar, Arg *arg, BarArg *a); +static int hover_taglabels(Bar *bar, BarArg *a, XMotionEvent *ev); diff --git a/dwm/patch/bar_tagpreview.c b/dwm/patch/bar_tagpreview.c new file mode 100755 index 0000000..27731b0 --- /dev/null +++ b/dwm/patch/bar_tagpreview.c @@ -0,0 +1,112 @@ +#include + +void +createpreview(Monitor *m) +{ + if (m->tagwin) { + XMoveResizeWindow( + dpy, m->tagwin, + m->mx, + m->bar->by + bh, + m->mw / scalepreview, + m->mh / scalepreview + ); + return; + } + + XSetWindowAttributes wa = { + .override_redirect = True, + #if BAR_ALPHA_PATCH + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + #else + .background_pixmap = ParentRelative, + #endif // BAR_ALPHA_PATCH + .event_mask = ButtonPressMask|ExposureMask + }; + + m->tagwin = XCreateWindow(dpy, root, m->wx, m->bar->by + bh, m->mw / scalepreview, m->mh / scalepreview, 0, + #if BAR_ALPHA_PATCH + depth, CopyFromParent, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa + #else + DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa + #endif // BAR_ALPHA_PATCH + ); + XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->tagwin); + XUnmapWindow(dpy, m->tagwin); +} + +void +hidetagpreview(Monitor *m) +{ + m->previewshow = 0; + XUnmapWindow(dpy, m->tagwin); +} + +void +showtagpreview(int tag, int x, int y) +{ + Monitor *m = selmon; + + if (!m->tagwin) + return; + + if (m->tagmap[tag]) { + XSetWindowBackgroundPixmap(dpy, m->tagwin, m->tagmap[tag]); + XCopyArea(dpy, m->tagmap[tag], m->tagwin, drw->gc, 0, 0, m->mw / scalepreview, m->mh / scalepreview, 0, 0); + XMoveWindow(dpy, m->tagwin, x, y); + XSync(dpy, False); + XMapWindow(dpy, m->tagwin); + } else + XUnmapWindow(dpy, m->tagwin); +} + +void +tagpreviewswitchtag(void) +{ + int i; + unsigned int occ = 0; + Client *c; + Imlib_Image image; + Monitor *m = selmon; + + if (!m->tagwin) + createpreview(m); + + for (c = m->clients; c; c = c->next) + occ |= c->tags; + for (i = 0; i < NUMTAGS; i++) { + if (m->tagset[m->seltags] & 1 << i) { + if (m->tagmap[i] != 0) { + XFreePixmap(dpy, m->tagmap[i]); + m->tagmap[i] = 0; + } + if (occ & 1 << i) { + image = imlib_create_image(sw, sh); + imlib_context_set_image(image); + imlib_context_set_display(dpy); + #if BAR_ALPHA_PATCH + imlib_image_set_has_alpha(1); + imlib_context_set_blend(0); + imlib_context_set_visual(visual); + #else + imlib_context_set_visual(DefaultVisual(dpy, screen)); + #endif // BAR_ALPHA_PATCH + imlib_context_set_drawable(root); + imlib_copy_drawable_to_image(0, m->mx, m->my, m->mw ,m->mh, 0, 0, 1); + #if BAR_ALPHA_PATCH + m->tagmap[i] = XCreatePixmap(dpy, m->tagwin, m->mw / scalepreview, m->mh / scalepreview, depth); + #else + m->tagmap[i] = XCreatePixmap(dpy, m->tagwin, m->mw / scalepreview, m->mh / scalepreview, DefaultDepth(dpy, screen)); + #endif // BAR_ALPHA_PATCH + imlib_context_set_drawable(m->tagmap[i]); + imlib_render_image_part_on_drawable_at_size(0, 0, m->mw, m->mh, 0, 0, m->mw / scalepreview, m->mh / scalepreview); + imlib_free_image(); + } + } + } +} diff --git a/dwm/patch/bar_tagpreview.h b/dwm/patch/bar_tagpreview.h new file mode 100755 index 0000000..44be36d --- /dev/null +++ b/dwm/patch/bar_tagpreview.h @@ -0,0 +1,4 @@ +static void createpreview(Monitor *m); +static void hidetagpreview(Monitor *m); +static void showtagpreview(int tag, int x, int y); +static void tagpreviewswitchtag(void); diff --git a/dwm/patch/bar_tags.c b/dwm/patch/bar_tags.c new file mode 100755 index 0000000..a705932 --- /dev/null +++ b/dwm/patch/bar_tags.c @@ -0,0 +1,151 @@ +int +width_tags(Bar *bar, BarArg *a) +{ + int w, i; + #if BAR_HIDEVACANTTAGS_PATCH + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + + for (w = 0, i = 0; i < NUMTAGS; i++) { + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + w += TEXTW(tagicon(bar->mon, i)); + } + return w; +} + +int +draw_tags(Bar *bar, BarArg *a) +{ + int invert; + int w, x = a->x; + unsigned int i, occ = 0, urg = 0; + char *icon; + Client *c; + Monitor *m = bar->mon; + + for (c = m->clients; c; c = c->next) { + #if BAR_HIDEVACANTTAGS_PATCH + occ |= c->tags == 255 ? 0 : c->tags; + #else + occ |= c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + if (c->isurgent) + urg |= c->tags; + } + for (i = 0; i < NUMTAGS; i++) { + #if BAR_HIDEVACANTTAGS_PATCH + /* do not draw vacant tags */ + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + + icon = tagicon(bar->mon, i); + invert = 0; + w = TEXTW(icon); + drw_setscheme(drw, scheme[ + m->tagset[m->seltags] & 1 << i + ? SchemeTagsSel + : urg & 1 << i + ? SchemeUrg + : SchemeTagsNorm + ]); + drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False); + drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + #if BAR_UNDERLINETAGS_PATCH + if (ulineall || m->tagset[m->seltags] & 1 << i) + drw_rect(drw, x + ulinepad, a->y + bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0); + #endif // BAR_UNDERLINETAGS_PATCH + x += w; + } + + return 1; +} + +int +click_tags(Bar *bar, Arg *arg, BarArg *a) +{ + int i = 0, x = 0; + #if BAR_HIDEVACANTTAGS_PATCH + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + + do { + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + x += TEXTW(tagicon(bar->mon, i)); + } while (a->x >= x && ++i < NUMTAGS); + if (i < NUMTAGS) { + arg->ui = 1 << i; + } + #if BAR_TAGPREVIEW_PATCH + if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + return ClkTagBar; +} + +int +hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev) +{ + #if BAR_TAGPREVIEW_PATCH + int i = 0, x = lrpad / 2; + int px, py; + Monitor *m = bar->mon; + #if VANITYGAPS_PATCH + int ov = gappov; + int oh = gappoh; + #else + int ov = 0; + int oh = 0; + #endif // VANITYGAPS_PATCH + + #if BAR_HIDEVACANTTAGS_PATCH + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + + do { + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + x += TEXTW(tagicon(bar->mon, i)); + } while (a->x >= x && ++i < NUMTAGS); + + if (i < NUMTAGS) { + if ((i + 1) != selmon->previewshow && !(selmon->tagset[selmon->seltags] & 1 << i)) { + if (bar->by > m->my + m->mh / 2) // bottom bar + py = bar->by - m->mh / scalepreview - oh; + else // top bar + py = bar->by + bar->bh + oh; + px = bar->bx + ev->x - m->mw / scalepreview / 2; + if (px + m->mw / scalepreview > m->mx + m->mw) + px = m->wx + m->ww - m->mw / scalepreview - ov; + else if (px < bar->bx) + px = m->wx + ov; + selmon->previewshow = i + 1; + showtagpreview(i, px, py); + } else if (selmon->tagset[selmon->seltags] & 1 << i) { + hidetagpreview(selmon); + } + } else if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + + return 1; +} diff --git a/dwm/patch/bar_tags.h b/dwm/patch/bar_tags.h new file mode 100755 index 0000000..70040d2 --- /dev/null +++ b/dwm/patch/bar_tags.h @@ -0,0 +1,4 @@ +static int width_tags(Bar *bar, BarArg *a); +static int draw_tags(Bar *bar, BarArg *a); +static int click_tags(Bar *bar, Arg *arg, BarArg *a); +static int hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev); diff --git a/dwm/patch/bar_vtcolors.c b/dwm/patch/bar_vtcolors.c new file mode 100755 index 0000000..7c66e2d --- /dev/null +++ b/dwm/patch/bar_vtcolors.c @@ -0,0 +1,69 @@ +void +get_vt_colors(void) +{ + char *cfs[3] = { + "/sys/module/vt/parameters/default_red", + "/sys/module/vt/parameters/default_grn", + "/sys/module/vt/parameters/default_blu", + }; + char vtcs[16][8]; + char tk[] = ","; + char cl[64]; + char *tp = NULL; + FILE *fp; + size_t r; + int i, c, n, len; + for (i = 0; i < 16; i++) + strcpy(vtcs[i], "#000000"); + + for (i = 0, r = 0; i < 3; i++) { + if ((fp = fopen(cfs[i], "r")) == NULL) + continue; + while ((cl[r] = fgetc(fp)) != EOF && cl[r] != '\n') + r++; + cl[r] = '\0'; + for (c = 0, tp = cl, n = 0; c < 16; c++, tp++) { + if ((r = strcspn(tp, tk)) == -1) + break; + for (n = 0; r && *tp >= 48 && *tp < 58; r--, tp++) + n = n * 10 - 48 + *tp; + vtcs[c][i * 2 + 1] = n / 16 < 10 ? n / 16 + 48 : n / 16 + 87; + vtcs[c][i * 2 + 2] = n % 16 < 10 ? n % 16 + 48 : n % 16 + 87; + } + fclose(fp); + } + + len = LENGTH(colors); + if (len > LENGTH(color_ptrs)) + len = LENGTH(color_ptrs); + for (i = 0; i < len; i++) { + for (c = 0; c < ColCount; c++) { + n = color_ptrs[i][c]; + if (n > -1 && strlen(colors[i][c]) >= strlen(vtcs[n])) + memcpy(colors[i][c], vtcs[n], 7); + } + } +} + +int get_luminance(char *r) +{ + char *c = r; + int n[3] = {0}; + int i = 0; + + while (*c) { + if (*c >= 48 && *c < 58) + n[i / 2] = n[i / 2] * 16 - 48 + *c; + else if (*c >= 65 && *c < 71) + n[i / 2] = n[i / 2] * 16 - 55 + *c; + else if (*c >= 97 && *c < 103) + n[i / 2] = n[i / 2] * 16 - 87 + *c; + else + i--; + i++; + c++; + } + + return (0.299 * n[0] + 0.587 * n[1] + 0.114 * n[2]) / 2.55; +} + diff --git a/dwm/patch/bar_vtcolors.h b/dwm/patch/bar_vtcolors.h new file mode 100755 index 0000000..8c5d6c1 --- /dev/null +++ b/dwm/patch/bar_vtcolors.h @@ -0,0 +1,3 @@ +static void get_vt_colors(void); +static int get_luminance(char *rgb); + diff --git a/dwm/patch/bar_winicon.c b/dwm/patch/bar_winicon.c new file mode 100755 index 0000000..697e8b9 --- /dev/null +++ b/dwm/patch/bar_winicon.c @@ -0,0 +1,145 @@ +static uint32_t prealpha(uint32_t p) { + uint8_t a = p >> 24u; + uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; + uint32_t g = (a * (p & 0x00FF00u)) >> 8u; + return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); +} + +Picture +geticonprop(Window win, unsigned int *picw, unsigned int *pich) +{ + int format; + unsigned long n, extra, *p = NULL; + Atom real; + + if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return None; + if (n == 0 || format != 32) { XFree(p); return None; } + + unsigned long *bstp = NULL; + uint32_t w, h, sz; + { + unsigned long *i; const unsigned long *end = p + n; + uint32_t bstd = UINT32_MAX, d, m; + for (i = p; i < end - 1; i += sz) { + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } + if ((sz = w * h) > end - i) break; + if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } + } + if (!bstp) { + for (i = p; i < end - 1; i += sz) { + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } + if ((sz = w * h) > end - i) break; + if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } + } + } + if (!bstp) { XFree(p); return None; } + } + + if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } + + uint32_t icw, ich; + if (w <= h) { + ich = ICONSIZE; icw = w * ICONSIZE / h; + if (icw == 0) icw = 1; + } + else { + icw = ICONSIZE; ich = h * ICONSIZE / w; + if (ich == 0) ich = 1; + } + *picw = icw; *pich = ich; + + uint32_t i, *bstp32 = (uint32_t *)bstp; + for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]); + + Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich); + XFree(p); + + return ret; +} + +Picture +drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) { + Pixmap pm; + Picture pic; + GC gc; + + if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) { + XImage img = { + srcw, srch, 0, ZPixmap, src, + ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, + 32, 0, 32, + 0, 0, 0 + }; + XInitImage(&img); + + pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32); + gc = XCreateGC(drw->dpy, pm, 0, NULL); + XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch); + XFreeGC(drw->dpy, gc); + + pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); + XFreePixmap(drw->dpy, pm); + + XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0); + XTransform xf; + xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; + xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0; + xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536; + XRenderSetPictureTransform(drw->dpy, pic, &xf); + } else { + Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src); + if (!origin) return None; + imlib_context_set_image(origin); + imlib_image_set_has_alpha(1); + Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth); + imlib_free_image_and_decache(); + if (!scaled) return None; + imlib_context_set_image(scaled); + imlib_image_set_has_alpha(1); + + XImage img = { + dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(), + ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, + 32, 0, 32, + 0, 0, 0 + }; + XInitImage(&img); + + pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32); + gc = XCreateGC(drw->dpy, pm, 0, NULL); + XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth); + imlib_free_image_and_decache(); + XFreeGC(drw->dpy, gc); + + pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); + XFreePixmap(drw->dpy, pm); + } + + return pic; +} + +void +drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) +{ + if (!drw) + return; + XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); +} + +void +freeicon(Client *c) +{ + if (c->icon) { + XRenderFreePicture(dpy, c->icon); + c->icon = None; + } +} + +void +updateicon(Client *c) +{ + freeicon(c); + c->icon = geticonprop(c->win, &c->icw, &c->ich); +} diff --git a/dwm/patch/bar_winicon.h b/dwm/patch/bar_winicon.h new file mode 100755 index 0000000..56fc6e3 --- /dev/null +++ b/dwm/patch/bar_winicon.h @@ -0,0 +1,9 @@ +#include +#include +#include + +static Picture drw_picture_create_resized(Drw *drw, char *src, unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h); +static void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); +static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); +static void freeicon(Client *c); +static void updateicon(Client *c); diff --git a/dwm/patch/bar_wintitle.c b/dwm/patch/bar_wintitle.c new file mode 100755 index 0000000..fdb54ae --- /dev/null +++ b/dwm/patch/bar_wintitle.c @@ -0,0 +1,88 @@ +int +width_wintitle(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_wintitle(Bar *bar, BarArg *a) +{ + #if BAR_TITLE_LEFT_PAD_PATCH && BAR_TITLE_RIGHT_PAD_PATCH + int x = a->x + lrpad / 2, w = a->w - lrpad; + #elif BAR_TITLE_LEFT_PAD_PATCH + int x = a->x + lrpad / 2, w = a->w - lrpad / 2; + #elif BAR_TITLE_RIGHT_PAD_PATCH + int x = a->x, w = a->w - lrpad / 2; + #else + int x = a->x, w = a->w; + #endif // BAR_TITLE_LEFT_PAD_PATCH | BAR_TITLE_RIGHT_PAD_PATCH + Monitor *m = bar->mon; + Client *c = m->sel; + + if (!c) { + drw_setscheme(drw, scheme[SchemeTitleNorm]); + drw_rect(drw, x, a->y, w, a->h, 1, 1); + return 0; + } + + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icw + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + + drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]); + #if BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH + XSetErrorHandler(xerrordummy); + #endif // BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH + + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) < w) + cpad = (w - TEXTW(c->name)) / 2; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + + #if BAR_WINICON_PATCH + if (ipad) { + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); + tx += ipad; + tw -= ipad; + } + #endif // BAR_WINICON_PATCH + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + + #if BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH + XSync(dpy, False); + XSetErrorHandler(xerror); + #endif // BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH + drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed); + return 1; +} + +int +click_wintitle(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkWinTitle; +} + diff --git a/dwm/patch/bar_wintitle.h b/dwm/patch/bar_wintitle.h new file mode 100755 index 0000000..7e8cce5 --- /dev/null +++ b/dwm/patch/bar_wintitle.h @@ -0,0 +1,4 @@ +static int width_wintitle(Bar *bar, BarArg *a); +static int draw_wintitle(Bar *bar, BarArg *a); +static int click_wintitle(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/bar_wintitle_floating.c b/dwm/patch/bar_wintitle_floating.c new file mode 100755 index 0000000..3a15b8e --- /dev/null +++ b/dwm/patch/bar_wintitle_floating.c @@ -0,0 +1,46 @@ +int +width_wintitle_floating(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_wintitle_floating(Bar *bar, BarArg *a) +{ + drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1); + return calc_wintitle_floating(bar->mon, a->x, a->w, -1, flextitledraw, NULL, a); +} + +int +click_wintitle_floating(Bar *bar, Arg *arg, BarArg *a) +{ + calc_wintitle_floating(bar->mon, 0, a->w, a->x, flextitleclick, arg, a); + return ClkWinTitle; +} + +int +calc_wintitle_floating( + Monitor *m, int offx, int tabw, int passx, + void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), + Arg *arg, BarArg *barg +) { + Client *c; + int clientsnfloating = 0, w, r; + int groupactive = GRP_FLOAT; + + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c) || HIDDEN(c)) + continue; + if (c->isfloating) + clientsnfloating++; + } + + if (!clientsnfloating) + return 0; + + w = tabw / clientsnfloating; + r = tabw % clientsnfloating; + c = flextitledrawarea(m, m->clients, offx, r, w, clientsnfloating, SCHEMEFOR(GRP_FLOAT), 0, 0, 1, passx, tabfn, arg, barg); + return 1; +} + diff --git a/dwm/patch/bar_wintitle_floating.h b/dwm/patch/bar_wintitle_floating.h new file mode 100755 index 0000000..e73d53a --- /dev/null +++ b/dwm/patch/bar_wintitle_floating.h @@ -0,0 +1,9 @@ +static int width_wintitle_floating(Bar *bar, BarArg *a); +static int draw_wintitle_floating(Bar *bar, BarArg *a); +static int click_wintitle_floating(Bar *bar, Arg *arg, BarArg *a); +static int calc_wintitle_floating( + Monitor *m, int offx, int tabw, int passx, + void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), + Arg *arg, BarArg *barg +); + diff --git a/dwm/patch/bar_wintitle_hidden.c b/dwm/patch/bar_wintitle_hidden.c new file mode 100755 index 0000000..2d2414c --- /dev/null +++ b/dwm/patch/bar_wintitle_hidden.c @@ -0,0 +1,46 @@ +int +width_wintitle_hidden(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_wintitle_hidden(Bar *bar, BarArg *a) +{ + drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1); + return calc_wintitle_hidden(bar->mon, a->x, a->w, -1, flextitledraw, NULL, a); +} + +int +click_wintitle_hidden(Bar *bar, Arg *arg, BarArg *a) +{ + calc_wintitle_hidden(bar->mon, 0, a->w, a->x, flextitleclick, arg, a); + return ClkWinTitle; +} + +int +calc_wintitle_hidden( + Monitor *m, int offx, int tabw, int passx, + void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), + Arg *arg, BarArg *barg +) { + Client *c; + int clientsnhidden = 0, w, r; + int groupactive = GRP_HIDDEN; + + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + clientsnhidden++; + } + + if (!clientsnhidden) + return 0; + + w = tabw / clientsnhidden; + r = tabw % clientsnhidden; + c = flextitledrawarea(m, m->clients, offx, r, w, clientsnhidden, SCHEMEFOR(GRP_HIDDEN), 0, 1, 0, passx, tabfn, arg, barg); + return 1; +} + diff --git a/dwm/patch/bar_wintitle_hidden.h b/dwm/patch/bar_wintitle_hidden.h new file mode 100755 index 0000000..0495d49 --- /dev/null +++ b/dwm/patch/bar_wintitle_hidden.h @@ -0,0 +1,9 @@ +static int width_wintitle_hidden(Bar *bar, BarArg *a); +static int draw_wintitle_hidden(Bar *bar, BarArg *a); +static int click_wintitle_hidden(Bar *bar, Arg *arg, BarArg *a); +static int calc_wintitle_hidden( + Monitor *m, int offx, int tabw, int passx, + void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), + Arg *arg, BarArg *barg +); + diff --git a/dwm/patch/bar_wintitleactions.c b/dwm/patch/bar_wintitleactions.c new file mode 100755 index 0000000..c4ea064 --- /dev/null +++ b/dwm/patch/bar_wintitleactions.c @@ -0,0 +1,106 @@ +void +hide(Client *c) { + + Client *n; + if (!c || HIDDEN(c)) + return; + + Window w = c->win; + static XWindowAttributes ra, ca; + + // more or less taken directly from blackbox's hide() function + XGrabServer(dpy); + XGetWindowAttributes(dpy, root, &ra); + XGetWindowAttributes(dpy, w, &ca); + // prevent UnmapNotify events + XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); + XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask); + XUnmapWindow(dpy, w); + setclientstate(c, IconicState); + XSelectInput(dpy, root, ra.your_event_mask); + XSelectInput(dpy, w, ca.your_event_mask); + XUngrabServer(dpy); + + if (c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + for (n = c->snext; n && (!ISVISIBLE(n) || HIDDEN(n)); n = n->snext); + if (!n) + for (n = c->mon->stack; n && (!ISVISIBLE(n) || HIDDEN(n)); n = n->snext); + } else { + n = nexttiled(c); + if (!n) + n = prevtiled(c); + } + focus(n); + arrange(c->mon); +} + +void +show(Client *c) +{ + if (!c || !HIDDEN(c)) + return; + + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + arrange(c->mon); +} + +void +togglewin(const Arg *arg) +{ + Client *c = (Client*)arg->v; + if (!c) + return; + if (!HIDDEN(c) && c == selmon->sel) + hide(c); + else { + if (HIDDEN(c)) + show(c); + focus(c); + restack(c->mon); + } +} + +Client * +prevtiled(Client *c) +{ + Client *p, *i; + for (p = NULL, i = c->mon->clients; c && i != c; i = i->next) + if (ISVISIBLE(i) && !HIDDEN(i)) + p = i; + return p; +} + +void +showhideclient(const Arg *arg) +{ + Client *c = (Client*)arg->v; + if (!c) + c = selmon->sel; + if (!c) + return; + + #if WARP_PATCH + force_warp = 1; + #endif // WARP_PATCH + if (HIDDEN(c)) { + show(c); + focus(c); + restack(c->mon); + } else { + hide(c); + } +} + +void +unhideall(const Arg *arg) +{ + Client *c = NULL; + for (c = selmon->clients; c; c = c->next) { + if (ISVISIBLE(c)) { + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + } + } + arrange(selmon); +} diff --git a/dwm/patch/bar_wintitleactions.h b/dwm/patch/bar_wintitleactions.h new file mode 100755 index 0000000..132e9f9 --- /dev/null +++ b/dwm/patch/bar_wintitleactions.h @@ -0,0 +1,7 @@ +static void hide(Client *c); +static void show(Client *c); +static void togglewin(const Arg *arg); +static Client * prevtiled(Client *c); +static void showhideclient(const Arg *arg); +static void unhideall(const Arg *arg); + diff --git a/dwm/patch/cfacts.c b/dwm/patch/cfacts.c new file mode 100755 index 0000000..e491a41 --- /dev/null +++ b/dwm/patch/cfacts.c @@ -0,0 +1,24 @@ +void +setcfact(const Arg *arg) +{ + float f; + Client *c; + + c = selmon->sel; + + if (!arg || !c || !selmon->lt[selmon->sellt]->arrange) + return; + if (!arg->f) + f = 1.0; + else if (arg->f > 4.0) // set fact absolutely + f = arg->f - 4.0; + else + f = arg->f + c->cfact; + if (f < 0.25) + f = 0.25; + else if (f > 4.0) + f = 4.0; + c->cfact = f; + arrange(selmon); +} + diff --git a/dwm/patch/cfacts.h b/dwm/patch/cfacts.h new file mode 100755 index 0000000..97f9f1c --- /dev/null +++ b/dwm/patch/cfacts.h @@ -0,0 +1,2 @@ +static void setcfact(const Arg *arg); + diff --git a/dwm/patch/cmdcustomize.c b/dwm/patch/cmdcustomize.c new file mode 100755 index 0000000..9769660 --- /dev/null +++ b/dwm/patch/cmdcustomize.c @@ -0,0 +1,6 @@ +char* +help(void) +{ + return "usage: dwm [-hv] [-fn font] [-nb color] [-nf color] [-sb color] [-sf color]\n[-df font] [-dnf color] [-dnb color] [-dsf color] [-dsb color]\n"; +} + diff --git a/dwm/patch/cmdcustomize.h b/dwm/patch/cmdcustomize.h new file mode 100755 index 0000000..46b75cf --- /dev/null +++ b/dwm/patch/cmdcustomize.h @@ -0,0 +1,2 @@ +static char* help(); + diff --git a/dwm/patch/combo.c b/dwm/patch/combo.c new file mode 100755 index 0000000..0b0bc5a --- /dev/null +++ b/dwm/patch/combo.c @@ -0,0 +1,39 @@ +static int combo = 0; + +#if !BAR_HOLDBAR_PATCH +void +keyrelease(XEvent *e) +{ + combo = 0; +} +#endif // !BAR_HOLDBAR_PATCH + +void +combotag(const Arg *arg) +{ + if (selmon->sel && arg->ui & TAGMASK) { + #if SWITCHTAG_PATCH + if (selmon->sel->switchtag) + selmon->sel->switchtag = 0; + #endif // SWITCHTAG_PATCH + if (combo) { + selmon->sel->tags |= arg->ui & TAGMASK; + } else { + combo = 1; + selmon->sel->tags = arg->ui & TAGMASK; + } + arrange(selmon); + focus(NULL); + } +} + +void +comboview(const Arg *arg) +{ + if (combo) { + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] | (arg->ui & TAGMASK) })); + } else { + combo = 1; + view(arg); + } +} diff --git a/dwm/patch/combo.h b/dwm/patch/combo.h new file mode 100755 index 0000000..0c42136 --- /dev/null +++ b/dwm/patch/combo.h @@ -0,0 +1,6 @@ +#if !BAR_HOLDBAR_PATCH +static void keyrelease(XEvent *e); +#endif // !BAR_HOLDBAR_PATCH +static void combotag(const Arg *arg); +static void comboview(const Arg *arg); + diff --git a/dwm/patch/cool_autostart.c b/dwm/patch/cool_autostart.c new file mode 100755 index 0000000..848f5ab --- /dev/null +++ b/dwm/patch/cool_autostart.c @@ -0,0 +1,37 @@ +/* dwm will keep pid's of processes from autostart array and kill them at quit */ +static pid_t *autostart_pids; +static size_t autostart_len; + +/* execute command from autostart array */ +static void +autostart_exec() +{ + const char *const *p; + struct sigaction sa; + size_t i = 0; + + /* count entries */ + for (p = autostart; *p; autostart_len++, p++) + while (*++p); + + autostart_pids = malloc(autostart_len * sizeof(pid_t)); + for (p = autostart; *p; i++, p++) { + if ((autostart_pids[i] = fork()) == 0) { + setsid(); + + /* Restore SIGCHLD sighandler to default before spawning a program */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); + + execvp(*p, (char *const *)p); + fprintf(stderr, "dwm: execvp %s\n", *p); + perror(" failed"); + _exit(EXIT_FAILURE); + } + /* skip arguments */ + while (*++p); + } +} + diff --git a/dwm/patch/cool_autostart.h b/dwm/patch/cool_autostart.h new file mode 100755 index 0000000..5534d99 --- /dev/null +++ b/dwm/patch/cool_autostart.h @@ -0,0 +1,2 @@ +static void autostart_exec(void); + diff --git a/dwm/patch/cyclelayouts.c b/dwm/patch/cyclelayouts.c new file mode 100755 index 0000000..b8a6199 --- /dev/null +++ b/dwm/patch/cyclelayouts.c @@ -0,0 +1,10 @@ +void +cyclelayout(const Arg *arg) +{ + int i; + int num_layouts = LENGTH(layouts); + + for (i = 0; i < num_layouts && &layouts[i] != selmon->lt[selmon->sellt]; i++); + i += arg->i; + setlayout(&((Arg) { .v = &layouts[(i % num_layouts + num_layouts) % num_layouts] })); // modulo +} diff --git a/dwm/patch/cyclelayouts.h b/dwm/patch/cyclelayouts.h new file mode 100755 index 0000000..3647d88 --- /dev/null +++ b/dwm/patch/cyclelayouts.h @@ -0,0 +1,2 @@ +static void cyclelayout(const Arg *arg); + diff --git a/dwm/patch/decorationhints.c b/dwm/patch/decorationhints.c new file mode 100755 index 0000000..78be5ea --- /dev/null +++ b/dwm/patch/decorationhints.c @@ -0,0 +1,39 @@ +static Atom motifatom; + +void +updatemotifhints(Client *c) +{ + Atom real; + int format; + unsigned char *p = NULL; + unsigned long n, extra; + unsigned long *motif; + int width, height; + + if (!decorhints) + return; + + if (XGetWindowProperty(dpy, c->win, motifatom, 0L, 5L, False, motifatom, + &real, &format, &n, &extra, &p) == Success && p != NULL) { + motif = (unsigned long*)p; + if (motif[MWM_HINTS_FLAGS_FIELD] & MWM_HINTS_DECORATIONS) { + width = WIDTH(c); + height = HEIGHT(c); + + if (motif[MWM_HINTS_DECORATIONS_FIELD] & MWM_DECOR_ALL || + motif[MWM_HINTS_DECORATIONS_FIELD] & MWM_DECOR_BORDER || + motif[MWM_HINTS_DECORATIONS_FIELD] & MWM_DECOR_TITLE) + #if SETBORDERPX_PATCH + c->bw = c->oldbw = c->mon->borderpx; + #else + c->bw = c->oldbw = borderpx; + #endif // SETBORDERPX_PATCH + else + c->bw = c->oldbw = 0; + + resize(c, c->x, c->y, width - (2*c->bw), height - (2*c->bw), 0); + } + XFree(p); + } +} + diff --git a/dwm/patch/decorationhints.h b/dwm/patch/decorationhints.h new file mode 100755 index 0000000..e28f507 --- /dev/null +++ b/dwm/patch/decorationhints.h @@ -0,0 +1,9 @@ +#define MWM_HINTS_FLAGS_FIELD 0 +#define MWM_HINTS_DECORATIONS_FIELD 2 +#define MWM_HINTS_DECORATIONS (1 << 1) +#define MWM_DECOR_ALL (1 << 0) +#define MWM_DECOR_BORDER (1 << 1) +#define MWM_DECOR_TITLE (1 << 3) + +static void updatemotifhints(Client *c); + diff --git a/dwm/patch/distributetags.c b/dwm/patch/distributetags.c new file mode 100755 index 0000000..d786774 --- /dev/null +++ b/dwm/patch/distributetags.c @@ -0,0 +1,31 @@ +void +distributetags(const Arg *arg) +{ + Client *c; + unsigned int ui = 1; + int i = 0; + + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH + + for (c = selmon->clients; c; c = c->next) { + if (HIDDEN(c)) + continue; + if (!(c->tags & TAGMASK)) + continue; + c->tags = (ui << i) & TAGMASK; + i = (i + 1) % NUMTAGS; + } + + #if TAGSYNC_PATCH + } + selmon = origselmon; + arrange(NULL); + focus(NULL); + #else + arrange(selmon); + focus(NULL); + #endif // TAGSYNC_PATCH +} diff --git a/dwm/patch/distributetags.h b/dwm/patch/distributetags.h new file mode 100755 index 0000000..3b276d9 --- /dev/null +++ b/dwm/patch/distributetags.h @@ -0,0 +1,2 @@ +static void distributetags(const Arg *arg); + diff --git a/dwm/patch/dragcfact.c b/dwm/patch/dragcfact.c new file mode 100755 index 0000000..7b83413 --- /dev/null +++ b/dwm/patch/dragcfact.c @@ -0,0 +1,83 @@ +void +dragcfact(const Arg *arg) +{ + int prev_x, prev_y, dist_x, dist_y; + float fact; + Client *c; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfloating) { + resizemouse(arg); + return; + } + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && !c->fakefullscreen) /* no support resizing fullscreen windows by mouse */ + return; + #else + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // !FAKEFULLSCREEN_PATCH + restack(selmon); + + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurIronCross]->cursor, CurrentTime) != GrabSuccess) + return; + + #if WARP_PATCH + ignore_warp = 1; + #endif // WARP_PATCH + + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); + + prev_x = prev_y = -999999; + + 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 / refreshrate_dragcfact)) + continue; + lasttime = ev.xmotion.time; + if (prev_x == -999999) { + prev_x = ev.xmotion.x_root; + prev_y = ev.xmotion.y_root; + } + + dist_x = ev.xmotion.x - prev_x; + dist_y = ev.xmotion.y - prev_y; + + if (abs(dist_x) > abs(dist_y)) { + fact = (float) 4.0 * dist_x / c->mon->ww; + } else { + fact = (float) -4.0 * dist_y / c->mon->wh; + } + + if (fact) + setcfact(&((Arg) { .f = fact })); + + prev_x = ev.xmotion.x; + prev_y = ev.xmotion.y; + break; + } + } while (ev.type != ButtonRelease); + + #if WARP_PATCH + ignore_warp = 0; + #endif // WARP_PATCH + + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); + + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + diff --git a/dwm/patch/dragcfact.h b/dwm/patch/dragcfact.h new file mode 100755 index 0000000..6a29783 --- /dev/null +++ b/dwm/patch/dragcfact.h @@ -0,0 +1,2 @@ +static void dragcfact(const Arg *arg); + diff --git a/dwm/patch/dragmfact.c b/dwm/patch/dragmfact.c new file mode 100755 index 0000000..afdfc1c --- /dev/null +++ b/dwm/patch/dragmfact.c @@ -0,0 +1,232 @@ +void +dragmfact(const Arg *arg) +{ + unsigned int n; + int py, px; // pointer coordinates + int ax, ay, aw, ah; // area position, width and height + int center = 0, horizontal = 0, mirror = 0, fixed = 0; // layout configuration + double fact; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + m = selmon; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + Client *c; + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + ax = m->wx; + ay = m->wy; + ah = m->wh; + aw = m->ww; + + if (!n) + return; + #if FLEXTILE_DELUXE_LAYOUT + else if (m->lt[m->sellt]->arrange == &flextile) { + int layout = m->ltaxis[LAYOUT]; + if (layout < 0) { + mirror = 1; + layout *= -1; + } + if (layout > FLOATING_MASTER) { + layout -= FLOATING_MASTER; + fixed = 1; + } + + if (layout == SPLIT_HORIZONTAL || layout == SPLIT_HORIZONTAL_DUAL_STACK) + horizontal = 1; + else if (layout == SPLIT_CENTERED_VERTICAL && (fixed || n - m->nmaster > 1)) + center = 1; + else if (layout == FLOATING_MASTER) { + center = 1; + if (aw < ah) + horizontal = 1; + } + else if (layout == SPLIT_CENTERED_HORIZONTAL) { + if (fixed || n - m->nmaster > 1) + center = 1; + horizontal = 1; + } + } + #endif // FLEXTILE_DELUXE_LAYOUT + #if CENTEREDMASTER_LAYOUT + else if (m->lt[m->sellt]->arrange == ¢eredmaster && (fixed || n - m->nmaster > 1)) + center = 1; + #endif // CENTEREDMASTER_LAYOUT + #if CENTEREDFLOATINGMASTER_LAYOUT + else if (m->lt[m->sellt]->arrange == ¢eredfloatingmaster) + center = 1; + #endif // CENTEREDFLOATINGMASTER_LAYOUT + #if BSTACK_LAYOUT + else if (m->lt[m->sellt]->arrange == &bstack) + horizontal = 1; + #endif // BSTACK_LAYOUT + #if BSTACKHORIZ_LAYOUT + else if (m->lt[m->sellt]->arrange == &bstackhoriz) + horizontal = 1; + #endif // BSTACKHORIZ_LAYOUT + + /* do not allow mfact to be modified under certain conditions */ + if (!m->lt[m->sellt]->arrange // floating layout + || (!fixed && m->nmaster && n <= m->nmaster) // no master + #if MONOCLE_LAYOUT + || m->lt[m->sellt]->arrange == &monocle + #endif // MONOCLE_LAYOUT + #if GRIDMODE_LAYOUT + || m->lt[m->sellt]->arrange == &grid + #endif // GRIDMODE_LAYOUT + #if HORIZGRID_LAYOUT + || m->lt[m->sellt]->arrange == &horizgrid + #endif // HORIZGRID_LAYOUT + #if GAPPLESSGRID_LAYOUT + || m->lt[m->sellt]->arrange == &gaplessgrid + #endif // GAPPLESSGRID_LAYOUT + #if NROWGRID_LAYOUT + || m->lt[m->sellt]->arrange == &nrowgrid + #endif // NROWGRID_LAYOUT + #if FLEXTILE_DELUXE_LAYOUT + || (m->lt[m->sellt]->arrange == &flextile && m->ltaxis[LAYOUT] == NO_SPLIT) + #endif // FLEXTILE_DELUXE_LAYOUT + ) + return; + + #if VANITYGAPS_PATCH + ay += oh; + ax += ov; + aw -= 2*ov; + ah -= 2*oh; + #endif // VANITYGAPS_PATCH + + if (center) { + if (horizontal) { + px = ax + aw / 2; + #if VANITYGAPS_PATCH + py = ay + ah / 2 + (ah - 2*ih) * (m->mfact / 2.0) + ih / 2; + #else + py = ay + ah / 2 + ah * m->mfact / 2.0; + #endif // VANITYGAPS_PATCH + } else { // vertical split + #if VANITYGAPS_PATCH + px = ax + aw / 2 + (aw - 2*iv) * m->mfact / 2.0 + iv / 2; + #else + px = ax + aw / 2 + aw * m->mfact / 2.0; + #endif // VANITYGAPS_PATCH + py = ay + ah / 2; + } + } else if (horizontal) { + px = ax + aw / 2; + if (mirror) + #if VANITYGAPS_PATCH + py = ay + (ah - ih) * (1.0 - m->mfact) + ih / 2; + #else + py = ay + (ah * (1.0 - m->mfact)); + #endif // VANITYGAPS_PATCH + else + #if VANITYGAPS_PATCH + py = ay + ((ah - ih) * m->mfact) + ih / 2; + #else + py = ay + (ah * m->mfact); + #endif // VANITYGAPS_PATCH + } else { // vertical split + if (mirror) + #if VANITYGAPS_PATCH + px = ax + (aw - iv) * (1.0 - m->mfact) + iv / 2; + #else + px = ax + (aw * m->mfact); + #endif // VANITYGAPS_PATCH + else + #if VANITYGAPS_PATCH + px = ax + ((aw - iv) * m->mfact) + iv / 2; + #else + px = ax + (aw * m->mfact); + #endif // VANITYGAPS_PATCH + py = ay + ah / 2; + } + + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[horizontal ? CurResizeVertArrow : CurResizeHorzArrow]->cursor, CurrentTime) != GrabSuccess) + return; + + #if WARP_PATCH + ignore_warp = 1; + #endif // WARP_PATCH + + XWarpPointer(dpy, None, root, 0, 0, 0, 0, px, py); + + 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 / refreshrate_dragmfact)) + continue; + if (lasttime != 0) { + px = ev.xmotion.x; + py = ev.xmotion.y; + } + lasttime = ev.xmotion.time; + + #if VANITYGAPS_PATCH + if (center) + if (horizontal) + if (py - ay > ah / 2) + fact = (double) 1.0 - (ay + ah - py - ih / 2) * 2 / (double) (ah - 2*ih); + else + fact = (double) 1.0 - (py - ay - ih / 2) * 2 / (double) (ah - 2*ih); + else + if (px - ax > aw / 2) + fact = (double) 1.0 - (ax + aw - px - iv / 2) * 2 / (double) (aw - 2*iv); + else + fact = (double) 1.0 - (px - ax - iv / 2) * 2 / (double) (aw - 2*iv); + else + if (horizontal) + fact = (double) (py - ay - ih / 2) / (double) (ah - ih); + else + fact = (double) (px - ax - iv / 2) / (double) (aw - iv); + #else + if (center) + if (horizontal) + if (py - ay > ah / 2) + fact = (double) 1.0 - (ay + ah - py) * 2 / (double) ah; + else + fact = (double) 1.0 - (py - ay) * 2 / (double) ah; + else + if (px - ax > aw / 2) + fact = (double) 1.0 - (ax + aw - px) * 2 / (double) aw; + else + fact = (double) 1.0 - (px - ax) * 2 / (double) aw; + else + if (horizontal) + fact = (double) (py - ay) / (double) ah; + else + fact = (double) (px - ax) / (double) aw; + #endif // VANITYGAPS_PATCH + + if (!center && mirror) + fact = 1.0 - fact; + + setmfact(&((Arg) { .f = 1.0 + fact })); + px = ev.xmotion.x; + py = ev.xmotion.y; + break; + } + } while (ev.type != ButtonRelease); + + #if WARP_PATCH + ignore_warp = 0; + #endif // WARP_PATCH + + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + diff --git a/dwm/patch/dragmfact.h b/dwm/patch/dragmfact.h new file mode 100755 index 0000000..a67432a --- /dev/null +++ b/dwm/patch/dragmfact.h @@ -0,0 +1,2 @@ +static void dragmfact(const Arg *arg); + diff --git a/dwm/patch/dwmc b/dwm/patch/dwmc new file mode 100755 index 0000000..2500ba7 --- /dev/null +++ b/dwm/patch/dwmc @@ -0,0 +1,136 @@ +#!/usr/bin/env bash + +signal() { + xsetroot -name "fsignal:$*" +} + +case $# in +1) + case $1 in + focusurgent) ;& + mirrorlayout) ;& + mpdcontrol) ;& + nametag) ;& + pushdown) ;& + pushup) ;& + self_restart) ;& + setlayout) ;& + setcfact) ;& + showhideclient) ;& + switchcol) ;& + view) ;& + viewall) ;& + viewtoleft) ;& + viewtoright) ;& + tagtoleft) ;& + tagtoright) ;& + tagandviewtoleft) ;& + tagandviewtoright) ;& + transfer) ;& + transferall) ;& + togglealttag) ;& + togglebar) ;& + toggletopbar) ;& + togglefloating) ;& + togglefullscreen) ;& + fullscreen) ;& + togglefakefullscreen) ;& + togglesticky) ;& + togglehorizontalmax) ;& + toggleverticalmax) ;& + togglemax) ;& + togglegaps) ;& + defaultgaps) ;& + unfloatvisible) ;& + winview) ;& + xrdb) ;& + zoom) ;& + killclient) ;& + quit) + signal $1 + ;; + *) + echo "Unknown command ($1) or missing one argument." + exit 1 + ;; + esac + ;; +2) + case $1 in + cyclelayout) ;& + explace) ;& + moveplace) ;& + mpdchange) ;& + setkeymode) ;& + switchtag) ;& + togglescratch) ;& + view) + signal $1 ui $2 + ;; + viewex) ;& + toggleviewex) ;& + tagallmon) ;& + tagswapmon) ;& + tagex) ;& + toggletagex) ;& + setborderpx) ;& + setgaps) ;& + setlayoutex) ;& + setlayoutaxisex) ;& + swapfocus) ;& + focusstack) ;& + pushstack) ;& + inplacerotate) ;& + rotatestack) ;& + rotatelayoutaxis) ;& + incnmaster) ;& + incnstack) ;& + incrgaps) ;& + incrigaps) ;& + incrogaps) ;& + incrihgaps) ;& + incrivgaps) ;& + incrohgaps) ;& + incrovgaps) ;& + movestack) ;& + shiftview) ;& + shiftviewclients) ;& + focusmon) ;& + tagmon) + signal $1 i $2 + ;; + setcfact) ;& + setmfact) + signal $1 f $2 + ;; + floatpos) + signal $1 v $2 + ;; + *) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; + esac + ;; +5) + case $1 in + setgaps) + # Expects "setgaps oh ov ih iv" where -1 means to keep existing values + [ $2 = -1 ] && oh=128 || oh=$2 + [ $3 = -1 ] && ov=128 || ov=$3 + [ $4 = -1 ] && ih=128 || ih=$4 + [ $5 = -1 ] && iv=128 || iv=$5 + signal $1 i $(((oh << 24) + (ov << 16) + (ih << 8) + iv)) + ;; + *) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; + esac + ;; +*) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; +esac + diff --git a/dwm/patch/dwmc.c b/dwm/patch/dwmc.c new file mode 100755 index 0000000..17f226f --- /dev/null +++ b/dwm/patch/dwmc.c @@ -0,0 +1,103 @@ +void +setlayoutex(const Arg *arg) +{ + setlayout(&((Arg) { .v = &layouts[arg->i] })); +} + +void +viewex(const Arg *arg) +{ + view(&((Arg) { .ui = 1 << arg->ui })); +} + +void +viewallex(const Arg *arg) +{ + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + view(&((Arg){.ui = ~SPTAGMASK})); + #else + view(&((Arg){.ui = ~0})); + #endif // SCRATCHPADS_PATCH +} + +void +toggleviewex(const Arg *arg) +{ + toggleview(&((Arg) { .ui = 1 << arg->ui })); +} + +void +tagex(const Arg *arg) +{ + tag(&((Arg) { .ui = 1 << arg->ui })); +} + +void +toggletagex(const Arg *arg) +{ + toggletag(&((Arg) { .ui = 1 << arg->ui })); +} + +void +tagallex(const Arg *arg) +{ + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + tag(&((Arg){.ui = ~SPTAGMASK})); + #else + tag(&((Arg){.ui = ~0})); + #endif // SCRATCHPADS_PATCH +} + +int +fake_signal(void) +{ + char fsignal[256]; + char indicator[9] = "fsignal:"; + char str_sig[50]; + char param[16]; + int i, len_str_sig, n, paramn; + size_t len_fsignal, len_indicator = strlen(indicator); + Arg arg; + + // Get root name property + if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { + len_fsignal = strlen(fsignal); + + // Check if this is indeed a fake signal + if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { + paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); + + if (paramn == 1) arg = (Arg) {0}; + else if (paramn > 2) return 1; + else if (strncmp(param, "i", n - len_str_sig) == 0) + #if IPC_PATCH + sscanf(fsignal + len_indicator + n, "%li", &(arg.i)); + #else + sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); + #endif // IPC_PATCH + else if (strncmp(param, "ui", n - len_str_sig) == 0) + #if IPC_PATCH + sscanf(fsignal + len_indicator + n, "%lu", &(arg.ui)); + #else + sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); + #endif // IPC_PATCH + else if (strncmp(param, "f", n - len_str_sig) == 0) + sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); + else if (strncmp(param, "v", n - len_str_sig) == 0) + arg.v = &(fsignal[len_indicator + n + 1]); + else return 1; + + // Check if a signal was found, and if so handle it + for (i = 0; i < LENGTH(signals); i++) + if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) + signals[i].func(&(arg)); + + // A fake signal was sent + return 1; + } + } + + // No fake signal was sent, so proceed with update + return 0; +} + diff --git a/dwm/patch/dwmc.h b/dwm/patch/dwmc.h new file mode 100755 index 0000000..66e23a9 --- /dev/null +++ b/dwm/patch/dwmc.h @@ -0,0 +1,14 @@ +typedef struct { + const char * sig; + void (*func)(const Arg *); +} Signal; + +static void setlayoutex(const Arg *arg); +static void viewex(const Arg *arg); +static void viewallex(const Arg *arg); +static void toggleviewex(const Arg *arg); +static void tagex(const Arg *arg); +static void toggletagex(const Arg *arg); +static void tagallex(const Arg *arg); +static int fake_signal(void); + diff --git a/dwm/patch/exresize.c b/dwm/patch/exresize.c new file mode 100755 index 0000000..ac3eab7 --- /dev/null +++ b/dwm/patch/exresize.c @@ -0,0 +1,196 @@ +#define EXPAND_LEFT (1 << 0) +#define EXPAND_RIGHT (1 << 2) +#define EXPAND_UP (1 << 4) +#define EXPAND_DOWN (1 << 6) + +#define IS_SET(q, w) ((q & w) != 0) +#define IS_FORCED(q, w) IS_SET((q << 1), w) + +#define EXPANDALL (EXPAND_LEFT | EXPAND_RIGHT | EXPAND_UP | EXPAND_DOWN) +#define UNEXPAND (EXPANDALL << 1) // Force all directions to 0 +#define FORCE_EXPANDALL ~0 // Force expand in all directions + +void +exresize(const Arg *arg) +{ + Client *c; + int x, y, nx, ny, nw, nh; + c = selmon->sel; + + if (!c || !arg) return; + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) + togglefloating(NULL); + if (c->expandmask != 0) + expand(UNEXPAND); + + x = ((int *)arg->v)[0]; + y = ((int *)arg->v)[1]; + + nw = MIN(selmon->ww - c->bw*2, c->w + x); + nh = MIN(selmon->wh - c->bw*2, c->h + y); + nx = c->x - x/2; + ny = c->y - y/2; + + if (!((abs(c->x + c->w/2 - (selmon->wx + selmon->ww/2)) < snap))) { + if ((nw == selmon->ww) || + (nx < selmon->wx) || + (abs(selmon->wx - c->x) < snap)) + nx = selmon->wx; + else if ((nx+nw > (selmon->wx + selmon->ww)) || + (abs((selmon->wx + selmon->ww) - (c->x + c->w)) < snap)) + nx = (selmon->wx + selmon->ww) - nw - c->bw*2; + } else + nx = selmon->wx + selmon->ww/2 - nw/2; + + if (!((abs(c->y + c->h/2 - (selmon->wy + selmon->wh/2)) < snap))) { + + if ((nh == selmon->wh) || + (ny < selmon->wy) || + (abs(selmon->wy - c->y) < snap)) + ny = selmon->wy; + else if ((ny+nh > (selmon->wy + selmon->wh)) || + (abs((selmon->wy + selmon->wh) - (c->y + c->h)) < snap)) + ny = (selmon->wy + selmon->wh) - nh - c->bw*2; + } else + ny = selmon->wy + selmon->wh/2 - nh/2; + + + resizeclient(c, nx, ny, MAX(nw, 32), MAX(nh, 32)); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); +} + +void +explace(const Arg *arg) +{ + Client *c; + int nx, ny; + + c = selmon->sel; + if (!c || (arg->ui >= 9)) return; + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) + togglefloating(NULL); + + nx = (arg->ui % 3) - 1; + ny = (arg->ui / 3) - 1; + + if (nx < 0) nx = selmon->wx; + else if (nx > 0) nx = selmon->wx + selmon->ww - c->w - c->bw*2; + else nx = selmon->wx + selmon->ww/2 - c->w/2; + + if (ny < 0) ny = selmon->wy; + else if (ny > 0) ny = selmon->wy + selmon->wh - c->h - c->bw*2; + else ny = selmon->wy + selmon->wh/2 - c->h/2; + + resize(c, nx, ny, c->w, c->h, True); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); +} + +int +calculate_expand(unsigned char mask, unsigned char curmask, + unsigned char *newmask, unsigned char key, + int *reset_value, int new_reset_value, + int max_value, int old_value) +{ + if (IS_SET(key, mask) || + (IS_SET(key, curmask) && (!IS_SET(key, mask) && IS_FORCED(key, mask))) || + (!IS_SET(key, curmask) && (IS_SET(key, mask) && IS_FORCED(key, mask)))) { + + if (IS_SET(key, mask) && (!IS_SET(key,curmask) || IS_FORCED(key,mask))) { + if (!IS_SET(key, curmask)) + *reset_value = new_reset_value; + *newmask |= key; + return max_value; + } else if ((IS_SET(key,curmask) && IS_SET(key, mask)) || + (!IS_SET(key, mask) && IS_FORCED(key, mask))) { + *newmask &= ~key; + return *reset_value; + } else { + *newmask &= ~key; + return old_value; + } + } else + return new_reset_value; +} + +void +expand(unsigned char mask) +{ + XEvent ev; + int nx1, ny1, nx2, ny2; + #if SETBORDERPX_PATCH + int bp = selmon->borderpx; + #else + int bp = borderpx; + #endif // SETBORDERPX_PATCH + unsigned char curmask; + unsigned char newmask; + + if (!selmon->sel || selmon->sel->isfixed) + return; + XRaiseWindow(dpy, selmon->sel->win); + newmask = curmask = selmon->sel->expandmask; + + if (curmask == 0) { + if(!selmon->lt[selmon->sellt]->arrange || selmon->sel->isfloating) + selmon->sel->wasfloating = 1; + else { + togglefloating(NULL); + selmon->sel->wasfloating = 0; + } + } + + nx1 = calculate_expand(mask, curmask, &newmask, + EXPAND_LEFT, &selmon->sel->expandx1, + selmon->sel->x, + selmon->wx, + selmon->sel->oldx); + nx2 = calculate_expand(mask, curmask, &newmask, + EXPAND_RIGHT, &selmon->sel->expandx2, + selmon->sel->x + selmon->sel->w, + selmon->wx + selmon->ww - 2*bp, + selmon->sel->oldw + selmon->sel->x); + ny1 = calculate_expand(mask, curmask, &newmask, + EXPAND_UP, &selmon->sel->expandy1, + selmon->sel->y, + selmon->wy, + selmon->sel->oldy); + ny2 = calculate_expand(mask, curmask, &newmask, + EXPAND_DOWN, &selmon->sel->expandy2, + selmon->sel->y + selmon->sel->h, + selmon->wy + selmon->wh - 2*bp, + selmon->sel->oldh + selmon->sel->y); + + + resizeclient(selmon->sel, nx1, ny1, MAX(nx2-nx1, 32), MAX(ny2-ny1, 32)); + + if ((newmask == 0) && (!selmon->sel->wasfloating)) + togglefloating(NULL); + selmon->sel->expandmask = newmask; + drawbar(selmon); + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +togglemaximize(const Arg *arg) +{ + if (arg->i > 0) expand(FORCE_EXPANDALL); + else if (arg->i < 0) expand(UNEXPAND); + else expand(EXPANDALL); +} + +void +toggleverticalexpand(const Arg *arg) +{ + if (arg->i < 0) expand(EXPAND_DOWN); + else if (arg->i > 0) expand(EXPAND_UP); + else expand(EXPAND_DOWN | EXPAND_UP); +} + +void +togglehorizontalexpand(const Arg *arg) +{ + if (arg->i < 0) expand(EXPAND_LEFT); + else if (arg->i > 0) expand(EXPAND_RIGHT); + else expand(EXPAND_LEFT | EXPAND_RIGHT); +} + diff --git a/dwm/patch/exresize.h b/dwm/patch/exresize.h new file mode 100755 index 0000000..73a636a --- /dev/null +++ b/dwm/patch/exresize.h @@ -0,0 +1,9 @@ +enum { EX_NW, EX_N, EX_NE, EX_W, EX_C, EX_E, EX_SW, EX_S, EX_SE }; + +void expand(unsigned char mask); +void togglemaximize(const Arg *arg); +void toggleverticalexpand(const Arg *arg); +void togglehorizontalexpand(const Arg *arg); +void exresize(const Arg *arg); +void explace(const Arg *arg); + diff --git a/dwm/patch/fakefullscreenclient.c b/dwm/patch/fakefullscreenclient.c new file mode 100755 index 0000000..509211f --- /dev/null +++ b/dwm/patch/fakefullscreenclient.c @@ -0,0 +1,19 @@ +void +togglefakefullscreen(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + + if (c->fakefullscreen != 1 && c->isfullscreen) { // exit fullscreen --> fake fullscreen + c->fakefullscreen = 2; + setfullscreen(c, 0); + } else if (c->fakefullscreen == 1) { + setfullscreen(c, 0); + c->fakefullscreen = 0; + } else { + c->fakefullscreen = 1; + setfullscreen(c, 1); + } +} + diff --git a/dwm/patch/fakefullscreenclient.h b/dwm/patch/fakefullscreenclient.h new file mode 100755 index 0000000..889eed6 --- /dev/null +++ b/dwm/patch/fakefullscreenclient.h @@ -0,0 +1,2 @@ +static void togglefakefullscreen(const Arg *arg); + diff --git a/dwm/patch/floatpos.c b/dwm/patch/floatpos.c new file mode 100755 index 0000000..f5e83a7 --- /dev/null +++ b/dwm/patch/floatpos.c @@ -0,0 +1,195 @@ +void +floatpos(const Arg *arg) +{ + Client *c = selmon->sel; + + if (!c || (selmon->lt[selmon->sellt]->arrange && !c->isfloating)) + return; + + setfloatpos(c, (char *)arg->v); + resizeclient(c, c->x, c->y, c->w, c->h); + + #if !FOCUSONCLICK_PATCH + XRaiseWindow(dpy, c->win); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); + #endif // FOCUSONCLICK_PATCH +} + +void +setfloatpos(Client *c, const char *floatpos) +{ + char xCh, yCh, wCh, hCh; + int x, y, w, h, wx, ww, wy, wh; + #if FLOATPOS_RESPECT_GAPS_PATCH && VANITYGAPS_PATCH + int oh, ov, ih, iv; + unsigned int n; + #endif // FLOATPOS_RESPECT_GAPS_PATCH | VANITYGAPS_PATCH + + if (!c || !floatpos) + return; + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) + return; + + switch(sscanf(floatpos, "%d%c %d%c %d%c %d%c", &x, &xCh, &y, &yCh, &w, &wCh, &h, &hCh)) { + case 4: + if (xCh == 'w' || xCh == 'W') { + w = x; wCh = xCh; + h = y; hCh = yCh; + x = -1; xCh = 'C'; + y = -1; yCh = 'C'; + } else if (xCh == 'p' || xCh == 'P') { + w = x; wCh = xCh; + h = y; hCh = yCh; + x = 0; xCh = 'G'; + y = 0; yCh = 'G'; + } else if (xCh == 'm' || xCh == 'M') { + getrootptr(&x, &y); + } else { + w = 0; wCh = 0; + h = 0; hCh = 0; + } + break; + case 8: + if (xCh == 'm' || xCh == 'M') + getrootptr(&x, &y); + break; + default: + return; + } + + #if FLOATPOS_RESPECT_GAPS_PATCH && VANITYGAPS_PATCH + getgaps(c->mon, &oh, &ov, &ih, &iv, &n); + wx = c->mon->wx + ov; + wy = c->mon->wy + oh; + ww = c->mon->ww - 2*ov; + wh = c->mon->wh - 2*oh; + #else + wx = c->mon->wx; + wy = c->mon->wy; + ww = c->mon->ww; + wh = c->mon->wh; + #endif // FLOATPOS_RESPECT_GAPS_PATCH | VANITYGAPS_PATCH + + getfloatpos(x, xCh, w, wCh, wx, ww, c->x, c->w, c->bw, floatposgrid_x, &c->x, &c->w); + getfloatpos(y, yCh, h, hCh, wy, wh, c->y, c->h, c->bw, floatposgrid_y, &c->y, &c->h); +} + +/* p - position, s - size, cp and cs represents current position and size */ +void +getfloatpos(int pos, char pCh, int size, char sCh, int min_p, int max_s, int cp, int cs, int cbw, int defgrid, int *out_p, int *out_s) +{ + int abs_p, abs_s, i, delta, rest; + + abs_p = pCh == 'A' || pCh == 'a'; + abs_s = sCh == 'A' || sCh == 'a'; + + cs += 2*cbw; + + switch(pCh) { + case 'A': // absolute position + cp = pos; + break; + case 'a': // absolute relative position + cp += pos; + break; + case 'y': + case 'x': // client relative position + cp = MIN(cp + pos, min_p + max_s); + break; + case 'Y': + case 'X': // client position relative to monitor + cp = min_p + MIN(pos, max_s); + break; + case 'S': // fixed client position (sticky) + case 'C': // fixed client position (center) + case 'Z': // fixed client right-hand position (position + size) + if (pos == -1) + break; + pos = MAX(MIN(pos, max_s), 0); + if (pCh == 'Z') + cs = abs((cp + cs) - (min_p + pos)); + else if (pCh == 'C') + cs = abs((cp + cs / 2) - (min_p + pos)); + else + cs = abs(cp - (min_p + pos)); + cp = min_p + pos; + sCh = 0; // size determined by position, override defined size + break; + case 'G': // grid + if (pos <= 0) + pos = defgrid; // default configurable + if (size == 0 || pos < 2 || (sCh != 'p' && sCh != 'P')) + break; + delta = (max_s - cs) / (pos - 1); + rest = max_s - cs - delta * (pos - 1); + if (sCh == 'P') { + if (size < 1 || size > pos) + break; + cp = min_p + delta * (size - 1); + } else { + for (i = 0; i < pos && cp >= min_p + delta * i + (i > pos - rest ? i + rest - pos + 1 : 0); i++); + cp = min_p + delta * (MAX(MIN(i + size, pos), 1) - 1) + (i > pos - rest ? i + rest - pos + 1 : 0); + } + break; + } + + switch(sCh) { + case 'A': // absolute size + cs = size; + break; + case 'a': // absolute relative size + cs = MAX(1, cs + size); + break; + case '%': // client size percentage in relation to monitor window area size + if (size <= 0) + break; + size = max_s * MIN(size, 100) / 100; + /* falls through */ + case 'h': + case 'w': // size relative to client + if (sCh == 'w' || sCh == 'h') { + if (size == 0) + break; + size += cs; + } + /* falls through */ + case 'H': + case 'W': // normal size, position takes precedence + if (pCh == 'S' && cp + size > min_p + max_s) + size = min_p + max_s - cp; + else if (size > max_s) + size = max_s; + + if (pCh == 'C') { // fixed client center, expand or contract client + delta = size - cs; + if (delta < 0 || (cp - delta / 2 + size <= min_p + max_s)) + cp -= delta / 2; + else if (cp - delta / 2 < min_p) + cp = min_p; + else if (delta) + cp = min_p + max_s; + } else if (pCh == 'Z') + cp -= size - cs; + + cs = size; + break; + } + + if (pCh == '%') // client mid-point position in relation to monitor window area size + cp = min_p + max_s * MAX(MIN(pos, 100), 0) / 100 - (cs) / 2; + if (pCh == 'm' || pCh == 'M') + cp = pos - cs / 2; + + if (!abs_p && cp < min_p) + cp = min_p; + if (cp + cs > min_p + max_s && !(abs_p && abs_s)) { + if (abs_p || cp == min_p) + cs = min_p + max_s - cp; + else + cp = min_p + max_s - cs; + } + + *out_p = cp; + *out_s = MAX(cs - 2*cbw, 1); +} + diff --git a/dwm/patch/floatpos.h b/dwm/patch/floatpos.h new file mode 100755 index 0000000..ecdcf0b --- /dev/null +++ b/dwm/patch/floatpos.h @@ -0,0 +1,4 @@ +static void floatpos(const Arg *arg); +static void setfloatpos(Client *c, const char *floatpos); +static void getfloatpos(int pos, char pCh, int size, char sCh, int min_p, int max_s, int cp, int cs, int cbw, int defgrid, int *out_p, int *out_s); + diff --git a/dwm/patch/focusadjacenttag.c b/dwm/patch/focusadjacenttag.c new file mode 100755 index 0000000..f0244a2 --- /dev/null +++ b/dwm/patch/focusadjacenttag.c @@ -0,0 +1,69 @@ +void +tagtoleft(const Arg *arg) +{ + unsigned int MASK = (1 << NUMTAGS) - 1; + if (selmon->sel != NULL + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] > 1) { + selmon->sel->tags >>= 1; + arrange(selmon); + focus(NULL); + } +} + +void +tagtoright(const Arg *arg) +{ + unsigned int MASK = (1 << NUMTAGS) - 1; + if (selmon->sel != NULL + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] & (MASK >> 1)) { + selmon->sel->tags <<= 1; + arrange(selmon); + focus(NULL); + } +} + +void +viewtoleft(const Arg *arg) +{ + unsigned int MASK = (1 << NUMTAGS) - 1; + if (__builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] > 1) { + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 })); + } +} + +void +viewtoright(const Arg *arg) +{ + unsigned int MASK = (1 << NUMTAGS) - 1; + if (__builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] & (MASK >> 1)) { + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 })); + } +} + +void +tagandviewtoleft(const Arg *arg) +{ + unsigned int MASK = (1 << NUMTAGS) - 1; + if (selmon->sel != NULL + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] > 1) { + selmon->sel->tags >>= 1; + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 })); + } +} + +void +tagandviewtoright(const Arg *arg) +{ + unsigned int MASK = (1 << NUMTAGS) - 1; + if (selmon->sel != NULL + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] & (MASK >> 1)) { + selmon->sel->tags <<= 1; + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 })); + } +} diff --git a/dwm/patch/focusadjacenttag.h b/dwm/patch/focusadjacenttag.h new file mode 100755 index 0000000..abd7439 --- /dev/null +++ b/dwm/patch/focusadjacenttag.h @@ -0,0 +1,7 @@ +static void tagtoleft(const Arg *arg); +static void tagtoright(const Arg *arg); +static void viewtoleft(const Arg *arg); +static void viewtoright(const Arg *arg); +static void tagandviewtoleft(const Arg *arg); +static void tagandviewtoright(const Arg *arg); + diff --git a/dwm/patch/focusdir.c b/dwm/patch/focusdir.c new file mode 100755 index 0000000..65798c5 --- /dev/null +++ b/dwm/patch/focusdir.c @@ -0,0 +1,66 @@ +void +focusdir(const Arg *arg) +{ + Client *s = selmon->sel, *f = NULL, *c, *next; + + if (!s) + return; + + unsigned int score = -1; + unsigned int client_score; + int dist; + int dirweight = 20; + int isfloating = s->isfloating; + + next = s->next; + if (!next) + next = s->mon->clients; + for (c = next; c != s; c = next) { + + next = c->next; + if (!next) + next = s->mon->clients; + + if (!ISVISIBLE(c) || c->isfloating != isfloating) // || HIDDEN(c) + continue; + + switch (arg->i) { + case 0: // left + dist = s->x - c->x - c->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(s->y - c->y); + break; + case 1: // right + dist = c->x - s->x - s->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(c->y - s->y); + break; + case 2: // up + dist = s->y - c->y - c->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(s->x - c->x); + break; + default: + case 3: // down + dist = c->y - s->y - s->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(c->x - s->x); + break; + } + + if (((arg->i == 0 || arg->i == 2) && client_score <= score) || client_score < score) { + score = client_score; + f = c; + } + } + + if (f && f != s) { + focus(f); + restack(f->mon); + } +} + diff --git a/dwm/patch/focusdir.h b/dwm/patch/focusdir.h new file mode 100755 index 0000000..0d82ebf --- /dev/null +++ b/dwm/patch/focusdir.h @@ -0,0 +1,2 @@ +static void focusdir(const Arg *arg); + diff --git a/dwm/patch/focusfollowmouse.c b/dwm/patch/focusfollowmouse.c new file mode 100755 index 0000000..d75a9da --- /dev/null +++ b/dwm/patch/focusfollowmouse.c @@ -0,0 +1,9 @@ +Client * +getpointerclient(void) +{ + Window dummy, win; + int di; + unsigned int dui; + XQueryPointer(dpy, root, &dummy, &win, &di, &di, &di, &di, &dui); + return wintoclient(win); +} diff --git a/dwm/patch/focusfollowmouse.h b/dwm/patch/focusfollowmouse.h new file mode 100755 index 0000000..6b24d5f --- /dev/null +++ b/dwm/patch/focusfollowmouse.h @@ -0,0 +1 @@ +static Client *getpointerclient(void); diff --git a/dwm/patch/focusmaster.c b/dwm/patch/focusmaster.c new file mode 100755 index 0000000..ae0771c --- /dev/null +++ b/dwm/patch/focusmaster.c @@ -0,0 +1,42 @@ +void +focusmaster(const Arg *arg) +{ + Client *master; + Monitor *m = selmon; + #if FOCUSMASTER_RETURN_PATCH + int i; + #endif // FOCUSMASTER_RETURN_PATCH + + if (m->nmaster < 1) + return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (!m->sel || (m->sel->isfullscreen && m->sel->fakefullscreen != 1 && lockfullscreen)) + return; + #else + if (!m->sel || (m->sel->isfullscreen && lockfullscreen)) + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // FAKEFULLSCREEN_PATCH + + master = nexttiled(m->clients); + + if (!master) + return; + + #if FOCUSMASTER_RETURN_PATCH + for (i = 0; !(m->tagset[m->seltags] & 1 << i); i++); + i++; + + if (m->sel == master) { + if (m->tagmarked[i] && ISVISIBLE(m->tagmarked[i])) + focus(m->tagmarked[i]); + } else { + m->tagmarked[i] = m->sel; + focus(master); + } + #else + focus(master); + #endif // FOCUSMASTER_RETURN_PATCH + restack(m); +} diff --git a/dwm/patch/focusmaster.h b/dwm/patch/focusmaster.h new file mode 100755 index 0000000..32e7c7c --- /dev/null +++ b/dwm/patch/focusmaster.h @@ -0,0 +1,2 @@ +static void focusmaster(const Arg *arg); + diff --git a/dwm/patch/focusurgent.c b/dwm/patch/focusurgent.c new file mode 100755 index 0000000..86a918e --- /dev/null +++ b/dwm/patch/focusurgent.c @@ -0,0 +1,16 @@ +void +focusurgent(const Arg *arg) +{ + Client *c; + int i; + for (c = selmon->clients; c && !c->isurgent; c = c->next); + if (c) { + for (i = 0; i < NUMTAGS && !((1 << i) & c->tags); i++); + if (i < NUMTAGS) { + if (((1 << i) & TAGMASK) != selmon->tagset[selmon->seltags]) + view(&((Arg) { .ui = 1 << i })); + focus(c); + } + } +} + diff --git a/dwm/patch/focusurgent.h b/dwm/patch/focusurgent.h new file mode 100755 index 0000000..854258d --- /dev/null +++ b/dwm/patch/focusurgent.h @@ -0,0 +1,2 @@ +static void focusurgent(const Arg *arg); + diff --git a/dwm/patch/fsignal.c b/dwm/patch/fsignal.c new file mode 100755 index 0000000..b0ce2ea --- /dev/null +++ b/dwm/patch/fsignal.c @@ -0,0 +1,41 @@ +int +fake_signal(void) +{ + char fsignal[256]; + char indicator[9] = "fsignal:"; + char str_signum[16]; + int i, v, signum; + size_t len_fsignal, len_indicator = strlen(indicator); + + // Get root name property + if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { + len_fsignal = strlen(fsignal); + + // Check if this is indeed a fake signal + if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { + memcpy(str_signum, &fsignal[len_indicator], len_fsignal - len_indicator); + str_signum[len_fsignal - len_indicator] = '\0'; + + // Convert string value into managable integer + for (i = signum = 0; i < strlen(str_signum); i++) { + v = str_signum[i] - '0'; + if (v >= 0 && v <= 9) { + signum = signum * 10 + v; + } + } + + // Check if a signal was found, and if so handle it + if (signum) + for (i = 0; i < LENGTH(signals); i++) + if (signum == signals[i].signum && signals[i].func) + signals[i].func(&(signals[i].arg)); + + // A fake signal was sent + return 1; + } + } + + // No fake signal was sent, so proceed with update + return 0; +} + diff --git a/dwm/patch/fsignal.h b/dwm/patch/fsignal.h new file mode 100755 index 0000000..55fed6c --- /dev/null +++ b/dwm/patch/fsignal.h @@ -0,0 +1,8 @@ +typedef struct { + unsigned int signum; + void (*func)(const Arg *); + const Arg arg; +} Signal; + +static int fake_signal(void); + diff --git a/dwm/patch/fullscreen.c b/dwm/patch/fullscreen.c new file mode 100755 index 0000000..667cdc9 --- /dev/null +++ b/dwm/patch/fullscreen.c @@ -0,0 +1,18 @@ +Layout *last_layout; + +void +fullscreen(const Arg *arg) +{ + int monocle_pos = 0; + if (selmon->showbar || last_layout == NULL) { + #if MONOCLE_LAYOUT + for (monocle_pos = 0, last_layout = (Layout *)layouts; !last_layout->arrange || last_layout->arrange != &monocle; monocle_pos++, last_layout++ ); + #endif // MONOCLE_LAYOUT + for (last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); + setlayout(&((Arg) { .v = &layouts[monocle_pos] })); + } else { + setlayout(&((Arg) { .v = last_layout })); + } + togglebar(arg); +} + diff --git a/dwm/patch/fullscreen.h b/dwm/patch/fullscreen.h new file mode 100755 index 0000000..72983e1 --- /dev/null +++ b/dwm/patch/fullscreen.h @@ -0,0 +1,2 @@ +static void fullscreen(const Arg *arg); + diff --git a/dwm/patch/games.c b/dwm/patch/games.c new file mode 100755 index 0000000..49961c2 --- /dev/null +++ b/dwm/patch/games.c @@ -0,0 +1,32 @@ +void +minimize(Client *c) +{ + if (!c || HIDDEN(c)) + return; + + Window w = c->win; + static XWindowAttributes ra, ca; + + /* More or less taken directly from blackbox's hide() function */ + XGrabServer(dpy); + XGetWindowAttributes(dpy, root, &ra); + XGetWindowAttributes(dpy, w, &ca); + /* Prevent UnmapNotify events */ + XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); + XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask); + XUnmapWindow(dpy, w); + setclientstate(c, IconicState); + XSelectInput(dpy, root, ra.your_event_mask); + XSelectInput(dpy, w, ca.your_event_mask); + XUngrabServer(dpy); +} + +void +unminimize(Client *c) +{ + if (!c || !HIDDEN(c)) + return; + + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); +} diff --git a/dwm/patch/games.h b/dwm/patch/games.h new file mode 100755 index 0000000..5e3e1bf --- /dev/null +++ b/dwm/patch/games.h @@ -0,0 +1,2 @@ +static void minimize(Client *c); +static void unminimize(Client *c); diff --git a/dwm/patch/include.c b/dwm/patch/include.c new file mode 100755 index 0000000..68d66af --- /dev/null +++ b/dwm/patch/include.c @@ -0,0 +1,421 @@ +/* Bar functionality */ +#include "bar_indicators.c" +#include "bar_tagicons.c" +#include "bar.c" + +#if BAR_ALPHA_PATCH +#include "bar_alpha.c" +#endif +#if BAR_ALTERNATIVE_TAGS_PATCH +#include "bar_alternativetags.c" +#endif +#if BAR_ANYBAR_PATCH +#include "bar_anybar.c" +#endif +#if BAR_DWMBLOCKS_PATCH && BAR_STATUSCMD_PATCH +#include "bar_dwmblocks.c" +#endif +#if BAR_EWMHTAGS_PATCH +#include "bar_ewmhtags.c" +#endif +#if COMBO_PATCH +#include "combo.c" +#endif +#if BAR_LAUNCHER_PATCH +#include "bar_launcher.c" +#endif +#if BAR_LTSYMBOL_PATCH +#include "bar_ltsymbol.c" +#endif +#if BAR_POWERLINE_STATUS_PATCH +#include "bar_powerline_status.c" +#endif +#if BAR_POWERLINE_TAGS_PATCH +#include "bar_powerline_tags.c" +#endif +#if BAR_STATUS_PATCH +#include "bar_status.c" +#endif +#if BAR_STATUS2D_PATCH +#include "bar_status2d.c" +#endif +#if BAR_STATUSBUTTON_PATCH +#include "bar_statusbutton.c" +#endif +#if BAR_STATUSCMD_PATCH +#include "bar_statuscmd.c" +#endif +#if BAR_STATUSCOLORS_PATCH +#include "bar_statuscolors.c" +#endif +#if BAR_WINICON_PATCH +#include "bar_winicon.c" +#endif +#if BAR_TABGROUPS_PATCH +#include "bar_tabgroups.c" +#endif +#if BAR_TAGPREVIEW_PATCH +#include "bar_tagpreview.c" +#endif +#if BAR_TAGS_PATCH +#include "bar_tags.c" +#endif +#if BAR_TAGLABELS_PATCH +#include "bar_taglabels.c" +#endif +#if BAR_TAGGRID_PATCH +#include "bar_taggrid.c" +#endif +#if BAR_WINTITLE_PATCH +#include "bar_wintitle.c" +#endif +#if BAR_FANCYBAR_PATCH +#include "bar_fancybar.c" +#endif +#if BAR_FLEXWINTITLE_PATCH +#include "bar_flexwintitle.c" +#if BAR_WINTITLE_FLOATING_PATCH +#include "bar_wintitle_floating.c" +#endif +#if BAR_WINTITLE_HIDDEN_PATCH +#include "bar_wintitle_hidden.c" +#endif +#endif // BAR_FLEXWINTITLE_PATCH +#if BAR_AWESOMEBAR_PATCH +#include "bar_awesomebar.c" +#endif +#if BAR_SYSTRAY_PATCH +#include "bar_systray.c" +#endif +#if BAR_HOLDBAR_PATCH +#include "bar_holdbar.c" +#endif +#if BAR_VTCOLORS_PATCH +#include "bar_vtcolors.c" +#endif +#if BAR_WINTITLEACTIONS_PATCH +#include "bar_wintitleactions.c" +#endif +#if BAR_LAYOUTMENU_PATCH +#include "bar_layoutmenu.c" +#endif + +/* Other patches */ +#if ALT_TAB_PATCH +#include "alttab.c" +#endif +#if ALWAYSONTOP_PATCH +#include "alwaysontop.c" +#endif +#if ASPECTRESIZE_PATCH +#include "aspectresize.c" +#endif +#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH +#include "attachx.c" +#endif +#if AUTOSTART_PATCH +#include "autostart.c" +#endif +#if BANISH_PATCH || PLACEMOUSE_PATCH +#include "recttoclient.c" +#endif +#if BANISH_PATCH +#include "banish.c" +#endif +#if CFACTS_PATCH +#include "cfacts.c" +#endif +#if CMDCUSTOMIZE_PATCH +#include "cmdcustomize.c" +#endif +#if COOL_AUTOSTART_PATCH +#include "cool_autostart.c" +#endif +#if CYCLELAYOUTS_PATCH +#include "cyclelayouts.c" +#endif +#if DECORATION_HINTS_PATCH +#include "decorationhints.c" +#endif +#if DISTRIBUTETAGS_PATCH +#include "distributetags.c" +#endif +#if DRAGCFACT_PATCH && CFACTS_PATCH +#include "dragcfact.c" +#endif +#if DWMC_PATCH +#include "dwmc.c" +#elif FSIGNAL_PATCH +#include "fsignal.c" +#endif +#if EXRESIZE_PATCH +#include "exresize.c" +#endif +#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH +#include "fakefullscreenclient.c" +#endif +#if FLOATPOS_PATCH +#include "floatpos.c" +#endif +#if FOCUSADJACENTTAG_PATCH +#include "focusadjacenttag.c" +#endif +#if FOCUSDIR_PATCH +#include "focusdir.c" +#endif +#if FOCUSFOLLOWMOUSE_PATCH +#include "focusfollowmouse.c" +#endif +#if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH +#include "focusmaster.c" +#endif +#if FOCUSURGENT_PATCH +#include "focusurgent.c" +#endif +#if FULLSCREEN_PATCH +#include "fullscreen.c" +#endif +#if GAMES_PATCH +#include "games.c" +#endif +#if INPLACEROTATE_PATCH +#include "inplacerotate.c" +#endif +#if IPC_PATCH +#include "ipc.c" +#ifdef VERSION +#include "ipc/IPCClient.c" +#include "ipc/yajl_dumps.c" +#include "ipc/ipc.c" +#include "ipc/util.c" +#endif +#endif // IPC_PATCH +#if INSETS_PATCH +#include "insets.c" +#endif +#if KEYMODES_PATCH +#include "keymodes.c" +#endif +#if KILLUNSEL_PATCH +#include "killunsel.c" +#endif +#if MAXIMIZE_PATCH +#include "maximize.c" +#endif +#if MPDCONTROL_PATCH +#include "mpdcontrol.c" +#endif +#if MOVECENTER_PATCH +#include "movecenter.c" +#endif +#if MOVEPLACE_PATCH +#include "moveplace.c" +#endif +#if MOVERESIZE_PATCH +#include "moveresize.c" +#endif +#if MOVESTACK_PATCH +#include "movestack.c" +#endif +#if NAMETAG_PATCH +#include "nametag.c" +#endif +#if NO_MOD_BUTTONS_PATCH +#include "nomodbuttons.c" +#endif +#if PERTAG_PATCH +#include "pertag.c" +#endif +#if PLACEDIR_PATCH +#include "placedir.c" +#endif +#if PLACEMOUSE_PATCH +#include "placemouse.c" +#endif +#if PUSH_NO_MASTER_PATCH +#include "push_no_master.c" +#elif PUSH_PATCH +#include "push.c" +#endif +#if REORGANIZETAGS_PATCH +#include "reorganizetags.c" +#endif +#if RESTARTSIG_PATCH +#include "restartsig.c" +#endif +#if RIODRAW_PATCH +#include "riodraw.c" +#endif +#if ROTATESTACK_PATCH +#include "rotatestack.c" +#endif +#if ROUNDED_CORNERS_PATCH +#include "roundedcorners.c" +#endif +#if RENAMED_SCRATCHPADS_PATCH +#include "renamed_scratchpads.c" +#elif SCRATCHPADS_PATCH +#include "scratchpad.c" +#endif +#if SCRATCHPAD_ALT_1_PATCH +#include "scratchpad_alt_1.c" +#endif +#if SELFRESTART_PATCH +#include "selfrestart.c" +#endif +#if SETBORDERPX_PATCH +#include "setborderpx.c" +#endif +#if SHIFTBOTH_PATCH || SHIFTSWAPTAGS_PATCH || SHIFTTAG_PATCH || SHIFTTAGCLIENTS_PATCH || SHIFTVIEW_PATCH || SHIFTVIEW_CLIENTS_PATCH +#include "shift.c" +#endif +#if SHIFTBOTH_PATCH +#include "shiftboth.c" +#endif +#if SHIFTSWAPTAGS_PATCH && SWAPTAGS_PATCH +#include "shiftswaptags.c" +#endif +#if SHIFTTAG_PATCH +#include "shifttag.c" +#endif +#if SHIFTTAGCLIENTS_PATCH +#include "shifttagclients.c" +#endif +#if SHIFTVIEW_PATCH +#include "shiftview.c" +#endif +#if SHIFTVIEW_CLIENTS_PATCH +#include "shiftviewclients.c" +#endif +#if SIZEHINTS_RULED_PATCH +#include "sizehints_ruled.c" +#endif +#if SORTSCREENS_PATCH +#ifdef XINERAMA +#include "sortscreens.c" +#endif // XINERAMA +#endif +#if STACKER_PATCH +#include "stacker.c" +#endif +#if STICKY_PATCH +#include "sticky.c" +#endif +#if SWALLOW_PATCH +#include "swallow.c" +#endif +#if SWAPFOCUS_PATCH && PERTAG_PATCH +#include "swapfocus.c" +#endif +#if SWAPTAGS_PATCH +#include "swaptags.c" +#endif +#if SWITCHCOL_PATCH +#include "switchcol.c" +#endif +#if TAB_PATCH +#include "tab.c" +#endif +#if TAGALL_PATCH +#include "tagall.c" +#endif +#if TAGALLMON_PATCH +#include "tagallmon.c" +#endif +#if TAGOTHERMONITOR_PATCH +#include "tagothermonitor.c" +#endif +#if TAGSWAPMON_PATCH +#include "tagswapmon.c" +#endif +#if TAPRESIZE_PATCH +#include "tapresize.c" +#endif +#if TOGGLEFULLSCREEN_PATCH +#include "togglefullscreen.c" +#endif +#if TOGGLETOPBAR_PATCH +#include "toggletopbar.c" +#endif +#if TRANSFER_PATCH +#include "transfer.c" +#endif +#if TRANSFER_ALL_PATCH +#include "transferall.c" +#endif +#if UNFLOATVISIBLE_PATCH +#include "unfloatvisible.c" +#endif +#if VANITYGAPS_PATCH +#include "vanitygaps.c" +#endif +#if WARP_PATCH +#include "warp.c" +#endif +#if WINVIEW_PATCH +#include "winview.c" +#endif +#if ZOOMSWAP_PATCH +#include "zoomswap.c" +#endif +#if XKB_PATCH +#include "xkb.c" +#endif +#if XRESOURCES_PATCH +#include "xresources.c" +#elif XRDB_PATCH +#include "xrdb.c" +#endif +#if DRAGMFACT_PATCH +#include "dragmfact.c" +#endif +#if SEAMLESS_RESTART_PATCH +#include "seamless_restart.c" +#endif +/* Layouts */ +#if BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || TILE_LAYOUT +#include "layout_facts.c" +#endif +#if BSTACK_LAYOUT +#include "layout_bstack.c" +#endif +#if BSTACKHORIZ_LAYOUT +#include "layout_bstackhoriz.c" +#endif +#if CENTEREDMASTER_LAYOUT +#include "layout_centeredmaster.c" +#endif +#if CENTEREDFLOATINGMASTER_LAYOUT +#include "layout_centeredfloatingmaster.c" +#endif +#if COLUMNS_LAYOUT +#include "layout_columns.c" +#endif +#if DECK_LAYOUT +#include "layout_deck.c" +#endif +#if FIBONACCI_DWINDLE_LAYOUT || FIBONACCI_SPIRAL_LAYOUT +#include "layout_fibonacci.c" +#endif +#if FLEXTILE_DELUXE_LAYOUT +#include "layout_flextile-deluxe.c" +#endif +#if GAPPLESSGRID_LAYOUT +#include "layout_gapplessgrid.c" +#endif +#if GRIDMODE_LAYOUT +#include "layout_grid.c" +#endif +#if HORIZGRID_LAYOUT +#include "layout_horizgrid.c" +#endif +#if MONOCLE_LAYOUT +#include "layout_monocle.c" +#endif +#if NROWGRID_LAYOUT +#include "layout_nrowgrid.c" +#endif +#if TILE_LAYOUT +#include "layout_tile.c" +#endif + diff --git a/dwm/patch/include.h b/dwm/patch/include.h new file mode 100755 index 0000000..b50bee0 --- /dev/null +++ b/dwm/patch/include.h @@ -0,0 +1,414 @@ +/* Bar functionality */ +#include "bar_indicators.h" +#include "bar_tagicons.h" +#include "bar.h" + +#if BAR_ALPHA_PATCH +#include "bar_alpha.h" +#endif +#if BAR_ALTERNATIVE_TAGS_PATCH +#include "bar_alternativetags.h" +#endif +#if BAR_ANYBAR_PATCH +#include "bar_anybar.h" +#endif +#if BAR_DWMBLOCKS_PATCH && BAR_STATUSCMD_PATCH +#include "bar_dwmblocks.h" +#endif +#if BAR_EWMHTAGS_PATCH +#include "bar_ewmhtags.h" +#endif +#if COMBO_PATCH +#include "combo.h" +#endif +#if BAR_HOLDBAR_PATCH +#include "bar_holdbar.h" +#endif +#if BAR_LAUNCHER_PATCH +#include "bar_launcher.h" +#endif +#if BAR_LTSYMBOL_PATCH +#include "bar_ltsymbol.h" +#endif +#if BAR_POWERLINE_STATUS_PATCH +#include "bar_powerline_status.h" +#endif +#if BAR_POWERLINE_TAGS_PATCH +#include "bar_powerline_tags.h" +#endif +#if BAR_STATUS_PATCH +#include "bar_status.h" +#endif +#if BAR_STATUS2D_PATCH +#include "bar_status2d.h" +#endif +#if BAR_STATUSBUTTON_PATCH +#include "bar_statusbutton.h" +#endif +#if BAR_STATUSCMD_PATCH +#include "bar_statuscmd.h" +#endif +#if BAR_STATUSCOLORS_PATCH +#include "bar_statuscolors.h" +#endif +#if BAR_WINICON_PATCH +#include "bar_winicon.h" +#endif +#if BAR_TABGROUPS_PATCH +#include "bar_tabgroups.h" +#endif +#if BAR_TAGS_PATCH +#include "bar_tags.h" +#endif +#if BAR_TAGLABELS_PATCH +#include "bar_taglabels.h" +#endif +#if BAR_TAGPREVIEW_PATCH +#include "bar_tagpreview.h" +#endif +#if BAR_TAGGRID_PATCH +#include "bar_taggrid.h" +#endif +#if BAR_WINTITLE_PATCH +#include "bar_wintitle.h" +#endif +#if BAR_FANCYBAR_PATCH +#include "bar_fancybar.h" +#endif +#if BAR_FLEXWINTITLE_PATCH +#include "bar_flexwintitle.h" +#if BAR_WINTITLE_FLOATING_PATCH +#include "bar_wintitle_floating.h" +#endif +#if BAR_WINTITLE_HIDDEN_PATCH +#include "bar_wintitle_hidden.h" +#endif +#endif // BAR_FLEXWINTITLE_PATCH +#if BAR_AWESOMEBAR_PATCH +#include "bar_awesomebar.h" +#endif +#if BAR_SYSTRAY_PATCH +#include "bar_systray.h" +#endif +#if BAR_VTCOLORS_PATCH +#include "bar_vtcolors.h" +#endif +#if BAR_WINTITLEACTIONS_PATCH +#include "bar_wintitleactions.h" +#endif +#if BAR_LAYOUTMENU_PATCH +#include "bar_layoutmenu.h" +#endif + +/* Other patches */ +#if ALT_TAB_PATCH +#include "alttab.h" +#endif +#if ALWAYSONTOP_PATCH +#include "alwaysontop.h" +#endif +#if ASPECTRESIZE_PATCH +#include "aspectresize.h" +#endif +#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH +#include "attachx.h" +#endif +#if AUTOSTART_PATCH +#include "autostart.h" +#endif +#if BANISH_PATCH || PLACEMOUSE_PATCH +#include "recttoclient.h" +#endif +#if BANISH_PATCH +#include "banish.h" +#endif +#if CFACTS_PATCH +#include "cfacts.h" +#endif +#if CMDCUSTOMIZE_PATCH +#include "cmdcustomize.h" +#endif +#if COOL_AUTOSTART_PATCH +#include "cool_autostart.h" +#endif +#if CYCLELAYOUTS_PATCH +#include "cyclelayouts.h" +#endif +#if DECORATION_HINTS_PATCH +#include "decorationhints.h" +#endif +#if DISTRIBUTETAGS_PATCH +#include "distributetags.h" +#endif +#if DRAGCFACT_PATCH && CFACTS_PATCH +#include "dragcfact.h" +#endif +#if DRAGMFACT_PATCH +#include "dragmfact.h" +#endif +#if DWMC_PATCH +#include "dwmc.h" +#elif FSIGNAL_PATCH +#include "fsignal.h" +#endif +#if EXRESIZE_PATCH +#include "exresize.h" +#endif +#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH +#include "fakefullscreenclient.h" +#endif +#if FLOATPOS_PATCH +#include "floatpos.h" +#endif +#if FOCUSDIR_PATCH +#include "focusdir.h" +#endif +#if FOCUSADJACENTTAG_PATCH +#include "focusadjacenttag.h" +#endif +#if FOCUSFOLLOWMOUSE_PATCH +#include "focusfollowmouse.h" +#endif +#if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH +#include "focusmaster.h" +#endif +#if FOCUSURGENT_PATCH +#include "focusurgent.h" +#endif +#if FULLSCREEN_PATCH +#include "fullscreen.h" +#endif +#if GAMES_PATCH +#include "games.h" +#endif +#if INPLACEROTATE_PATCH +#include "inplacerotate.h" +#endif +#if IPC_PATCH +#include "ipc.h" +#include "ipc/ipc.h" +#include "ipc/util.h" +#endif +#if INSETS_PATCH +#include "insets.h" +#endif +#if KEYMODES_PATCH +#include "keymodes.h" +#endif +#if KILLUNSEL_PATCH +#include "killunsel.h" +#endif +#if MAXIMIZE_PATCH +#include "maximize.h" +#endif +#if MPDCONTROL_PATCH +#include "mpdcontrol.h" +#endif +#if MOVECENTER_PATCH +#include "movecenter.h" +#endif +#if MOVEPLACE_PATCH +#include "moveplace.h" +#endif +#if MOVERESIZE_PATCH +#include "moveresize.h" +#endif +#if MOVESTACK_PATCH +#include "movestack.h" +#endif +#if NAMETAG_PATCH +#include "nametag.h" +#endif +#if NO_MOD_BUTTONS_PATCH +#include "nomodbuttons.h" +#endif +#if PERTAG_PATCH +#include "pertag.h" +#endif +#if PLACEDIR_PATCH +#include "placedir.h" +#endif +#if PLACEMOUSE_PATCH +#include "placemouse.h" +#endif +#if PUSH_NO_MASTER_PATCH +#include "push_no_master.h" +#elif PUSH_PATCH +#include "push.h" +#endif +#if REORGANIZETAGS_PATCH +#include "reorganizetags.h" +#endif +#if RESTARTSIG_PATCH +#include "restartsig.h" +#endif +#if RIODRAW_PATCH +#include "riodraw.h" +#endif +#if ROTATESTACK_PATCH +#include "rotatestack.h" +#endif +#if ROUNDED_CORNERS_PATCH +#include "roundedcorners.h" +#endif +#if RENAMED_SCRATCHPADS_PATCH +#include "renamed_scratchpads.h" +#elif SCRATCHPADS_PATCH +#include "scratchpad.h" +#endif +#if SCRATCHPAD_ALT_1_PATCH +#include "scratchpad_alt_1.h" +#endif +#if SEAMLESS_RESTART_PATCH +#include "seamless_restart.h" +#endif +#if SELFRESTART_PATCH +#include "selfrestart.h" +#endif +#if SETBORDERPX_PATCH +#include "setborderpx.h" +#endif +#if SHIFTBOTH_PATCH || SHIFTSWAPTAGS_PATCH || SHIFTTAG_PATCH || SHIFTTAGCLIENTS_PATCH || SHIFTVIEW_PATCH || SHIFTVIEW_CLIENTS_PATCH +#include "shift.h" +#endif +#if SHIFTBOTH_PATCH +#include "shiftboth.h" +#endif +#if SHIFTSWAPTAGS_PATCH && SWAPTAGS_PATCH +#include "shiftswaptags.h" +#endif +#if SHIFTTAG_PATCH +#include "shifttag.h" +#endif +#if SHIFTTAGCLIENTS_PATCH +#include "shifttagclients.h" +#endif +#if SHIFTVIEW_PATCH +#include "shiftview.h" +#endif +#if SHIFTVIEW_CLIENTS_PATCH +#include "shiftviewclients.h" +#endif +#if SIZEHINTS_RULED_PATCH +#include "sizehints_ruled.h" +#endif +#if SORTSCREENS_PATCH +#ifdef XINERAMA +#include "sortscreens.h" +#endif // XINERAMA +#endif +#if STACKER_PATCH +#include "stacker.h" +#endif +#if STICKY_PATCH +#include "sticky.h" +#endif +#if SWALLOW_PATCH +#include "swallow.h" +#endif +#if SWAPFOCUS_PATCH && PERTAG_PATCH +#include "swapfocus.h" +#endif +#if SWAPTAGS_PATCH +#include "swaptags.h" +#endif +#if SWITCHCOL_PATCH +#include "switchcol.h" +#endif +#if TAB_PATCH +#include "tab.h" +#endif +#if TAGALL_PATCH +#include "tagall.h" +#endif +#if TAGALLMON_PATCH +#include "tagallmon.h" +#endif +#if TAGOTHERMONITOR_PATCH +#include "tagothermonitor.h" +#endif +#if TAGSWAPMON_PATCH +#include "tagswapmon.h" +#endif +#if TAPRESIZE_PATCH +#include "tapresize.h" +#endif +#if TOGGLEFULLSCREEN_PATCH +#include "togglefullscreen.h" +#endif +#if TOGGLETOPBAR_PATCH +#include "toggletopbar.h" +#endif +#if TRANSFER_PATCH +#include "transfer.h" +#endif +#if TRANSFER_ALL_PATCH +#include "transferall.h" +#endif +#if UNFLOATVISIBLE_PATCH +#include "unfloatvisible.h" +#endif +#if VANITYGAPS_PATCH +#include "vanitygaps.h" +#endif +#if WARP_PATCH +#include "warp.h" +#endif +#if WINVIEW_PATCH +#include "winview.h" +#endif +#if ZOOMSWAP_PATCH +#include "zoomswap.h" +#endif +#if XKB_PATCH +#include "xkb.h" +#endif +#if XRESOURCES_PATCH +#include "xresources.h" +#elif XRDB_PATCH +#include "xrdb.h" +#endif +/* Layouts */ +#if BSTACK_LAYOUT +#include "layout_bstack.h" +#endif +#if BSTACKHORIZ_LAYOUT +#include "layout_bstackhoriz.h" +#endif +#if CENTEREDMASTER_LAYOUT +#include "layout_centeredmaster.h" +#endif +#if CENTEREDFLOATINGMASTER_LAYOUT +#include "layout_centeredfloatingmaster.h" +#endif +#if COLUMNS_LAYOUT +#include "layout_columns.h" +#endif +#if DECK_LAYOUT +#include "layout_deck.h" +#endif +#if FIBONACCI_DWINDLE_LAYOUT || FIBONACCI_SPIRAL_LAYOUT +#include "layout_fibonacci.h" +#endif +#if FLEXTILE_DELUXE_LAYOUT +#include "layout_flextile-deluxe.h" +#endif +#if GAPPLESSGRID_LAYOUT +#include "layout_gapplessgrid.h" +#endif +#if GRIDMODE_LAYOUT +#include "layout_grid.h" +#endif +#if HORIZGRID_LAYOUT +#include "layout_horizgrid.h" +#endif +#if MONOCLE_LAYOUT +#include "layout_monocle.h" +#endif +#if NROWGRID_LAYOUT +#include "layout_nrowgrid.h" +#endif +#if TILE_LAYOUT +#include "layout_tile.h" +#endif + diff --git a/dwm/patch/inplacerotate.c b/dwm/patch/inplacerotate.c new file mode 100755 index 0000000..b700e04 --- /dev/null +++ b/dwm/patch/inplacerotate.c @@ -0,0 +1,84 @@ +void +insertclient(Client *item, Client *insertItem, int after) +{ + Client *c; + if (item == NULL || insertItem == NULL || item == insertItem) + return; + detach(insertItem); + if (!after && selmon->clients == item) { + attach(insertItem); + return; + } + if (after) { + c = item; + } else { + for (c = selmon->clients; c; c = c->next) { + if (c->next == item) + break; + } + } + insertItem->next = c->next; + c->next = insertItem; +} + +void +inplacerotate(const Arg *arg) +{ + if (!selmon->sel || (selmon->sel->isfloating && !arg->f)) + return; + + unsigned int selidx = 0, i = 0; + Client *c = NULL, *stail = NULL, *mhead = NULL, *mtail = NULL, *shead = NULL; + + // Determine positionings for insertclient + for (c = selmon->clients; c; c = c->next) { + if (ISVISIBLE(c) && !(c->isfloating)) { + if (selmon->sel == c) + selidx = i; + if (i == selmon->nmaster - 1) + mtail = c; + if (i == selmon->nmaster) + shead = c; + if (mhead == NULL) + mhead = c; + stail = c; + i++; + } + } + + switch(arg->i) { + case 1: + if (selidx >= selmon->nmaster) + insertclient(shead, stail, 0); + else + insertclient(mhead, mtail, 0); + break; + case -1: + if (selidx >= selmon->nmaster) + insertclient(stail, shead, 1); + else + insertclient(mtail, mhead, 1); + break; + case 2: + insertclient(selmon->clients, stail, 0); + break; + case -2: + insertclient(stail, selmon->clients, 1); + break; + } + + // Restore focus position + i = 0; + for (c = selmon->clients; c; c = c->next) { + if (!ISVISIBLE(c) || (c->isfloating)) + continue; + if (i == selidx) { + focus(c); + break; + } + i++; + } + arrange(selmon); + focus(c); +} + diff --git a/dwm/patch/inplacerotate.h b/dwm/patch/inplacerotate.h new file mode 100755 index 0000000..2669375 --- /dev/null +++ b/dwm/patch/inplacerotate.h @@ -0,0 +1,2 @@ +static void inplacerotate(const Arg *arg); + diff --git a/dwm/patch/insets.c b/dwm/patch/insets.c new file mode 100755 index 0000000..8ad99b3 --- /dev/null +++ b/dwm/patch/insets.c @@ -0,0 +1,19 @@ +void +setinset(Monitor *m, Inset inset) +{ + Bar *bar; + m->inset = inset; + updatebarpos(m); + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(m); +} + +void +updateinset(const Arg *arg) +{ + Inset *inset = (Inset *)arg->v; + for (Monitor *m = mons; m; m = m->next) + setinset(m, *inset); +} + diff --git a/dwm/patch/insets.h b/dwm/patch/insets.h new file mode 100755 index 0000000..54635db --- /dev/null +++ b/dwm/patch/insets.h @@ -0,0 +1,3 @@ +static void setinset(Monitor *m, Inset inset); +static void updateinset(const Arg *arg); + diff --git a/dwm/patch/ipc.c b/dwm/patch/ipc.c new file mode 100755 index 0000000..f5ec62c --- /dev/null +++ b/dwm/patch/ipc.c @@ -0,0 +1,111 @@ +static int epoll_fd; +static int dpy_fd; +static Monitor *lastselmon; + +int +handlexevent(struct epoll_event *ev) +{ + if (ev->events & EPOLLIN) { + XEvent ev; + while (running && XPending(dpy)) { + XNextEvent(dpy, &ev); + #if XKB_PATCH + /* Unfortunately the xkbEventType is not constant hence it can't be part of the + * normal event handler below */ + if (ev.type == xkbEventType) { + xkbeventnotify(&ev); + continue; + } + #endif // XKB_PATCH + + if (handler[ev.type]) { + handler[ev.type](&ev); /* call handler */ + ipc_send_events(mons, &lastselmon, selmon); + } + } + } else if (ev-> events & EPOLLHUP) + return -1; + + return 0; +} + +void +setlayoutsafe(const Arg *arg) +{ + const Layout *ltptr = (Layout *)arg->v; + if (ltptr == 0) + setlayout(arg); + for (int i = 0; i < LENGTH(layouts); i++) { + if (ltptr == &layouts[i]) + setlayout(arg); + } +} + +void +setupepoll(void) +{ + epoll_fd = epoll_create1(0); + dpy_fd = ConnectionNumber(dpy); + struct epoll_event dpy_event; + + // Initialize struct to 0 + memset(&dpy_event, 0, sizeof(dpy_event)); + + DEBUG("Display socket is fd %d\n", dpy_fd); + + if (epoll_fd == -1) + fputs("Failed to create epoll file descriptor", stderr); + + dpy_event.events = EPOLLIN; + dpy_event.data.fd = dpy_fd; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, dpy_fd, &dpy_event)) { + fputs("Failed to add display file descriptor to epoll", stderr); + close(epoll_fd); + exit(1); + } + + if (ipc_init(ipcsockpath, epoll_fd, ipccommands, LENGTH(ipccommands)) < 0) + fputs("Failed to initialize IPC\n", stderr); +} + +void +setstatus(const Arg *arg) +{ + Monitor *m; + #if BAR_EXTRASTATUS_PATCH + if (arg->v == NULL) { + strcpy(stext, "dwm-"VERSION); + estext[0] = '\0'; + } else { + strcpy(rawstext, arg->v); + char *e = strchr(rawstext, statussep); + if (e) { + *e = '\0'; e++; + #if BAR_STATUSCMD_PATCH + strncpy(rawestext, e, sizeof(estext) - 1); + copyvalidchars(estext, rawestext); + #else + strncpy(estext, e, sizeof(estext) - 1); + #endif // BAR_STATUSCMD_PATCH + } else { + estext[0] = '\0'; + } + #if BAR_STATUSCMD_PATCH + copyvalidchars(stext, rawstext); + #else + strncpy(stext, rawstext, sizeof(stext) - 1); + #endif // BAR_STATUSCMD_PATCH + } + #elif BAR_STATUSCMD_PATCH + if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) + strcpy(stext, "dwm-"VERSION); + else + copyvalidchars(stext, rawstext); + #else + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + #endif // BAR_EXTRASTATUS_PATCH | BAR_STATUSCMD_PATCH + for (m = mons; m; m = m->next) + drawbar(m); +} + diff --git a/dwm/patch/ipc.h b/dwm/patch/ipc.h new file mode 100755 index 0000000..ac8fb73 --- /dev/null +++ b/dwm/patch/ipc.h @@ -0,0 +1,7 @@ +#include + +static int handlexevent(struct epoll_event *ev); +static void setlayoutsafe(const Arg *arg); +static void setupepoll(void); +static void setstatus(const Arg *arg); + diff --git a/dwm/patch/ipc/IPCClient.c b/dwm/patch/ipc/IPCClient.c new file mode 100755 index 0000000..a157513 --- /dev/null +++ b/dwm/patch/ipc/IPCClient.c @@ -0,0 +1,67 @@ +#include "IPCClient.h" + +#include +#include + +#include "util.h" + +IPCClient * +ipc_client_new(int fd) +{ + IPCClient *c = (IPCClient *)malloc(sizeof(IPCClient)); + + if (c == NULL) return NULL; + + // Initialize struct + memset(&c->event, 0, sizeof(struct epoll_event)); + + c->buffer_size = 0; + c->buffer = NULL; + c->fd = fd; + c->event.data.fd = fd; + c->next = NULL; + c->prev = NULL; + c->subscriptions = 0; + + return c; +} + +void +ipc_list_add_client(IPCClientList *list, IPCClient *nc) +{ + DEBUG("Adding client with fd %d to list\n", nc->fd); + + if (*list == NULL) { + // List is empty, point list at first client + *list = nc; + } else { + IPCClient *c; + // Go to last client in list + for (c = *list; c && c->next; c = c->next) + ; + c->next = nc; + nc->prev = c; + } +} + +void +ipc_list_remove_client(IPCClientList *list, IPCClient *c) +{ + IPCClient *cprev = c->prev; + IPCClient *cnext = c->next; + + if (cprev != NULL) cprev->next = c->next; + if (cnext != NULL) cnext->prev = c->prev; + if (c == *list) *list = c->next; +} + +IPCClient * +ipc_list_get_client(IPCClientList list, int fd) +{ + for (IPCClient *c = list; c; c = c->next) { + if (c->fd == fd) return c; + } + + return NULL; +} + diff --git a/dwm/patch/ipc/IPCClient.h b/dwm/patch/ipc/IPCClient.h new file mode 100755 index 0000000..ee93030 --- /dev/null +++ b/dwm/patch/ipc/IPCClient.h @@ -0,0 +1,62 @@ +#ifndef IPC_CLIENT_H_ +#define IPC_CLIENT_H_ + +#include +#include +#include + +typedef struct IPCClient IPCClient; +/** + * This structure contains the details of an IPC Client and pointers for a + * linked list + */ +struct IPCClient { + int fd; + int subscriptions; + + char *buffer; + uint32_t buffer_size; + + struct epoll_event event; + IPCClient *next; + IPCClient *prev; +}; + +typedef IPCClient *IPCClientList; + +/** + * Allocate memory for new IPCClient with the specified file descriptor and + * initialize struct. + * + * @param fd File descriptor of IPC client + * + * @return Address to allocated IPCClient struct + */ +IPCClient *ipc_client_new(int fd); + +/** + * Add an IPC Client to the specified list + * + * @param list Address of the list to add the client to + * @param nc Address of the IPCClient + */ +void ipc_list_add_client(IPCClientList *list, IPCClient *nc); + +/** + * Remove an IPCClient from the specified list + * + * @param list Address of the list to remove the client from + * @param c Address of the IPCClient + */ +void ipc_list_remove_client(IPCClientList *list, IPCClient *c); + +/** + * Get an IPCClient from the specified IPCClient list + * + * @param list List to remove the client from + * @param fd File descriptor of the IPCClient + */ +IPCClient *ipc_list_get_client(IPCClientList list, int fd); + +#endif // IPC_CLIENT_H_ + diff --git a/dwm/patch/ipc/dwm-msg.c b/dwm/patch/ipc/dwm-msg.c new file mode 100755 index 0000000..ca1e1a4 --- /dev/null +++ b/dwm/patch/ipc/dwm-msg.c @@ -0,0 +1,549 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPC_MAGIC "DWM-IPC" +// clang-format off +#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' } +// clang-format on +#define IPC_MAGIC_LEN 7 // Not including null char + +#define IPC_EVENT_TAG_CHANGE "tag_change_event" +#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event" +#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event" +#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event" +#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event" +#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event" + +#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) +#define YINT(num) yajl_gen_integer(gen, num) +#define YDOUBLE(num) yajl_gen_double(gen, num) +#define YBOOL(v) yajl_gen_bool(gen, v) +#define YNULL() yajl_gen_null(gen) +#define YARR(body) \ + { \ + yajl_gen_array_open(gen); \ + body; \ + yajl_gen_array_close(gen); \ + } +#define YMAP(body) \ + { \ + yajl_gen_map_open(gen); \ + body; \ + yajl_gen_map_close(gen); \ + } + +typedef unsigned long Window; + +const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock"; +static int sock_fd = -1; +static unsigned int ignore_reply = 0; + +typedef enum IPCMessageType { + IPC_TYPE_RUN_COMMAND = 0, + IPC_TYPE_GET_MONITORS = 1, + IPC_TYPE_GET_TAGS = 2, + IPC_TYPE_GET_LAYOUTS = 3, + IPC_TYPE_GET_DWM_CLIENT = 4, + IPC_TYPE_SUBSCRIBE = 5, + IPC_TYPE_EVENT = 6 +} IPCMessageType; + +// Every IPC message must begin with this +typedef struct dwm_ipc_header { + uint8_t magic[IPC_MAGIC_LEN]; + uint32_t size; + uint8_t type; +} __attribute((packed)) dwm_ipc_header_t; + +static int +recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply) +{ + uint32_t read_bytes = 0; + const int32_t to_read = sizeof(dwm_ipc_header_t); + char header[to_read]; + char *walk = header; + + // Try to read header + while (read_bytes < to_read) { + ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes); + + if (n == 0) { + if (read_bytes == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -2; + } else { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -3; + } + } else if (n == -1) { + return -1; + } + + read_bytes += n; + } + + // Check if magic string in header matches + if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) { + fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n", + IPC_MAGIC_LEN, walk, IPC_MAGIC); + return -3; + } + + walk += IPC_MAGIC_LEN; + + // Extract reply size + memcpy(reply_size, walk, sizeof(uint32_t)); + walk += sizeof(uint32_t); + + // Extract message type + memcpy(msg_type, walk, sizeof(uint8_t)); + walk += sizeof(uint8_t); + + (*reply) = malloc(*reply_size); + + // Extract payload + read_bytes = 0; + while (read_bytes < *reply_size) { + ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes); + + if (n == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading payload."); + fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", + read_bytes, *reply_size); + free(*reply); + return -2; + } else if (n == -1) { + if (errno == EINTR || errno == EAGAIN) continue; + free(*reply); + return -1; + } + + read_bytes += n; + } + + return 0; +} + +static int +read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg) +{ + int ret = -1; + + while (ret != 0) { + ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg); + + if (ret < 0) { + // Try again (non-fatal error) + if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue; + + fprintf(stderr, "Error receiving response from socket. "); + fprintf(stderr, "The connection might have been lost.\n"); + exit(2); + } + } + + return 0; +} + +static ssize_t +write_socket(const void *buf, size_t count) +{ + size_t written = 0; + + while (written < count) { + const ssize_t n = + write(sock_fd, ((uint8_t *)buf) + written, count - written); + + if (n == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + else + return n; + } + written += n; + } + return written; +} + +static void +connect_to_socket() +{ + struct sockaddr_un addr; + + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + + // Initialize struct to 0 + memset(&addr, 0, sizeof(struct sockaddr_un)); + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, DEFAULT_SOCKET_PATH); + + connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)); + + sock_fd = sock; +} + +static int +send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg) +{ + dwm_ipc_header_t header = { + .magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type}; + + size_t header_size = sizeof(dwm_ipc_header_t); + size_t total_size = header_size + msg_size; + + uint8_t buffer[total_size]; + + // Copy header to buffer + memcpy(buffer, &header, header_size); + // Copy message to buffer + memcpy(buffer + header_size, msg, header.size); + + write_socket(buffer, total_size); + + return 0; +} + +static int +is_float(const char *s) +{ + size_t len = strlen(s); + int is_dot_used = 0; + int is_minus_used = 0; + + // Floats can only have one decimal point in between or digits + // Optionally, floats can also be below zero (negative) + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) { + is_dot_used = 1; + continue; + } else if (!is_minus_used && s[i] == '-' && i == 0) { + is_minus_used = 1; + continue; + } else + return 0; + } + + return 1; +} + +static int +is_unsigned_int(const char *s) +{ + size_t len = strlen(s); + + // Unsigned int can only have digits + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else + return 0; + } + + return 1; +} + +static int +is_signed_int(const char *s) +{ + size_t len = strlen(s); + + // Signed int can only have digits and a negative sign at the start + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else if (i == 0 && s[i] == '-') { + continue; + } else + return 0; + } + + return 1; +} + +static void +flush_socket_reply() +{ + IPCMessageType reply_type; + uint32_t reply_size; + char *reply; + + read_socket(&reply_type, &reply_size, &reply); + + free(reply); +} + +static void +print_socket_reply() +{ + IPCMessageType reply_type; + uint32_t reply_size; + char *reply; + + read_socket(&reply_type, &reply_size, &reply); + + printf("%.*s\n", reply_size, reply); + fflush(stdout); + free(reply); +} + +static int +run_command(const char *name, char *args[], int argc) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "command": "", + // "args": [ ... ] + // } + // clang-format off + YMAP( + YSTR("command"); YSTR(name); + YSTR("args"); YARR( + for (int i = 0; i < argc; i++) { + if (is_signed_int(args[i])) { + long long num = atoll(args[i]); + YINT(num); + } else if (is_float(args[i])) { + float num = atof(args[i]); + YDOUBLE(num); + } else { + YSTR(args[i]); + } + } + ) + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg); + + if (!ignore_reply) + print_socket_reply(); + else + flush_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static int +get_monitors() +{ + send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)""); + print_socket_reply(); + return 0; +} + +static int +get_tags() +{ + send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)""); + print_socket_reply(); + + return 0; +} + +static int +get_layouts() +{ + send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)""); + print_socket_reply(); + + return 0; +} + +static int +get_dwm_client(Window win) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "client_window_id": "" + // } + // clang-format off + YMAP( + YSTR("client_window_id"); YINT(win); + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg); + + print_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static int +subscribe(const char *event) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "event": "", + // "action": "subscribe" + // } + // clang-format off + YMAP( + YSTR("event"); YSTR(event); + YSTR("action"); YSTR("subscribe"); + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg); + + if (!ignore_reply) + print_socket_reply(); + else + flush_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static void +usage_error(const char *prog_name, const char *format, ...) +{ + va_list args; + va_start(args, format); + + fprintf(stderr, "Error: "); + vfprintf(stderr, format, args); + fprintf(stderr, "\nusage: %s [...]\n", prog_name); + fprintf(stderr, "Try '%s help'\n", prog_name); + + va_end(args); + exit(1); +} + +static void +print_usage(const char *name) +{ + printf("usage: %s [options] [...]\n", name); + puts(""); + puts("Commands:"); + puts(" run_command [args...] Run an IPC command"); + puts(""); + puts(" get_monitors Get monitor properties"); + puts(""); + puts(" get_tags Get list of tags"); + puts(""); + puts(" get_layouts Get list of layouts"); + puts(""); + puts(" get_dwm_client Get dwm client proprties"); + puts(""); + puts(" subscribe [events...] Subscribe to specified events"); + puts(" Options: " IPC_EVENT_TAG_CHANGE ","); + puts(" " IPC_EVENT_LAYOUT_CHANGE ","); + puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ","); + puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ","); + puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ","); + puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE); + puts(""); + puts(" help Display this message"); + puts(""); + puts("Options:"); + puts(" --ignore-reply Don't print reply messages from"); + puts(" run_command and subscribe."); + puts(""); +} + +int +main(int argc, char *argv[]) +{ + const char *prog_name = argv[0]; + + connect_to_socket(); + if (sock_fd == -1) { + fprintf(stderr, "Failed to connect to socket\n"); + return 1; + } + + int i = 1; + if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) { + ignore_reply = 1; + i++; + } + + if (i >= argc) usage_error(prog_name, "Expected an argument, got none"); + + if (!argc || strcmp(argv[i], "help") == 0) + print_usage(prog_name); + else if (strcmp(argv[i], "run_command") == 0) { + if (++i >= argc) usage_error(prog_name, "No command specified"); + // Command name + char *command = argv[i]; + // Command arguments are everything after command name + char **command_args = argv + ++i; + // Number of command arguments + int command_argc = argc - i; + run_command(command, command_args, command_argc); + } else if (strcmp(argv[i], "get_monitors") == 0) { + get_monitors(); + } else if (strcmp(argv[i], "get_tags") == 0) { + get_tags(); + } else if (strcmp(argv[i], "get_layouts") == 0) { + get_layouts(); + } else if (strcmp(argv[i], "get_dwm_client") == 0) { + if (++i < argc) { + if (is_unsigned_int(argv[i])) { + Window win = atol(argv[i]); + get_dwm_client(win); + } else + usage_error(prog_name, "Expected unsigned integer argument"); + } else + usage_error(prog_name, "Expected the window id"); + } else if (strcmp(argv[i], "subscribe") == 0) { + if (++i < argc) { + for (int j = i; j < argc; j++) subscribe(argv[j]); + } else + usage_error(prog_name, "Expected event name"); + // Keep listening for events forever + while (1) { + print_socket_reply(); + } + } else + usage_error(prog_name, "Invalid argument '%s'", argv[i]); + + return 0; +} + diff --git a/dwm/patch/ipc/ipc.c b/dwm/patch/ipc/ipc.c new file mode 100755 index 0000000..eae9667 --- /dev/null +++ b/dwm/patch/ipc/ipc.c @@ -0,0 +1,1202 @@ +#include "ipc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "yajl_dumps.h" + +static struct sockaddr_un sockaddr; +static struct epoll_event sock_epoll_event; +static IPCClientList ipc_clients = NULL; +static int epoll_fd = -1; +static int sock_fd = -1; +static IPCCommand *ipc_commands; +static unsigned int ipc_commands_len; +// Max size is 1 MB +static const uint32_t MAX_MESSAGE_SIZE = 1000000; +static const int IPC_SOCKET_BACKLOG = 5; + +/** + * Create IPC socket at specified path and return file descriptor to socket. + * This initializes the static variable sockaddr. + */ +static int +ipc_create_socket(const char *filename) +{ + char *normal_filename; + char *parent; + const size_t addr_size = sizeof(struct sockaddr_un); + const int sock_type = SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC; + + normalizepath(filename, &normal_filename); + + // In case socket file exists + unlink(normal_filename); + + // For portability clear the addr structure, since some implementations have + // nonstandard fields in the structure + memset(&sockaddr, 0, addr_size); + + parentdir(normal_filename, &parent); + // Create parent directories + mkdirp(parent); + free(parent); + + sockaddr.sun_family = AF_LOCAL; + strcpy(sockaddr.sun_path, normal_filename); + free(normal_filename); + + sock_fd = socket(AF_LOCAL, sock_type, 0); + if (sock_fd == -1) { + fputs("Failed to create socket\n", stderr); + return -1; + } + + DEBUG("Created socket at %s\n", sockaddr.sun_path); + + if (bind(sock_fd, (const struct sockaddr *)&sockaddr, addr_size) == -1) { + fputs("Failed to bind socket\n", stderr); + return -1; + } + + DEBUG("Socket binded\n"); + + if (listen(sock_fd, IPC_SOCKET_BACKLOG) < 0) { + fputs("Failed to listen for connections on socket\n", stderr); + return -1; + } + + DEBUG("Now listening for connections on socket\n"); + + return sock_fd; +} + +/** + * Internal function used to receive IPC messages from a given file descriptor. + * + * Returns -1 on error reading (could be EAGAIN or EINTR) + * Returns -2 if EOF before header could be read + * Returns -3 if invalid IPC header + * Returns -4 if message length exceeds MAX_MESSAGE_SIZE + */ +static int +ipc_recv_message(int fd, uint8_t *msg_type, uint32_t *reply_size, + uint8_t **reply) +{ + uint32_t read_bytes = 0; + const int32_t to_read = sizeof(dwm_ipc_header_t); + char header[to_read]; + char *walk = header; + + // Try to read header + while (read_bytes < to_read) { + const ssize_t n = read(fd, header + read_bytes, to_read - read_bytes); + + if (n == 0) { + if (read_bytes == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -2; + } else { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -3; + } + } else if (n == -1) { + // errno will still be set + return -1; + } + + read_bytes += n; + } + + // Check if magic string in header matches + if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) { + fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n", + IPC_MAGIC_LEN, walk, IPC_MAGIC); + return -3; + } + + walk += IPC_MAGIC_LEN; + + // Extract reply size + memcpy(reply_size, walk, sizeof(uint32_t)); + walk += sizeof(uint32_t); + + if (*reply_size > MAX_MESSAGE_SIZE) { + fprintf(stderr, "Message too long: %" PRIu32 " bytes. ", *reply_size); + fprintf(stderr, "Maximum message size is: %d\n", MAX_MESSAGE_SIZE); + return -4; + } + + // Extract message type + memcpy(msg_type, walk, sizeof(uint8_t)); + walk += sizeof(uint8_t); + + if (*reply_size > 0) + (*reply) = malloc(*reply_size); + else + return 0; + + read_bytes = 0; + while (read_bytes < *reply_size) { + const ssize_t n = read(fd, *reply + read_bytes, *reply_size - read_bytes); + + if (n == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading payload."); + fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", + read_bytes, *reply_size); + free(*reply); + return -2; + } else if (n == -1) { + // TODO: Should we return and wait for another epoll event? + // This would require saving the partial read in some way. + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) continue; + + free(*reply); + return -1; + } + + read_bytes += n; + } + + return 0; +} + +/** + * Internal function used to write a buffer to a file descriptor + * + * Returns number of bytes written if successful write + * Returns 0 if no bytes were written due to EAGAIN or EWOULDBLOCK + * Returns -1 on unknown error trying to write, errno will carry over from + * write() call + */ +static ssize_t +ipc_write_message(int fd, const void *buf, size_t count) +{ + size_t written = 0; + + while (written < count) { + const ssize_t n = write(fd, (uint8_t *)buf + written, count - written); + + if (n == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + return written; + else if (errno == EINTR) + continue; + else + return n; + } + + written += n; + DEBUG("Wrote %zu/%zu to client at fd %d\n", written, count, fd); + } + + return written; +} + +/** + * Initialization for generic event message. This is used to allocate the yajl + * handle, set yajl options, and in the future any other initialization that + * should occur for event messages. + */ +static void +ipc_event_init_message(yajl_gen *gen) +{ + *gen = yajl_gen_alloc(NULL); + yajl_gen_config(*gen, yajl_gen_beautify, 1); +} + +/** + * Prepares buffers of IPC subscribers of specified event using buffer from yajl + * handle. + */ +static void +ipc_event_prepare_send_message(yajl_gen gen, IPCEvent event) +{ + const unsigned char *buffer; + size_t len = 0; + + yajl_gen_get_buf(gen, &buffer, &len); + len++; // For null char + + for (IPCClient *c = ipc_clients; c; c = c->next) { + if (c->subscriptions & event) { + DEBUG("Sending selected client change event to fd %d\n", c->fd); + ipc_prepare_send_message(c, IPC_TYPE_EVENT, len, (char *)buffer); + } + } + + // Not documented, but this frees temp_buffer + yajl_gen_free(gen); +} + +/** + * Initialization for generic reply message. This is used to allocate the yajl + * handle, set yajl options, and in the future any other initialization that + * should occur for reply messages. + */ +static void +ipc_reply_init_message(yajl_gen *gen) +{ + *gen = yajl_gen_alloc(NULL); + yajl_gen_config(*gen, yajl_gen_beautify, 1); +} + +/** + * Prepares the IPC client's buffer with a message using the buffer of the yajl + * handle. + */ +static void +ipc_reply_prepare_send_message(yajl_gen gen, IPCClient *c, + IPCMessageType msg_type) +{ + const unsigned char *buffer; + size_t len = 0; + + yajl_gen_get_buf(gen, &buffer, &len); + len++; // For null char + + ipc_prepare_send_message(c, msg_type, len, (const char *)buffer); + + // Not documented, but this frees temp_buffer + yajl_gen_free(gen); +} + +/** + * Find the IPCCommand with the specified name + * + * Returns 0 if a command with the specified name was found + * Returns -1 if a command with the specified name could not be found + */ +static int +ipc_get_ipc_command(const char *name, IPCCommand *ipc_command) +{ + for (int i = 0; i < ipc_commands_len; i++) { + if (strcmp(ipc_commands[i].name, name) == 0) { + *ipc_command = ipc_commands[i]; + return 0; + } + } + + return -1; +} + +/** + * Parse a IPC_TYPE_RUN_COMMAND message from a client. This function extracts + * the arguments, argument count, argument types, and command name and returns + * the parsed information as an IPCParsedCommand. If this function returns + * successfully, the parsed_command must be freed using + * ipc_free_parsed_command_members. + * + * Returns 0 if the message was successfully parsed + * Returns -1 otherwise + */ +static int +ipc_parse_run_command(char *msg, IPCParsedCommand *parsed_command) +{ + char error_buffer[1000]; + yajl_val parent = yajl_tree_parse(msg, error_buffer, 1000); + + if (parent == NULL) { + fputs("Failed to parse command from client\n", stderr); + fprintf(stderr, "%s\n", error_buffer); + fprintf(stderr, "Tried to parse: %s\n", msg); + return -1; + } + + // Format: + // { + // "command": "" + // "args": [ "arg1", "arg2", ... ] + // } + const char *command_path[] = {"command", 0}; + yajl_val command_val = yajl_tree_get(parent, command_path, yajl_t_string); + + if (command_val == NULL) { + fputs("No command key found in client message\n", stderr); + yajl_tree_free(parent); + return -1; + } + + const char *command_name = YAJL_GET_STRING(command_val); + size_t command_name_len = strlen(command_name); + parsed_command->name = (char *)malloc((command_name_len + 1) * sizeof(char)); + strcpy(parsed_command->name, command_name); + + DEBUG("Received command: %s\n", parsed_command->name); + + const char *args_path[] = {"args", 0}; + yajl_val args_val = yajl_tree_get(parent, args_path, yajl_t_array); + + if (args_val == NULL) { + fputs("No args key found in client message\n", stderr); + yajl_tree_free(parent); + return -1; + } + + unsigned int *argc = &parsed_command->argc; + Arg **args = &parsed_command->args; + ArgType **arg_types = &parsed_command->arg_types; + + *argc = args_val->u.array.len; + + // If no arguments are specified, make a dummy argument to pass to the + // function. This is just the way dwm's void(Arg*) functions are setup. + if (*argc == 0) { + *args = (Arg *)malloc(sizeof(Arg)); + *arg_types = (ArgType *)malloc(sizeof(ArgType)); + (*arg_types)[0] = ARG_TYPE_NONE; + (*args)[0].f = 0; + (*argc)++; + } else if (*argc > 0) { + *args = (Arg *)calloc(*argc, sizeof(Arg)); + *arg_types = (ArgType *)malloc(*argc * sizeof(ArgType)); + + for (int i = 0; i < *argc; i++) { + yajl_val arg_val = args_val->u.array.values[i]; + + if (YAJL_IS_NUMBER(arg_val)) { + if (YAJL_IS_INTEGER(arg_val)) { + // Any values below 0 must be a signed int + if (YAJL_GET_INTEGER(arg_val) < 0) { + (*args)[i].i = YAJL_GET_INTEGER(arg_val); + (*arg_types)[i] = ARG_TYPE_SINT; + DEBUG("i=%ld\n", (*args)[i].i); + // Any values above 0 should be an unsigned int + } else if (YAJL_GET_INTEGER(arg_val) >= 0) { + (*args)[i].ui = YAJL_GET_INTEGER(arg_val); + (*arg_types)[i] = ARG_TYPE_UINT; + DEBUG("ui=%ld\n", (*args)[i].i); + } + // If the number is not an integer, it must be a float + } else { + (*args)[i].f = (float)YAJL_GET_DOUBLE(arg_val); + (*arg_types)[i] = ARG_TYPE_FLOAT; + DEBUG("f=%f\n", (*args)[i].f); + // If argument is not a number, it must be a string + } + } else if (YAJL_IS_STRING(arg_val)) { + char *arg_s = YAJL_GET_STRING(arg_val); + size_t arg_s_size = (strlen(arg_s) + 1) * sizeof(char); + (*args)[i].v = (char *)malloc(arg_s_size); + (*arg_types)[i] = ARG_TYPE_STR; + strcpy((char *)(*args)[i].v, arg_s); + } + } + } + + yajl_tree_free(parent); + + return 0; +} + +/** + * Free the members of a IPCParsedCommand struct + */ +static void +ipc_free_parsed_command_members(IPCParsedCommand *command) +{ + for (int i = 0; i < command->argc; i++) { + if (command->arg_types[i] == ARG_TYPE_STR) free((void *)command->args[i].v); + } + free(command->args); + free(command->arg_types); + free(command->name); +} + +/** + * Check if the given arguments are the correct length and type. Also do any + * casting to correct the types. + * + * Returns 0 if the arguments were the correct length and types + * Returns -1 if the argument count doesn't match + * Returns -2 if the argument types don't match + */ +static int +ipc_validate_run_command(IPCParsedCommand *parsed, const IPCCommand actual) +{ + if (actual.argc != parsed->argc) return -1; + + for (int i = 0; i < parsed->argc; i++) { + ArgType ptype = parsed->arg_types[i]; + ArgType atype = actual.arg_types[i]; + + if (ptype != atype) { + if (ptype == ARG_TYPE_UINT && atype == ARG_TYPE_PTR) + // If this argument is supposed to be a void pointer, cast it + parsed->args[i].v = (void *)parsed->args[i].ui; + else if (ptype == ARG_TYPE_UINT && atype == ARG_TYPE_SINT) + // If this argument is supposed to be a signed int, cast it + parsed->args[i].i = parsed->args[i].ui; + else + return -2; + } + } + + return 0; +} + +/** + * Convert event name to their IPCEvent equivalent enum value + * + * Returns 0 if a valid event name was given + * Returns -1 otherwise + */ +static int +ipc_event_stoi(const char *subscription, IPCEvent *event) +{ + if (strcmp(subscription, "tag_change_event") == 0) + *event = IPC_EVENT_TAG_CHANGE; + else if (strcmp(subscription, "client_focus_change_event") == 0) + *event = IPC_EVENT_CLIENT_FOCUS_CHANGE; + else if (strcmp(subscription, "layout_change_event") == 0) + *event = IPC_EVENT_LAYOUT_CHANGE; + else if (strcmp(subscription, "monitor_focus_change_event") == 0) + *event = IPC_EVENT_MONITOR_FOCUS_CHANGE; + else if (strcmp(subscription, "focused_title_change_event") == 0) + *event = IPC_EVENT_FOCUSED_TITLE_CHANGE; + else if (strcmp(subscription, "focused_state_change_event") == 0) + *event = IPC_EVENT_FOCUSED_STATE_CHANGE; + else + return -1; + return 0; +} + +/** + * Parse a IPC_TYPE_SUBSCRIBE message from a client. This function extracts the + * event name and the subscription action from the message. + * + * Returns 0 if message was successfully parsed + * Returns -1 otherwise + */ +static int +ipc_parse_subscribe(const char *msg, IPCSubscriptionAction *subscribe, + IPCEvent *event) +{ + char error_buffer[100]; + yajl_val parent = yajl_tree_parse((char *)msg, error_buffer, 100); + + if (parent == NULL) { + fputs("Failed to parse command from client\n", stderr); + fprintf(stderr, "%s\n", error_buffer); + return -1; + } + + // Format: + // { + // "event": "" + // "action": "" + // } + const char *event_path[] = {"event", 0}; + yajl_val event_val = yajl_tree_get(parent, event_path, yajl_t_string); + + if (event_val == NULL) { + fputs("No 'event' key found in client message\n", stderr); + return -1; + } + + const char *event_str = YAJL_GET_STRING(event_val); + DEBUG("Received event: %s\n", event_str); + + if (ipc_event_stoi(event_str, event) < 0) return -1; + + const char *action_path[] = {"action", 0}; + yajl_val action_val = yajl_tree_get(parent, action_path, yajl_t_string); + + if (action_val == NULL) { + fputs("No 'action' key found in client message\n", stderr); + return -1; + } + + const char *action = YAJL_GET_STRING(action_val); + + if (strcmp(action, "subscribe") == 0) + *subscribe = IPC_ACTION_SUBSCRIBE; + else if (strcmp(action, "unsubscribe") == 0) + *subscribe = IPC_ACTION_UNSUBSCRIBE; + else { + fputs("Invalid action specified for subscription\n", stderr); + return -1; + } + + yajl_tree_free(parent); + + return 0; +} + +/** + * Parse an IPC_TYPE_GET_DWM_CLIENT message from a client. This function + * extracts the window id from the message. + * + * Returns 0 if message was successfully parsed + * Returns -1 otherwise + */ +static int +ipc_parse_get_dwm_client(const char *msg, Window *win) +{ + char error_buffer[100]; + + yajl_val parent = yajl_tree_parse(msg, error_buffer, 100); + + if (parent == NULL) { + fputs("Failed to parse message from client\n", stderr); + fprintf(stderr, "%s\n", error_buffer); + return -1; + } + + // Format: + // { + // "client_window_id": + // } + const char *win_path[] = {"client_window_id", 0}; + yajl_val win_val = yajl_tree_get(parent, win_path, yajl_t_number); + + if (win_val == NULL) { + fputs("No client window id found in client message\n", stderr); + return -1; + } + + *win = YAJL_GET_INTEGER(win_val); + + yajl_tree_free(parent); + + return 0; +} + +/** + * Called when an IPC_TYPE_RUN_COMMAND message is received from a client. This + * function parses, executes the given command, and prepares a reply message to + * the client indicating success/failure. + * + * NOTE: There is currently no check for argument validity beyond the number of + * arguments given and types of arguments. There is also no way to check if the + * function succeeded based on dwm's void(const Arg*) function types. Pointer + * arguments can cause crashes if they are not validated in the function itself. + * + * Returns 0 if message was successfully parsed + * Returns -1 on failure parsing message + */ +static int +ipc_run_command(IPCClient *ipc_client, char *msg) +{ + IPCParsedCommand parsed_command; + IPCCommand ipc_command; + + // Initialize struct + memset(&parsed_command, 0, sizeof(IPCParsedCommand)); + + if (ipc_parse_run_command(msg, &parsed_command) < 0) { + ipc_prepare_reply_failure(ipc_client, IPC_TYPE_RUN_COMMAND, + "Failed to parse run command"); + return -1; + } + + if (ipc_get_ipc_command(parsed_command.name, &ipc_command) < 0) { + ipc_prepare_reply_failure(ipc_client, IPC_TYPE_RUN_COMMAND, + "Command %s not found", parsed_command.name); + ipc_free_parsed_command_members(&parsed_command); + return -1; + } + + int res = ipc_validate_run_command(&parsed_command, ipc_command); + if (res < 0) { + if (res == -1) + ipc_prepare_reply_failure(ipc_client, IPC_TYPE_RUN_COMMAND, + "%u arguments provided, %u expected", + parsed_command.argc, ipc_command.argc); + else if (res == -2) + ipc_prepare_reply_failure(ipc_client, IPC_TYPE_RUN_COMMAND, + "Type mismatch"); + ipc_free_parsed_command_members(&parsed_command); + return -1; + } + + if (parsed_command.argc == 1) + ipc_command.func.single_param(parsed_command.args); + else if (parsed_command.argc > 1) + ipc_command.func.array_param(parsed_command.args, parsed_command.argc); + + DEBUG("Called function for command %s\n", parsed_command.name); + + ipc_free_parsed_command_members(&parsed_command); + + ipc_prepare_reply_success(ipc_client, IPC_TYPE_RUN_COMMAND); + return 0; +} + +/** + * Called when an IPC_TYPE_GET_MONITORS message is received from a client. It + * prepares a reply with the properties of all of the monitors in JSON. + */ +static void +ipc_get_monitors(IPCClient *c, Monitor *mons, Monitor *selmon) +{ + yajl_gen gen; + ipc_reply_init_message(&gen); + dump_monitors(gen, mons, selmon); + + ipc_reply_prepare_send_message(gen, c, IPC_TYPE_GET_MONITORS); +} + +/** + * Called when an IPC_TYPE_GET_TAGS message is received from a client. It + * prepares a reply with info about all the tags in JSON. + */ +static void +ipc_get_tags(IPCClient *c, const int tags_len) +{ + yajl_gen gen; + ipc_reply_init_message(&gen); + + dump_tags(gen, tags_len); + + ipc_reply_prepare_send_message(gen, c, IPC_TYPE_GET_TAGS); +} + +/** + * Called when an IPC_TYPE_GET_LAYOUTS message is received from a client. It + * prepares a reply with a JSON array of available layouts + */ +static void +ipc_get_layouts(IPCClient *c, const Layout layouts[], const int layouts_len) +{ + yajl_gen gen; + ipc_reply_init_message(&gen); + + dump_layouts(gen, layouts, layouts_len); + + ipc_reply_prepare_send_message(gen, c, IPC_TYPE_GET_LAYOUTS); +} + +/** + * Called when an IPC_TYPE_GET_DWM_CLIENT message is received from a client. It + * prepares a JSON reply with the properties of the client with the specified + * window XID. + * + * Returns 0 if the message was successfully parsed and if the client with the + * specified window XID was found + * Returns -1 if the message could not be parsed + */ +static int +ipc_get_dwm_client(IPCClient *ipc_client, const char *msg, const Monitor *mons) +{ + Window win; + + if (ipc_parse_get_dwm_client(msg, &win) < 0) return -1; + + // Find client with specified window XID + for (const Monitor *m = mons; m; m = m->next) + for (Client *c = m->clients; c; c = c->next) + if (c->win == win) { + yajl_gen gen; + ipc_reply_init_message(&gen); + + dump_client(gen, c); + + ipc_reply_prepare_send_message(gen, ipc_client, + IPC_TYPE_GET_DWM_CLIENT); + + return 0; + } + + ipc_prepare_reply_failure(ipc_client, IPC_TYPE_GET_DWM_CLIENT, + "Client with window id %d not found", win); + return -1; +} + +/** + * Called when an IPC_TYPE_SUBSCRIBE message is received from a client. It + * subscribes/unsubscribes the client from the specified event and replies with + * the result. + * + * Returns 0 if the message was successfully parsed. + * Returns -1 if the message could not be parsed + */ +static int +ipc_subscribe(IPCClient *c, const char *msg) +{ + IPCSubscriptionAction action = IPC_ACTION_SUBSCRIBE; + IPCEvent event = 0; + + if (ipc_parse_subscribe(msg, &action, &event)) { + ipc_prepare_reply_failure(c, IPC_TYPE_SUBSCRIBE, "Event does not exist"); + return -1; + } + + if (action == IPC_ACTION_SUBSCRIBE) { + DEBUG("Subscribing client on fd %d to %d\n", c->fd, event); + c->subscriptions |= event; + } else if (action == IPC_ACTION_UNSUBSCRIBE) { + DEBUG("Unsubscribing client on fd %d to %d\n", c->fd, event); + c->subscriptions ^= event; + } else { + ipc_prepare_reply_failure(c, IPC_TYPE_SUBSCRIBE, + "Invalid subscription action"); + return -1; + } + + ipc_prepare_reply_success(c, IPC_TYPE_SUBSCRIBE); + return 0; +} + +int +ipc_init(const char *socket_path, const int p_epoll_fd, IPCCommand commands[], + const int commands_len) +{ + // Initialize struct to 0 + memset(&sock_epoll_event, 0, sizeof(sock_epoll_event)); + + int socket_fd = ipc_create_socket(socket_path); + if (socket_fd < 0) return -1; + + ipc_commands = commands; + ipc_commands_len = commands_len; + + epoll_fd = p_epoll_fd; + + // Wake up to incoming connection requests + sock_epoll_event.data.fd = socket_fd; + sock_epoll_event.events = EPOLLIN; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &sock_epoll_event)) { + fputs("Failed to add sock file descriptor to epoll", stderr); + return -1; + } + + return socket_fd; +} + +void +ipc_cleanup() +{ + IPCClient *c = ipc_clients; + // Free clients and their buffers + while (c) { + ipc_drop_client(c); + c = ipc_clients; + } + + // Stop waking up for socket events + epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sock_fd, &sock_epoll_event); + + // Uninitialize all static variables + epoll_fd = -1; + sock_fd = -1; + ipc_commands = NULL; + ipc_commands_len = 0; + memset(&sock_epoll_event, 0, sizeof(struct epoll_event)); + memset(&sockaddr, 0, sizeof(struct sockaddr_un)); + + // Delete socket + unlink(sockaddr.sun_path); + + shutdown(sock_fd, SHUT_RDWR); + close(sock_fd); +} + +int +ipc_get_sock_fd() +{ + return sock_fd; +} + +IPCClient * +ipc_get_client(int fd) +{ + return ipc_list_get_client(ipc_clients, fd); +} + +int +ipc_is_client_registered(int fd) +{ + return (ipc_get_client(fd) != NULL); +} + +int +ipc_accept_client() +{ + int fd = -1; + + struct sockaddr_un client_addr; + socklen_t len = 0; + + // For portability clear the addr structure, since some implementations + // have nonstandard fields in the structure + memset(&client_addr, 0, sizeof(struct sockaddr_un)); + + fd = accept(sock_fd, (struct sockaddr *)&client_addr, &len); + if (fd < 0 && errno != EINTR) { + fputs("Failed to accept IPC connection from client", stderr); + return -1; + } + + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { + shutdown(fd, SHUT_RDWR); + close(fd); + fputs("Failed to set flags on new client fd", stderr); + } + + IPCClient *nc = ipc_client_new(fd); + if (nc == NULL) return -1; + + // Wake up to messages from this client + nc->event.data.fd = fd; + nc->event.events = EPOLLIN | EPOLLHUP; + epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &nc->event); + + ipc_list_add_client(&ipc_clients, nc); + + DEBUG("%s%d\n", "New client at fd: ", fd); + + return fd; +} + +int +ipc_drop_client(IPCClient *c) +{ + int fd = c->fd; + shutdown(fd, SHUT_RDWR); + int res = close(fd); + + if (res == 0) { + struct epoll_event ev; + + // Stop waking up to messages from this client + epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ev); + ipc_list_remove_client(&ipc_clients, c); + + free(c->buffer); + free(c); + + DEBUG("Successfully removed client on fd %d\n", fd); + } else if (res < 0 && res != EINTR) { + fprintf(stderr, "Failed to close fd %d\n", fd); + } + + return res; +} + +int +ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size, + char **msg) +{ + int fd = c->fd; + int ret = + ipc_recv_message(fd, (uint8_t *)msg_type, msg_size, (uint8_t **)msg); + + if (ret < 0) { + // This will happen if these errors occur while reading header + if (ret == -1 && + (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) + return -2; + + fprintf(stderr, "Error reading message: dropping client at fd %d\n", fd); + ipc_drop_client(c); + + return -1; + } + + // Make sure receive message is null terminated to avoid parsing issues + if (*msg_size > 0) { + size_t len = *msg_size; + nullterminate(msg, &len); + *msg_size = len; + } + + DEBUG("[fd %d] ", fd); + if (*msg_size > 0) + DEBUG("Received message: '%.*s' ", *msg_size, *msg); + else + DEBUG("Received empty message "); + DEBUG("Message type: %" PRIu8 " ", (uint8_t)*msg_type); + DEBUG("Message size: %" PRIu32 "\n", *msg_size); + + return 0; +} + +ssize_t +ipc_write_client(IPCClient *c) +{ + const ssize_t n = ipc_write_message(c->fd, c->buffer, c->buffer_size); + + if (n < 0) return n; + + // TODO: Deal with client timeouts + + if (n == c->buffer_size) { + c->buffer_size = 0; + free(c->buffer); + // No dangling pointers! + c->buffer = NULL; + // Stop waking up when client is ready to receive messages + if (c->event.events & EPOLLOUT) { + c->event.events -= EPOLLOUT; + epoll_ctl(epoll_fd, EPOLL_CTL_MOD, c->fd, &c->event); + } + return n; + } + + // Shift unwritten buffer to beginning of buffer and reallocate + c->buffer_size -= n; + memmove(c->buffer, c->buffer + n, c->buffer_size); + c->buffer = (char *)realloc(c->buffer, c->buffer_size); + + return n; +} + +void +ipc_prepare_send_message(IPCClient *c, const IPCMessageType msg_type, + const uint32_t msg_size, const char *msg) +{ + dwm_ipc_header_t header = { + .magic = IPC_MAGIC_ARR, .type = msg_type, .size = msg_size}; + + uint32_t header_size = sizeof(dwm_ipc_header_t); + uint32_t packet_size = header_size + msg_size; + + if (c->buffer == NULL) + c->buffer = (char *)malloc(c->buffer_size + packet_size); + else + c->buffer = (char *)realloc(c->buffer, c->buffer_size + packet_size); + + // Copy header to end of client buffer + memcpy(c->buffer + c->buffer_size, &header, header_size); + c->buffer_size += header_size; + + // Copy message to end of client buffer + memcpy(c->buffer + c->buffer_size, msg, msg_size); + c->buffer_size += msg_size; + + // Wake up when client is ready to receive messages + c->event.events |= EPOLLOUT; + epoll_ctl(epoll_fd, EPOLL_CTL_MOD, c->fd, &c->event); +} + +void +ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type, + const char *format, ...) +{ + yajl_gen gen; + va_list args; + + // Get output size + va_start(args, format); + size_t len = vsnprintf(NULL, 0, format, args); + va_end(args); + char *buffer = (char *)malloc((len + 1) * sizeof(char)); + + ipc_reply_init_message(&gen); + + va_start(args, format); + vsnprintf(buffer, len + 1, format, args); + va_end(args); + dump_error_message(gen, buffer); + + ipc_reply_prepare_send_message(gen, c, msg_type); + fprintf(stderr, "[fd %d] Error: %s\n", c->fd, buffer); + + free(buffer); +} + +void +ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type) +{ + const char *success_msg = "{\"result\":\"success\"}"; + const size_t msg_len = strlen(success_msg) + 1; // +1 for null char + + ipc_prepare_send_message(c, msg_type, msg_len, success_msg); +} + +void +ipc_tag_change_event(int mon_num, TagState old_state, TagState new_state) +{ + yajl_gen gen; + ipc_event_init_message(&gen); + dump_tag_event(gen, mon_num, old_state, new_state); + ipc_event_prepare_send_message(gen, IPC_EVENT_TAG_CHANGE); +} + +void +ipc_client_focus_change_event(int mon_num, Client *old_client, + Client *new_client) +{ + yajl_gen gen; + ipc_event_init_message(&gen); + dump_client_focus_change_event(gen, old_client, new_client, mon_num); + ipc_event_prepare_send_message(gen, IPC_EVENT_CLIENT_FOCUS_CHANGE); +} + +void +ipc_layout_change_event(const int mon_num, const char *old_symbol, + const Layout *old_layout, const char *new_symbol, + const Layout *new_layout) +{ + yajl_gen gen; + ipc_event_init_message(&gen); + dump_layout_change_event(gen, mon_num, old_symbol, old_layout, new_symbol, + new_layout); + ipc_event_prepare_send_message(gen, IPC_EVENT_LAYOUT_CHANGE); +} + +void +ipc_monitor_focus_change_event(const int last_mon_num, const int new_mon_num) +{ + yajl_gen gen; + ipc_event_init_message(&gen); + dump_monitor_focus_change_event(gen, last_mon_num, new_mon_num); + ipc_event_prepare_send_message(gen, IPC_EVENT_MONITOR_FOCUS_CHANGE); +} + +void +ipc_focused_title_change_event(const int mon_num, const Window client_id, + const char *old_name, const char *new_name) +{ + yajl_gen gen; + ipc_event_init_message(&gen); + dump_focused_title_change_event(gen, mon_num, client_id, old_name, new_name); + ipc_event_prepare_send_message(gen, IPC_EVENT_FOCUSED_TITLE_CHANGE); +} + +void +ipc_focused_state_change_event(const int mon_num, const Window client_id, + const ClientState *old_state, + const ClientState *new_state) +{ + yajl_gen gen; + ipc_event_init_message(&gen); + dump_focused_state_change_event(gen, mon_num, client_id, old_state, + new_state); + ipc_event_prepare_send_message(gen, IPC_EVENT_FOCUSED_STATE_CHANGE); +} + +void +ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon) +{ + for (Monitor *m = mons; m; m = m->next) { + unsigned int urg = 0, occ = 0, tagset = 0; + + for (Client *c = m->clients; c; c = c->next) { + occ |= c->tags; + + if (c->isurgent) urg |= c->tags; + } + tagset = m->tagset[m->seltags]; + + TagState new_state = {.selected = tagset, .occupied = occ, .urgent = urg}; + + if (memcmp(&m->tagstate, &new_state, sizeof(TagState)) != 0) { + ipc_tag_change_event(m->num, m->tagstate, new_state); + m->tagstate = new_state; + } + + if (m->lastsel != m->sel) { + ipc_client_focus_change_event(m->num, m->lastsel, m->sel); + m->lastsel = m->sel; + } + + if (strcmp(m->ltsymbol, m->lastltsymbol) != 0 || + m->lastlt != m->lt[m->sellt]) { + ipc_layout_change_event(m->num, m->lastltsymbol, m->lastlt, m->ltsymbol, + m->lt[m->sellt]); + strcpy(m->lastltsymbol, m->ltsymbol); + m->lastlt = m->lt[m->sellt]; + } + + if (*lastselmon != selmon) { + if (*lastselmon != NULL) + ipc_monitor_focus_change_event((*lastselmon)->num, selmon->num); + *lastselmon = selmon; + } + + Client *sel = m->sel; + if (!sel) continue; + ClientState *o = &m->sel->prevstate; + ClientState n = {.oldstate = sel->oldstate, + .isfixed = sel->isfixed, + .isfloating = sel->isfloating, + .isfullscreen = sel->isfullscreen, + .isurgent = sel->isurgent, + .neverfocus = sel->neverfocus}; + if (memcmp(o, &n, sizeof(ClientState)) != 0) { + ipc_focused_state_change_event(m->num, m->sel->win, o, &n); + *o = n; + } + } +} + +int +ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons, + Monitor **lastselmon, Monitor *selmon, const int tags_len, + const Layout *layouts, const int layouts_len) +{ + int fd = ev->data.fd; + IPCClient *c = ipc_get_client(fd); + + if (ev->events & EPOLLHUP) { + DEBUG("EPOLLHUP received from client at fd %d\n", fd); + ipc_drop_client(c); + } else if (ev->events & EPOLLOUT) { + DEBUG("Sending message to client at fd %d...\n", fd); + if (c->buffer_size) ipc_write_client(c); + } else if (ev->events & EPOLLIN) { + IPCMessageType msg_type = 0; + uint32_t msg_size = 0; + char *msg = NULL; + + DEBUG("Received message from fd %d\n", fd); + if (ipc_read_client(c, &msg_type, &msg_size, &msg) < 0) return -1; + + if (msg_type == IPC_TYPE_GET_MONITORS) + ipc_get_monitors(c, mons, selmon); + else if (msg_type == IPC_TYPE_GET_TAGS) + ipc_get_tags(c, tags_len); + else if (msg_type == IPC_TYPE_GET_LAYOUTS) + ipc_get_layouts(c, layouts, layouts_len); + else if (msg_type == IPC_TYPE_RUN_COMMAND) { + if (ipc_run_command(c, msg) < 0) return -1; + ipc_send_events(mons, lastselmon, selmon); + } else if (msg_type == IPC_TYPE_GET_DWM_CLIENT) { + if (ipc_get_dwm_client(c, msg, mons) < 0) return -1; + } else if (msg_type == IPC_TYPE_SUBSCRIBE) { + if (ipc_subscribe(c, msg) < 0) return -1; + } else { + fprintf(stderr, "Invalid message type received from fd %d", fd); + ipc_prepare_reply_failure(c, msg_type, "Invalid message type: %d", + msg_type); + } + free(msg); + } else { + fprintf(stderr, "Epoll event returned %d from fd %d\n", ev->events, fd); + return -1; + } + + return 0; +} + +int +ipc_handle_socket_epoll_event(struct epoll_event *ev) +{ + if (!(ev->events & EPOLLIN)) return -1; + + // EPOLLIN means incoming client connection request + fputs("Received EPOLLIN event on socket\n", stderr); + int new_fd = ipc_accept_client(); + + return new_fd; +} + diff --git a/dwm/patch/ipc/ipc.h b/dwm/patch/ipc/ipc.h new file mode 100755 index 0000000..4a72fb8 --- /dev/null +++ b/dwm/patch/ipc/ipc.h @@ -0,0 +1,320 @@ +#ifndef IPC_H_ +#define IPC_H_ + +#include +#include +#include + +#include "IPCClient.h" + +// clang-format off +#define IPC_MAGIC "DWM-IPC" +#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C'} +#define IPC_MAGIC_LEN 7 // Not including null char + +#define IPCCOMMAND(FUNC, ARGC, TYPES) \ + { #FUNC, {FUNC }, ARGC, (ArgType[ARGC])TYPES } +// clang-format on + +typedef enum IPCMessageType { + IPC_TYPE_RUN_COMMAND = 0, + IPC_TYPE_GET_MONITORS = 1, + IPC_TYPE_GET_TAGS = 2, + IPC_TYPE_GET_LAYOUTS = 3, + IPC_TYPE_GET_DWM_CLIENT = 4, + IPC_TYPE_SUBSCRIBE = 5, + IPC_TYPE_EVENT = 6 +} IPCMessageType; + +typedef enum IPCEvent { + IPC_EVENT_TAG_CHANGE = 1 << 0, + IPC_EVENT_CLIENT_FOCUS_CHANGE = 1 << 1, + IPC_EVENT_LAYOUT_CHANGE = 1 << 2, + IPC_EVENT_MONITOR_FOCUS_CHANGE = 1 << 3, + IPC_EVENT_FOCUSED_TITLE_CHANGE = 1 << 4, + IPC_EVENT_FOCUSED_STATE_CHANGE = 1 << 5 +} IPCEvent; + +typedef enum IPCSubscriptionAction { + IPC_ACTION_UNSUBSCRIBE = 0, + IPC_ACTION_SUBSCRIBE = 1 +} IPCSubscriptionAction; + +/** + * Every IPC packet starts with this structure + */ +typedef struct dwm_ipc_header { + uint8_t magic[IPC_MAGIC_LEN]; + uint32_t size; + uint8_t type; +} __attribute((packed)) dwm_ipc_header_t; + +typedef enum ArgType { + ARG_TYPE_NONE = 0, + ARG_TYPE_UINT = 1, + ARG_TYPE_SINT = 2, + ARG_TYPE_FLOAT = 3, + ARG_TYPE_PTR = 4, + ARG_TYPE_STR = 5 +} ArgType; + +/** + * An IPCCommand function can have either of these function signatures + */ +typedef union ArgFunction { + void (*single_param)(const Arg *); + void (*array_param)(const Arg *, int); +} ArgFunction; + +typedef struct IPCCommand { + char *name; + ArgFunction func; + unsigned int argc; + ArgType *arg_types; +} IPCCommand; + +typedef struct IPCParsedCommand { + char *name; + Arg *args; + ArgType *arg_types; + unsigned int argc; +} IPCParsedCommand; + +/** + * Initialize the IPC socket and the IPC module + * + * @param socket_path Path to create the socket at + * @param epoll_fd File descriptor for epoll + * @param commands Address of IPCCommands array defined in config.h + * @param commands_len Length of commands[] array + * + * @return int The file descriptor of the socket if it was successfully created, + * -1 otherwise + */ +int ipc_init(const char *socket_path, const int p_epoll_fd, + IPCCommand commands[], const int commands_len); + +/** + * Uninitialize the socket and module. Free allocated memory and restore static + * variables to their state before ipc_init + */ +void ipc_cleanup(); + +/** + * Get the file descriptor of the IPC socket + * + * @return int File descriptor of IPC socket, -1 if socket not created. + */ +int ipc_get_sock_fd(); + +/** + * Get address to IPCClient with specified file descriptor + * + * @param fd File descriptor of IPC Client + * + * @return Address to IPCClient with specified file descriptor, -1 otherwise + */ +IPCClient *ipc_get_client(int fd); + +/** + * Check if an IPC client exists with the specified file descriptor + * + * @param fd File descriptor + * + * @return int 1 if client exists, 0 otherwise + */ +int ipc_is_client_registered(int fd); + +/** + * Disconnect an IPCClient from the socket and remove the client from the list + * of known connected clients + * + * @param c Address of IPCClient + * + * @return 0 if the client's file descriptor was closed successfully, the + * result of executing close() on the file descriptor otherwise. + */ +int ipc_drop_client(IPCClient *c); + +/** + * Accept an IPC Client requesting to connect to the socket and add it to the + * list of clients + * + * @return File descriptor of new client, -1 on error + */ +int ipc_accept_client(); + +/** + * Read an incoming message from an accepted IPC client + * + * @param c Address of IPCClient + * @param msg_type Address to IPCMessageType variable which will be assigned + * the message type of the received message + * @param msg_size Address to uint32_t variable which will be assigned the size + * of the received message + * @param msg Address to char* variable which will be assigned the address of + * the received message. This must be freed using free(). + * + * @return 0 on success, -1 on error reading message, -2 if reading the message + * resulted in EAGAIN, EINTR, or EWOULDBLOCK. + */ +int ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size, + char **msg); + +/** + * Write any pending buffer of the client to the client's socket + * + * @param c Client whose buffer to write + * + * @return Number of bytes written >= 0, -1 otherwise. errno will still be set + * from the write operation. + */ +ssize_t ipc_write_client(IPCClient *c); + +/** + * Prepare a message in the specified client's buffer. + * + * @param c Client to prepare message for + * @param msg_type Type of message to prepare + * @param msg_size Size of the message in bytes. Should not exceed + * MAX_MESSAGE_SIZE + * @param msg Message to prepare (not including header). This pointer can be + * freed after the function invocation. + */ +void ipc_prepare_send_message(IPCClient *c, const IPCMessageType msg_type, + const uint32_t msg_size, const char *msg); + +/** + * Prepare an error message in the specified client's buffer + * + * @param c Client to prepare message for + * @param msg_type Type of message + * @param format Format string following vsprintf + * @param ... Arguments for format string + */ +void ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type, + const char *format, ...); + +/** + * Prepare a success message in the specified client's buffer + * + * @param c Client to prepare message for + * @param msg_type Type of message + */ +void ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type); + +/** + * Send a tag_change_event to all subscribers. Should be called only when there + * has been a tag state change. + * + * @param mon_num The index of the monitor (Monitor.num property) + * @param old_state The old tag state + * @param new_state The new (now current) tag state + */ +void ipc_tag_change_event(const int mon_num, TagState old_state, + TagState new_state); + +/** + * Send a client_focus_change_event to all subscribers. Should be called only + * when the client focus changes. + * + * @param mon_num The index of the monitor (Monitor.num property) + * @param old_client The old DWM client selection (Monitor.oldsel) + * @param new_client The new (now current) DWM client selection + */ +void ipc_client_focus_change_event(const int mon_num, Client *old_client, + Client *new_client); + +/** + * Send a layout_change_event to all subscribers. Should be called only + * when there has been a layout change. + * + * @param mon_num The index of the monitor (Monitor.num property) + * @param old_symbol The old layout symbol + * @param old_layout Address to the old Layout + * @param new_symbol The new (now current) layout symbol + * @param new_layout Address to the new Layout + */ +void ipc_layout_change_event(const int mon_num, const char *old_symbol, + const Layout *old_layout, const char *new_symbol, + const Layout *new_layout); + +/** + * Send a monitor_focus_change_event to all subscribers. Should be called only + * when the monitor focus changes. + * + * @param last_mon_num The index of the previously selected monitor + * @param new_mon_num The index of the newly selected monitor + */ +void ipc_monitor_focus_change_event(const int last_mon_num, + const int new_mon_num); + +/** + * Send a focused_title_change_event to all subscribers. Should only be called + * if a selected client has a title change. + * + * @param mon_num Index of the client's monitor + * @param client_id Window XID of client + * @param old_name Old name of the client window + * @param new_name New name of the client window + */ +void ipc_focused_title_change_event(const int mon_num, const Window client_id, + const char *old_name, const char *new_name); + +/** + * Send a focused_state_change_event to all subscribers. Should only be called + * if a selected client has a state change. + * + * @param mon_num Index of the client's monitor + * @param client_id Window XID of client + * @param old_state Old state of the client + * @param new_state New state of the client + */ +void ipc_focused_state_change_event(const int mon_num, const Window client_id, + const ClientState *old_state, + const ClientState *new_state); +/** + * Check to see if an event has occured and call the *_change_event functions + * accordingly + * + * @param mons Address of Monitor pointing to start of linked list + * @param lastselmon Address of pointer to previously selected monitor + * @param selmon Address of selected Monitor + */ +void ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon); + +/** + * Handle an epoll event caused by a registered IPC client. Read, process, and + * handle any received messages from clients. Write pending buffer to client if + * the client is ready to receive messages. Drop clients that have sent an + * EPOLLHUP. + * + * @param ev Associated epoll event returned by epoll_wait + * @param mons Address of Monitor pointing to start of linked list + * @param selmon Address of selected Monitor + * @param lastselmon Address of pointer to previously selected monitor + * @param tags Array of tag names + * @param tags_len Length of tags array + * @param layouts Array of available layouts + * @param layouts_len Length of layouts array + * + * @return 0 if event was successfully handled, -1 on any error receiving + * or handling incoming messages or unhandled epoll event. + */ +int ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons, + Monitor **lastselmon, Monitor *selmon, const int tags_len, + const Layout *layouts, const int layouts_len); + +/** + * Handle an epoll event caused by the IPC socket. This function only handles an + * EPOLLIN event indicating a new client requesting to connect to the socket. + * + * @param ev Associated epoll event returned by epoll_wait + * + * @return 0, if the event was successfully handled, -1 if not an EPOLLIN event + * or if a new IPC client connection request could not be accepted. + */ +int ipc_handle_socket_epoll_event(struct epoll_event *ev); + +#endif /* IPC_H_ */ + diff --git a/dwm/patch/ipc/util.c b/dwm/patch/ipc/util.c new file mode 100755 index 0000000..7ea425e --- /dev/null +++ b/dwm/patch/ipc/util.c @@ -0,0 +1,136 @@ +#include +#include + +int +normalizepath(const char *path, char **normal) +{ + size_t len = strlen(path); + *normal = (char *)malloc((len + 1) * sizeof(char)); + const char *walk = path; + const char *match; + size_t newlen = 0; + + while ((match = strchr(walk, '/'))) { + // Copy everything between match and walk + strncpy(*normal + newlen, walk, match - walk); + newlen += match - walk; + walk += match - walk; + + // Skip all repeating slashes + while (*walk == '/') + walk++; + + // If not last character in path + if (walk != path + len) + (*normal)[newlen++] = '/'; + } + + (*normal)[newlen++] = '\0'; + + // Copy remaining path + strcat(*normal, walk); + newlen += strlen(walk); + + *normal = (char *)realloc(*normal, newlen * sizeof(char)); + + return 0; +} + +int +parentdir(const char *path, char **parent) +{ + char *normal; + char *walk; + + normalizepath(path, &normal); + + // Pointer to last '/' + if (!(walk = strrchr(normal, '/'))) { + free(normal); + return -1; + } + + // Get path up to last '/' + size_t len = walk - normal; + *parent = (char *)malloc((len + 1) * sizeof(char)); + + // Copy path up to last '/' + strncpy(*parent, normal, len); + // Add null char + (*parent)[len] = '\0'; + + free(normal); + + return 0; +} + +int +mkdirp(const char *path) +{ + char *normal; + char *walk; + size_t normallen; + + normalizepath(path, &normal); + normallen = strlen(normal); + walk = normal; + + while (walk < normal + normallen + 1) { + // Get length from walk to next / + size_t n = strcspn(walk, "/"); + + // Skip path / + if (n == 0) { + walk++; + continue; + } + + // Length of current path segment + size_t curpathlen = walk - normal + n; + char curpath[curpathlen + 1]; + struct stat s; + + // Copy path segment to stat + strncpy(curpath, normal, curpathlen); + strcpy(curpath + curpathlen, ""); + int res = stat(curpath, &s); + + if (res < 0) { + if (errno == ENOENT) { + DEBUG("Making directory %s\n", curpath); + if (mkdir(curpath, 0700) < 0) { + fprintf(stderr, "Failed to make directory %s\n", curpath); + perror(""); + free(normal); + return -1; + } + } else { + fprintf(stderr, "Error statting directory %s\n", curpath); + perror(""); + free(normal); + return -1; + } + } + + // Continue to next path segment + walk += n; + } + + free(normal); + + return 0; +} + +int +nullterminate(char **str, size_t *len) +{ + if ((*str)[*len - 1] == '\0') + return 0; + + (*len)++; + *str = (char*)realloc(*str, *len * sizeof(char)); + (*str)[*len - 1] = '\0'; + + return 0; +} + diff --git a/dwm/patch/ipc/util.h b/dwm/patch/ipc/util.h new file mode 100755 index 0000000..8d2a626 --- /dev/null +++ b/dwm/patch/ipc/util.h @@ -0,0 +1,5 @@ +int normalizepath(const char *path, char **normal); +int mkdirp(const char *path); +int parentdir(const char *path, char **parent); +int nullterminate(char **str, size_t *len); + diff --git a/dwm/patch/ipc/yajl_dumps.c b/dwm/patch/ipc/yajl_dumps.c new file mode 100755 index 0000000..b24a429 --- /dev/null +++ b/dwm/patch/ipc/yajl_dumps.c @@ -0,0 +1,356 @@ +#include "yajl_dumps.h" + +#include + +int +dump_tag(yajl_gen gen, const char *name, const int tag_mask) +{ + if (!name) + return 0; + + // clang-format off + YMAP( + YSTR("bit_mask"); YINT(tag_mask); + YSTR("name"); YSTR(name); + ) + // clang-format on + return 0; +} + +int +dump_tags(yajl_gen gen, int tags_len) +{ + // clang-format off + YARR( + for (int i = 0; i < tags_len; i++) + dump_tag(gen, tagicon(mons, i), 1 << i); + ) + // clang-format on + + return 0; +} + +int +dump_client(yajl_gen gen, Client *c) +{ + // clang-format off + YMAP( + YSTR("name"); YSTR(c->name); + YSTR("tags"); YINT(c->tags); + YSTR("window_id"); YINT(c->win); + YSTR("monitor_number"); YINT(c->mon->num); + + YSTR("geometry"); YMAP( + YSTR("current"); YMAP ( + YSTR("x"); YINT(c->x); + YSTR("y"); YINT(c->y); + YSTR("width"); YINT(c->w); + YSTR("height"); YINT(c->h); + ) + YSTR("old"); YMAP( + YSTR("x"); YINT(c->oldx); + YSTR("y"); YINT(c->oldy); + YSTR("width"); YINT(c->oldw); + YSTR("height"); YINT(c->oldh); + ) + ) + + YSTR("size_hints"); YMAP( + YSTR("base"); YMAP( + YSTR("width"); YINT(c->basew); + YSTR("height"); YINT(c->baseh); + ) + YSTR("step"); YMAP( + YSTR("width"); YINT(c->incw); + YSTR("height"); YINT(c->inch); + ) + YSTR("max"); YMAP( + YSTR("width"); YINT(c->maxw); + YSTR("height"); YINT(c->maxh); + ) + YSTR("min"); YMAP( + YSTR("width"); YINT(c->minw); + YSTR("height"); YINT(c->minh); + ) + YSTR("aspect_ratio"); YMAP( + YSTR("min"); YDOUBLE(c->mina); + YSTR("max"); YDOUBLE(c->maxa); + ) + ) + + YSTR("border_width"); YMAP( + YSTR("current"); YINT(c->bw); + YSTR("old"); YINT(c->oldbw); + ) + + YSTR("states"); YMAP( + YSTR("is_fixed"); YBOOL(c->isfixed); + YSTR("is_floating"); YBOOL(c->isfloating); + YSTR("is_urgent"); YBOOL(c->isurgent); + YSTR("never_focus"); YBOOL(c->neverfocus); + YSTR("old_state"); YBOOL(c->oldstate); + YSTR("is_fullscreen"); YBOOL(c->isfullscreen); + ) + ) + // clang-format on + + return 0; +} + +int +dump_monitor(yajl_gen gen, Monitor *mon, int is_selected) +{ + // clang-format off + YMAP( + YSTR("master_factor"); YDOUBLE(mon->mfact); + YSTR("num_master"); YINT(mon->nmaster); + YSTR("num"); YINT(mon->num); + YSTR("is_selected"); YBOOL(is_selected); + + YSTR("monitor_geometry"); YMAP( + YSTR("x"); YINT(mon->mx); + YSTR("y"); YINT(mon->my); + YSTR("width"); YINT(mon->mw); + YSTR("height"); YINT(mon->mh); + ) + + YSTR("window_geometry"); YMAP( + YSTR("x"); YINT(mon->wx); + YSTR("y"); YINT(mon->wy); + YSTR("width"); YINT(mon->ww); + YSTR("height"); YINT(mon->wh); + ) + + YSTR("tagset"); YMAP( + YSTR("current"); YINT(mon->tagset[mon->seltags]); + YSTR("old"); YINT(mon->tagset[mon->seltags ^ 1]); + ) + + YSTR("tag_state"); dump_tag_state(gen, mon->tagstate); + + YSTR("clients"); YMAP( + YSTR("selected"); YINT(mon->sel ? mon->sel->win : 0); + YSTR("stack"); YARR( + for (Client* c = mon->stack; c; c = c->snext) + YINT(c->win); + ) + YSTR("all"); YARR( + for (Client* c = mon->clients; c; c = c->next) + YINT(c->win); + ) + ) + + YSTR("layout"); YMAP( + YSTR("symbol"); YMAP( + YSTR("current"); YSTR(mon->ltsymbol); + YSTR("old"); YSTR(mon->lastltsymbol); + ) + YSTR("address"); YMAP( + YSTR("current"); YINT((uintptr_t)mon->lt[mon->sellt]); + YSTR("old"); YINT((uintptr_t)mon->lt[mon->sellt ^ 1]); + ) + ) + + if (mon->bar) { + YSTR("bar"); YMAP( + YSTR("y"); YINT(mon->bar->by); + YSTR("is_shown"); YBOOL(mon->showbar); + YSTR("is_top"); YBOOL(mon->bar->topbar); + YSTR("window_id"); YINT(mon->bar->win); + ) + } + ) + // clang-format on + + return 0; +} + +int +dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon) +{ + // clang-format off + YARR( + for (Monitor *mon = mons; mon; mon = mon->next) { + if (mon == selmon) + dump_monitor(gen, mon, 1); + else + dump_monitor(gen, mon, 0); + } + ) + // clang-format on + + return 0; +} + +int +dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len) +{ + // clang-format off + YARR( + for (int i = 0; i < layouts_len; i++) { + YMAP( + // Check for a NULL pointer. The cycle layouts patch adds an entry at + // the end of the layouts array with a NULL pointer for the symbol + YSTR("symbol"); YSTR((layouts[i].symbol ? layouts[i].symbol : "")); + YSTR("address"); YINT((uintptr_t)(layouts + i)); + ) + } + ) + // clang-format on + + return 0; +} + +int +dump_tag_state(yajl_gen gen, TagState state) +{ + // clang-format off + YMAP( + YSTR("selected"); YINT(state.selected); + YSTR("occupied"); YINT(state.occupied); + YSTR("urgent"); YINT(state.urgent); + ) + // clang-format on + + return 0; +} + +int +dump_tag_event(yajl_gen gen, int mon_num, TagState old_state, + TagState new_state) +{ + // clang-format off + YMAP( + YSTR("tag_change_event"); YMAP( + YSTR("monitor_number"); YINT(mon_num); + YSTR("old_state"); dump_tag_state(gen, old_state); + YSTR("new_state"); dump_tag_state(gen, new_state); + ) + ) + // clang-format on + + return 0; +} + +int +dump_client_focus_change_event(yajl_gen gen, Client *old_client, + Client *new_client, int mon_num) +{ + // clang-format off + YMAP( + YSTR("client_focus_change_event"); YMAP( + YSTR("monitor_number"); YINT(mon_num); + YSTR("old_win_id"); old_client == NULL ? YNULL() : YINT(old_client->win); + YSTR("new_win_id"); new_client == NULL ? YNULL() : YINT(new_client->win); + ) + ) + // clang-format on + + return 0; +} + +int +dump_layout_change_event(yajl_gen gen, const int mon_num, + const char *old_symbol, const Layout *old_layout, + const char *new_symbol, const Layout *new_layout) +{ + // clang-format off + YMAP( + YSTR("layout_change_event"); YMAP( + YSTR("monitor_number"); YINT(mon_num); + YSTR("old_symbol"); YSTR(old_symbol); + YSTR("old_address"); YINT((uintptr_t)old_layout); + YSTR("new_symbol"); YSTR(new_symbol); + YSTR("new_address"); YINT((uintptr_t)new_layout); + ) + ) + // clang-format on + + return 0; +} + +int +dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num, + const int new_mon_num) +{ + // clang-format off + YMAP( + YSTR("monitor_focus_change_event"); YMAP( + YSTR("old_monitor_number"); YINT(last_mon_num); + YSTR("new_monitor_number"); YINT(new_mon_num); + ) + ) + // clang-format on + + return 0; +} + +int +dump_focused_title_change_event(yajl_gen gen, const int mon_num, + const Window client_id, const char *old_name, + const char *new_name) +{ + // clang-format off + YMAP( + YSTR("focused_title_change_event"); YMAP( + YSTR("monitor_number"); YINT(mon_num); + YSTR("client_window_id"); YINT(client_id); + YSTR("old_name"); YSTR(old_name); + YSTR("new_name"); YSTR(new_name); + ) + ) + // clang-format on + + return 0; +} + +int +dump_client_state(yajl_gen gen, const ClientState *state) +{ + // clang-format off + YMAP( + YSTR("old_state"); YBOOL(state->oldstate); + YSTR("is_fixed"); YBOOL(state->isfixed); + YSTR("is_floating"); YBOOL(state->isfloating); + YSTR("is_fullscreen"); YBOOL(state->isfullscreen); + YSTR("is_urgent"); YBOOL(state->isurgent); + YSTR("never_focus"); YBOOL(state->neverfocus); + ) + // clang-format on + + return 0; +} + +int +dump_focused_state_change_event(yajl_gen gen, const int mon_num, + const Window client_id, + const ClientState *old_state, + const ClientState *new_state) +{ + // clang-format off + YMAP( + YSTR("focused_state_change_event"); YMAP( + YSTR("monitor_number"); YINT(mon_num); + YSTR("client_window_id"); YINT(client_id); + YSTR("old_state"); dump_client_state(gen, old_state); + YSTR("new_state"); dump_client_state(gen, new_state); + ) + ) + // clang-format on + + return 0; +} + +int +dump_error_message(yajl_gen gen, const char *reason) +{ + // clang-format off + YMAP( + YSTR("result"); YSTR("error"); + YSTR("reason"); YSTR(reason); + ) + // clang-format on + + return 0; +} + diff --git a/dwm/patch/ipc/yajl_dumps.h b/dwm/patch/ipc/yajl_dumps.h new file mode 100755 index 0000000..bb57a17 --- /dev/null +++ b/dwm/patch/ipc/yajl_dumps.h @@ -0,0 +1,66 @@ +#ifndef YAJL_DUMPS_H_ +#define YAJL_DUMPS_H_ + +#include +#include + +#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) +#define YINT(num) yajl_gen_integer(gen, num) +#define YDOUBLE(num) yajl_gen_double(gen, num) +#define YBOOL(v) yajl_gen_bool(gen, v) +#define YNULL() yajl_gen_null(gen) +#define YARR(body) \ + { \ + yajl_gen_array_open(gen); \ + body; \ + yajl_gen_array_close(gen); \ + } +#define YMAP(body) \ + { \ + yajl_gen_map_open(gen); \ + body; \ + yajl_gen_map_close(gen); \ + } + +int dump_tag(yajl_gen gen, const char *name, const int tag_mask); + +int dump_tags(yajl_gen gen, int tags_len); + +int dump_client(yajl_gen gen, Client *c); + +int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected); + +int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon); + +int dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len); + +int dump_tag_state(yajl_gen gen, TagState state); + +int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state, + TagState new_state); + +int dump_client_focus_change_event(yajl_gen gen, Client *old_client, + Client *new_client, int mon_num); + +int dump_layout_change_event(yajl_gen gen, const int mon_num, + const char *old_symbol, const Layout *old_layout, + const char *new_symbol, const Layout *new_layout); + +int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num, + const int new_mon_num); + +int dump_focused_title_change_event(yajl_gen gen, const int mon_num, + const Window client_id, + const char *old_name, const char *new_name); + +int dump_client_state(yajl_gen gen, const ClientState *state); + +int dump_focused_state_change_event(yajl_gen gen, const int mon_num, + const Window client_id, + const ClientState *old_state, + const ClientState *new_state); + +int dump_error_message(yajl_gen gen, const char *reason); + +#endif // YAJL_DUMPS_H_ + diff --git a/dwm/patch/keymodes.c b/dwm/patch/keymodes.c new file mode 100755 index 0000000..6f2f840 --- /dev/null +++ b/dwm/patch/keymodes.c @@ -0,0 +1,144 @@ +/* function implementations */ +void +clearcmd(const Arg *arg) +{ + unsigned int i; + + for (i = 0; i < LENGTH(cmdkeysym); i++) { + cmdkeysym[i] = 0; + cmdmod[i] = 0; + } +} + +void +grabkeys(void) +{ + if (keymode == INSERTMODE) { + grabdefkeys(); + } else if (keymode == COMMANDMODE) { + XUngrabKey(dpy, AnyKey, AnyModifier, root); + XGrabKey(dpy, AnyKey, AnyModifier, root, + True, GrabModeAsync, GrabModeAsync); + } +} + +int +isprotodel(Client *c) +{ + int n; + Atom *protocols; + int ret = 0; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!ret && n--) + ret = protocols[n] == wmatom[WMDelete]; + XFree(protocols); + } + return ret; +} + + +void +keypress(XEvent *e) +{ + unsigned int i, j; + Arg a = {0}; + Bool ismatch = False, maybematch = False; + KeySym keysym; + XKeyEvent *ev; + + if (keymode == INSERTMODE) + keydefpress(e); + else if (keymode == COMMANDMODE) { + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + if (keysym < XK_Shift_L || keysym > XK_Hyper_R) { + for (i = 0; i < LENGTH(cmdkeys); i++) + if (keysym == cmdkeys[i].keysym + && CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state) + && cmdkeys[i].func) { + cmdkeys[i].func(&(cmdkeys[i].arg)); + ismatch = True; + break; + } + if (!ismatch) { + for (j = 0; j < LENGTH(cmdkeysym); j++) + if (cmdkeysym[j] == 0) { + cmdkeysym[j] = keysym; + cmdmod[j] = ev->state; + break; + } + for (i = 0; i < LENGTH(commands); i++) { + for (j = 0; j < LENGTH(cmdkeysym); j++) { + if (cmdkeysym[j] == commands[i].keysym[j] + && CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j])) + ismatch = True; + else if (cmdkeysym[j] == 0 + && cmdmod[j] == 0) { + ismatch = False; + maybematch = True; + break; + } else { + ismatch = False; + break; + } + } + if (ismatch) { + if (commands[i].func) + commands[i].func(&(commands[i].arg)); + clearcmd(&a); + break; + } + + } + if (!maybematch) + clearcmd(&a); + } + } + } +} + +void +onlyclient(const Arg *arg) +{ + Client *c; + XEvent ev; + + if (!selmon->sel) + return; + for (c = selmon->clients; c; c = c->next) { + if (c != selmon->sel && ISVISIBLE(c)) { + if (isprotodel(c)) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = wmatom[WMDelete]; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + else { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, c->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + } + } +} + +void +setkeymode(const Arg *arg) +{ + Arg a = {0}; + + if (!arg) + return; + keymode = arg->ui; + clearcmd(&a); + grabkeys(); +} + diff --git a/dwm/patch/keymodes.h b/dwm/patch/keymodes.h new file mode 100755 index 0000000..0a46125 --- /dev/null +++ b/dwm/patch/keymodes.h @@ -0,0 +1,22 @@ +#define COMMANDMODE 1 +#define INSERTMODE 2 + +typedef struct { + unsigned int mod[4]; + KeySym keysym[4]; + void (*func)(const Arg *); + const Arg arg; +} Command; + +static void clearcmd(const Arg *arg); +static void grabkeys(void); +static int isprotodel(Client *c); +static void keypress(XEvent *e); +static void onlyclient(const Arg *arg); +static void setkeymode(const Arg *arg); + +/* variables */ +static unsigned int cmdmod[4]; +static unsigned int keymode = INSERTMODE; +static KeySym cmdkeysym[4]; + diff --git a/dwm/patch/killunsel.c b/dwm/patch/killunsel.c new file mode 100755 index 0000000..8d7a7b8 --- /dev/null +++ b/dwm/patch/killunsel.c @@ -0,0 +1,28 @@ +void +killunsel(const Arg *arg) +{ + Client *i = NULL; + + if (!selmon->sel) + return; + + for (i = selmon->clients; i; i = i->next) { + if (ISVISIBLE(i) && i != selmon->sel) { + #if BAR_SYSTRAY_PATCH + if (!sendevent(i->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0, 0, 0)) + #else + if (!sendevent(i, wmatom[WMDelete])) + #endif // BAR_SYSTRAY_PATCH + { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, i->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + } + } +} + diff --git a/dwm/patch/killunsel.h b/dwm/patch/killunsel.h new file mode 100755 index 0000000..4fc154f --- /dev/null +++ b/dwm/patch/killunsel.h @@ -0,0 +1,2 @@ +static void killunsel(const Arg *arg); + diff --git a/dwm/patch/layout_bstack.c b/dwm/patch/layout_bstack.c new file mode 100755 index 0000000..8989975 --- /dev/null +++ b/dwm/patch/layout_bstack.c @@ -0,0 +1,75 @@ +static void +bstack(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (n == 0) + return; + + #if VANITYGAPS_PATCH + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); + sw = m->ww - 2*ov - iv * (n - m->nmaster - 1); + + if (m->nmaster && n > m->nmaster) { + sh = (mh - ih) * (1 - m->mfact); + mh = (mh - ih) * m->mfact; + sx = mx; + sy = my + mh + ih; + } + #else + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (m->nmaster && n > m->nmaster) { + sh = mh * (1 - m->mfact); + mh = mh * m->mfact; + sy = my + mh; + } + #endif // VANITYGAPS_PATCH + + getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i < m->nmaster) { + #if CFACTS_PATCH + resize(c, mx, my, (mw / mfacts) * c->cfact + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #else + resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + mx += WIDTH(c) + iv; + #else + mx += WIDTH(c); + #endif + } else { + #if CFACTS_PATCH + resize(c, sx, sy, (sw / sfacts) * c->cfact + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + #else + resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + sx += WIDTH(c) + iv; + #else + sx += WIDTH(c); + #endif + } + } +} + diff --git a/dwm/patch/layout_bstack.h b/dwm/patch/layout_bstack.h new file mode 100755 index 0000000..07e8c0a --- /dev/null +++ b/dwm/patch/layout_bstack.h @@ -0,0 +1,2 @@ +static void bstack(Monitor *m); + diff --git a/dwm/patch/layout_bstackhoriz.c b/dwm/patch/layout_bstackhoriz.c new file mode 100755 index 0000000..462301c --- /dev/null +++ b/dwm/patch/layout_bstackhoriz.c @@ -0,0 +1,77 @@ +static void +bstackhoriz(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (n == 0) + return; + + #if VANITYGAPS_PATCH + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + mh = m->wh - 2*oh; + sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); + mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); + sw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sh = (mh - ih) * (1 - m->mfact); + mh = (mh - ih) * m->mfact; + sy = my + mh + ih; + sh = m->wh - mh - 2*oh - ih * (n - m->nmaster); + } + #else + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (m->nmaster && n > m->nmaster) { + sh = mh * (1 - m->mfact); + mh = mh * m->mfact; + sy = my + mh; + sh = m->wh - mh; + } + #endif // VANITYGAPS_PATCH + + getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i < m->nmaster) { + #if CFACTS_PATCH + resize(c, mx, my, (mw / mfacts) * c->cfact + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #else + resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + mx += WIDTH(c) + iv; + #else + mx += WIDTH(c); + #endif + } else { + #if CFACTS_PATCH + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) * c->cfact + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + sy += HEIGHT(c) + ih; + #else + sy += HEIGHT(c); + #endif + } + } +} + diff --git a/dwm/patch/layout_bstackhoriz.h b/dwm/patch/layout_bstackhoriz.h new file mode 100755 index 0000000..a421d6f --- /dev/null +++ b/dwm/patch/layout_bstackhoriz.h @@ -0,0 +1,2 @@ +static void bstackhoriz(Monitor *m); + diff --git a/dwm/patch/layout_centeredfloatingmaster.c b/dwm/patch/layout_centeredfloatingmaster.c new file mode 100755 index 0000000..6d1aff0 --- /dev/null +++ b/dwm/patch/layout_centeredfloatingmaster.c @@ -0,0 +1,95 @@ +void +centeredfloatingmaster(Monitor *m) +{ + unsigned int i, n; + float mfacts, sfacts; + int mrest, srest; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + Client *c; + + #if VANITYGAPS_PATCH + float mivf = 1.0; // master inner vertical gap factor + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (n == 0) + return; + + #if VANITYGAPS_PATCH + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + mw = m->ww - 2*ov - iv*(n - 1); + sw = m->ww - 2*ov - iv*(n - m->nmaster - 1); + + if (m->nmaster && n > m->nmaster) { + mivf = 0.8; + /* go mfact box in the center if more than nmaster clients */ + if (m->ww > m->wh) { + mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1); + mh = m->wh * 0.9; + } else { + mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1); + mh = m->wh * m->mfact; + } + mx = m->wx + (m->ww - mw) / 2; + my = m->wy + (m->wh - mh - 2*oh) / 2; + + sx = m->wx + ov; + sy = m->wy + oh; + sh = m->wh - 2*oh; + } + #else + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (m->nmaster && n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + if (m->ww > m->wh) { + mw = m->ww * m->mfact; + mh = m->wh * 0.9; + } else { + mw = m->ww * 0.9; + mh = m->wh * m->mfact; + } + mx = m->wx + (m->ww - mw) / 2; + my = m->wy + (m->wh - mh) / 2; + } + #endif // VANITYGAPS_PATCH + + getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + /* nmaster clients are stacked horizontally, in the center of the screen */ + #if CFACTS_PATCH + resize(c, mx, my, (mw / mfacts) * c->cfact + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #else + resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + mx += WIDTH(c) + iv*mivf; + #else + mx += WIDTH(c); + #endif + } else { + /* stack clients are stacked horizontally */ + #if CFACTS_PATCH + resize(c, sx, sy, (sw / sfacts) * c->cfact + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + #else + resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + sx += WIDTH(c) + iv; + #else + sx += WIDTH(c); + #endif + } +} + diff --git a/dwm/patch/layout_centeredfloatingmaster.h b/dwm/patch/layout_centeredfloatingmaster.h new file mode 100755 index 0000000..66b0b0e --- /dev/null +++ b/dwm/patch/layout_centeredfloatingmaster.h @@ -0,0 +1,2 @@ +static void centeredfloatingmaster(Monitor *m); + diff --git a/dwm/patch/layout_centeredmaster.c b/dwm/patch/layout_centeredmaster.c new file mode 100755 index 0000000..39aa67f --- /dev/null +++ b/dwm/patch/layout_centeredmaster.c @@ -0,0 +1,160 @@ +void +centeredmaster(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int lx = 0, ly = 0, lw = 0, lh = 0; + int rx = 0, ry = 0, rw = 0, rh = 0; + float mfacts = 0, lfacts = 0, rfacts = 0; + int mtotal = 0, ltotal = 0, rtotal = 0; + int mrest = 0, lrest = 0, rrest = 0; + Client *c; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (n == 0) + return; + + /* initialize areas */ + #if VANITYGAPS_PATCH + mx = m->wx + ov; + my = m->wy + oh; + mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1); + mw = m->ww - 2*ov; + lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1); + rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1)); + + if (m->nmaster && n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + if (n - m->nmaster > 1) { + /* ||<-S->|<---M--->|<-S->|| */ + mw = (m->ww - 2*ov - 2*iv) * m->mfact; + lw = (m->ww - mw - 2*ov - 2*iv) / 2; + mx += lw + iv; + } else { + /* ||<---M--->|<-S->|| */ + mw = (mw - iv) * m->mfact; + lw = m->ww - mw - iv - 2*ov; + } + rw = lw; + lx = m->wx + ov; + ly = m->wy + oh; + rx = mx + mw + iv; + ry = m->wy + oh; + } + #else + mx = m->wx; + my = m->wy; + mh = m->wh; + mw = m->ww; + lh = m->wh; + rh = m->wh; + + if (m->nmaster && n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + if (n - m->nmaster > 1) { + /* ||<-S->|<---M--->|<-S->|| */ + mw = m->ww * m->mfact; + lw = (m->ww - mw) / 2; + mx += lw; + } else { + /* ||<---M--->|<-S->|| */ + mw = mw * m->mfact; + lw = m->ww - mw; + } + rw = lw; + lx = m->wx; + ly = m->wy; + rx = mx + mw; + ry = m->wy; + } + #endif // VANITYGAPS_PATCH + + /* calculate facts */ + #if CFACTS_PATCH + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { + if (!m->nmaster || n < m->nmaster) + mfacts += c->cfact; // total factor of master area + else if ((n - m->nmaster) % 2) + lfacts += c->cfact; // total factor of left hand stack area + else + rfacts += c->cfact; // total factor of right hand stack area + } + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (!m->nmaster || n < m->nmaster) + mtotal += mh / mfacts; + else if ((n - m->nmaster) % 2) + ltotal += lh * (c->cfact / lfacts); + else + rtotal += rh * (c->cfact / rfacts); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { + if (!m->nmaster || n < m->nmaster) + mfacts += 1; + else if ((n - m->nmaster) % 2) + lfacts += 1; // total factor of left hand stack area + else + rfacts += 1; // total factor of right hand stack area + } + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (!m->nmaster || n < m->nmaster) + mtotal += mh / mfacts; + else if ((n - m->nmaster) % 2) + ltotal += lh / lfacts; + else + rtotal += rh / rfacts; + #endif // CFACTS_PATCH + + mrest = mh - mtotal; + lrest = lh - ltotal; + rrest = rh - rtotal; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (!m->nmaster || i < m->nmaster) { + /* nmaster clients are stacked vertically, in the center of the screen */ + #if CFACTS_PATCH + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) * c->cfact + (i < mrest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + my += HEIGHT(c) + ih; + #else + my += HEIGHT(c); + #endif + } else { + /* stack clients are stacked vertically */ + if ((i - m->nmaster) % 2 ) { + #if CFACTS_PATCH + resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) * c->cfact + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + ly += HEIGHT(c) + ih; + #else + ly += HEIGHT(c); + #endif + } else { + #if CFACTS_PATCH + resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) * c->cfact + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + ry += HEIGHT(c) + ih; + #else + ry += HEIGHT(c); + #endif + } + } + } +} + diff --git a/dwm/patch/layout_centeredmaster.h b/dwm/patch/layout_centeredmaster.h new file mode 100755 index 0000000..703f8b8 --- /dev/null +++ b/dwm/patch/layout_centeredmaster.h @@ -0,0 +1,2 @@ +static void centeredmaster(Monitor *m); + diff --git a/dwm/patch/layout_columns.c b/dwm/patch/layout_columns.c new file mode 100755 index 0000000..8a0e551 --- /dev/null +++ b/dwm/patch/layout_columns.c @@ -0,0 +1,74 @@ +static void +col(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (n == 0) + return; + + #if VANITYGAPS_PATCH + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + mh = m->wh - 2*oh; + sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); + mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); + sw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = (mw - iv) * m->mfact; + sx = mx + mw + iv * m->nmaster; + } + #else + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (m->nmaster && n > m->nmaster) { + sw = mw * (1 - m->mfact); + mw = mw * m->mfact; + sx = mx + mw; + } + #endif // VANITYGAPS_PATCH + + getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + #if CFACTS_PATCH + resize(c, mx, my, (mw / mfacts) * c->cfact + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #else + resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + mx += WIDTH(c) + iv; + #else + mx += WIDTH(c); + #endif + } else { + #if CFACTS_PATCH + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) * c->cfact + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + sy += HEIGHT(c) + ih; + #else + sy += HEIGHT(c); + #endif + } +} + diff --git a/dwm/patch/layout_columns.h b/dwm/patch/layout_columns.h new file mode 100755 index 0000000..017243e --- /dev/null +++ b/dwm/patch/layout_columns.h @@ -0,0 +1,2 @@ +static void col(Monitor *m); + diff --git a/dwm/patch/layout_deck.c b/dwm/patch/layout_deck.c new file mode 100755 index 0000000..1cabf0e --- /dev/null +++ b/dwm/patch/layout_deck.c @@ -0,0 +1,67 @@ +static void +deck(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (n == 0) + return; + + #if VANITYGAPS_PATCH + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); + sw = mw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = (mw - iv) * m->mfact; + sx = mx + mw + iv; + sh = m->wh - 2*oh; + } + #else + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (m->nmaster && n > m->nmaster) { + sw = mw * (1 - m->mfact); + mw = mw * m->mfact; + sx = mx + mw; + } + #endif // VANITYGAPS_PATCH + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + if (n - m->nmaster > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + #if CFACTS_PATCH + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) * c->cfact + (i < mrest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + my += HEIGHT(c) + ih; + #else + my += HEIGHT(c); + #endif + } else { + resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0); + } +} + diff --git a/dwm/patch/layout_deck.h b/dwm/patch/layout_deck.h new file mode 100755 index 0000000..b6e3c41 --- /dev/null +++ b/dwm/patch/layout_deck.h @@ -0,0 +1,2 @@ +static void deck(Monitor *m); + diff --git a/dwm/patch/layout_facts.c b/dwm/patch/layout_facts.c new file mode 100755 index 0000000..611e89e --- /dev/null +++ b/dwm/patch/layout_facts.c @@ -0,0 +1,52 @@ +#if CFACTS_PATCH +void +getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) +{ + unsigned int n; + float mfacts = 0, sfacts = 0; + int mtotal = 0, stotal = 0; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mfacts += c->cfact; + else + sfacts += c->cfact; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mtotal += msize * (c->cfact / mfacts); + else + stotal += ssize * (c->cfact / sfacts); + + *mf = mfacts; // total factor of master area + *sf = sfacts; // total factor of stack area + *mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split + *sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split +} +#else +void +getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) +{ + unsigned int n; + float mfacts, sfacts; + int mtotal = 0, stotal = 0; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + mfacts = MIN(n, m->nmaster); + sfacts = n - m->nmaster; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mtotal += msize / mfacts; + else + stotal += ssize / sfacts; + + *mf = mfacts; // total factor of master area + *sf = sfacts; // total factor of stack area + *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split + *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split +} +#endif // CFACTS_PATCH + diff --git a/dwm/patch/layout_fibonacci.c b/dwm/patch/layout_fibonacci.c new file mode 100755 index 0000000..4c5eb72 --- /dev/null +++ b/dwm/patch/layout_fibonacci.c @@ -0,0 +1,191 @@ +#if VANITYGAPS_PATCH +void +fibonacci(Monitor *m, int s) +{ + unsigned int i, n; + int nx, ny, nw, nh; + int oh, ov, ih, iv; + int nv, hrest = 0, wrest = 0, r = 1; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + nx = m->wx + ov; + ny = oh; + nw = m->ww - 2*ov; + nh = m->wh - 2*oh; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { + if (r) { + if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw)) + || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) { + r = 0; + } + if (r && i < n - 1) { + if (i % 2) { + nv = (nh - ih) / 2; + hrest = nh - 2*nv - ih; + nh = nv; + } else { + nv = (nw - iv) / 2; + wrest = nw - 2*nv - iv; + nw = nv; + } + + if ((i % 4) == 2 && !s) + nx += nw + iv; + else if ((i % 4) == 3 && !s) + ny += nh + ih; + } + + if ((i % 4) == 0) { + if (s) { + ny += nh + ih; + nh += hrest; + } + else { + nh -= hrest; + ny -= nh + ih; + } + } + else if ((i % 4) == 1) { + nx += nw + iv; + nw += wrest; + } + else if ((i % 4) == 2) { + ny += nh + ih; + nh += hrest; + if (i < n - 1) + nw += wrest; + } + else if ((i % 4) == 3) { + if (s) { + nx += nw + iv; + nw -= wrest; + } else { + nw -= wrest; + nx -= nw + iv; + nh += hrest; + } + } + if (i == 0) { + if (n != 1) { + nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact); + wrest = 0; + } + ny = m->wy + oh; + } + else if (i == 1) + nw = m->ww - nw - iv - 2*ov; + i++; + } + + resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); + } +} +#else +void +fibonacci(Monitor *m, int s) +{ + unsigned int i, n; + int nx, ny, nw, nh; + int nv, hrest = 0, wrest = 0, r = 1; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + nx = m->wx; + ny = m->wy; + nw = m->ww; + nh = m->wh; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { + if (r) { + if ((i % 2 && nh / 2 <= (bh + 2*c->bw)) + || (!(i % 2) && nw / 2 <= (bh + 2*c->bw))) { + r = 0; + } + if (r && i < n - 1) { + if (i % 2) { + nv = nh / 2; + hrest = nh - 2*nv; + nh = nv; + } else { + nv = nw / 2; + wrest = nw - 2*nv; + nw = nv; + } + + if ((i % 4) == 2 && !s) + nx += nw; + else if ((i % 4) == 3 && !s) + ny += nh; + } + + if ((i % 4) == 0) { + if (s) { + ny += nh; + nh += hrest; + } + else { + nh -= hrest; + ny -= nh; + } + } + else if ((i % 4) == 1) { + nx += nw; + nw += wrest; + } + else if ((i % 4) == 2) { + ny += nh; + nh += hrest; + if (i < n - 1) + nw += wrest; + } + else if ((i % 4) == 3) { + if (s) { + nx += nw; + nw -= wrest; + } else { + nw -= wrest; + nx -= nw; + nh += hrest; + } + } + if (i == 0) { + if (n != 1) { + nw = m->ww - m->ww * (1 - m->mfact); + wrest = 0; + } + ny = m->wy; + } + else if (i == 1) + nw = m->ww - nw; + i++; + } + + resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); + } +} +#endif + +#if FIBONACCI_DWINDLE_LAYOUT +static void +dwindle(Monitor *m) +{ + fibonacci(m, 1); +} +#endif + +#if FIBONACCI_SPIRAL_LAYOUT +static void +spiral(Monitor *m) +{ + fibonacci(m, 0); +} +#endif + diff --git a/dwm/patch/layout_fibonacci.h b/dwm/patch/layout_fibonacci.h new file mode 100755 index 0000000..3d6f77f --- /dev/null +++ b/dwm/patch/layout_fibonacci.h @@ -0,0 +1,8 @@ +#if FIBONACCI_DWINDLE_LAYOUT +static void dwindle(Monitor *m); +#endif // FIBONACCI_DWINDLE_LAYOUT +static void fibonacci(Monitor *m, int s); +#if FIBONACCI_SPIRAL_LAYOUT +static void spiral(Monitor *m); +#endif // FIBONACCI_SPIRAL_LAYOUT + diff --git a/dwm/patch/layout_flextile-deluxe.c b/dwm/patch/layout_flextile-deluxe.c new file mode 100755 index 0000000..ec7cd7d --- /dev/null +++ b/dwm/patch/layout_flextile-deluxe.c @@ -0,0 +1,891 @@ +typedef struct { + void (*arrange)(Monitor *, int, int, int, int, int, int, int); +} LayoutArranger; + +typedef struct { + void (*arrange)(Monitor *, int, int, int, int, int, int, int, int, int); +} TileArranger; + +static const LayoutArranger flexlayouts[] = { + { layout_no_split }, + { layout_split_vertical }, + { layout_split_horizontal }, + { layout_split_centered_vertical }, + { layout_split_centered_horizontal }, + { layout_split_vertical_dual_stack }, + { layout_split_horizontal_dual_stack }, + { layout_floating_master }, + { layout_split_vertical_fixed }, + { layout_split_horizontal_fixed }, + { layout_split_centered_vertical_fixed }, + { layout_split_centered_horizontal_fixed }, + { layout_split_vertical_dual_stack_fixed }, + { layout_split_horizontal_dual_stack_fixed }, + { layout_floating_master_fixed }, +}; + +static const TileArranger flextiles[] = { + { arrange_top_to_bottom }, + { arrange_left_to_right }, + { arrange_monocle }, + { arrange_gapplessgrid }, + { arrange_gapplessgrid_alt1 }, + { arrange_gapplessgrid_alt2 }, + { arrange_gridmode }, + { arrange_horizgrid }, + { arrange_dwindle }, + { arrange_spiral }, + { arrange_tatami }, +}; + +static void +getfactsforrange(Monitor *m, int an, int ai, int size, int *rest, float *fact) +{ + int i; + float facts; + Client *c; + int total = 0; + + facts = 0; + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i >= ai && i < (ai + an)) + #if CFACTS_PATCH + facts += c->cfact; + #else + facts += 1; + #endif // CFACTS_PATCH + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i >= ai && i < (ai + an)) + #if CFACTS_PATCH + total += size * (c->cfact / facts); + #else + total += size / facts; + #endif // CFACTS_PATCH + + *rest = size - total; + *fact = facts; +} + +#if IPC_PATCH || DWMC_PATCH +static void +setlayoutaxisex(const Arg *arg) +{ + int axis, arr; + + axis = arg->i & 0x3; // lower two bytes indicates layout, master or stack1-2 + arr = ((arg->i & 0xFC) >> 2); // remaining six upper bytes indicate arrangement + + if ((axis == 0 && abs(arr) > LAYOUT_LAST) + || (axis > 0 && (arr > AXIS_LAST || arr < 0))) + arr = 0; + + selmon->ltaxis[axis] = arr; + #if PERTAG_PATCH + selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis]; + #endif // PERTAG_PATCH + arrange(selmon); +} +#endif // IPC_PATCH | DWMC_PATCH + +static void +layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + (&flextiles[m->ltaxis[m->nmaster >= n ? MASTER : STACK]])->arrange(m, x, y, h, w, ih, iv, n, n, 0); +} + +static void +layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + /* Split master into master + stack if we have enough clients */ + if (m->nmaster && n > m->nmaster) { + layout_split_vertical_fixed(m, x, y, h, w, ih, iv, n); + } else { + layout_no_split(m, x, y, h, w, ih, iv, n); + } +} + +static void +layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + int sw, sx; + + sw = (w - iv) * (1 - m->mfact); + w = (w - iv) * m->mfact; + if (m->ltaxis[LAYOUT] < 0) { // mirror + sx = x; + x += sw + iv; + } else { + sx = x + w + iv; + } + + (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); + (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, n - m->nmaster, m->nmaster); +} + +static void +layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + /* Split master into master + stack if we have enough clients */ + if (!m->nmaster || n <= m->nmaster) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { + layout_split_vertical(m, x, y, h, w, ih, iv, n); + } else { + layout_split_vertical_dual_stack_fixed(m, x, y, h, w, ih, iv, n); + } +} + +static void +layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + int sh, sw, sx, oy, sc; + + if (m->nstack) + sc = m->nstack; + else + sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); + + sw = (w - iv) * (1 - m->mfact); + sh = (h - ih) / 2; + w = (w - iv) * m->mfact; + oy = y + sh + ih; + if (m->ltaxis[LAYOUT] < 0) { // mirror + sx = x; + x += sw + iv; + } else { + sx = x + w + iv; + } + + (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); + (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, sh, sw, ih, iv, n, sc, m->nmaster); + (&flextiles[m->ltaxis[STACK2]])->arrange(m, sx, oy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); +} + +static void +layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + /* Split master into master + stack if we have enough clients */ + if (m->nmaster && n > m->nmaster) { + layout_split_horizontal_fixed(m, x, y, h, w, ih, iv, n); + } else { + layout_no_split(m, x, y, h, w, ih, iv, n); + } +} + +static void +layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + int sh, sy; + + sh = (h - ih) * (1 - m->mfact); + h = (h - ih) * m->mfact; + if (m->ltaxis[LAYOUT] < 0) { // mirror + sy = y; + y += sh + ih; + } else { + sy = y + h + ih; + } + + (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); + (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, n - m->nmaster, m->nmaster); +} + +static void +layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + /* Split master into master + stack if we have enough clients */ + if (!m->nmaster || n <= m->nmaster) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { + layout_split_horizontal(m, x, y, h, w, ih, iv, n); + } else { + layout_split_horizontal_dual_stack_fixed(m, x, y, h, w, ih, iv, n); + } +} + +static void +layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + int sh, sy, ox, sc; + + if (m->nstack) + sc = m->nstack; + else + sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); + + sh = (h - ih) * (1 - m->mfact); + h = (h - ih) * m->mfact; + sw = (w - iv) / 2; + ox = x + sw + iv; + if (m->ltaxis[LAYOUT] < 0) { // mirror + sy = y; + y += sh + ih; + } else { + sy = y + h + ih; + } + + (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); + (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, sw, ih, iv, n, sc, m->nmaster); + (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, sy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); +} + +static void +layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + /* Split master into master + stack if we have enough clients */ + if (!m->nmaster || n <= m->nmaster) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { + layout_split_vertical(m, x, y, h, w, ih, iv, n); + } else { + layout_split_centered_vertical_fixed(m, x, y, h, w, ih, iv, n); + } +} + +static void +layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + int sw, sx, ox, sc; + + if (m->nstack) + sc = m->nstack; + else + sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); + + sw = (w - 2*iv) * (1 - m->mfact) / 2; + w = (w - 2*iv) * m->mfact; + if (m->ltaxis[LAYOUT] < 0) { // mirror + sx = x; + x += sw + iv; + ox = x + w + iv; + } else { + ox = x; + x += sw + iv; + sx = x + w + iv; + } + + (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); + (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, sc, m->nmaster); + (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, y, h, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); +} + +static void +layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + /* Split master into master + stack if we have enough clients */ + if (!m->nmaster || n <= m->nmaster) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) { + layout_split_horizontal(m, x, y, h, w, ih, iv, n); + } else { + layout_split_centered_horizontal_fixed(m, x, y, h, w, ih, iv, n); + } +} + +static void +layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + int sh, sy, oy, sc; + + if (m->nstack) + sc = m->nstack; + else + sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0); + + sh = (h - 2*ih) * (1 - m->mfact) / 2; + h = (h - 2*ih) * m->mfact; + if (m->ltaxis[LAYOUT] < 0) { // mirror + sy = y; + y += sh + ih; + oy = y + h + ih; + } else { + oy = y; + y += sh + ih; + sy = y + h + ih; + } + + (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0); + (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, sc, m->nmaster); + (&flextiles[m->ltaxis[STACK2]])->arrange(m, x, oy, sh, w, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc); +} + +static void +layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + /* Split master into master + stack if we have enough clients */ + if (!m->nmaster || n <= m->nmaster) { + layout_no_split(m, x, y, h, w, ih, iv, n); + } else { + layout_floating_master_fixed(m, x, y, h, w, ih, iv, n); + } +} + +static void +layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n) +{ + int mh, mw; + + /* Draw stack area first */ + (&flextiles[m->ltaxis[STACK]])->arrange(m, x, y, h, w, ih, iv, n, n - m->nmaster, m->nmaster); + + if (w > h) { + mw = w * m->mfact; + mh = h * 0.9; + } else { + mw = w * 0.9; + mh = h * m->mfact; + } + x = x + (w - mw) / 2; + y = y + (h - mh) / 2; + + (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, mh, mw, ih, iv, n, m->nmaster, 0); +} + +static void +arrange_left_to_right(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int i, rest; + float facts, fact = 1; + Client *c; + + if (ai + an > n) + an = n - ai; + + w -= iv * (an - 1); + getfactsforrange(m, an, ai, w, &rest, &facts); + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i >= ai && i < (ai + an)) { + #if CFACTS_PATCH + fact = c->cfact; + #endif // CFACTS_PATCH + resize(c, x, y, w * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), h - (2*c->bw), 0); + x += WIDTH(c) + iv; + } + } +} + +static void +arrange_top_to_bottom(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int i, rest; + float facts, fact = 1; + Client *c; + + if (ai + an > n) + an = n - ai; + + h -= ih * (an - 1); + getfactsforrange(m, an, ai, h, &rest, &facts); + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i >= ai && i < (ai + an)) { + #if CFACTS_PATCH + fact = c->cfact; + #endif // CFACTS_PATCH + resize(c, x, y, w - (2*c->bw), h * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), 0); + y += HEIGHT(c) + ih; + } + } +} + +static void +arrange_monocle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int i; + Client *c; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i >= ai && i < (ai + an)) + resize(c, x, y, w - (2*c->bw), h - (2*c->bw), 0); +} + +static void +arrange_gridmode(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int i, cols, rows, ch, cw, cx, cy, cc, cr, chrest, cwrest; // counters + Client *c; + + /* grid dimensions */ + for (rows = 0; rows <= an/2; rows++) + if (rows*rows >= an) + break; + cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows; + + /* window geoms (cell height/width) */ + ch = (h - ih * (rows - 1)) / (rows ? rows : 1); + cw = (w - iv * (cols - 1)) / (cols ? cols : 1); + chrest = h - ih * (rows - 1) - ch * rows; + cwrest = w - iv * (cols - 1) - cw * cols; + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i >= ai && i < (ai + an)) { + cc = ((i - ai) / rows); // client column number + cr = ((i - ai) % rows); // client row number + cx = x + cc * (cw + iv) + MIN(cc, cwrest); + cy = y + cr * (ch + ih) + MIN(cr, chrest); + resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); + } + } +} + +static void +arrange_horizgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int ntop, nbottom, rh, rest; + + /* Exception when there is only one client; don't split into two rows */ + if (an == 1) { + arrange_monocle(m, x, y, h, w, ih, iv, n, an, ai); + return; + } + + ntop = an / 2; + nbottom = an - ntop; + rh = (h - ih) / 2; + rest = h - ih - rh * 2; + arrange_left_to_right(m, x, y, rh + rest, w, ih, iv, n, ntop, ai); + arrange_left_to_right(m, x, y + rh + ih + rest, rh, w, ih, iv, n, nbottom, ai + ntop); +} + +static void +arrange_gapplessgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int i, cols, rows, ch, cw, cn, rn, cc, rrest, crest; // counters + Client *c; + + /* grid dimensions */ + for (cols = 1; cols <= an/2; cols++) + if (cols*cols >= an) + break; + if (an == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ + cols = 2; + rows = an/cols; + cn = rn = cc = 0; // reset column no, row no, client count + + ch = (h - ih * (rows - 1)) / rows; + rrest = (h - ih * (rows - 1)) - ch * rows; + cw = (w - iv * (cols - 1)) / cols; + crest = (w - iv * (cols - 1)) - cw * cols; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i >= ai && i < (ai + an)) { + if (cc/rows + 1 > cols - an%cols) { + rows = an/cols + 1; + ch = (h - ih * (rows - 1)) / rows; + rrest = (h - ih * (rows - 1)) - ch * rows; + } + resize(c, + x, + y + rn*(ch + ih) + MIN(rn, rrest), + cw + (cn < crest ? 1 : 0) - 2*c->bw, + ch + (rn < rrest ? 1 : 0) - 2*c->bw, + 0); + rn++; + cc++; + if (rn >= rows) { + rn = 0; + x += cw + ih + (cn < crest ? 1 : 0); + cn++; + } + } + } +} + +/* This version of gappless grid fills rows first */ +static void +arrange_gapplessgrid_alt1(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int i, cols, rows, rest, ch; + + /* grid dimensions */ + for (cols = 1; cols <= an/2; cols++) + if (cols*cols >= an) + break; + rows = (cols && (cols - 1) * cols >= an) ? cols - 1 : cols; + ch = (h - ih * (rows - 1)) / (rows ? rows : 1); + rest = (h - ih * (rows - 1)) - ch * rows; + + for (i = 0; i < rows; i++) { + arrange_left_to_right(m, x, y, ch + (i < rest ? 1 : 0), w, ih, iv, n, MIN(cols, an - i*cols), ai + i*cols); + y += ch + (i < rest ? 1 : 0) + ih; + } +} + +/* This version of gappless grid fills columns first */ +static void +arrange_gapplessgrid_alt2(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + int i, cols, rows, rest, cw; + + /* grid dimensions */ + for (rows = 0; rows <= an/2; rows++) + if (rows*rows >= an) + break; + cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows; + cw = (w - iv * (cols - 1)) / (cols ? cols : 1); + rest = (w - iv * (cols - 1)) - cw * cols; + + for (i = 0; i < cols; i++) { + arrange_top_to_bottom(m, x, y, h, cw + (i < rest ? 1 : 0), ih, iv, n, MIN(rows, an - i*rows), ai + i*rows); + x += cw + (i < rest ? 1 : 0) + iv; + } +} + +static void +arrange_fibonacci(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai, int s) +{ + int i, j, nv, hrest = 0, wrest = 0, nx = x, ny = y, nw = w, nh = h, r = 1; + Client *c; + + for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) { + if (j >= ai && j < (ai + an)) { + if (r) { + if ((i % 2 && ((nh - ih) / 2) <= (bh + 2*c->bw)) || (!(i % 2) && ((nw - iv) / 2) <= (bh + 2*c->bw))) { + r = 0; + } + if (r && i < an - 1) { + if (i % 2) { + nv = (nh - ih) / 2; + hrest = nh - 2*nv - ih; + nh = nv; + } else { + nv = (nw - iv) / 2; + wrest = nw - 2*nv - iv; + nw = nv; + } + + if ((i % 4) == 2 && !s) + nx += nw + iv; + else if ((i % 4) == 3 && !s) + ny += nh + ih; + } + if ((i % 4) == 0) { + if (s) { + ny += nh + ih; + nh += hrest; + } else { + nh -= hrest; + ny -= nh + ih; + } + } else if ((i % 4) == 1) { + nx += nw + iv; + nw += wrest; + } else if ((i % 4) == 2) { + ny += nh + ih; + nh += hrest; + if (i < n - 1) + nw += wrest; + } else if ((i % 4) == 3) { + if (s) { + nx += nw + iv; + nw -= wrest; + } else { + nw -= wrest; + nx -= nw + iv; + nh += hrest; + } + } + if (i == 0) { + if (an != 1) { + nw = (w - iv) - (w - iv) * (1 - m->mfact); + wrest = 0; + } + ny = y; + } else if (i == 1) + nw = w - nw - iv; + i++; + } + + resize(c, nx, ny, nw - 2 * c->bw, nh - 2*c->bw, False); + } + } +} + +static void +arrange_dwindle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 1); +} + +static void +arrange_spiral(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 0); +} + +static void +arrange_tatami(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai) +{ + unsigned int i, j, nx, ny, nw, nh, tnx, tny, tnw, tnh, nhrest, hrest, wrest, areas, mats, cats; + Client *c; + + nx = x; + ny = y; + nw = w; + nh = h; + + mats = an / 5; + cats = an % 5; + hrest = 0; + wrest = 0; + + areas = mats + (cats > 0); + nh = (h - ih * (areas - 1)) / areas; + nhrest = (h - ih * (areas - 1)) % areas; + + for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) { + if (j >= ai && j < (ai + an)) { + + tnw = nw; + tnx = nx; + tnh = nh; + tny = ny; + + if (j < ai + cats) { + /* Arrange cats (all excess clients that can't be tiled as mats). Cats sleep on mats. */ + + switch (cats) { + case 1: // fill + break; + case 2: // up and down + if ((i % 5) == 0) //up + tnh = (nh - ih) / 2 + (nh - ih) % 2; + else if ((i % 5) == 1) { //down + tny += (nh - ih) / 2 + (nh - ih) % 2 + ih; + tnh = (nh - ih) / 2; + } + break; + case 3: //bottom, up-left and up-right + if ((i % 5) == 0) { // up-left + tnw = (nw - iv) / 2 + (nw - iv) % 2; + tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3; + } else if ((i % 5) == 1) { // up-right + tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv; + tnw = (nw - iv) / 2; + tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3; + } else if ((i % 5) == 2) { //bottom + tnh = (nh - ih) / 3; + tny += (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3 + ih; + } + break; + case 4: // bottom, left, right and top + if ((i % 5) == 0) { //top + hrest = (nh - 2 * ih) % 4; + tnh = (nh - 2 * ih) / 4 + (hrest ? 1 : 0); + } else if ((i % 5) == 1) { // left + tnw = (nw - iv) / 2 + (nw - iv) % 2; + tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih; + tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0); + } else if ((i % 5) == 2) { // right + tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv; + tnw = (nw - iv) / 2; + tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih; + tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0); + } else if ((i % 5) == 3) { // bottom + tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0) + 2 * ih; + tnh = (nh - 2 * ih) / 4 + (hrest > 2 ? 1 : 0); + } + break; + } + + } else { + /* Arrange mats. One mat is a collection of five clients arranged tatami style */ + + if (((i - cats) % 5) == 0) { + if ((cats > 0) || ((i - cats) >= 5)) { + tny = ny = ny + nh + (nhrest > 0 ? 1 : 0) + ih; + --nhrest; + } + } + + switch ((i - cats) % 5) { + case 0: // top-left-vert + wrest = (nw - 2 * iv) % 3; + hrest = (nh - 2 * ih) % 3; + tnw = (nw - 2 * iv) / 3 + (wrest ? 1 : 0); + tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv; + break; + case 1: // top-right-hor + tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv; + tnw = (nw - 2 * iv) * 2 / 3 + (wrest > 1 ? 1 : 0) + iv; + tnh = (nh - 2 * ih) / 3 + (hrest ? 1 : 0); + break; + case 2: // center + tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv; + tnw = (nw - 2 * iv) / 3 + (wrest > 1 ? 1 : 0); + tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih; + tnh = (nh - 2 * ih) / 3 + (hrest > 1 ? 1 : 0); + break; + case 3: // bottom-right-vert + tnx += (nw - 2 * iv) * 2 / 3 + wrest + 2 * iv; + tnw = (nw - 2 * iv) / 3; + tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih; + tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv; + break; + case 4: // (oldest) bottom-left-hor + tnw = (nw - 2 * iv) * 2 / 3 + wrest + iv; + tny += (nh - 2 * ih) * 2 / 3 + hrest + 2 * iv; + tnh = (nh - 2 * ih) / 3; + break; + } + + } + + resize(c, tnx, tny, tnw - 2 * c->bw, tnh - 2 * c->bw, False); + ++i; + } + } +} + +static void +flextile(Monitor *m) +{ + unsigned int n; + int oh = 0, ov = 0, ih = 0, iv = 0; // gaps outer/inner horizontal/vertical + + #if VANITYGAPS_PATCH + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + Client *c; + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (m->lt[m->sellt]->preset.layout != m->ltaxis[LAYOUT] || + m->lt[m->sellt]->preset.masteraxis != m->ltaxis[MASTER] || + m->lt[m->sellt]->preset.stack1axis != m->ltaxis[STACK] || + m->lt[m->sellt]->preset.stack2axis != m->ltaxis[STACK2]) + setflexsymbols(m, n); + else if (m->lt[m->sellt]->preset.symbolfunc != NULL) + m->lt[m->sellt]->preset.symbolfunc(m, n); + + if (n == 0) + return; + + #if VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH + /* No outer gap if full screen monocle */ + if (abs(m->ltaxis[MASTER]) == MONOCLE && (abs(m->ltaxis[LAYOUT]) == NO_SPLIT || n <= m->nmaster)) { + oh = 0; + ov = 0; + } + #endif // VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH + + (&flexlayouts[abs(m->ltaxis[LAYOUT])])->arrange(m, m->wx + ov, m->wy + oh, m->wh - 2*oh, m->ww - 2*ov, ih, iv, n); + return; +} + +static void +setflexsymbols(Monitor *m, unsigned int n) +{ + int l; + char sym1, sym2, sym3; + Client *c; + + if (n == 0) + for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + + l = abs(m->ltaxis[LAYOUT]); + if (m->ltaxis[MASTER] == MONOCLE && (l == NO_SPLIT || !m->nmaster || n <= m->nmaster)) { + monoclesymbols(m, n); + return; + } + + if (m->ltaxis[STACK] == MONOCLE && (l == SPLIT_VERTICAL || l == SPLIT_HORIZONTAL_FIXED)) { + decksymbols(m, n); + return; + } + + /* Layout symbols */ + if (l == NO_SPLIT || !m->nmaster) { + sym1 = sym2 = sym3 = (int)tilesymb[m->ltaxis[MASTER]]; + } else { + sym2 = layoutsymb[l]; + if (m->ltaxis[LAYOUT] < 0) { + sym1 = tilesymb[m->ltaxis[STACK]]; + sym3 = tilesymb[m->ltaxis[MASTER]]; + } else { + sym1 = tilesymb[m->ltaxis[MASTER]]; + sym3 = tilesymb[m->ltaxis[STACK]]; + } + } + + snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3); +} + +static void +monoclesymbols(Monitor *m, unsigned int n) +{ + if (n > 0) + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); + else + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[M]"); +} + +static void +decksymbols(Monitor *m, unsigned int n) +{ + if (n > m->nmaster) + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[]%d", n); + else + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[D]"); +} + +/* Mirror layout axis for flextile */ +void +mirrorlayout(const Arg *arg) +{ + if (!selmon->lt[selmon->sellt]->arrange) + return; + selmon->ltaxis[LAYOUT] *= -1; + #if PERTAG_PATCH + selmon->pertag->ltaxis[selmon->pertag->curtag][0] = selmon->ltaxis[LAYOUT]; + #endif // PERTAG_PATCH + arrange(selmon); +} + +/* Rotate layout axis for flextile */ +void +rotatelayoutaxis(const Arg *arg) +{ + int incr = (arg->i > 0 ? 1 : -1); + int axis = abs(arg->i) - 1; + + if (!selmon->lt[selmon->sellt]->arrange) + return; + if (axis == LAYOUT) { + if (selmon->ltaxis[LAYOUT] >= 0) { + selmon->ltaxis[LAYOUT] += incr; + if (selmon->ltaxis[LAYOUT] >= LAYOUT_LAST) + selmon->ltaxis[LAYOUT] = 0; + else if (selmon->ltaxis[LAYOUT] < 0) + selmon->ltaxis[LAYOUT] = LAYOUT_LAST - 1; + } else { + selmon->ltaxis[LAYOUT] -= incr; + if (selmon->ltaxis[LAYOUT] <= -LAYOUT_LAST) + selmon->ltaxis[LAYOUT] = 0; + else if (selmon->ltaxis[LAYOUT] > 0) + selmon->ltaxis[LAYOUT] = -LAYOUT_LAST + 1; + } + } else { + selmon->ltaxis[axis] += incr; + if (selmon->ltaxis[axis] >= AXIS_LAST) + selmon->ltaxis[axis] = 0; + else if (selmon->ltaxis[axis] < 0) + selmon->ltaxis[axis] = AXIS_LAST - 1; + } + #if PERTAG_PATCH + selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis]; + #endif // PERTAG_PATCH + arrange(selmon); + setflexsymbols(selmon, 0); +} + +void +incnstack(const Arg *arg) +{ + #if PERTAG_PATCH + selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag] = MAX(selmon->nstack + arg->i, 0); + #else + selmon->nstack = MAX(selmon->nstack + arg->i, 0); + #endif // PERTAG_PATCH + arrange(selmon); +} + diff --git a/dwm/patch/layout_flextile-deluxe.h b/dwm/patch/layout_flextile-deluxe.h new file mode 100755 index 0000000..92df5c5 --- /dev/null +++ b/dwm/patch/layout_flextile-deluxe.h @@ -0,0 +1,121 @@ +static void flextile(Monitor *m); +static void getfactsforrange(Monitor *m, int an, int ai, int size, int *rest, float *fact); +static void mirrorlayout(const Arg *arg); +static void rotatelayoutaxis(const Arg *arg); +#if IPC_PATCH || DWMC_PATCH +static void setlayoutaxisex(const Arg *arg); +#endif // IPC_PATCH | DWMC_PATCH +static void incnstack(const Arg *arg); + +/* Symbol handlers */ +static void setflexsymbols(Monitor *m, unsigned int n); +static void monoclesymbols(Monitor *m, unsigned int n); +static void decksymbols(Monitor *m, unsigned int n); + +/* Layout split */ +static void layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); +static void layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n); + +/* Layout tile arrangements */ +static void arrange_left_to_right(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_top_to_bottom(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_monocle(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_gapplessgrid(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_gapplessgrid_alt1(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_gapplessgrid_alt2(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_gridmode(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_horizgrid(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_dwindle(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_spiral(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); +static void arrange_tatami(Monitor *m, int ax, int ay, int ah, int aw, int ih, int iv, int n, int an, int ai); + +/* Named flextile constants */ +enum { + LAYOUT, // controls overall layout arrangement / split + MASTER, // indicates the tile arrangement for the master area + STACK, // indicates the tile arrangement for the stack area + STACK2, // indicates the tile arrangement for the secondary stack area + LTAXIS_LAST, +}; + +/* Layout arrangements */ +enum { + NO_SPLIT, + SPLIT_VERTICAL, // master stack vertical split + SPLIT_HORIZONTAL, // master stack horizontal split + SPLIT_CENTERED_VERTICAL, // centered master vertical split + SPLIT_CENTERED_HORIZONTAL, // centered master horizontal split + SPLIT_VERTICAL_DUAL_STACK, // master stack vertical split with dual stack + SPLIT_HORIZONTAL_DUAL_STACK, // master stack vertical split with dual stack + FLOATING_MASTER, // (fake) floating master + SPLIT_VERTICAL_FIXED, // master stack vertical fixed split + SPLIT_HORIZONTAL_FIXED, // master stack horizontal fixed split + SPLIT_CENTERED_VERTICAL_FIXED, // centered master vertical fixed split + SPLIT_CENTERED_HORIZONTAL_FIXED, // centered master horizontal fixed split + SPLIT_VERTICAL_DUAL_STACK_FIXED, // master stack vertical split with fixed dual stack + SPLIT_HORIZONTAL_DUAL_STACK_FIXED, // master stack vertical split with fixed dual stack + FLOATING_MASTER_FIXED, // (fake) fixed floating master + LAYOUT_LAST, +}; + +static char layoutsymb[] = { + 32, // " ", + 124, // "|", + 61, // "=", + 94, // "^", + 126, // "~", + 58, // ":", + 59, // ";", + 43, // "+", + 124, // "¦", + 61, // "=", + 94, // "^", + 126, // "~", + 58, // ":", + 59, // ";", + 43, // "+", +}; + +/* Tile arrangements */ +enum { + TOP_TO_BOTTOM, // clients are arranged vertically + LEFT_TO_RIGHT, // clients are arranged horizontally + MONOCLE, // clients are arranged in deck / monocle mode + GAPPLESSGRID, // clients are arranged in a gappless grid (original formula) + GAPPLESSGRID_ALT1, // clients are arranged in a gappless grid (alt. 1, fills rows first) + GAPPLESSGRID_ALT2, // clients are arranged in a gappless grid (alt. 2, fills columns first) + GRIDMODE, // clients are arranged in a grid + HORIZGRID, // clients are arranged in a horizontal grid + DWINDLE, // clients are arranged in fibonacci dwindle mode + SPIRAL, // clients are arranged in fibonacci spiral mode + TATAMI, // clients are arranged as tatami mats + AXIS_LAST, +}; + +static char tilesymb[] = { + 61, // "=", + 124, // "|", + 68, // "D", + 71, // "G", + 49, // "1", + 50, // "2" + 35, // "#", + 126, // "~", + 92, // "\\", + 64, // "@", + 84, // "T", +}; + diff --git a/dwm/patch/layout_gapplessgrid.c b/dwm/patch/layout_gapplessgrid.c new file mode 100755 index 0000000..79f236a --- /dev/null +++ b/dwm/patch/layout_gapplessgrid.c @@ -0,0 +1,99 @@ +#if VANITYGAPS_PATCH +void +gaplessgrid(Monitor *m) +{ + unsigned int i, n; + int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters + int oh, ov, ih, iv; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + /* grid dimensions */ + for (cols = 0; cols <= n/2; cols++) + if (cols*cols >= n) + break; + if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ + cols = 2; + rows = n/cols; + cn = rn = 0; // reset column no, row no, client count + + ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; + cw = (m->ww - 2*ov - iv * (cols - 1)) / cols; + rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; + crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; + x = m->wx + ov; + y = m->wy + oh; + + for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { + if (i/rows + 1 > cols - n%cols) { + rows = n/cols + 1; + ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; + rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; + } + resize(c, + x, + y + rn*(ch + ih) + MIN(rn, rrest), + cw + (cn < crest ? 1 : 0) - 2*c->bw, + ch + (rn < rrest ? 1 : 0) - 2*c->bw, + 0); + rn++; + if (rn >= rows) { + rn = 0; + x += cw + ih + (cn < crest ? 1 : 0); + cn++; + } + } +} +#else +void +gaplessgrid(Monitor *m) +{ + unsigned int i, n; + int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + /* grid dimensions */ + for (cols = 0; cols <= n/2; cols++) + if (cols*cols >= n) + break; + if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ + cols = 2; + rows = n/cols; + cn = rn = 0; // reset column no, row no, client count + + ch = m->wh / rows; + cw = m->ww / cols; + rrest = m->wh - ch * rows; + crest = m->ww - cw * cols; + x = m->wx; + y = m->wy; + + for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { + if (i/rows + 1 > cols - n%cols) { + rows = n/cols + 1; + ch = m->wh / rows; + rrest = m->wh - ch * rows; + } + resize(c, + x, + y + rn*ch + MIN(rn, rrest), + cw + (cn < crest ? 1 : 0) - 2*c->bw, + ch + (rn < rrest ? 1 : 0) - 2*c->bw, + 0); + rn++; + if (rn >= rows) { + rn = 0; + x += cw + (cn < crest ? 1 : 0); + cn++; + } + } +} +#endif + diff --git a/dwm/patch/layout_gapplessgrid.h b/dwm/patch/layout_gapplessgrid.h new file mode 100755 index 0000000..1a4ffc2 --- /dev/null +++ b/dwm/patch/layout_gapplessgrid.h @@ -0,0 +1,2 @@ +static void gaplessgrid(Monitor *m); + diff --git a/dwm/patch/layout_grid.c b/dwm/patch/layout_grid.c new file mode 100755 index 0000000..7ac832f --- /dev/null +++ b/dwm/patch/layout_grid.c @@ -0,0 +1,61 @@ +#if VANITYGAPS_PATCH +void +grid(Monitor *m) +{ + unsigned int i, n; + int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows; + int oh, ov, ih, iv; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + + /* grid dimensions */ + for (rows = 0; rows <= n/2; rows++) + if (rows*rows >= n) + break; + cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; + + /* window geoms (cell height/width) */ + ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1); + cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1); + chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; + cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + cc = i / rows; + cr = i % rows; + cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest); + cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest); + resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); + } +} +#else +void +grid(Monitor *m) +{ + unsigned int i, n; + int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + + /* grid dimensions */ + for (rows = 0; rows <= n/2; rows++) + if (rows*rows >= n) + break; + cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; + + /* window geoms (cell height/width) */ + ch = m->wh / (rows ? rows : 1); + cw = m->ww / (cols ? cols : 1); + chrest = m->wh - ch * rows; + cwrest = m->ww - cw * cols; + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + cc = i / rows; + cr = i % rows; + cx = m->wx + cc * cw + MIN(cc, cwrest); + cy = m->wy + cr * ch + MIN(cr, chrest); + resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); + } +} +#endif + diff --git a/dwm/patch/layout_grid.h b/dwm/patch/layout_grid.h new file mode 100755 index 0000000..2c03abb --- /dev/null +++ b/dwm/patch/layout_grid.h @@ -0,0 +1,2 @@ +static void grid(Monitor *m); + diff --git a/dwm/patch/layout_horizgrid.c b/dwm/patch/layout_horizgrid.c new file mode 100755 index 0000000..beb8e0b --- /dev/null +++ b/dwm/patch/layout_horizgrid.c @@ -0,0 +1,104 @@ +void +horizgrid(Monitor *m) { + Client *c; + unsigned int n, i; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + int ntop; + float mfacts = 0, sfacts = 0; + int mrest, srest, mtotal = 0, stotal = 0; + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + if (n == 0) + return; + + if (n <= 2) + ntop = n; + else { + ntop = n / 2; + } + + #if VANITYGAPS_PATCH + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + sw = mw = m->ww - 2*ov; + + if (n > ntop) { + sh = (mh - ih) / 2; + mh = mh - ih - sh; + sy = my + mh + ih; + mw = m->ww - 2*ov - iv * (ntop - 1); + sw = m->ww - 2*ov - iv * (n - ntop - 1); + } + #else + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (n > ntop) { + sh = mh / 2; + mh = mh - sh; + sy = my + mh; + } + #endif // VANITYGAPS_PATCH + + /* calculate facts */ + #if CFACTS_PATCH + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < ntop) + mfacts += c->cfact; + else + sfacts += c->cfact; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < ntop) + mtotal += mh * (c->cfact / mfacts); + else + stotal += sw * (c->cfact / sfacts); + #else + mfacts = ntop; + sfacts = n - ntop; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < ntop) + mtotal += mh / mfacts; + else + stotal += sw / sfacts; + #endif // CFACTS_PATCH + + mrest = mh - mtotal; + srest = sw - stotal; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < ntop) { + #if CFACTS_PATCH + resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #else + resize(c, mx, my, mw / mfacts + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + mx += WIDTH(c) + iv; + #else + mx += WIDTH(c); + #endif // VANITYGAPS_PATCH + } else { + #if CFACTS_PATCH + resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + #else + resize(c, sx, sy, sw / sfacts + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + sx += WIDTH(c) + iv; + #else + sx += WIDTH(c); + #endif // VANITYGAPS_PATCH + } +} + diff --git a/dwm/patch/layout_horizgrid.h b/dwm/patch/layout_horizgrid.h new file mode 100755 index 0000000..799fa9c --- /dev/null +++ b/dwm/patch/layout_horizgrid.h @@ -0,0 +1,2 @@ +static void horizgrid(Monitor *m); + diff --git a/dwm/patch/layout_monocle.c b/dwm/patch/layout_monocle.c new file mode 100755 index 0000000..f7b5bc3 --- /dev/null +++ b/dwm/patch/layout_monocle.c @@ -0,0 +1,38 @@ +#if VANITYGAPS_PATCH && VANITYGAPS_MONOCLE_PATCH +void +monocle(Monitor *m) +{ + unsigned int n; + int oh, ov, ih, iv; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + + #if !MONOCLESYMBOL_PATCH + if (n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); + #endif // MONOCLESYMBOL_PATCH + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) + resize(c, m->wx + ov, m->wy + oh, m->ww - 2 * c->bw - 2 * ov, m->wh - 2 * c->bw - 2 * oh, 0); +} +#else +void +monocle(Monitor *m) +{ + #if !MONOCLESYMBOL_PATCH + unsigned int n = 0; + #endif // MONOCLESYMBOL_PATCH + Client *c; + + #if !MONOCLESYMBOL_PATCH + 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); + #endif // MONOCLESYMBOL_PATCH + 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); +} +#endif // VANITYGAPS_PATCH + diff --git a/dwm/patch/layout_monocle.h b/dwm/patch/layout_monocle.h new file mode 100755 index 0000000..f32e49f --- /dev/null +++ b/dwm/patch/layout_monocle.h @@ -0,0 +1,2 @@ +static void monocle(Monitor *m); + diff --git a/dwm/patch/layout_nrowgrid.c b/dwm/patch/layout_nrowgrid.c new file mode 100755 index 0000000..7fada74 --- /dev/null +++ b/dwm/patch/layout_nrowgrid.c @@ -0,0 +1,104 @@ +#if VANITYGAPS_PATCH +void +nrowgrid(Monitor *m) +{ + unsigned int n = 0, i = 0, ri = 0, ci = 0; /* counters */ + int oh, ov, ih, iv; /* vanitygap settings */ + unsigned int cx, cy, cw, ch; /* client geometry */ + unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */ + unsigned int cols, rows = m->nmaster + 1; + Client *c; + + /* count clients */ + getgaps(m, &oh, &ov, &ih, &iv, &n); + + /* nothing to do here */ + if (n == 0) + return; + + /* force 2 clients to always split vertically */ + if (FORCE_VSPLIT && n == 2) + rows = 1; + + /* never allow empty rows */ + if (n < rows) + rows = n; + + /* define first row */ + cols = n / rows; + uc = cols; + cy = m->wy + oh; + ch = (m->wh - 2*oh - ih*(rows - 1)) / rows; + uh = ch; + + for (c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, ci++) { + if (ci == cols) { + uw = 0; + ci = 0; + ri++; + + /* next row */ + cols = (n - uc) / (rows - ri); + uc += cols; + cy = m->wy + oh + uh + ih; + uh += ch + ih; + } + + cx = m->wx + ov + uw; + cw = (m->ww - 2*ov - uw) / (cols - ci); + uw += cw + iv; + + resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0); + } +} +#else +void +nrowgrid(Monitor *m) +{ + unsigned int n = 0, i = 0, ri = 0, ci = 0; /* counters */ + unsigned int cx, cy, cw, ch; /* client geometry */ + unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */ + unsigned int cols, rows = m->nmaster + 1; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + /* force 2 clients to always split vertically */ + if (FORCE_VSPLIT && n == 2) + rows = 1; + + /* never allow empty rows */ + if (n < rows) + rows = n; + + /* define first row */ + cols = n / rows; + uc = cols; + cy = m->wy; + ch = m->wh / rows; + uh = ch; + + for (c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, ci++) { + if (ci == cols) { + uw = 0; + ci = 0; + ri++; + + /* next row */ + cols = (n - uc) / (rows - ri); + uc += cols; + cy = m->wy + uh; + uh += ch; + } + + cx = m->wx + uw; + cw = (m->ww - uw) / (cols - ci); + uw += cw; + + resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0); + } +} +#endif + diff --git a/dwm/patch/layout_nrowgrid.h b/dwm/patch/layout_nrowgrid.h new file mode 100755 index 0000000..9cce593 --- /dev/null +++ b/dwm/patch/layout_nrowgrid.h @@ -0,0 +1,2 @@ +static void nrowgrid(Monitor *m); + diff --git a/dwm/patch/layout_tile.c b/dwm/patch/layout_tile.c new file mode 100755 index 0000000..cd4f1ae --- /dev/null +++ b/dwm/patch/layout_tile.c @@ -0,0 +1,74 @@ +static void +tile(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + + #if VANITYGAPS_PATCH + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + #else + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + #endif // VANITYGAPS_PATCH + + if (n == 0) + return; + + #if VANITYGAPS_PATCH + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); + sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); + sw = mw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = (mw - iv) * m->mfact; + sx = mx + mw + iv; + } + #else + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (m->nmaster && n > m->nmaster) { + sw = mw * (1 - m->mfact); + mw = mw * m->mfact; + sx = mx + mw; + } + #endif // VANITYGAPS_PATCH + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + #if CFACTS_PATCH + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) * c->cfact + (i < mrest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + my += HEIGHT(c) + ih; + #else + my += HEIGHT(c); + #endif + } else { + #if CFACTS_PATCH + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) * c->cfact + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + #else + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + #endif // CFACTS_PATCH + #if VANITYGAPS_PATCH + sy += HEIGHT(c) + ih; + #else + sy += HEIGHT(c); + #endif + } +} + diff --git a/dwm/patch/layout_tile.h b/dwm/patch/layout_tile.h new file mode 100755 index 0000000..4aff634 --- /dev/null +++ b/dwm/patch/layout_tile.h @@ -0,0 +1,2 @@ +static void tile(Monitor *m); + diff --git a/dwm/patch/layoutmenu.sh b/dwm/patch/layoutmenu.sh new file mode 100755 index 0000000..0bb0456 --- /dev/null +++ b/dwm/patch/layoutmenu.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +cat <<> Floating Layout 1 +[M] Monocle Layout 2 +EOF + diff --git a/dwm/patch/maximize.c b/dwm/patch/maximize.c new file mode 100755 index 0000000..c89dbda --- /dev/null +++ b/dwm/patch/maximize.c @@ -0,0 +1,70 @@ +void +maximize(int x, int y, int w, int h) +{ + XEvent ev; + + if (!selmon->sel || selmon->sel->isfixed) + return; + XRaiseWindow(dpy, selmon->sel->win); + if (!selmon->sel->ismax) { + if (!selmon->lt[selmon->sellt]->arrange || selmon->sel->isfloating) + selmon->sel->wasfloating = True; + else { + togglefloating(NULL); + selmon->sel->wasfloating = False; + } + selmon->sel->oldx = selmon->sel->x; + selmon->sel->oldy = selmon->sel->y; + selmon->sel->oldw = selmon->sel->w; + selmon->sel->oldh = selmon->sel->h; + resize(selmon->sel, x, y, w, h, True); + selmon->sel->ismax = True; + } + else { + resize(selmon->sel, selmon->sel->oldx, selmon->sel->oldy, selmon->sel->oldw, selmon->sel->oldh, True); + if (!selmon->sel->wasfloating) + togglefloating(NULL); + selmon->sel->ismax = False; + } + drawbar(selmon); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +#if SETBORDERPX_PATCH +void +togglemax(const Arg *arg) +{ + maximize(selmon->wx, selmon->wy, selmon->ww - 2 * selmon->borderpx, selmon->wh - 2 * selmon->borderpx); +} + +void +toggleverticalmax(const Arg *arg) +{ + maximize(selmon->sel->x, selmon->wy, selmon->sel->w, selmon->wh - 2 * selmon->borderpx); +} + +void +togglehorizontalmax(const Arg *arg) +{ + maximize(selmon->wx, selmon->sel->y, selmon->ww - 2 * selmon->borderpx, selmon->sel->h); +} +#else +void +togglemax(const Arg *arg) +{ + maximize(selmon->wx, selmon->wy, selmon->ww - 2 * borderpx, selmon->wh - 2 * borderpx); +} + +void +toggleverticalmax(const Arg *arg) +{ + maximize(selmon->sel->x, selmon->wy, selmon->sel->w, selmon->wh - 2 * borderpx); +} + +void +togglehorizontalmax(const Arg *arg) +{ + maximize(selmon->wx, selmon->sel->y, selmon->ww - 2 * borderpx, selmon->sel->h); +} +#endif // SETBORDERPX_PATCH + diff --git a/dwm/patch/maximize.h b/dwm/patch/maximize.h new file mode 100755 index 0000000..f3c6c9a --- /dev/null +++ b/dwm/patch/maximize.h @@ -0,0 +1,5 @@ +static void maximize(int x, int y, int w, int h); +static void togglemax(const Arg *arg); +static void toggleverticalmax(const Arg *arg); +static void togglehorizontalmax(const Arg *arg); + diff --git a/dwm/patch/movecenter.c b/dwm/patch/movecenter.c new file mode 100755 index 0000000..b91f731 --- /dev/null +++ b/dwm/patch/movecenter.c @@ -0,0 +1,15 @@ +void +movecenter(const Arg *arg) +{ + Client *c = selmon->sel; + XEvent ev; + + if (!c || !c->isfloating) + return; + + c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; + c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; + XMoveWindow(dpy, c->win, c->x, c->y); + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} diff --git a/dwm/patch/movecenter.h b/dwm/patch/movecenter.h new file mode 100755 index 0000000..a0d0992 --- /dev/null +++ b/dwm/patch/movecenter.h @@ -0,0 +1 @@ +static void movecenter(const Arg *arg); diff --git a/dwm/patch/moveplace.c b/dwm/patch/moveplace.c new file mode 100755 index 0000000..7211417 --- /dev/null +++ b/dwm/patch/moveplace.c @@ -0,0 +1,30 @@ +void +moveplace(const Arg *arg) +{ + Client *c; + int nh, nw, nx, ny; + c = selmon->sel; + if (!c || (arg->ui >= 9)) + return; + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) + togglefloating(NULL); + nh = (selmon->wh / 3) - (c->bw * 2); + nw = (selmon->ww / 3) - (c->bw * 2); + nx = (arg->ui % 3) -1; + ny = (arg->ui / 3) -1; + if (nx < 0) + nx = selmon->wx; + else if (nx > 0) + nx = selmon->wx + selmon->ww - nw - c->bw*2; + else + nx = selmon->wx + selmon->ww/2 - nw/2 - c->bw; + if (ny <0) + ny = selmon->wy; + else if (ny > 0) + ny = selmon->wy + selmon->wh - nh - c->bw*2; + else + ny = selmon->wy + selmon->wh/2 - nh/2 - c->bw; + resize(c, nx, ny, nw, nh, True); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, nw/2, nh/2); +} + diff --git a/dwm/patch/moveplace.h b/dwm/patch/moveplace.h new file mode 100755 index 0000000..57bc924 --- /dev/null +++ b/dwm/patch/moveplace.h @@ -0,0 +1,4 @@ +enum { WIN_NW, WIN_N, WIN_NE, WIN_W, WIN_C, WIN_E, WIN_SW, WIN_S, WIN_SE }; + +static void moveplace(const Arg *arg); + diff --git a/dwm/patch/moveresize.c b/dwm/patch/moveresize.c new file mode 100755 index 0000000..75d58e2 --- /dev/null +++ b/dwm/patch/moveresize.c @@ -0,0 +1,65 @@ +void +moveresize(const Arg *arg) { + /* only floating windows can be moved */ + Client *c; + c = selmon->sel; + int x, y, w, h, nx, ny, nw, nh, ox, oy, ow, oh; + char xAbs, yAbs, wAbs, hAbs; + int msx, msy, dx, dy, nmx, nmy; + unsigned int dui; + Window dummy; + + if (!c || !arg) + return; + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) + return; + if (sscanf((char *)arg->v, "%d%c %d%c %d%c %d%c", &x, &xAbs, &y, &yAbs, &w, &wAbs, &h, &hAbs) != 8) + return; + + /* compute new window position; prevent window from be positioned outside the current monitor */ + nw = c->w + w; + if (wAbs == 'W') + nw = w < selmon->mw - 2 * c->bw ? w : selmon->mw - 2 * c->bw; + + nh = c->h + h; + if (hAbs == 'H') + nh = h < selmon->mh - 2 * c->bw ? h : selmon->mh - 2 * c->bw; + + nx = c->x + x; + if (xAbs == 'X') { + if (x < selmon->mx) + nx = selmon->mx; + else if (x > selmon->mx + selmon->mw) + nx = selmon->mx + selmon->mw - nw - 2 * c->bw; + else + nx = x; + } + + ny = c->y + y; + if (yAbs == 'Y') { + if (y < selmon->my) + ny = selmon->my; + else if (y > selmon->my + selmon->mh) + ny = selmon->my + selmon->mh - nh - 2 * c->bw; + else + ny = y; + } + + ox = c->x; + oy = c->y; + ow = c->w; + oh = c->h; + + XRaiseWindow(dpy, c->win); + Bool xqp = XQueryPointer(dpy, root, &dummy, &dummy, &msx, &msy, &dx, &dy, &dui); + resize(c, nx, ny, nw, nh, True); + + /* move cursor along with the window to avoid problems caused by the sloppy focus */ + if (xqp && ox <= msx && (ox + ow) >= msx && oy <= msy && (oy + oh) >= msy) + { + nmx = c->x - ox + c->w - ow; + nmy = c->y - oy + c->h - oh; + XWarpPointer(dpy, None, None, 0, 0, 0, 0, nmx, nmy); + } +} + diff --git a/dwm/patch/moveresize.h b/dwm/patch/moveresize.h new file mode 100755 index 0000000..919ebad --- /dev/null +++ b/dwm/patch/moveresize.h @@ -0,0 +1,2 @@ +static void moveresize(const Arg *arg); + diff --git a/dwm/patch/movestack.c b/dwm/patch/movestack.c new file mode 100755 index 0000000..fe97f1d --- /dev/null +++ b/dwm/patch/movestack.c @@ -0,0 +1,51 @@ +void +movestack(const Arg *arg) +{ + Client *c = NULL, *p = NULL, *pc = NULL, *i; + if (arg->i > 0) { + if (!selmon->sel) + return; + /* 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/patch/movestack.h b/dwm/patch/movestack.h new file mode 100755 index 0000000..25f198f --- /dev/null +++ b/dwm/patch/movestack.h @@ -0,0 +1,2 @@ +static void movestack(const Arg *arg); + diff --git a/dwm/patch/mpdcontrol.c b/dwm/patch/mpdcontrol.c new file mode 100755 index 0000000..fc81e07 --- /dev/null +++ b/dwm/patch/mpdcontrol.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include + +#include + +#define MPDHOST "localhost" +#define MPDPORT 6600 + +struct mpd_connection *get_conn() +{ + struct mpd_connection *conn; + + conn = mpd_connection_new(MPDHOST, MPDPORT, 1000); + + if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { + fprintf(stderr, "Could not connect to mpd: %s\n", mpd_connection_get_error_message(conn)); + + mpd_connection_free(conn); + return NULL; + } + + return conn; +} + +void mpdchange(const Arg *direction) +{ + struct mpd_connection *conn; + + conn = get_conn(); + + if (conn == NULL) { + return; + } + + if (direction->i > 0) { + mpd_run_next(conn); + } + else { + mpd_run_previous(conn); + } + + mpd_connection_free(conn); +} + +char *get_regerror(int errcode, regex_t *compiled) +{ + size_t length = regerror(errcode, compiled, NULL, 0); + char *buffer = malloc(length); + (void) regerror(errcode, compiled, buffer, length); + + return buffer; +} + +void mpdcontrol() +{ + struct mpd_connection *conn; + struct mpd_status *status; + struct mpd_song *song; + enum mpd_state state; + + const char *filename; + + regex_t expr; + + conn = get_conn(); + + if (conn == NULL) { + return; + } + + status = mpd_run_status(conn); + + if (status == NULL) { + fprintf(stderr, "Could not get mpd status: %s\n", mpd_status_get_error(status)); + + mpd_status_free(status); + mpd_connection_free(conn); + return; + } + + state = mpd_status_get_state(status); + + if (state == MPD_STATE_STOP || state == MPD_STATE_PAUSE) { + mpd_run_play(conn); + mpd_status_free(status); + mpd_connection_free(conn); + } + else if (state != MPD_STATE_UNKNOWN) { //playing some music + song = mpd_run_current_song(conn); + + if (song == NULL){ + fprintf(stderr, "Error fetching current song!\n"); + + mpd_song_free(song); + mpd_status_free(status); + mpd_connection_free(conn); + return; + } + + filename = mpd_song_get_uri(song); + + int errcode = regcomp(&expr, "^[[:alnum:]]+://", REG_EXTENDED|REG_NOSUB); + if (errcode != 0) { + char *err = get_regerror(errcode, &expr); + fprintf(stderr, "Could not compile regexp: %s\n", err); + + mpd_song_free(song); + mpd_status_free(status); + mpd_connection_free(conn); + free(err); + regfree(&expr); + return; + } + + int matchcode = regexec(&expr, filename, 0, NULL, 0); + + if (matchcode == 0) { + if (strstr(filename, "file://") == filename) { //match just at the start of the filename + //this means that mpd is playing a file outside the music_dir, + //but on disk, so we can safely pause + mpd_run_toggle_pause(conn); + } + else { + mpd_run_stop(conn); + } + } + else if (matchcode == REG_NOMATCH) { + mpd_run_toggle_pause(conn); + } + else { + char *err = get_regerror(matchcode, &expr); + fprintf(stderr, "Error while matching regexp: %s\n", err); + + free(err); + } + + regfree(&expr); + mpd_song_free(song); + mpd_status_free(status); + mpd_connection_free(conn); + } +} + diff --git a/dwm/patch/mpdcontrol.h b/dwm/patch/mpdcontrol.h new file mode 100755 index 0000000..1ce304e --- /dev/null +++ b/dwm/patch/mpdcontrol.h @@ -0,0 +1,3 @@ +static void mpdchange(const Arg *direction); +static void mpdcontrol(); + diff --git a/dwm/patch/nametag.c b/dwm/patch/nametag.c new file mode 100755 index 0000000..2b7b038 --- /dev/null +++ b/dwm/patch/nametag.c @@ -0,0 +1,61 @@ +void +nametag(const Arg *arg) +{ + char *p, name[MAX_TAGLEN]; + FILE *f; + int i, group; + int tagindex; + Monitor *m = selmon; + #if BAR_ALTTAGSDECORATION_PATCH + Client *c; + int occ = 0; + + for (c = m->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_ALTTAGSDECORATION_PATCH + + errno = 0; // popen(3p) says on failure it "may" set errno + if (!(f = popen(NAMETAG_COMMAND, "r"))) { + fprintf(stderr, "dwm: popen command failed%s%s\n", errno ? ": " : "", errno ? strerror(errno) : ""); + return; + } + + if (!(p = fgets(name, MAX_TAGLEN, f)) && (i = errno) && ferror(f)) + fprintf(stderr, "dwm: fgets failed: %s\n", strerror(i)); + + pclose(f); + + if (!p) + return; + if ((p = strchr(name, '\n'))) + *p = '\0'; + + for (i = 0; i < NUMTAGS; i++) { + if (m->tagset[m->seltags] & (1 << i)) { + + tagindex = i + NUMTAGS * m->num; + if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS])) + tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]); + + #if BAR_ALTTAGSDECORATION_PATCH + if (occ & 1 << i) + group = ALT_TAGS_DECORATION; + else + #endif // BAR_ALTTAGSDECORATION_PATCH + #if BAR_ALTERNATIVE_TAGS_PATCH + if (m->alttag) + group = ALTERNATIVE_TAGS; + else + #endif // BAR_ALTERNATIVE_TAGS_PATCH + group = DEFAULT_TAGS; + + #if NAMETAG_PREPEND_PATCH + if (snprintf(tagicons[group][i], MAX_TAGLEN, NAMETAG_FORMAT, i+1, name) < 0) + fprintf(stderr, "nametag: if statement to avoid -Wformat-truncation= warnings\n"); + #else + snprintf(tagicons[group][i], MAX_TAGLEN, NAMETAG_FORMAT, name); + #endif // NAMETAG_PREPEND_PATCH + } + } + drawbars(); +} diff --git a/dwm/patch/nametag.h b/dwm/patch/nametag.h new file mode 100755 index 0000000..3e632be --- /dev/null +++ b/dwm/patch/nametag.h @@ -0,0 +1 @@ +static void nametag(const Arg *arg); diff --git a/dwm/patch/nomodbuttons.c b/dwm/patch/nomodbuttons.c new file mode 100755 index 0000000..9c196de --- /dev/null +++ b/dwm/patch/nomodbuttons.c @@ -0,0 +1,8 @@ +void +togglenomodbuttons(const Arg *arg) +{ + nomodbuttons = !nomodbuttons; + if (selmon->sel) + grabbuttons(selmon->sel, 1); +} + diff --git a/dwm/patch/nomodbuttons.h b/dwm/patch/nomodbuttons.h new file mode 100755 index 0000000..a613ed4 --- /dev/null +++ b/dwm/patch/nomodbuttons.h @@ -0,0 +1,2 @@ +static void togglenomodbuttons(const Arg *arg); + diff --git a/dwm/patch/pertag.c b/dwm/patch/pertag.c new file mode 100755 index 0000000..8a4f4d2 --- /dev/null +++ b/dwm/patch/pertag.c @@ -0,0 +1,71 @@ +struct Pertag { + unsigned int curtag; /* current tag index */ + int nmasters[NUMTAGS + 1]; /* number of windows in master area */ + #if FLEXTILE_DELUXE_LAYOUT + int nstacks[NUMTAGS + 1]; /* number of windows in primary stack area */ + int ltaxis[NUMTAGS + 1][LTAXIS_LAST]; + const Layout *ltidxs[NUMTAGS + 1][3]; /* matrix of tags and layouts indexes */ + #else + const Layout *ltidxs[NUMTAGS + 1][2]; /* matrix of tags and layouts indexes */ + #endif // FLEXTILE_DELUXE_LAYOUT + float mfacts[NUMTAGS + 1]; /* mfacts per tag */ + unsigned int sellts[NUMTAGS + 1]; /* selected layouts */ + #if PERTAGBAR_PATCH + int showbars[NUMTAGS + 1]; /* display bar for the current tag */ + #endif // PERTAGBAR_PATCH + #if SWAPFOCUS_PATCH + Client *prevclient[NUMTAGS + 1]; + #endif // SWAPFOCUS_PATCH + #if ZOOMSWAP_PATCH + Client *prevzooms[NUMTAGS + 1]; /* store zoom information */ + #endif // ZOOMSWAP_PATCH + #if PERTAG_VANITYGAPS_PATCH && VANITYGAPS_PATCH + int enablegaps[NUMTAGS + 1]; + int gaps[NUMTAGS + 1]; + #endif // PERTAG_VANITYGAPS_PATCH | VANITYGAPS_PATCH +}; + +void +pertagview(const Arg *arg) +{ + int i; + + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + if (arg->ui == ~SPTAGMASK) + #else + if (arg->ui == ~0) + #endif // SCRATCHPADS_PATCH + selmon->pertag->curtag = 0; + else { + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + selmon->pertag->curtag = i + 1; + } + + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + #if FLEXTILE_DELUXE_LAYOUT + selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag]; + #endif // FLEXTILE_DELUXE_LAYOUT + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + + #if PERTAG_VANITYGAPS_PATCH && VANITYGAPS_PATCH + selmon->gappoh = (selmon->pertag->gaps[selmon->pertag->curtag] & 0xff) >> 0; + selmon->gappov = (selmon->pertag->gaps[selmon->pertag->curtag] & 0xff00) >> 8; + selmon->gappih = (selmon->pertag->gaps[selmon->pertag->curtag] & 0xff0000) >> 16; + selmon->gappiv = (selmon->pertag->gaps[selmon->pertag->curtag] & 0xff000000) >> 24; + #endif // PERTAG_VANITYGAPS_PATCH | VANITYGAPS_PATCH + + #if FLEXTILE_DELUXE_LAYOUT + selmon->ltaxis[LAYOUT] = selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT]; + selmon->ltaxis[MASTER] = selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER]; + selmon->ltaxis[STACK] = selmon->pertag->ltaxis[selmon->pertag->curtag][STACK]; + selmon->ltaxis[STACK2] = selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2]; + #endif // FLEXTILE_DELUXE_LAYOUT + #if PERTAGBAR_PATCH + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + #endif // PERTAGBAR_PATCH +} + diff --git a/dwm/patch/pertag.h b/dwm/patch/pertag.h new file mode 100755 index 0000000..5c53ac9 --- /dev/null +++ b/dwm/patch/pertag.h @@ -0,0 +1,2 @@ +static void pertagview(const Arg *arg); + diff --git a/dwm/patch/placedir.c b/dwm/patch/placedir.c new file mode 100755 index 0000000..6fdfd63 --- /dev/null +++ b/dwm/patch/placedir.c @@ -0,0 +1,96 @@ +void +placedir(const Arg *arg) +{ + Client *s = selmon->sel, *f = NULL, *c, *next, *fprior, *sprior; + + if (!s || s->isfloating) + return; + + unsigned int score = -1; + unsigned int client_score; + int dist; + int dirweight = 20; + + next = s->next; + if (!next) + next = s->mon->clients; + for (c = next; c != s; c = next) { + + next = c->next; + if (!next) + next = s->mon->clients; + + if (!ISVISIBLE(c)) // || HIDDEN(c) + continue; + + switch (arg->i) { + case 0: // left + dist = s->x - c->x - c->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(s->y - c->y); + break; + case 1: // right + dist = c->x - s->x - s->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(c->y - s->y); + break; + case 2: // up + dist = s->y - c->y - c->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(s->x - c->x); + break; + default: + case 3: // down + dist = c->y - s->y - s->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(c->x - s->x); + break; + } + + if (((arg->i == 0 || arg->i == 2) && client_score <= score) || client_score < score) { + score = client_score; + f = c; + } + } + + if (f && f != s) { + for (fprior = f->mon->clients; fprior && fprior->next != f; fprior = fprior->next); + for (sprior = s->mon->clients; sprior && sprior->next != s; sprior = sprior->next); + + if (s == fprior) { + next = f->next; + if (sprior) + sprior->next = f; + else + f->mon->clients = f; + f->next = s; + s->next = next; + } else if (f == sprior) { + next = s->next; + if (fprior) + fprior->next = s; + else + s->mon->clients = s; + s->next = f; + f->next = next; + } else { // clients are not adjacent to each other + next = f->next; + f->next = s->next; + s->next = next; + if (fprior) + fprior->next = s; + else + s->mon->clients = s; + if (sprior) + sprior->next = f; + else + f->mon->clients = f; + } + + arrange(f->mon); + } +} diff --git a/dwm/patch/placedir.h b/dwm/patch/placedir.h new file mode 100755 index 0000000..a2c864a --- /dev/null +++ b/dwm/patch/placedir.h @@ -0,0 +1 @@ +static void placedir(const Arg *arg); diff --git a/dwm/patch/placemouse.c b/dwm/patch/placemouse.c new file mode 100755 index 0000000..267ccdd --- /dev/null +++ b/dwm/patch/placemouse.c @@ -0,0 +1,139 @@ +void +moveorplace(const Arg *arg) { + if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating))) + movemouse(arg); + else + placemouse(arg); +} + +void +placemouse(const Arg *arg) +{ + int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0; + Client *c, *r = NULL, *at, *prevr; + Monitor *m; + XEvent ev; + XWindowAttributes wa; + Time lasttime = 0; + int attachmode, prevattachmode; + attachmode = prevattachmode = -1; + + if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */ + return; + if (c->isfullscreen) /* no support placing fullscreen windows by mouse */ + return; + restack(selmon); + prevr = c; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + + c->isfloating = 0; + c->beingmoved = 1; + + XGetWindowAttributes(dpy, c->win, &wa); + ocx = wa.x; + ocy = wa.y; + + if (arg->i == 2) // warp cursor to client center + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2); + + if (!getrootptr(&x, &y)) + return; + + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch (ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate_placemouse)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + + if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap)) + freemove = 1; + + if (freemove) + XMoveWindow(dpy, c->win, nx, ny); + + if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon) + selmon = m; + + if (arg->i == 1) { // tiled position is relative to the client window center point + px = nx + wa.width / 2; + py = ny + wa.height / 2; + } else { // tiled position is relative to the mouse cursor + px = ev.xmotion.x; + py = ev.xmotion.y; + } + + r = recttoclient(px, py, 1, 1, 0); + + if (!r || r == c) + break; + + if ((((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w) + && (abs(r->y - py) < r->h / 2)) || (abs(r->x - px) < r->w / 2)) + attachmode = 1; // above + else + attachmode = 0; // below + + if ((r && r != prevr) || (attachmode != prevattachmode)) { + detachstack(c); + detach(c); + if (c->mon != r->mon) { + arrangemon(c->mon); + c->tags = r->mon->tagset[r->mon->seltags]; + } + + c->mon = r->mon; + r->mon->sel = r; + + if (attachmode) { + if (r == r->mon->clients) + attach(c); + else { + for (at = r->mon->clients; at->next != r; at = at->next); + c->next = at->next; + at->next = c; + } + } else { + c->next = r->next; + r->next = c; + } + + attachstack(c); + arrangemon(r->mon); + prevr = r; + prevattachmode = attachmode; + } + break; + } + } while (ev.type != ButtonRelease); + XUngrabPointer(dpy, CurrentTime); + + if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) { + detach(c); + detachstack(c); + arrangemon(c->mon); + c->mon = m; + c->tags = m->tagset[m->seltags]; + attach(c); + attachstack(c); + selmon = m; + } + + focus(c); + c->beingmoved = 0; + + if (nx != -9999) + resize(c, nx, ny, c->w, c->h, 0); + arrangemon(c->mon); +} diff --git a/dwm/patch/placemouse.h b/dwm/patch/placemouse.h new file mode 100755 index 0000000..1573919 --- /dev/null +++ b/dwm/patch/placemouse.h @@ -0,0 +1,2 @@ +static void moveorplace(const Arg *arg); +static void placemouse(const Arg *arg); diff --git a/dwm/patch/push.c b/dwm/patch/push.c new file mode 100755 index 0000000..68123a6 --- /dev/null +++ b/dwm/patch/push.c @@ -0,0 +1,74 @@ +static Client * +nextc(Client *c, float f) +{ + if (!f) + return nexttiled(c); + + for (; c && !ISVISIBLE(c); c = c->next); + return c; +} + +static Client * +prevc(Client *c, float f) +{ + Client *p, *r; + + for (p = selmon->clients, r = NULL; c && p && p != c; p = p->next) + if ((f || !p->isfloating) && ISVISIBLE(p)) + r = p; + return r; +} + +static void +pushup(const Arg *arg) +{ + Client *sel = selmon->sel; + Client *c; + + if (!sel || (sel->isfloating && !arg->f)) + return; + if ((c = prevc(sel, arg->f))) { + /* attach before c */ + detach(sel); + sel->next = c; + if (selmon->clients == c) + selmon->clients = sel; + else { + for (c = selmon->clients; c->next != sel->next; c = c->next); + c->next = sel; + } + } else { + /* move to the end */ + for (c = sel; c->next; c = c->next); + if (sel != c) { + detach(sel); + sel->next = NULL; + c->next = sel; + } + } + focus(sel); + arrange(selmon); +} + +static void +pushdown(const Arg *arg) +{ + Client *sel = selmon->sel; + Client *c; + + if (!sel || (sel->isfloating && !arg->f)) + return; + if ((c = nextc(sel->next, arg->f))) { + /* attach after c */ + detach(sel); + sel->next = c->next; + c->next = sel; + } else { + /* move to the front */ + detach(sel); + attach(sel); + } + focus(sel); + arrange(selmon); +} + diff --git a/dwm/patch/push.h b/dwm/patch/push.h new file mode 100755 index 0000000..6415f80 --- /dev/null +++ b/dwm/patch/push.h @@ -0,0 +1,5 @@ +static Client * nextc(Client *c, float f); +static Client * prevc(Client *c, float f); +static void pushup(const Arg *arg); +static void pushdown(const Arg *arg); + diff --git a/dwm/patch/push_no_master.c b/dwm/patch/push_no_master.c new file mode 100755 index 0000000..2d78cf4 --- /dev/null +++ b/dwm/patch/push_no_master.c @@ -0,0 +1,44 @@ +Client * +prevt(Client *c) +{ + Client *p, *r; + + for (p = selmon->clients, r = NULL; p && p != c; p = p->next) + if (!p->isfloating && ISVISIBLE(p)) + r = p; + return r; +} + +void +pushup(const Arg *arg) +{ + Client *sel = selmon->sel, *c; + + if (!sel || sel->isfloating) + return; + if ((c = prevt(sel)) && c != nexttiled(selmon->clients)) { + detach(sel); + sel->next = c; + for (c = selmon->clients; c->next != sel->next; c = c->next); + c->next = sel; + } + focus(sel); + arrange(selmon); +} + +void +pushdown(const Arg *arg) +{ + Client *sel = selmon->sel, *c; + + if (!sel || sel->isfloating || sel == nexttiled(selmon->clients)) + return; + if ((c = nexttiled(sel->next))) { + detach(sel); + sel->next = c->next; + c->next = sel; + } + focus(sel); + arrange(selmon); +} + diff --git a/dwm/patch/push_no_master.h b/dwm/patch/push_no_master.h new file mode 100755 index 0000000..6904fb0 --- /dev/null +++ b/dwm/patch/push_no_master.h @@ -0,0 +1,4 @@ +Client * prevt(Client *c); +static void pushup(const Arg *arg); +static void pushdown(const Arg *arg); + diff --git a/dwm/patch/recttoclient.c b/dwm/patch/recttoclient.c new file mode 100755 index 0000000..58d2234 --- /dev/null +++ b/dwm/patch/recttoclient.c @@ -0,0 +1,16 @@ +Client * +recttoclient(int x, int y, int w, int h, int include_floating) +{ + Client *c, *r = NULL; + int a, area = 1; + + for (c = selmon->stack; c; c = c->snext) { + if (!ISVISIBLE(c) || (c->isfloating && !include_floating)) + continue; + if ((a = INTERSECTC(x, y, w, h, c)) >= area) { + area = a; + r = c; + } + } + return r; +} diff --git a/dwm/patch/recttoclient.h b/dwm/patch/recttoclient.h new file mode 100755 index 0000000..6f71a9d --- /dev/null +++ b/dwm/patch/recttoclient.h @@ -0,0 +1,4 @@ +#define INTERSECTC(X,Y,W,H,Z) (MAX(0, MIN((X)+(W),(Z)->x+(Z)->w) - MAX((X),(Z)->x)) \ + * MAX(0, MIN((Y)+(H),(Z)->y+(Z)->h) - MAX((Y),(Z)->y))) + +static Client *recttoclient(int x, int y, int w, int h, int include_floating); diff --git a/dwm/patch/renamed_scratchpads.c b/dwm/patch/renamed_scratchpads.c new file mode 100755 index 0000000..154c057 --- /dev/null +++ b/dwm/patch/renamed_scratchpads.c @@ -0,0 +1,138 @@ +void +removescratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + c->scratchkey = 0; +} + +void +setscratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + + c->scratchkey = ((char**)arg->v)[0][0]; +} + +void +togglescratch(const Arg *arg) +{ + Client *c, *next, *last = NULL, *found = NULL, *monclients = NULL; + Monitor *mon; + int scratchvisible = 0; // whether the scratchpads are currently visible or not + int multimonscratch = 0; // whether we have scratchpads that are placed on multiple monitors + int scratchmon = -1; // the monitor where the scratchpads exist + int numscratchpads = 0; // count of scratchpads + + /* Looping through monitors and client's twice, the first time to work out whether we need + to move clients across from one monitor to another or not */ + for (mon = mons; mon; mon = mon->next) + for (c = mon->clients; c; c = c->next) { + if (c->scratchkey != ((char**)arg->v)[0][0]) + continue; + if (scratchmon != -1 && scratchmon != mon->num) + multimonscratch = 1; + if (c->mon->tagset[c->mon->seltags] & c->tags) // && !HIDDEN(c) + ++scratchvisible; + scratchmon = mon->num; + ++numscratchpads; + } + + /* Now for the real deal. The logic should go like: + - hidden scratchpads will be shown + - shown scratchpads will be hidden, unless they are being moved to the current monitor + - the scratchpads will be moved to the current monitor if they all reside on the same monitor + - multiple scratchpads residing on separate monitors will be left in place + */ + for (mon = mons; mon; mon = mon->next) { + for (c = mon->stack; c; c = next) { + next = c->snext; + if (c->scratchkey != ((char**)arg->v)[0][0]) + continue; + + #if BAR_WINTITLEACTIONS_PATCH + /* unhide scratchpad if hidden */ + if (HIDDEN(c)) { + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + } + #endif // BAR_WINTITLEACTIONS_PATCH + + /* Record the first found scratchpad client for focus purposes, but prioritise the + scratchpad on the current monitor if one exists */ + if (!found || (mon == selmon && found->mon != selmon)) + found = c; + + /* If scratchpad clients reside on another monitor and we are moving them across then + as we are looping through monitors we could be moving a client to a monitor that has + not been processed yet, hence we could be processing a scratchpad twice. To avoid + this we detach them and add them to a temporary list (monclients) which is to be + processed later. */ + if (!multimonscratch && c->mon != selmon) { + detach(c); + detachstack(c); + c->next = NULL; + /* Note that we are adding clients at the end of the list, this is to preserve the + order of clients as they were on the adjacent monitor (relevant when tiled) */ + if (last) + last = last->next = c; + else + last = monclients = c; + } else if (scratchvisible == numscratchpads) { + c->tags = 0; + } else { + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColBorder].pixel); + c->tags = c->mon->tagset[c->mon->seltags]; + if (c->isfloating) + XRaiseWindow(dpy, c->win); + } + } + } + + /* Attach moved scratchpad clients on the selected monitor */ + for (c = monclients; c; c = next) { + next = c->next; + mon = c->mon; + c->mon = selmon; + c->tags = selmon->tagset[selmon->seltags]; + /* Attach scratchpad clients from other monitors at the bottom of the stack */ + if (selmon->clients) { + for (last = selmon->clients; last && last->next; last = last->next); + last->next = c; + } else + selmon->clients = c; + c->next = NULL; + attachstack(c); + + /* Center floating scratchpad windows when moved from one monitor to another */ + if (c->isfloating) { + if (c->w > selmon->ww) + c->w = selmon->ww - c->bw * 2; + if (c->h > selmon->wh) + c->h = selmon->wh - c->bw * 2; + + if (numscratchpads > 1) { + c->x = c->mon->wx + (c->x - mon->wx) * ((double)(abs(c->mon->ww - WIDTH(c))) / MAX(abs(mon->ww - WIDTH(c)), 1)); + c->y = c->mon->wy + (c->y - mon->wy) * ((double)(abs(c->mon->wh - HEIGHT(c))) / MAX(abs(mon->wh - HEIGHT(c)), 1)); + } else if (c->x < c->mon->mx || c->x > c->mon->mx + c->mon->mw || + c->y < c->mon->my || c->y > c->mon->my + c->mon->mh) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + resizeclient(c, c->x, c->y, c->w, c->h); + XRaiseWindow(dpy, c->win); + } + } + + if (found) { + focus(ISVISIBLE(found) ? found : NULL); + arrange(NULL); + if (found->isfloating) + XRaiseWindow(dpy, found->win); + } else { + spawn(&(Arg){ .v = (const void *)(((char * const *)arg->v) + 1) }); + } +} diff --git a/dwm/patch/renamed_scratchpads.h b/dwm/patch/renamed_scratchpads.h new file mode 100755 index 0000000..bbff93c --- /dev/null +++ b/dwm/patch/renamed_scratchpads.h @@ -0,0 +1,3 @@ +static void removescratch(const Arg *arg); +static void setscratch(const Arg *arg); +static void togglescratch(const Arg *arg); diff --git a/dwm/patch/reorganizetags.c b/dwm/patch/reorganizetags.c new file mode 100755 index 0000000..440d75c --- /dev/null +++ b/dwm/patch/reorganizetags.c @@ -0,0 +1,42 @@ +void +reorganizetags(const Arg *arg) +{ + Client *c; + unsigned int occ, unocc, i; + unsigned int tagdest[NUMTAGS]; + + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH + + occ = 0; + for (c = selmon->clients; c; c = c->next) + occ |= (1 << (ffs(c->tags)-1)); + unocc = 0; + for (i = 0; i < NUMTAGS; ++i) { + while (unocc < i && (occ & (1 << unocc))) + unocc++; + if (occ & (1 << i)) { + tagdest[i] = unocc; + occ &= ~(1 << i); + occ |= 1 << unocc; + } + } + + for (c = selmon->clients; c; c = c->next) + c->tags = 1 << tagdest[ffs(c->tags)-1]; + #if TAGSYNC_PATCH + } + selmon = origselmon; + #endif // TAGSYNC_PATCH + + if (selmon->sel) + view(&((Arg) { .ui = selmon->sel->tags })); + else + #if TAGSYNC_PATCH + arrange(NULL); + #else + arrange(selmon); + #endif // TAGSYNC_PATCH +} diff --git a/dwm/patch/reorganizetags.h b/dwm/patch/reorganizetags.h new file mode 100755 index 0000000..c4917af --- /dev/null +++ b/dwm/patch/reorganizetags.h @@ -0,0 +1,2 @@ +static void reorganizetags(const Arg *arg); + diff --git a/dwm/patch/restartsig.c b/dwm/patch/restartsig.c new file mode 100755 index 0000000..adb61b5 --- /dev/null +++ b/dwm/patch/restartsig.c @@ -0,0 +1,16 @@ +static int restart = 0; + +void +sighup(int unused) +{ + Arg a = {.i = 1}; + quit(&a); +} + +void +sigterm(int unused) +{ + Arg a = {.i = 0}; + quit(&a); +} + diff --git a/dwm/patch/restartsig.h b/dwm/patch/restartsig.h new file mode 100755 index 0000000..b16975b --- /dev/null +++ b/dwm/patch/restartsig.h @@ -0,0 +1,3 @@ +static void sighup(int unused); +static void sigterm(int unused); + diff --git a/dwm/patch/riodraw.c b/dwm/patch/riodraw.c new file mode 100755 index 0000000..aebf726 --- /dev/null +++ b/dwm/patch/riodraw.c @@ -0,0 +1,105 @@ +/* drag out an area using slop and resize the selected window to it. */ +int +riodraw(Client *c, const char slopstyle[]) +{ + int i; + char str[100]; + char strout[100]; + char tmpstring[30] = {0}; + char slopcmd[100] = "slop -f x%xx%yx%wx%hx "; + int firstchar = 0; + int counter = 0; + + strcat(slopcmd, slopstyle); + FILE *fp = popen(slopcmd, "r"); + + while (fgets(str, 100, fp) != NULL) + strcat(strout, str); + + pclose(fp); + + if (strlen(strout) < 6) + return 0; + + for (i = 0; i < strlen(strout); i++){ + if (!firstchar) { + if (strout[i] == 'x') + firstchar = 1; + continue; + } + + if (strout[i] != 'x') + tmpstring[strlen(tmpstring)] = strout[i]; + else { + riodimensions[counter] = atoi(tmpstring); + counter++; + memset(tmpstring,0,strlen(tmpstring)); + } + } + + if (riodimensions[0] <= -40 || riodimensions[1] <= -40 || riodimensions[2] <= 50 || riodimensions[3] <= 50) { + riodimensions[3] = -1; + return 0; + } + + if (c) { + rioposition(c, riodimensions[0], riodimensions[1], riodimensions[2], riodimensions[3]); + return 0; + } + + return 1; +} + +void +rioposition(Client *c, int x, int y, int w, int h) +{ + Monitor *m; + if ((m = recttomon(x, y, w, h)) && m != c->mon) { + detach(c); + detachstack(c); + arrange(c->mon); + c->mon = m; + c->tags = m->tagset[m->seltags]; + attach(c); + attachstack(c); + selmon = m; + focus(c); + } + + c->isfloating = 1; + if (riodraw_borders) + resizeclient(c, x, y, w - (c->bw * 2), h - (c->bw * 2)); + else + resizeclient(c, x - c->bw, y - c->bw, w, h); + drawbar(c->mon); + arrange(c->mon); + + riodimensions[3] = -1; + riopid = 0; +} + +/* drag out an area using slop and resize the selected window to it */ +void +rioresize(const Arg *arg) +{ + Client *c = (arg && arg->v ? (Client*)arg->v : selmon->sel); + if (c) + riodraw(c, slopresizestyle); +} + +/* Spawn a new window and drag out an area using slop to position it while the window is + * initialising in the background. */ +void +riospawn(const Arg *arg) +{ + riopid = spawncmd(arg); + riodraw(NULL, slopspawnstyle); +} + +void +riospawnsync(const Arg *arg) +{ + if (riodraw(NULL, slopspawnstyle)) + riopid = spawncmd(arg); +} + diff --git a/dwm/patch/riodraw.h b/dwm/patch/riodraw.h new file mode 100755 index 0000000..7756aeb --- /dev/null +++ b/dwm/patch/riodraw.h @@ -0,0 +1,6 @@ +static int riodraw(Client *c, const char slopstyle[]); +static void rioposition(Client *c, int x, int y, int w, int h); +static void rioresize(const Arg *arg); +static void riospawn(const Arg *arg); +static void riospawnsync(const Arg *arg); + diff --git a/dwm/patch/rotatestack.c b/dwm/patch/rotatestack.c new file mode 100755 index 0000000..41df8b1 --- /dev/null +++ b/dwm/patch/rotatestack.c @@ -0,0 +1,53 @@ +void +enqueue(Client *c) +{ + Client *l; + for (l = c->mon->clients; l && l->next; l = l->next); + if (l) { + l->next = c; + c->next = NULL; + } +} + +void +enqueuestack(Client *c) +{ + Client *l; + for (l = c->mon->stack; l && l->snext; l = l->snext); + if (l) { + l->snext = c; + c->snext = NULL; + } +} + +void +rotatestack(const Arg *arg) +{ + Client *c = NULL, *f; + + if (!selmon->sel) + return; + f = selmon->sel; + if (arg->i > 0) { + for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); + if (c){ + detach(c); + attach(c); + detachstack(c); + attachstack(c); + } + } else { + if ((c = nexttiled(selmon->clients))){ + detach(c); + enqueue(c); + detachstack(c); + enqueuestack(c); + } + } + if (c){ + arrange(selmon); + focus(f); + restack(selmon); + } +} + diff --git a/dwm/patch/rotatestack.h b/dwm/patch/rotatestack.h new file mode 100755 index 0000000..ea64e68 --- /dev/null +++ b/dwm/patch/rotatestack.h @@ -0,0 +1,4 @@ +static void enqueue(Client *c); +static void enqueuestack(Client *c); +static void rotatestack(const Arg *arg); + diff --git a/dwm/patch/roundedcorners.c b/dwm/patch/roundedcorners.c new file mode 100755 index 0000000..c6a1bbb --- /dev/null +++ b/dwm/patch/roundedcorners.c @@ -0,0 +1,53 @@ +#include + +void drawroundedcorners(Client *c) +{ + XWindowAttributes win_attr; + Pixmap mask; + XGCValues xgcv; + GC shape_gc; + int dia, w, h; + + if (corner_radius <= 0 || !c) + return; + + /* Clear window shape if fullscreen */ + if (c->w == c->mon->mw && c->h == c->mon->mh) { + XRectangle rect = { .x = 0, .y = 0, .width = c->w, .height = c->h }; + XShapeCombineRectangles(dpy, c->win, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 1); + return; + } + + if (!XGetWindowAttributes(dpy, c->win, &win_attr)) + return; + + dia = 2 * corner_radius; + w = c->w + 2 * c->bw; + h = c->h + 2 * c->bw; + if (w < dia || h < dia) + return; + + mask = XCreatePixmap(dpy, c->win, w, h, 1); + if (!mask) + return; + + shape_gc = XCreateGC(dpy, mask, 0, &xgcv); + if (!shape_gc) { + XFreePixmap(dpy, mask); + free(shape_gc); + return; + } + + XSetForeground(dpy, shape_gc, 0); + XFillRectangle(dpy, mask, shape_gc, 0, 0, w, h); + XSetForeground(dpy, shape_gc, 1); + XFillArc(dpy, mask, shape_gc, 0, 0, dia, dia, 0, 23040); + XFillArc(dpy, mask, shape_gc, w-dia-1, 0, dia, dia, 0, 23040); + XFillArc(dpy, mask, shape_gc, 0, h-dia-1, dia, dia, 0, 23040); + XFillArc(dpy, mask, shape_gc, w-dia-1, h-dia-1, dia, dia, 0, 23040); + XFillRectangle(dpy, mask, shape_gc, corner_radius, 0, w-dia, h); + XFillRectangle(dpy, mask, shape_gc, 0, corner_radius, w, h-dia); + XShapeCombineMask(dpy, c->win, ShapeBounding, -c->bw, -c->bw, mask, ShapeSet); + XFreePixmap(dpy, mask); + XFreeGC(dpy, shape_gc); +} diff --git a/dwm/patch/roundedcorners.h b/dwm/patch/roundedcorners.h new file mode 100755 index 0000000..31a1f31 --- /dev/null +++ b/dwm/patch/roundedcorners.h @@ -0,0 +1,2 @@ +static void drawroundedcorners(Client *c); + diff --git a/dwm/patch/scratchpad.c b/dwm/patch/scratchpad.c new file mode 100755 index 0000000..013e35f --- /dev/null +++ b/dwm/patch/scratchpad.c @@ -0,0 +1,77 @@ +void +removescratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + unsigned int scratchtag = SPTAG(arg->ui); + c->tags = c->mon->tagset[c->mon->seltags] ^ scratchtag; + arrange(c->mon); +} + +void +setscratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + unsigned int scratchtag = SPTAG(arg->ui); + c->tags = scratchtag; + arrange(c->mon); +} + +void +togglescratch(const Arg *arg) +{ + Client *c = NULL, *next = NULL, *found = NULL; + Monitor *mon; + unsigned int scratchtag = SPTAG(arg->ui); + unsigned int newtagset = 0; + int nh = 0, nw = 0; + Arg sparg = {.v = scratchpads[arg->ui].cmd}; + + for (mon = mons; mon; mon = mon->next) { + for (c = mon->clients; c; c = next) { + next = c->next; + if (!(c->tags & scratchtag)) + continue; + + found = c; + + if (HIDDEN(c)) { + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + newtagset = 0; + } else + newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; + + if (c->mon != selmon) { + if (c->mon->tagset[c->mon->seltags] & SPTAGMASK) + c->mon->tagset[c->mon->seltags] ^= scratchtag; + if (c->w > selmon->ww) + nw = selmon->ww - c->bw * 2; + if (c->h > selmon->wh) + nh = selmon->wh - c->bw * 2; + if (nw > 0 || nh > 0) + resizeclient(c, c->x, c->y, nw ? nw : c->w, nh ? nh : c->h); + sendmon(c, selmon); + } + } + } + + if (found) { + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + arrange(selmon); + focus(NULL); + } + if (ISVISIBLE(found)) { + focus(found); + restack(selmon); + } + } else { + selmon->tagset[selmon->seltags] |= scratchtag; + spawn(&sparg); + } +} + diff --git a/dwm/patch/scratchpad.h b/dwm/patch/scratchpad.h new file mode 100755 index 0000000..6230266 --- /dev/null +++ b/dwm/patch/scratchpad.h @@ -0,0 +1,9 @@ +typedef struct { + const char *name; + const void *cmd; +} Sp; + +static void removescratch(const Arg *arg); +static void setscratch(const Arg *arg); +static void togglescratch(const Arg *arg); + diff --git a/dwm/patch/scratchpad_alt_1.c b/dwm/patch/scratchpad_alt_1.c new file mode 100755 index 0000000..8704582 --- /dev/null +++ b/dwm/patch/scratchpad_alt_1.c @@ -0,0 +1,72 @@ +static Client * scratchpad_last_showed = NULL; + +void +scratchpad_hide() +{ + if (selmon->sel) { + selmon->sel->tags = SCRATCHPAD_MASK; + selmon->sel->isfloating = 1; + arrange(selmon); + focus(NULL); + } +} + +_Bool +scratchpad_last_showed_is_killed(void) +{ + Client *c; + for (c = selmon->clients; c && c != scratchpad_last_showed; c = c->next); + return (c == NULL); +} + +void +scratchpad_remove() +{ + if (selmon->sel && scratchpad_last_showed != NULL && selmon->sel == scratchpad_last_showed) + scratchpad_last_showed = NULL; +} + +void +scratchpad_show() +{ + if (scratchpad_last_showed == NULL || scratchpad_last_showed_is_killed()) { + scratchpad_show_first(); + return; + } + + if (scratchpad_last_showed->tags != SCRATCHPAD_MASK) { + scratchpad_last_showed->tags = SCRATCHPAD_MASK; + arrange(selmon); + focus(NULL); + return; + } + + Client *c; + + for (c = selmon->clients; c && c != scratchpad_last_showed; c = c->next); + for (c = (c ? c->next : NULL); c && c->tags != SCRATCHPAD_MASK; c = c->next); + + if (c) + scratchpad_show_client(c); + else + scratchpad_show_first(); +} + +void +scratchpad_show_client(Client* c) +{ + scratchpad_last_showed = c; + c->tags = selmon->tagset[selmon->seltags]; + focus(c); + arrange(selmon); +} + +void +scratchpad_show_first(void) +{ + Client *c; + for (c = selmon->clients; c && c->tags != SCRATCHPAD_MASK; c = c->next); + if (c) + scratchpad_show_client(c); +} + diff --git a/dwm/patch/scratchpad_alt_1.h b/dwm/patch/scratchpad_alt_1.h new file mode 100755 index 0000000..4e25f11 --- /dev/null +++ b/dwm/patch/scratchpad_alt_1.h @@ -0,0 +1,9 @@ +#define SCRATCHPAD_MASK (1u << NUMTAGS) + +static void scratchpad_hide(); +static _Bool scratchpad_last_showed_is_killed(void); +static void scratchpad_remove(); +static void scratchpad_show(); +static void scratchpad_show_client(Client *c); +static void scratchpad_show_first(void); + diff --git a/dwm/patch/seamless_restart.c b/dwm/patch/seamless_restart.c new file mode 100755 index 0000000..9c1d8f0 --- /dev/null +++ b/dwm/patch/seamless_restart.c @@ -0,0 +1,478 @@ +void +persistmonitorstate(Monitor *m) +{ + Client *c; + unsigned int i; + + setmonitortags(m); + setmonitorfields(m); + + /* Set client atoms */ + for (i = 1, c = m->clients; c; c = c->next, ++i) { + c->idx = i; + persistclientstate(c); + #if SWALLOW_PATCH + if (c->swallowing) { + c->swallowing->idx = i; + persistclientstate(c->swallowing); + } + #endif // SWALLOW_PATCH + } +} + +int +restoremonitorstate(Monitor *m) +{ + return getmonitortags(m) | getmonitorfields(m); +} + +void +persistclientstate(Client *c) +{ + setclienttags(c); + setclientfields(c); + #if SAVEFLOATS_PATCH + savewindowfloatposition(c, c->mon); + #endif // SAVEFLOATS_PATCH +} + +int +restoreclientstate(Client *c) +{ + int restored = getclientfields(c); + getclienttags(c); + #if SAVEFLOATS_PATCH + restorewindowfloatposition(c, c->mon ? c->mon : selmon); + #endif // SAVEFLOATS_PATCH + return restored; +} + +void setmonitorfields(Monitor *m) +{ + #if PERTAG_PATCH + unsigned int i; + #endif // PERTAG_PATCH + char atom[22] = {0}; + Atom monitor_fields; + #if FLEXTILE_DELUXE_LAYOUT + unsigned int flextile_deluxe_bitmask; + #endif // FLEXTILE_DELUXE_LAYOUT + + sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num); + monitor_fields = XInternAtom(dpy, atom, False); + + /* Perists workspace information in 32 bits laid out like this: + * + * |0|0000|0|0000|0000|0000|0000|0000|000|000 + * | | | | | | | | | |-- nmaster + * | | | | | | | | |-- nstack + * | | | | | | | |-- layout + * | | | | | | |-- flextile LAYOUT (split) + * | | | | | |-- flextile MASTER + * | | | | |-- flextile STACK1 + * | | | |-- flextile STACK2 + * | | |-- flextile mirror layout (indicated by negative layout) + * | | + * | |-- reserved + * |-- showbar + */ + #if PERTAG_PATCH + for (i = 0; i <= NUMTAGS; i++) { + #if FLEXTILE_DELUXE_LAYOUT + flextile_deluxe_bitmask = (m->pertag->nstacks[i] & 0x7) << 3; + if (m->pertag->ltidxs[i][m->pertag->sellts[i]]->arrange == flextile) { + flextile_deluxe_bitmask |= + (abs(m->pertag->ltaxis[i][LAYOUT]) & 0xF) << 10 | + (m->pertag->ltaxis[i][MASTER] & 0xF) << 14 | + (m->pertag->ltaxis[i][STACK] & 0xF) << 18 | + (m->pertag->ltaxis[i][STACK2] & 0xF) << 22 | + (m->pertag->ltaxis[i][LAYOUT] < 0 ? 1 : 0) << 24; + } + #endif // FLEXTILE_DELUXE_L1AYOUT + uint32_t data[] = { + #if FLEXTILE_DELUXE_LAYOUT + flextile_deluxe_bitmask | + #endif // FLEXTILE_DELUXE_LAYOUT + (m->pertag->nmasters[i] & 0x7) | + (getlayoutindex(m->pertag->ltidxs[i][m->pertag->sellts[i]]) & 0xF) << 6 | + #if PERTAGBAR_PATCH + m->pertag->showbars[i] << 31 + #else + m->showbar << 31 + #endif // PERTAGBAR_PATCH + }; + + XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32, + i ? PropModeAppend : PropModeReplace, (unsigned char *)data, 1); + } + #else // !PERTAG_PATCH + #if FLEXTILE_DELUXE_LAYOUT + flextile_deluxe_bitmask = (m->nstack & 0x7) << 3; + if (m->lt[m->sellt]->arrange == flextile) { + flextile_deluxe_bitmask |= + (abs(m->ltaxis[LAYOUT]) & 0xF) << 10 | + (m->ltaxis[MASTER] & 0xF) << 14 | + (m->ltaxis[STACK] & 0xF) << 18 | + (m->ltaxis[STACK2] & 0xF) << 22 | + (m->ltaxis[LAYOUT] < 0 ? 1 : 0) << 24; + } + #endif // FLEXTILE_DELUXE_L1AYOUT + uint32_t data[] = { + #if FLEXTILE_DELUXE_LAYOUT + flextile_deluxe_bitmask | + #endif // FLEXTILE_DELUXE_LAYOUT + (m->nmaster & 0x7) | + (getlayoutindex(m->lt[m->sellt]) & 0xF) << 6 | + m->showbar << 31 + }; + + XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)data, 1); + #endif // PERTAG_PATCH +} + +int +getlayoutindex(const Layout *layout) +{ + int i; + + for (i = 0; i < LENGTH(layouts) && &layouts[i] != layout; i++); + if (i == LENGTH(layouts)) + i = 0; + return i; +} + +int +getmonitorfields(Monitor *m) +{ + int di, layout_index; + #if PERTAG_PATCH + unsigned int i, restored = 0; + unsigned int tags = m->tagset[m->seltags] << 1; + #endif // PERTAG_PATCH + unsigned long dl, nitems; + unsigned char *p = NULL; + char atom[22] = {0}; + Atom da, state = None; + + sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num); + Atom dwm_monitor = XInternAtom(dpy, atom, False); + if (!dwm_monitor) + return 0; + + #if PERTAG_PATCH + for (i = 0; i <= NUMTAGS; i++) { + if (!(XGetWindowProperty(dpy, root, dwm_monitor, i, (NUMTAGS + 1) * sizeof dl, + False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { + break; + } + + if (!nitems) { + XFree(p); + break; + } + + /* See bit layout in the persistmonitorstate function */ + state = *(Atom *)p; + + m->pertag->nmasters[i] = state & 0x7; + layout_index = (state >> 6) & 0xF; + if (layout_index < LENGTH(layouts)) + m->pertag->ltidxs[i][m->pertag->sellts[i]] = &layouts[layout_index]; + #if FLEXTILE_DELUXE_LAYOUT + m->pertag->nstacks[i] = (state >> 3) & 0x7; + if (m->pertag->ltidxs[i][m->pertag->sellts[i]]->arrange == flextile) { + m->pertag->ltaxis[i][LAYOUT] = (state >> 10) & 0xF; + m->pertag->ltaxis[i][MASTER] = (state >> 14) & 0xF; + m->pertag->ltaxis[i][STACK] = (state >> 18) & 0xF; + m->pertag->ltaxis[i][STACK2] = (state >> 22) & 0xF; + if (state >> 24 & 0x1) { + m->pertag->ltaxis[i][LAYOUT] *= -1; + } + } + #endif // FLEXTILE_DELUXE_LAYOUT + #if PERTAGBAR_PATCH + m->pertag->showbars[i] = (state >> 31) & 0x1; + #endif // PERTAGBAR_PATCH + + if (!restored && i && (tags & (1 << i))) { + m->nmaster = m->pertag->nmasters[i]; + m->sellt = m->pertag->sellts[i]; + m->lt[m->sellt] = m->pertag->ltidxs[i][m->sellt]; + #if FLEXTILE_DELUXE_LAYOUT + m->nstack = m->pertag->nstacks[i]; + if (m->lt[m->sellt]->arrange == flextile) { + m->ltaxis[LAYOUT] = m->pertag->ltaxis[i][LAYOUT]; + m->ltaxis[MASTER] = m->pertag->ltaxis[i][MASTER]; + m->ltaxis[STACK] = m->pertag->ltaxis[i][STACK]; + m->ltaxis[STACK2] = m->pertag->ltaxis[i][STACK2]; + } + #endif // FLEXTILE_DELUXE_LAYOUT + #if PERTAGBAR_PATCH + m->showbar = m->pertag->showbars[i]; + #else + m->showbar = (state >> 31) & 0x1; + #endif // PERTAGBAR_PATCH + restored = 1; + } + + XFree(p); + } + + return restored; + #else // !PERTAG_PATCH + if (!(XGetWindowProperty(dpy, root, dwm_monitor, 0L, sizeof dl, + False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { + return 0; + } + + if (nitems) { + state = *(Atom *)p; + + /* See bit layout in the persistmonitorstate function */ + m->nmaster = state & 0x7; + #if FLEXTILE_DELUXE_LAYOUT + m->nstack = (state >> 3) & 0x7; + #endif // FLEXTILE_DELUXE_LAYOUT + layout_index = (state >> 6) & 0xF; + if (layout_index < LENGTH(layouts)) + m->lt[m->sellt] = &layouts[layout_index]; + #if FLEXTILE_DELUXE_LAYOUT + if (m->lt[m->sellt]->arrange == flextile) { + m->ltaxis[LAYOUT] = (state >> 10) & 0xF; + m->ltaxis[MASTER] = (state >> 14) & 0xF; + m->ltaxis[STACK] = (state >> 18) & 0xF; + m->ltaxis[STACK2] = (state >> 22) & 0xF; + } + #endif // FLEXTILE_DELUXE_LAYOUT + m->showbar = (state >> 31) & 0x1; + } + + XFree(p); + return 1; + #endif // PERTAG_PATCH +} + +void +setmonitortags(Monitor *m) +{ + char atom[22] = {0}; + Atom monitor_tags; + + sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num); + monitor_tags = XInternAtom(dpy, atom, False); + + uint32_t data[] = { m->tagset[m->seltags] }; + XChangeProperty(dpy, root, monitor_tags, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +int +getmonitortags(Monitor *m) +{ + int di; + unsigned long dl, nitems; + unsigned char *p = NULL; + char atom[22] = {0}; + Atom da, monitor_tags = None, tags; + + sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num); + monitor_tags = XInternAtom(dpy, atom, False); + + if (!(XGetWindowProperty(dpy, root, monitor_tags, 0L, sizeof dl, + False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { + return 0; + } + + if (nitems) { + tags = *(Atom *)p; + m->tagset[m->seltags] = tags & TAGMASK; + } + + XFree(p); + return 1; +} + +void +setclientfields(Client *c) +{ + /* Perists client information in 32 bits laid out like this: + * + * |00000000|00000|0|0|0|0|0|0|0|0|00000000|000 + * | | | | | | | | | | | |-- monitor index + * | | | | | | | | | | |-- client index + * | | | | | | | | | |-- isfloating + * | | | | | | | | |-- ispermanent + * | | | | | | | |-- isterminal + * | | | | | | |-- noswallow + * | | | | | |-- issteam + * | | | | |-- issticky + * | | | |-- fakefullscreen + * | | |-- isfreesize + * | | + * | |-- reserved + * |-- scratchkey (for scratchpads) + */ + uint32_t data[] = { + (c->mon->num & 0x7) + | (c->idx & 0xFF) << 3 + | (c->isfloating & 0x1) << 11 + #if ISPERMANENT_PATCH + | (c->ispermanent & 0x1) << 12 + #endif // ISPERMANENT_PATCH + #if SWALLOW_PATCH + | (c->isterminal & 0x1) << 13 + | (c->noswallow & 0x1) << 14 + #endif // SWALLOW_PATCH + #if STEAM_PATCH + | (c->issteam & 0x1) << 15 + #endif // STEAM_PATCH + #if STICKY_PATCH + | (c->issticky & 0x1) << 16 + #endif // STICKY_PATCH + #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + | (c->fakefullscreen & 0x1) << 17 + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + | (c->isfreesize & 0x1) << 18 + #endif // SIZEHINTS_ISFREESIZE_PATCH + #if RENAMED_SCRATCHPADS_PATCH + | (c->scratchkey & 0xFF) << 24 + #endif // RENAMED_SCRATCHPADS_PATCH + }; + XChangeProperty(dpy, c->win, clientatom[ClientFields], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +int +getclientfields(Client *c) +{ + Monitor *m; + Atom fields = getatomprop(c, clientatom[ClientFields], AnyPropertyType); + if (fields == None) + return 0; + + /* See bit layout in the setclientfields function */ + for (m = mons; m; m = m->next) + if (m->num == (fields & 0x7)) { + c->mon = m; + break; + } + c->idx = (fields >> 3) & 0xFF; + c->isfloating = (fields >> 11) & 0x1; + #if ISPERMANENT_PATCH + c->ispermanent = (fields >> 12) & 0x1; + #endif // ISPERMANENT_PATCH + #if SWALLOW_PATCH + c->isterminal = (fields >> 13) & 0x1; + c->noswallow = (fields >> 14) & 0x1; + #endif // SWALLOW_PATCH + #if STEAM_PATCH + c->issteam = (fields >> 15) & 0x1; + #endif // STEAM_PATCH + #if STICKY_PATCH + c->issticky = (fields >> 16) & 0x1; + #endif // STICKY_PATCH + #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + c->fakefullscreen = (fields >> 17) & 0x1; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + c->isfreesize = (fields >> 18) & 0x1; + #endif // SIZEHINTS_ISFREESIZE_PATCH + #if RENAMED_SCRATCHPADS_PATCH + c->scratchkey = (fields >> 24) & 0xFF; + #endif // RENAMED_SCRATCHPADS_PATCH + return 1; +} + +void +setclienttags(Client *c) +{ + uint32_t data[] = { c->tags }; + XChangeProperty(dpy, c->win, clientatom[ClientTags], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +int +getclienttags(Client *c) +{ + Atom tags = getatomprop(c, clientatom[ClientTags], AnyPropertyType); + if (tags == None) + return 0; + + c->tags = tags & TAGMASK; + return 1; +} + +#if SAVEFLOATS_PATCH +void +savewindowfloatposition(Client *c, Monitor *m) +{ + char atom[22] = {0}; + if (c->sfx == -9999) + return; + + sprintf(atom, "_DWM_FLOATPOS_%u", m->num); + uint32_t pos[] = { (MAX(c->sfx - m->mx, 0) & 0xffff) | ((MAX(c->sfy - m->my, 0) & 0xffff) << 16) }; + XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pos, 1); + + sprintf(atom, "_DWM_FLOATSIZE_%u", m->num); + uint32_t size[] = { (c->sfw & 0xffff) | ((c->sfh & 0xffff) << 16) }; + XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)size, 1); + + XSync(dpy, False); +} + +int +restorewindowfloatposition(Client *c, Monitor *m) +{ + char atom[22] = {0}; + Atom key, value; + int x, y, w, h; + + if (m == NULL) + return 0; + + sprintf(atom, "_DWM_FLOATPOS_%u", m->num); + + key = XInternAtom(dpy, atom, False); + if (!key) + return 0; + + value = getatomprop(c, key, AnyPropertyType); + if (!value) + return 0; + + x = value & 0xffff; + y = value >> 16; + + sprintf(atom, "_DWM_FLOATSIZE_%u", m->num); + + key = XInternAtom(dpy, atom, False); + if (!key) + return 0; + + value = getatomprop(c, key, AnyPropertyType); + if (!value) + return 0; + + w = value & 0xffff; + h = value >> 16; + + if (w <= 0 || h <= 0) { + fprintf(stderr, "restorewindowfloatposition: bad float values x = %d, y = %d, w = %d, h = %d for client = %s\n", x, y, w, h, c->name); + return 0; + } + + c->sfx = m->mx + x; + c->sfy = m->my + y; + c->sfw = w; + c->sfh = h; + + if (c->isfloating) { + c->x = c->sfx; + c->y = c->sfy; + c->w = c->sfw; + c->h = c->sfh; + } + + return 1; +} +#endif // SAVEFLOATS_PATCH diff --git a/dwm/patch/seamless_restart.h b/dwm/patch/seamless_restart.h new file mode 100755 index 0000000..ef29fa7 --- /dev/null +++ b/dwm/patch/seamless_restart.h @@ -0,0 +1,19 @@ +#include + +static void persistmonitorstate(Monitor *m); +static int restoremonitorstate(Monitor *m); +static void persistclientstate(Client *c); +static int restoreclientstate(Client *c); +static void setmonitorfields(Monitor *m); +static int getmonitorfields(Monitor *m); +static void setmonitortags(Monitor *m); +static int getmonitortags(Monitor *m); +static void setclientfields(Client *c); +static int getclientfields(Client *c); +static void setclienttags(Client *c); +static int getclienttags(Client *c); +static int getlayoutindex(const Layout *layout); +#if SAVEFLOATS_PATCH +static void savewindowfloatposition(Client *c, Monitor *m); +static int restorewindowfloatposition(Client *c, Monitor *m); +#endif // SAVEFLOATS_PATCH diff --git a/dwm/patch/selfrestart.c b/dwm/patch/selfrestart.c new file mode 100755 index 0000000..f733867 --- /dev/null +++ b/dwm/patch/selfrestart.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +/** + * Magically finds the current's executable path + * + * I'm doing the do{}while(); trick because Linux (what I'm running) is not + * POSIX compilant and so lstat() cannot be trusted on /proc entries + * + * @return char* the path of the current executable + */ +char *get_dwm_path() +{ + struct stat s; + int r, length, rate = 42; + char *path = NULL; + + if (lstat("/proc/self/exe", &s) == -1) { + perror("lstat:"); + return NULL; + } + + length = s.st_size + 1 - rate; + + do + { + length+=rate; + + free(path); + path = malloc(sizeof(char) * length); + + if (path == NULL){ + perror("malloc:"); + return NULL; + } + + r = readlink("/proc/self/exe", path, length); + + if (r == -1){ + perror("readlink:"); + return NULL; + } + } while (r >= length); + + path[r] = '\0'; + + return path; +} + +/** + * self-restart + * + * Initially inspired by: Yu-Jie Lin + * https://sites.google.com/site/yjlnotes/notes/dwm + */ +void self_restart(const Arg *arg) +{ + char *const argv[] = {get_dwm_path(), NULL}; + + if (argv[0] == NULL) { + return; + } + + execv(argv[0], argv); +} + diff --git a/dwm/patch/selfrestart.h b/dwm/patch/selfrestart.h new file mode 100755 index 0000000..3fd0b81 --- /dev/null +++ b/dwm/patch/selfrestart.h @@ -0,0 +1,3 @@ +char *get_dwm_path(); +void self_restart(const Arg *arg); + diff --git a/dwm/patch/setborderpx.c b/dwm/patch/setborderpx.c new file mode 100755 index 0000000..250a939 --- /dev/null +++ b/dwm/patch/setborderpx.c @@ -0,0 +1,58 @@ +void +setborderpx(const Arg *arg) +{ + Client *c; + Monitor *m = selmon; + #if BAR_BORDER_PATCH + Bar *bar; + #endif // BAR_BORDER_PATCH + int prev_borderpx = m->borderpx; + m->borderpx = arg->i + ? MAX(m->borderpx + arg->i, 0) + : m->borderpx == borderpx + ? 0 + : borderpx; + int delta = 2 * (m->borderpx - prev_borderpx); + + #if BAR_BORDER_PATCH + if (!barborderpx) { + for (bar = m->bar; bar; bar = bar->next) { + bar->bh = bar->bh - 2 * bar->borderpx + 2 * m->borderpx; + bar->borderpx = m->borderpx; + } + updatebarpos(m); + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + } + #endif // BAR_BORDER_PATCH + + for (c = m->clients; c; c = c->next) { + c->bw = m->borderpx; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && !c->fakefullscreen) + continue; + #else + if (c->isfullscreen) + continue; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // FAKEFULLSCREEN_PATCH + #if BAR_WINTITLEACTIONS_PATCH + if (HIDDEN(c)) + continue; + #endif // BAR_WINTITLEACTIONS_PATCH + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + if ((c->tags & SPTAGMASK) && !ISVISIBLE(c)) + continue; + #endif // SCRATCHPADS_PATCH + #if SCRATCHPAD_ALT_1_PATCH + if ((c->tags & SCRATCHPAD_MASK)) + continue; + #endif // SCRATCHPAD_ALT_1_PATCH + if (!c->isfloating && m->lt[m->sellt]->arrange) + continue; + + resizeclient(c, c->x, c->y, c->w - delta, c->h - delta); + } + arrange(m); +} diff --git a/dwm/patch/setborderpx.h b/dwm/patch/setborderpx.h new file mode 100755 index 0000000..a92ae0b --- /dev/null +++ b/dwm/patch/setborderpx.h @@ -0,0 +1,2 @@ +static void setborderpx(const Arg *arg); + diff --git a/dwm/patch/shift.c b/dwm/patch/shift.c new file mode 100755 index 0000000..66b4dce --- /dev/null +++ b/dwm/patch/shift.c @@ -0,0 +1,50 @@ +static Arg +shift(const Arg *arg, int clients) +{ + Arg shifted; + Client *c; + unsigned int tagmask = 0; + + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + shifted.ui = selmon->tagset[selmon->seltags] & ~SPTAGMASK; + #else + shifted.ui = selmon->tagset[selmon->seltags]; + #endif // SCRATCHPADS_PATCH + + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) + #endif // TAGSYNC_PATCH + for (c = selmon->clients; c && clients; c = c->next) { + if (c == selmon->sel) + continue; + #if STICKY_PATCH + if (c->issticky) + continue; + #endif // STICKY_PATCH + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + if (!(c->tags & SPTAGMASK)) + tagmask |= c->tags; + #elif SCRATCHPAD_ALT_1_PATCH + if (!(c->tags & SCRATCHPAD_MASK)) + tagmask |= c->tags; + #else + tagmask |= c->tags; + #endif // SCRATCHPADS_PATCH + } + #if TAGSYNC_PATCH + selmon = origselmon; + #endif // TAGSYNC_PATCH + + do { + if (arg->i > 0) // left circular shift + shifted.ui = (shifted.ui << arg->i) | (shifted.ui >> (NUMTAGS - arg->i)); + else // right circular shift + shifted.ui = (shifted.ui >> -arg->i) | (shifted.ui << (NUMTAGS + arg->i)); + #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH + shifted.ui &= ~SPTAGMASK; + #endif // SCRATCHPADS_PATCH + } while (tagmask && !(shifted.ui & tagmask)); + + return shifted; +} diff --git a/dwm/patch/shift.h b/dwm/patch/shift.h new file mode 100755 index 0000000..45f1665 --- /dev/null +++ b/dwm/patch/shift.h @@ -0,0 +1 @@ +static Arg shift(const Arg *arg, int clients); diff --git a/dwm/patch/shiftboth.c b/dwm/patch/shiftboth.c new file mode 100755 index 0000000..d51d4ac --- /dev/null +++ b/dwm/patch/shiftboth.c @@ -0,0 +1,7 @@ +void +shiftboth(const Arg *arg) +{ + Arg shifted = shift(arg, 0); + tag(&shifted); + view(&shifted); +} diff --git a/dwm/patch/shiftboth.h b/dwm/patch/shiftboth.h new file mode 100755 index 0000000..7a9b8c2 --- /dev/null +++ b/dwm/patch/shiftboth.h @@ -0,0 +1 @@ +static void shiftboth(const Arg *arg); diff --git a/dwm/patch/shiftswaptags.c b/dwm/patch/shiftswaptags.c new file mode 100755 index 0000000..abf6047 --- /dev/null +++ b/dwm/patch/shiftswaptags.c @@ -0,0 +1,7 @@ +/* swaps "tags" (all the clients) with the next/prev tag. */ +void +shiftswaptags(const Arg *arg) +{ + Arg shifted = shift(arg, 0); + swaptags(&shifted); +} diff --git a/dwm/patch/shiftswaptags.h b/dwm/patch/shiftswaptags.h new file mode 100755 index 0000000..1977e36 --- /dev/null +++ b/dwm/patch/shiftswaptags.h @@ -0,0 +1 @@ +static void shiftswaptags(const Arg *arg); diff --git a/dwm/patch/shifttag.c b/dwm/patch/shifttag.c new file mode 100755 index 0000000..0f9dcea --- /dev/null +++ b/dwm/patch/shifttag.c @@ -0,0 +1,7 @@ +/* Sends a window to the next/prev tag */ +void +shifttag(const Arg *arg) +{ + Arg shifted = shift(arg, 0); + tag(&shifted); +} diff --git a/dwm/patch/shifttag.h b/dwm/patch/shifttag.h new file mode 100755 index 0000000..624787f --- /dev/null +++ b/dwm/patch/shifttag.h @@ -0,0 +1 @@ +static void shifttag(const Arg *arg); diff --git a/dwm/patch/shifttagclients.c b/dwm/patch/shifttagclients.c new file mode 100755 index 0000000..f672395 --- /dev/null +++ b/dwm/patch/shifttagclients.c @@ -0,0 +1,7 @@ +/* Sends a window to the next/prev tag that has a client, else it moves it to the next/prev one. */ +void +shifttagclients(const Arg *arg) +{ + Arg shifted = shift(arg, 1); + tag(&shifted); +} diff --git a/dwm/patch/shifttagclients.h b/dwm/patch/shifttagclients.h new file mode 100755 index 0000000..43049a0 --- /dev/null +++ b/dwm/patch/shifttagclients.h @@ -0,0 +1 @@ +static void shifttagclients(const Arg *arg); diff --git a/dwm/patch/shiftview.c b/dwm/patch/shiftview.c new file mode 100755 index 0000000..d3038d6 --- /dev/null +++ b/dwm/patch/shiftview.c @@ -0,0 +1,6 @@ +void +shiftview(const Arg *arg) +{ + Arg shifted = shift(arg, 0); + view(&shifted); +} diff --git a/dwm/patch/shiftview.h b/dwm/patch/shiftview.h new file mode 100755 index 0000000..7bf3a14 --- /dev/null +++ b/dwm/patch/shiftview.h @@ -0,0 +1 @@ +static void shiftview(const Arg *arg); diff --git a/dwm/patch/shiftviewclients.c b/dwm/patch/shiftviewclients.c new file mode 100755 index 0000000..7abebb2 --- /dev/null +++ b/dwm/patch/shiftviewclients.c @@ -0,0 +1,6 @@ +void +shiftviewclients(const Arg *arg) +{ + Arg shifted = shift(arg, 1); + view(&shifted); +} diff --git a/dwm/patch/shiftviewclients.h b/dwm/patch/shiftviewclients.h new file mode 100755 index 0000000..2f652cd --- /dev/null +++ b/dwm/patch/shiftviewclients.h @@ -0,0 +1 @@ +static void shiftviewclients(const Arg *arg); diff --git a/dwm/patch/sizehints_ruled.c b/dwm/patch/sizehints_ruled.c new file mode 100755 index 0000000..6e97f9e --- /dev/null +++ b/dwm/patch/sizehints_ruled.c @@ -0,0 +1,39 @@ +void +checkfloatingrules(Client *c) +{ + const char *class, *instance; + Atom wintype; + #if WINDOWROLERULE_PATCH + char role[64]; + #endif // WINDOWROLERULE_PATCH + unsigned int i; + const Rule *r; + XClassHint ch = { NULL, NULL }; + + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM); + #if WINDOWROLERULE_PATCH + gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role)); + #endif // WINDOWROLERULE_PATCH + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + #if WINDOWROLERULE_PATCH + && (!r->role || strstr(role, r->role)) + #endif // WINDOWROLERULE_PATCH + && (!r->instance || strstr(instance, r->instance)) + && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False))) + { + c->isfloating = r->isfloating; + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); +} + diff --git a/dwm/patch/sizehints_ruled.h b/dwm/patch/sizehints_ruled.h new file mode 100755 index 0000000..14c6719 --- /dev/null +++ b/dwm/patch/sizehints_ruled.h @@ -0,0 +1,2 @@ +static void checkfloatingrules(Client *c); + diff --git a/dwm/patch/sortscreens.c b/dwm/patch/sortscreens.c new file mode 100755 index 0000000..538e2c1 --- /dev/null +++ b/dwm/patch/sortscreens.c @@ -0,0 +1,16 @@ +void +sortscreens(XineramaScreenInfo *screens, int n) +{ + int i, j; + XineramaScreenInfo *screen = ecalloc(1, sizeof(XineramaScreenInfo)); + + for (i = 0; i < n; i++) + for (j = i + 1; j < n; j++) + if (RIGHTOF(screens[i], screens[j])) { + memcpy(&screen[0], &screens[i], sizeof(XineramaScreenInfo)); + memcpy(&screens[i], &screens[j], sizeof(XineramaScreenInfo)); + memcpy(&screens[j], &screen[0], sizeof(XineramaScreenInfo)); + } + XFree(screen); +} + diff --git a/dwm/patch/sortscreens.h b/dwm/patch/sortscreens.h new file mode 100755 index 0000000..82915f4 --- /dev/null +++ b/dwm/patch/sortscreens.h @@ -0,0 +1,4 @@ +#define RIGHTOF(a,b) (a.y_org > b.y_org) || ((a.y_org == b.y_org) && (a.x_org > b.x_org)) + +static void sortscreens(XineramaScreenInfo *screens, int n); + diff --git a/dwm/patch/stacker.c b/dwm/patch/stacker.c new file mode 100755 index 0000000..ed8b76b --- /dev/null +++ b/dwm/patch/stacker.c @@ -0,0 +1,113 @@ +void +focusstack(const Arg *arg) +{ + int i = stackpos(arg); + Client *c, *p; + + if (i < 0) + return; + + #if LOSEFULLSCREEN_PATCH + if (!selmon->sel) + return; + #elif FAKEFULLSCREEN_CLIENT_PATCH + if (!selmon->sel || (selmon->sel->isfullscreen && !selmon->sel->fakefullscreen)) + return; + #else + if (!selmon->sel || selmon->sel->isfullscreen) + return; + #endif // LOSEFULLSCREEN_PATCH + + #if BAR_WINTITLEACTIONS_PATCH + for (p = NULL, c = selmon->clients; c && (i || !ISVISIBLE(c) || HIDDEN(c)); + i -= (ISVISIBLE(c) && !HIDDEN(c) ? 1 : 0), p = c, c = c->next); + #else + for (p = NULL, c = selmon->clients; c && (i || !ISVISIBLE(c)); + i -= (ISVISIBLE(c) ? 1 : 0), p = c, c = c->next); + #endif // BAR_WINTITLEACTIONS_PATCH + focus(c ? c : p); + restack(selmon); +} + +void +pushstack(const Arg *arg) +{ + int i = stackpos(arg); + Client *sel = selmon->sel, *c, *p; + + if (i < 0) + return; + else if (i == 0) { + detach(sel); + attach(sel); + } + else { + for (p = NULL, c = selmon->clients; c; p = c, c = c->next) + #if BAR_WINTITLEACTIONS_PATCH + if (!(i -= (ISVISIBLE(c) && !HIDDEN(c) && c != sel))) + #else + if (!(i -= (ISVISIBLE(c) && c != sel))) + #endif // BAR_WINTITLEACTIONS_PATCH + break; + c = c ? c : p; + detach(sel); + sel->next = c->next; + c->next = sel; + } + arrange(selmon); +} + +int +stackpos(const Arg *arg) +{ + int n, i; + Client *c, *l; + + if (!selmon->clients) + return -1; + + #if BAR_WINTITLEACTIONS_PATCH + if (arg->i == PREVSEL) { + for (l = selmon->stack; l && (!ISVISIBLE(l) || HIDDEN(l) || l == selmon->sel); l = l->snext); + if (!l) + return -1; + for (i = 0, c = selmon->clients; c != l; i += (ISVISIBLE(c) && !HIDDEN(c) ? 1 : 0), c = c->next); + return i; + } + else if (ISINC(arg->i)) { + if (!selmon->sel) + return -1; + for (i = 0, c = selmon->clients; c != selmon->sel; i += (ISVISIBLE(c) && !HIDDEN(c) ? 1 : 0), c = c->next); + for (n = i; c; n += (ISVISIBLE(c) && !HIDDEN(c) ? 1 : 0), c = c->next); + return MOD(i + GETINC(arg->i), n); + } + else if (arg->i < 0) { + for (i = 0, c = selmon->clients; c; i += (ISVISIBLE(c) && !HIDDEN(c) ? 1 : 0), c = c->next); + return MAX(i + arg->i, 0); + } + else + return arg->i; + #else // !BAR_WINTITLEACTIONS_PATCH + if (arg->i == PREVSEL) { + for (l = selmon->stack; l && (!ISVISIBLE(l) || l == selmon->sel); l = l->snext); + if (!l) + return -1; + for (i = 0, c = selmon->clients; c != l; i += (ISVISIBLE(c) ? 1 : 0), c = c->next); + return i; + } + else if (ISINC(arg->i)) { + if (!selmon->sel) + return -1; + for (i = 0, c = selmon->clients; c != selmon->sel; i += (ISVISIBLE(c) ? 1 : 0), c = c->next); + for (n = i; c; n += (ISVISIBLE(c) ? 1 : 0), c = c->next); + return MOD(i + GETINC(arg->i), n); + } + else if (arg->i < 0) { + for (i = 0, c = selmon->clients; c; i += (ISVISIBLE(c) ? 1 : 0), c = c->next); + return MAX(i + arg->i, 0); + } + else + return arg->i; + #endif // BAR_WINTITLEACTIONS_PATCH +} + diff --git a/dwm/patch/stacker.h b/dwm/patch/stacker.h new file mode 100755 index 0000000..ee420bd --- /dev/null +++ b/dwm/patch/stacker.h @@ -0,0 +1,11 @@ +#define GETINC(X) ((X) - 2000) +#define INC(X) ((X) + 2000) +#define ISINC(X) ((X) > 1000 && (X) < 3000) +#define PREVSEL 3000 +#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) +#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) + +static void focusstack(const Arg *arg); +static void pushstack(const Arg *arg); +static int stackpos(const Arg *arg); + diff --git a/dwm/patch/sticky.c b/dwm/patch/sticky.c new file mode 100755 index 0000000..420c3e0 --- /dev/null +++ b/dwm/patch/sticky.c @@ -0,0 +1,9 @@ +void +togglesticky(const Arg *arg) +{ + if (!selmon->sel) + return; + selmon->sel->issticky = !selmon->sel->issticky; + arrange(selmon); +} + diff --git a/dwm/patch/sticky.h b/dwm/patch/sticky.h new file mode 100755 index 0000000..277bb34 --- /dev/null +++ b/dwm/patch/sticky.h @@ -0,0 +1,2 @@ +static void togglesticky(const Arg *arg); + diff --git a/dwm/patch/swallow.c b/dwm/patch/swallow.c new file mode 100755 index 0000000..9bd691b --- /dev/null +++ b/dwm/patch/swallow.c @@ -0,0 +1,257 @@ +#include +#include +#ifdef __OpenBSD__ +#include +#include +#endif /* __OpenBSD__ */ + +static int scanner; +static xcb_connection_t *xcon; + +int +swallow(Client *p, Client *c) +{ + Client *s; + XWindowChanges wc; + #if NOBORDER_PATCH + int border_padding = 0; + #endif // NOBORDER_PATCH + + if (c->noswallow > 0 || c->isterminal) + return 0; + if (c->noswallow < 0 && !swallowfloating && c->isfloating) + return 0; + + XMapWindow(dpy, c->win); + + detach(c); + detachstack(c); + + setclientstate(c, WithdrawnState); + XUnmapWindow(dpy, p->win); + + p->swallowing = c; + c->mon = p->mon; + + Window w = p->win; + p->win = c->win; + c->win = w; + + XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(p->win), 1); + + #if BAR_WINICON_PATCH + updateicon(p); + #endif + updatetitle(p); + s = scanner ? c : p; + #if BAR_EWMHTAGS_PATCH + setfloatinghint(s); + #endif // BAR_EWMHTAGS_PATCH + + #if NOBORDER_PATCH + wc.border_width = p->bw; + if (noborder(p)) { + wc.border_width = 0; + border_padding = p->bw * 2; + } + + XConfigureWindow(dpy, p->win, CWBorderWidth, &wc); + XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w + border_padding, s->h + border_padding); + #else + wc.border_width = p->bw; + XConfigureWindow(dpy, p->win, CWBorderWidth, &wc); + XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); + #endif // NOBORDER_PATCH + + #if !BAR_FLEXWINTITLE_PATCH + XSetWindowBorder(dpy, p->win, scheme[SchemeNorm][ColBorder].pixel); + #endif // BAR_FLEXWINTITLE_PATCH + + arrange(p->mon); + configure(p); + updateclientlist(); + + return 1; +} + +void +unswallow(Client *c) +{ + XWindowChanges wc; + c->win = c->swallowing->win; + #if NOBORDER_PATCH + int border_padding = 0; + #endif // NOBORDER_PATCH + + free(c->swallowing); + c->swallowing = NULL; + + XDeleteProperty(dpy, c->win, netatom[NetClientList]); + + /* unfullscreen the client */ + setfullscreen(c, 0); + #if BAR_WINICON_PATCH + updateicon(c); + #endif + updatetitle(c); + arrange(c->mon); + XMapWindow(dpy, c->win); + + #if NOBORDER_PATCH + wc.border_width = c->bw; + if (noborder(c)) { + wc.border_width = 0; + border_padding = c->bw * 2; + } + + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w + border_padding, c->h + border_padding); + #else + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + #endif // NOBORDER_PATCH + #if !BAR_FLEXWINTITLE_PATCH + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + #endif // BAR_FLEXWINTITLE_PATCH + + #if BAR_EWMHTAGS_PATCH + setfloatinghint(c); + #endif // BAR_EWMHTAGS_PATCH + setclientstate(c, NormalState); + arrange(c->mon); + focus(NULL); +} + +pid_t +winpid(Window w) +{ + pid_t result = 0; + + #ifdef __linux__ + xcb_res_client_id_spec_t spec = {0}; + spec.client = w; + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; + + xcb_generic_error_t *e = NULL; + xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); + xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); + + if (!r) + return (pid_t)0; + + xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); + for (; i.rem; xcb_res_client_id_value_next(&i)) { + spec = i.data->spec; + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { + uint32_t *t = xcb_res_client_id_value_value(i.data); + result = *t; + break; + } + } + + free(r); + + if (result == (pid_t)-1) + result = 0; + + #endif /* __linux__ */ + #ifdef __OpenBSD__ + Atom type; + int format; + unsigned long len, bytes; + unsigned char *prop; + pid_t ret; + + if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) + return 0; + + ret = *(pid_t*)prop; + XFree(prop); + result = ret; + #endif /* __OpenBSD__ */ + + return result; +} + +pid_t +getparentprocess(pid_t p) +{ + unsigned int v = 0; + +#ifdef __linux__ + FILE *f; + char buf[256]; + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); + + if (!(f = fopen(buf, "r"))) + return (pid_t)0; + + if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) + v = (pid_t)0; + fclose(f); +#endif /* __linux__ */ +#ifdef __OpenBSD__ + int n; + kvm_t *kd; + struct kinfo_proc *kp; + + kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); + if (!kd) + return 0; + + kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); + v = kp->p_ppid; +#endif /* __OpenBSD__ */ + return (pid_t)v; +} + +int +isdescprocess(pid_t p, pid_t c) +{ + while (p != c && c != 0) + c = getparentprocess(c); + + return (int)c; +} + +Client * +termforwin(const Client *w) +{ + Client *c; + Monitor *m; + + if (!w->pid || w->isterminal) + return NULL; + + c = selmon->sel; + if (c && c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) + return c; + + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) { + if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) + return c; + } + } + + return NULL; +} + +Client * +swallowingclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) { + if (c->swallowing && c->swallowing->win == w) + return c; + } + } + + return NULL; +} + diff --git a/dwm/patch/swallow.h b/dwm/patch/swallow.h new file mode 100755 index 0000000..529fea9 --- /dev/null +++ b/dwm/patch/swallow.h @@ -0,0 +1,8 @@ +static pid_t getparentprocess(pid_t p); +static int isdescprocess(pid_t p, pid_t c); +static int swallow(Client *p, Client *c); +static Client *swallowingclient(Window w); +static Client *termforwin(const Client *c); +static void unswallow(Client *c); +static pid_t winpid(Window w); + diff --git a/dwm/patch/swapfocus.c b/dwm/patch/swapfocus.c new file mode 100755 index 0000000..ec85c2e --- /dev/null +++ b/dwm/patch/swapfocus.c @@ -0,0 +1,22 @@ +void +swapfocus(const Arg *arg) +{ + if (!selmon->sel) + return; + if (selmon->pertag->prevclient[selmon->pertag->curtag] != NULL + && ISVISIBLE(selmon->pertag->prevclient[selmon->pertag->curtag])) { + focus(selmon->pertag->prevclient[selmon->pertag->curtag]); + restack(selmon->pertag->prevclient[selmon->pertag->curtag]->mon); + } + else { + Client *c = NULL; + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + if (c) { + focus(c); + restack(selmon); + } + } +} + diff --git a/dwm/patch/swapfocus.h b/dwm/patch/swapfocus.h new file mode 100755 index 0000000..e547d2f --- /dev/null +++ b/dwm/patch/swapfocus.h @@ -0,0 +1,2 @@ +static void swapfocus(const Arg *arg); + diff --git a/dwm/patch/swaptags.c b/dwm/patch/swaptags.c new file mode 100755 index 0000000..d2341ef --- /dev/null +++ b/dwm/patch/swaptags.c @@ -0,0 +1,30 @@ +void +swaptags(const Arg *arg) +{ + Client *c; + unsigned int newtag = arg->ui & TAGMASK; + unsigned int curtag = selmon->tagset[selmon->seltags]; + + if (newtag == curtag || !curtag || (curtag & (curtag-1))) + return; + + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH + + for (c = selmon->clients; c != NULL; c = c->next) { + if ((c->tags & newtag) || (c->tags & curtag)) + c->tags ^= curtag ^ newtag; + + if (!c->tags) + c->tags = newtag; + } + + #if TAGSYNC_PATCH + } + selmon = origselmon; + #endif // TAGSYNC_PATCH + + view(&((Arg) { .ui = newtag })); +} diff --git a/dwm/patch/swaptags.h b/dwm/patch/swaptags.h new file mode 100755 index 0000000..fdadf3a --- /dev/null +++ b/dwm/patch/swaptags.h @@ -0,0 +1,2 @@ +static void swaptags(const Arg *arg); + diff --git a/dwm/patch/switchcol.c b/dwm/patch/switchcol.c new file mode 100755 index 0000000..6caf8ba --- /dev/null +++ b/dwm/patch/switchcol.c @@ -0,0 +1,29 @@ +void +switchcol(const Arg *arg) +{ + Client *c, *t; + int col = 0; + int i; + + if (!selmon->sel) + return; + for (i = 0, c = nexttiled(selmon->clients); c ; + c = nexttiled(c->next), i++) { + if (c == selmon->sel) + col = (i + 1) > selmon->nmaster; + } + if (i <= selmon->nmaster) + return; + for (c = selmon->stack; c; c = c->snext) { + if (!ISVISIBLE(c)) + continue; + for (i = 0, t = nexttiled(selmon->clients); t && t != c; + t = nexttiled(t->next), i++); + if (t && (i + 1 > selmon->nmaster) != col) { + focus(c); + restack(selmon); + break; + } + } +} + diff --git a/dwm/patch/switchcol.h b/dwm/patch/switchcol.h new file mode 100755 index 0000000..8c7cded --- /dev/null +++ b/dwm/patch/switchcol.h @@ -0,0 +1,2 @@ +static void switchcol(const Arg *arg); + diff --git a/dwm/patch/tab.c b/dwm/patch/tab.c new file mode 100755 index 0000000..30a14d1 --- /dev/null +++ b/dwm/patch/tab.c @@ -0,0 +1,133 @@ +static int th = 0; /* tab bar geometry */ + +void +drawtabs(void) +{ + Monitor *m; + + for (m = mons; m; m = m->next) + drawtab(m); +} + +static int +cmpint(const void *p1, const void *p2) +{ + /* The actual arguments to this function are "pointers to + pointers to char", but strcmp(3) arguments are "pointers + to char", hence the following cast plus dereference */ + return *((int*) p1) > * (int*) p2; +} + +void +drawtab(Monitor *m) +{ + Client *c; + int i; + int itag = -1; + char view_info[50]; + int view_info_w = 0; + int sorted_label_widths[MAXTABS]; + int tot_width; + int maxsize = bh; + int x = 0; + int w = 0; + + // view_info: indicate the tag which is displayed in the view + for (i = 0; i < NUMTAGS; ++i) { + if ((selmon->tagset[selmon->seltags] >> i) & 1) { + if (itag >=0) { // more than one tag selected + itag = -1; + break; + } + itag = i; + } + } + + if (0 <= itag && itag < NUMTAGS) { + snprintf(view_info, sizeof view_info, "[%s]", tagicon(m, itag)); + } else { + strncpy(view_info, "[...]", sizeof view_info); + } + view_info[sizeof(view_info) - 1 ] = 0; + view_info_w = TEXTW(view_info); + tot_width = view_info_w; + + /* Calculates number of labels and their width */ + m->ntabs = 0; + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c) || HIDDEN(c)) + continue; + m->tab_widths[m->ntabs] = TEXTW(c->name); + tot_width += m->tab_widths[m->ntabs]; + ++m->ntabs; + if (m->ntabs >= MAXTABS) + break; + } + + if (tot_width > m->ww) { // not enough space to display the labels, they need to be truncated + memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); + qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); + tot_width = view_info_w; + for (i = 0; i < m->ntabs; ++i) { + if (tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) + break; + tot_width += sorted_label_widths[i]; + } + maxsize = (m->ww - tot_width) / (m->ntabs - i); + } else { + maxsize = m->ww; + } + i = 0; + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c) || HIDDEN(c)) + continue; + if (i >= m->ntabs) + break; + if (m->tab_widths[i] > maxsize) + m->tab_widths[i] = maxsize; + w = m->tab_widths[i]; + drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, th, 0, c->name, 0, False); + x += w; + ++i; + } + + drw_setscheme(drw, scheme[SchemeNorm]); + + /* cleans interspace between window names and current viewed tag label */ + w = m->ww - view_info_w - x; + drw_text(drw, x, 0, w, th, 0, "", 0, False); + + /* view info */ + x += w; + w = view_info_w; + drw_text(drw, x, 0, w, th, 0, view_info, 0, False); + + drw_map(drw, m->tabwin, 0, 0, m->ww, th); +} + +void +focuswin(const Arg* arg) +{ + int iwin = arg->i; + Client* c = NULL; + for (c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next) { + if (ISVISIBLE(c) && !HIDDEN(c)) + --iwin; + }; + if (c) { + focus(c); + restack(selmon); + } +} + +void +tabmode(const Arg *arg) +{ + if (arg && arg->i >= 0) + selmon->showtab = arg->ui % showtab_nmodes; + else + selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; + arrange(selmon); +} + diff --git a/dwm/patch/tab.h b/dwm/patch/tab.h new file mode 100755 index 0000000..44161d7 --- /dev/null +++ b/dwm/patch/tab.h @@ -0,0 +1,5 @@ +static void drawtab(Monitor *m); +static void drawtabs(void); +static void focuswin(const Arg* arg); +static void tabmode(const Arg *arg); + diff --git a/dwm/patch/tagall.c b/dwm/patch/tagall.c new file mode 100755 index 0000000..7abe7cc --- /dev/null +++ b/dwm/patch/tagall.c @@ -0,0 +1,26 @@ +void +tagall(const Arg *arg) +{ + if (!selmon->clients) + return; + /* if parameter starts with F, just move floating windows */ + int floating_only = (char *)arg->v && ((char *)arg->v)[0] == 'F' ? 1 : 0; + int tag = (char *)arg->v ? atoi(((char *)arg->v) + floating_only) : 0; + int j; + Client* c; + if (tag >= 0 && tag < NUMTAGS) + for (c = selmon->clients; c; c = c->next) + { + if (!floating_only || c->isfloating) + for (j = 0; j < NUMTAGS; j++) + { + if (c->tags & 1 << j && selmon->tagset[selmon->seltags] & 1 << j) + { + c->tags = c->tags ^ (1 << j & TAGMASK); + c->tags = c->tags | 1 << (tag-1); + } + } + } + arrange(selmon); +} + diff --git a/dwm/patch/tagall.h b/dwm/patch/tagall.h new file mode 100755 index 0000000..f36c9f8 --- /dev/null +++ b/dwm/patch/tagall.h @@ -0,0 +1,2 @@ +static void tagall(const Arg *arg); + diff --git a/dwm/patch/tagallmon.c b/dwm/patch/tagallmon.c new file mode 100755 index 0000000..3dee569 --- /dev/null +++ b/dwm/patch/tagallmon.c @@ -0,0 +1,49 @@ +void +tagallmon(const Arg *arg) +{ + Monitor *m; + Client *c, *last, *slast, *next; + + if (!mons->next) + return; + + m = dirtomon(arg->i); + for (last = m->clients; last && last->next; last = last->next); + for (slast = m->stack; slast && slast->snext; slast = slast->snext); + + for (c = selmon->clients; c; c = next) { + next = c->next; + if (!ISVISIBLE(c)) + continue; + unfocus(c, 1, NULL); + detach(c); + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + c->next = NULL; + c->snext = NULL; + if (last) + last = last->next = c; + else + m->clients = last = c; + if (slast) + slast = slast->snext = c; + else + m->stack = slast = c; + if (c->isfullscreen) { + #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + if (c->fakefullscreen != 1) { + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } + #elif !FAKEFULLSCREEN_PATCH + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + #endif // FAKEFULLSCREEN_CLIENT_PATCH + } + } + + arrange(NULL); + focus(NULL); +} + diff --git a/dwm/patch/tagallmon.h b/dwm/patch/tagallmon.h new file mode 100755 index 0000000..9abf535 --- /dev/null +++ b/dwm/patch/tagallmon.h @@ -0,0 +1,2 @@ +static void tagallmon(const Arg *arg); + diff --git a/dwm/patch/tagothermonitor.c b/dwm/patch/tagothermonitor.c new file mode 100755 index 0000000..90739dc --- /dev/null +++ b/dwm/patch/tagothermonitor.c @@ -0,0 +1,44 @@ +#if IPC_PATCH || DWMC_PATCH +void +tagnextmonex(const Arg *arg) +{ + tagnextmon(&((Arg) { .ui = 1 << arg->ui })); +} + +void +tagprevmonex(const Arg *arg) +{ + tagprevmon(&((Arg) { .ui = 1 << arg->ui })); +} +#endif // IPC_PATCH | DWMC_PATCH + +void +tagnextmon(const Arg *arg) +{ + tagothermon(arg, 1); +} + +void +tagprevmon(const Arg *arg) +{ + tagothermon(arg, -1); +} + +void +tagothermon(const Arg *arg, int dir) +{ + Client *sel; + Monitor *newmon; + + if (!selmon->sel || !mons->next) + return; + sel = selmon->sel; + newmon = dirtomon(dir); + sendmon(sel, newmon); + if (arg->ui & TAGMASK) { + sel->tags = arg->ui & TAGMASK; + arrange(newmon); + focus(NULL); + } +} + diff --git a/dwm/patch/tagothermonitor.h b/dwm/patch/tagothermonitor.h new file mode 100755 index 0000000..8ebe975 --- /dev/null +++ b/dwm/patch/tagothermonitor.h @@ -0,0 +1,9 @@ +#if IPC_PATCH || DWMC_PATCH +static void tagnextmonex(const Arg *arg); +static void tagprevmonex(const Arg *arg); +#endif // IPC_PATCH | DWMC_PATCH + +static void tagnextmon(const Arg *arg); +static void tagprevmon(const Arg *arg); +static void tagothermon(const Arg *arg, int dir); + diff --git a/dwm/patch/tagswapmon.c b/dwm/patch/tagswapmon.c new file mode 100755 index 0000000..915512e --- /dev/null +++ b/dwm/patch/tagswapmon.c @@ -0,0 +1,75 @@ +void +tagswapmon(const Arg *arg) +{ + Monitor *m; + Client *c, *sc = NULL, *mc = NULL, *next; + + if (!mons->next) + return; + + m = dirtomon(arg->i); + + for (c = selmon->clients; c; c = next) { + next = c->next; + if (!ISVISIBLE(c)) + continue; + unfocus(c, 1, NULL); + detach(c); + detachstack(c); + c->next = sc; + sc = c; + } + + for (c = m->clients; c; c = next) { + next = c->next; + if (!ISVISIBLE(c)) + continue; + unfocus(c, 1, NULL); + detach(c); + detachstack(c); + c->next = mc; + mc = c; + } + + for (c = sc; c; c = next) { + next = c->next; + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + if (c->isfullscreen) { + #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + if (c->fakefullscreen != 1) { + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } + #elif !FAKEFULLSCREEN_PATCH + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + #endif // FAKEFULLSCREEN_CLIENT_PATCH + } + } + + for (c = mc; c; c = next) { + next = c->next; + c->mon = selmon; + c->tags = selmon->tagset[selmon->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + if (c->isfullscreen) { + #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH + if (c->fakefullscreen != 1) { + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } + #elif !FAKEFULLSCREEN_PATCH + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + #endif // FAKEFULLSCREEN_CLIENT_PATCH + } + } + + arrange(NULL); + focus(NULL); +} + diff --git a/dwm/patch/tagswapmon.h b/dwm/patch/tagswapmon.h new file mode 100755 index 0000000..949f591 --- /dev/null +++ b/dwm/patch/tagswapmon.h @@ -0,0 +1,2 @@ +static void tagswapmon(const Arg *arg); + diff --git a/dwm/patch/tapresize.c b/dwm/patch/tapresize.c new file mode 100755 index 0000000..7b918cb --- /dev/null +++ b/dwm/patch/tapresize.c @@ -0,0 +1,46 @@ +void +resizemousescroll(const Arg *arg) +{ + int nw, nh; + Client *c; + Monitor *m; + XEvent ev; + int dw = *((int*)arg->v + 1); + int dh = *(int*)arg->v; + + if (!(c = selmon->sel)) + return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */ + return; + #else + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // !FAKEFULLSCREEN_PATCH + restack(selmon); + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + nw = MAX(c->w + dw, 1); + nh = MAX(c->h + dh, 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); + 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); + } +} + diff --git a/dwm/patch/tapresize.h b/dwm/patch/tapresize.h new file mode 100755 index 0000000..fe6d227 --- /dev/null +++ b/dwm/patch/tapresize.h @@ -0,0 +1,2 @@ +static void resizemousescroll(const Arg *arg); + diff --git a/dwm/patch/togglefullscreen.c b/dwm/patch/togglefullscreen.c new file mode 100755 index 0000000..18857f5 --- /dev/null +++ b/dwm/patch/togglefullscreen.c @@ -0,0 +1,18 @@ +void +togglefullscreen(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + + #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + if (c->fakefullscreen == 1) { // fake fullscreen --> fullscreen + c->fakefullscreen = 2; + setfullscreen(c, 1); + } else + setfullscreen(c, !c->isfullscreen); + #else + setfullscreen(c, !c->isfullscreen); + #endif // FAKEFULLSCREEN_CLIENT_PATCH +} + diff --git a/dwm/patch/togglefullscreen.h b/dwm/patch/togglefullscreen.h new file mode 100755 index 0000000..96a6770 --- /dev/null +++ b/dwm/patch/togglefullscreen.h @@ -0,0 +1,2 @@ +static void togglefullscreen(const Arg *arg); + diff --git a/dwm/patch/toggletopbar.c b/dwm/patch/toggletopbar.c new file mode 100755 index 0000000..8ccc9ac --- /dev/null +++ b/dwm/patch/toggletopbar.c @@ -0,0 +1,20 @@ +void +toggletopbar(const Arg *arg) +{ + Bar *bar; + Monitor *m = selmon; + + for (bar = m->bar; bar; bar = bar->next) + bar->topbar = !bar->topbar; + + if (!m->showbar) { + togglebar(NULL); + return; + } + + updatebarpos(m); + + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(m); +} diff --git a/dwm/patch/toggletopbar.h b/dwm/patch/toggletopbar.h new file mode 100755 index 0000000..af8e443 --- /dev/null +++ b/dwm/patch/toggletopbar.h @@ -0,0 +1 @@ +static void toggletopbar(const Arg *arg); diff --git a/dwm/patch/transfer.c b/dwm/patch/transfer.c new file mode 100755 index 0000000..ce64319 --- /dev/null +++ b/dwm/patch/transfer.c @@ -0,0 +1,34 @@ +void +transfer(const Arg *arg) +{ + Client *c, *mtail = selmon->clients, *stail = NULL, *insertafter; + int transfertostack = 0, i, nmasterclients; + + for (i = 0, c = selmon->clients; c; c = c->next) { + if (!ISVISIBLE(c) || c->isfloating) continue; + if (selmon->sel == c) { transfertostack = i < selmon->nmaster && selmon->nmaster != 0; } + if (i < selmon->nmaster) { nmasterclients++; mtail = c; } + stail = c; + i++; + } + if (!selmon->sel || selmon->sel->isfloating || i == 0) { + return; + } else if (transfertostack) { + selmon->nmaster = MIN(i, selmon->nmaster) - 1; + insertafter = stail; + } else { + selmon->nmaster = selmon->nmaster + 1; + insertafter = mtail; + } + if (insertafter != selmon->sel) { + detach(selmon->sel); + if (selmon->nmaster == 1 && !transfertostack) { + attach(selmon->sel); // Head prepend case + } else { + selmon->sel->next = insertafter->next; + insertafter->next = selmon->sel; + } + } + arrange(selmon); +} + diff --git a/dwm/patch/transfer.h b/dwm/patch/transfer.h new file mode 100755 index 0000000..e887dae --- /dev/null +++ b/dwm/patch/transfer.h @@ -0,0 +1,2 @@ +static void transfer(const Arg *arg); + diff --git a/dwm/patch/transferall.c b/dwm/patch/transferall.c new file mode 100755 index 0000000..ee823b1 --- /dev/null +++ b/dwm/patch/transferall.c @@ -0,0 +1,26 @@ +void +transferall(const Arg *arg) +{ + Client *c, *n = selmon->clients, *attachfrom = NULL; + int i = 0, nstackclients = 0; + while (n) { + c = n; + n = c->next; + if (!ISVISIBLE(c) || c->isfloating) continue; + if (i >= selmon->nmaster) { + detach(c); + if (!attachfrom) { + attach(c); + } else { + c->next = attachfrom->next; + attachfrom->next = c; + } + attachfrom = c; + nstackclients++; + } + i++; + } + selmon->nmaster = nstackclients; + arrange(selmon); +} + diff --git a/dwm/patch/transferall.h b/dwm/patch/transferall.h new file mode 100755 index 0000000..a424ec8 --- /dev/null +++ b/dwm/patch/transferall.h @@ -0,0 +1,2 @@ +static void transferall(const Arg *arg); + diff --git a/dwm/patch/unfloatvisible.c b/dwm/patch/unfloatvisible.c new file mode 100755 index 0000000..fb8888f --- /dev/null +++ b/dwm/patch/unfloatvisible.c @@ -0,0 +1,15 @@ +void +unfloatvisible(const Arg *arg) +{ + Client *c; + + for (c = selmon->clients; c; c = c->next) + if (ISVISIBLE(c) && c->isfloating) + c->isfloating = c->isfixed; + + if (arg && arg->v) + setlayout(arg); + else + arrange(selmon); +} + diff --git a/dwm/patch/unfloatvisible.h b/dwm/patch/unfloatvisible.h new file mode 100755 index 0000000..f15bc66 --- /dev/null +++ b/dwm/patch/unfloatvisible.h @@ -0,0 +1,2 @@ +static void unfloatvisible(const Arg *arg); + diff --git a/dwm/patch/vanitygaps.c b/dwm/patch/vanitygaps.c new file mode 100755 index 0000000..bf51660 --- /dev/null +++ b/dwm/patch/vanitygaps.c @@ -0,0 +1,228 @@ +/* Settings */ +#if !(PERTAG_VANITYGAPS_PATCH || PERMON_VANITYGAPS_PATCH) +static int enablegaps = 1; +#endif // PERTAG_VANITYGAPS_PATCH + +static void +setgaps(int oh, int ov, int ih, int iv) +{ + if (oh < 0) oh = 0; + if (ov < 0) ov = 0; + if (ih < 0) ih = 0; + if (iv < 0) iv = 0; + + selmon->gappoh = oh; + selmon->gappov = ov; + selmon->gappih = ih; + selmon->gappiv = iv; + + #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH + selmon->pertag->gaps[selmon->pertag->curtag] = + ((oh & 0xFF) << 0) | ((ov & 0xFF) << 8) | ((ih & 0xFF) << 16) | ((iv & 0xFF) << 24); + #endif // PERTAG_VANITYGAPS_PATCH + + arrange(selmon); +} + +#if IPC_PATCH || DWMC_PATCH +/* External function that takes one integer and splits it + * into four gap values: + * - outer horizontal (oh) + * - outer vertical (ov) + * - inner horizontal (ih) + * - inner vertical (iv) + * + * Each value is represented as one byte with the uppermost + * bit of each byte indicating whether or not to keep the + * current value. + * + * Example: + * + * 10000000 10000000 00001111 00001111 + * | | | | + * + keep oh + keep ov + ih 15px + iv 15px + * + * This gives an int of: + * 10000000100000000000111100001111 = 2155876111 + * + * Thus this command should set inner gaps to 15: + * xsetroot -name "fsignal:setgaps i 2155876111" + */ +static void +setgapsex(const Arg *arg) +{ + int oh = selmon->gappoh; + int ov = selmon->gappov; + int ih = selmon->gappih; + int iv = selmon->gappiv; + + if (!(arg->i & (1 << 31))) + oh = (arg->i & 0x7f000000) >> 24; + if (!(arg->i & (1 << 23))) + ov = (arg->i & 0x7f0000) >> 16; + if (!(arg->i & (1 << 15))) + ih = (arg->i & 0x7f00) >> 8; + if (!(arg->i & (1 << 7))) + iv = (arg->i & 0x7f); + + /* Auto enable gaps if disabled */ + #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH + if (!selmon->pertag->enablegaps[selmon->pertag->curtag]) + selmon->pertag->enablegaps[selmon->pertag->curtag] = 1; + #elif PERMON_VANITYGAPS_PATCH + selmon->enablegaps = 1; + #else + if (!enablegaps) + enablegaps = 1; + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH + + setgaps(oh, ov, ih, iv); +} +#endif // IPC_PATCH | DWMC_PATCH + +static void +togglegaps(const Arg *arg) +{ + #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH + selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag]; + #elif PERMON_VANITYGAPS_PATCH + selmon->enablegaps = !selmon->enablegaps; + #else + enablegaps = !enablegaps; + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH + + #if BAR_PADDING_VANITYGAPS_PATCH + #if PERMON_VANITYGAPS_PATCH + updatebarpos(selmon); + for (Bar *bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #else + for (Monitor *m = mons; m; m = m->next) { + updatebarpos(m); + for (Bar *bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + } + #endif // PERMON_VANITYGAPS_PATCH + + #if BAR_SYSTRAY_PATCH + drawbarwin(systray->bar); + #endif // BAR_SYSTRAY_PATCH + #endif // BAR_PADDING_VANITYGAPS_PATCH + + #if (PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH) || PERMON_VANITYGAPS_PATCH + arrange(selmon); + #else + arrange(NULL); + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH +} + +static void +defaultgaps(const Arg *arg) +{ + setgaps(gappoh, gappov, gappih, gappiv); +} + +static void +incrgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov + arg->i, + selmon->gappih + arg->i, + selmon->gappiv + arg->i + ); +} + +static void +incrigaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih + arg->i, + selmon->gappiv + arg->i + ); +} + +static void +incrogaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov + arg->i, + selmon->gappih, + selmon->gappiv + ); +} + +static void +incrohgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov, + selmon->gappih, + selmon->gappiv + ); +} + +static void +incrovgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov + arg->i, + selmon->gappih, + selmon->gappiv + ); +} + +static void +incrihgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih + arg->i, + selmon->gappiv + ); +} + +static void +incrivgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih, + selmon->gappiv + arg->i + ); +} + +#if DRAGMFACT_PATCH || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || FIBONACCI_DWINDLE_LAYOUT || FIBONACCI_SPIRAL_LAYOUT || GAPPLESSGRID_LAYOUT || NROWGRID_LAYOUT || HORIZGRID_LAYOUT || BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || GRIDMODE_LAYOUT || FLEXTILE_DELUXE_LAYOUT || TILE_LAYOUT || (VANITYGAPS_MONOCLE_PATCH && MONOCLE_LAYOUT) +static void +getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) +{ + unsigned int n, oe, ie; + #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH + oe = ie = m->pertag->enablegaps[m->pertag->curtag]; + #elif PERMON_VANITYGAPS_PATCH + oe = ie = m->enablegaps; + #else + oe = ie = enablegaps; + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 1) { + oe *= smartgaps_fact; // outer gaps disabled or multiplied when only one client + } + + *oh = m->gappoh*oe; // outer horizontal gap + *ov = m->gappov*oe; // outer vertical gap + *ih = m->gappih*ie; // inner horizontal gap + *iv = m->gappiv*ie; // inner vertical gap + *nc = n; // number of clients +} +#endif + diff --git a/dwm/patch/vanitygaps.h b/dwm/patch/vanitygaps.h new file mode 100755 index 0000000..b8f2109 --- /dev/null +++ b/dwm/patch/vanitygaps.h @@ -0,0 +1,20 @@ +/* Key binding functions */ +static void defaultgaps(const Arg *arg); +static void incrgaps(const Arg *arg); +static void incrigaps(const Arg *arg); +static void incrogaps(const Arg *arg); +static void incrohgaps(const Arg *arg); +static void incrovgaps(const Arg *arg); +static void incrihgaps(const Arg *arg); +static void incrivgaps(const Arg *arg); +static void togglegaps(const Arg *arg); + +/* Internals */ +#if DRAGMFACT_PATCH || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || FIBONACCI_DWINDLE_LAYOUT || FIBONACCI_SPIRAL_LAYOUT || GAPPLESSGRID_LAYOUT || NROWGRID_LAYOUT || HORIZGRID_LAYOUT || BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || GRIDMODE_LAYOUT || FLEXTILE_DELUXE_LAYOUT || TILE_LAYOUT || (VANITYGAPS_MONOCLE_PATCH && MONOCLE_LAYOUT) +static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); +#endif +static void setgaps(int oh, int ov, int ih, int iv); +#if IPC_PATCH || DWMC_PATCH +static void setgapsex(const Arg *arg); +#endif // IPC_PATCH | DWMC_PATCH + diff --git a/dwm/patch/warp.c b/dwm/patch/warp.c new file mode 100755 index 0000000..77efc43 --- /dev/null +++ b/dwm/patch/warp.c @@ -0,0 +1,46 @@ +void +warp(const Client *c) +{ + Monitor *m; + Bar *bar; + int x, y; + + if (ignore_warp) + return; + + if (!c) { + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2); + return; + } + + #if BANISH_PATCH + if (cursor_hidden) { + mouse_x = c->x + c->w/2; + mouse_y = c->y + c->h/2; + return; + } + #endif // BANISH_PATCH + + if (!getrootptr(&x, &y)) + return; + + if (!force_warp && + (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)) + return; + + force_warp = 0; + + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (x > bar->bx && + x < bar->bx + bar->bw && + y > bar->by && + y < bar->by + bar->bh) + return; + + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); +} + diff --git a/dwm/patch/warp.h b/dwm/patch/warp.h new file mode 100755 index 0000000..d79d75f --- /dev/null +++ b/dwm/patch/warp.h @@ -0,0 +1,2 @@ +static void warp(const Client *c); + diff --git a/dwm/patch/winview.c b/dwm/patch/winview.c new file mode 100755 index 0000000..f54c20c --- /dev/null +++ b/dwm/patch/winview.c @@ -0,0 +1,21 @@ +/* Selects for the view of the focused window. The list of tags */ +/* to be displayed is matched to the focused window tag list. */ +void +winview(const Arg* arg) +{ + Window win, win_r, win_p, *win_c; + unsigned nc; + int unused; + Client* c; + Arg a; + + if (!XGetInputFocus(dpy, &win, &unused)) return; + while (XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) + && win_p != win_r) win = win_p; + + if (!(c = wintoclient(win))) return; + + a.ui = c->tags; + view(&a); +} + diff --git a/dwm/patch/winview.h b/dwm/patch/winview.h new file mode 100755 index 0000000..9c2ec97 --- /dev/null +++ b/dwm/patch/winview.h @@ -0,0 +1,2 @@ +static void winview(const Arg* arg); + diff --git a/dwm/patch/xkb.c b/dwm/patch/xkb.c new file mode 100755 index 0000000..d779733 --- /dev/null +++ b/dwm/patch/xkb.c @@ -0,0 +1,68 @@ +static XkbInfo xkbGlobal; +static XkbInfo *xkbSaved = NULL; + +static XkbInfo * +createxkb(Window w) +{ + XkbInfo *xkb; + + xkb = malloc(sizeof *xkb); + if (xkb == NULL) + die("fatal: could not malloc() %u bytes\n", sizeof *xkb); + xkb->group = xkbGlobal.group; + xkb->w = w; + xkb->next = xkbSaved; + if (xkbSaved != NULL) + xkbSaved->prev = xkb; + xkb->prev = NULL; + xkbSaved = xkb; + + return xkb; +} + +XkbInfo * +findxkb(Window w) +{ + XkbInfo *xkb; + for (xkb = xkbSaved; xkb != NULL; xkb = xkb->next) + if (xkb->w == w) + return xkb; + return NULL; +} + +void +xkbeventnotify(XEvent *e) +{ + XkbEvent *ev; + + ev = (XkbEvent *) e; + switch (ev->any.xkb_type) { + case XkbStateNotify: + xkbGlobal.group = ev->state.locked_group; + if (selmon != NULL && selmon->sel != NULL) + selmon->sel->xkb->group = xkbGlobal.group; + drawbars(); + break; + } +} + +/* xkb bar module */ +int +width_xkb(Bar *bar, BarArg *a) +{ + return TEXTW(xkb_layouts[xkbGlobal.group]); +} + +int +draw_xkb(Bar *bar, BarArg *a) +{ + drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, xkb_layouts[xkbGlobal.group], 0, False); + return 1; +} + +int +click_xkb(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkXKB; +} + diff --git a/dwm/patch/xkb.h b/dwm/patch/xkb.h new file mode 100755 index 0000000..2c6d33a --- /dev/null +++ b/dwm/patch/xkb.h @@ -0,0 +1,8 @@ +static XkbInfo *createxkb(Window w); +static XkbInfo *findxkb(Window w); +static void xkbeventnotify(XEvent *e); + +static int width_xkb(Bar *bar, BarArg *a); +static int draw_xkb(Bar *bar, BarArg *a); +static int click_xkb(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/xrdb.c b/dwm/patch/xrdb.c new file mode 100755 index 0000000..9b26eb3 --- /dev/null +++ b/dwm/patch/xrdb.c @@ -0,0 +1,146 @@ +void +load_xresources() +{ + Display *display; + char * resm; + XrmDatabase xrdb; + char *type; + XrmValue value; + + display = XOpenDisplay(NULL); + + if (display != NULL) { + resm = XResourceManagerString(display); + + if (resm != NULL) { + xrdb = XrmGetStringDatabase(resm); + + if (xrdb != NULL) { + XRDB_LOAD_COLOR("dwm.normfgcolor", normfgcolor); + XRDB_LOAD_COLOR("dwm.normbgcolor", normbgcolor); + XRDB_LOAD_COLOR("dwm.normbordercolor", normbordercolor); + XRDB_LOAD_COLOR("dwm.normfloatcolor", normfloatcolor); + XRDB_LOAD_COLOR("dwm.selfgcolor", selfgcolor); + XRDB_LOAD_COLOR("dwm.selbgcolor", selbgcolor); + XRDB_LOAD_COLOR("dwm.selbordercolor", selbordercolor); + XRDB_LOAD_COLOR("dwm.selfloatcolor", selfloatcolor); + XRDB_LOAD_COLOR("dwm.titlenormfgcolor", titlenormfgcolor); + XRDB_LOAD_COLOR("dwm.titlenormbgcolor", titlenormbgcolor); + XRDB_LOAD_COLOR("dwm.titlenormbordercolor", titlenormbordercolor); + XRDB_LOAD_COLOR("dwm.titlenormfloatcolor", titlenormfloatcolor); + XRDB_LOAD_COLOR("dwm.titleselfgcolor", titleselfgcolor); + XRDB_LOAD_COLOR("dwm.titleselbgcolor", titleselbgcolor); + XRDB_LOAD_COLOR("dwm.titleselbordercolor", titleselbordercolor); + XRDB_LOAD_COLOR("dwm.titleselfloatcolor", titleselfloatcolor); + XRDB_LOAD_COLOR("dwm.tagsnormfgcolor", tagsnormfgcolor); + XRDB_LOAD_COLOR("dwm.tagsnormbgcolor", tagsnormbgcolor); + XRDB_LOAD_COLOR("dwm.tagsnormbordercolor", tagsnormbordercolor); + XRDB_LOAD_COLOR("dwm.tagsnormfloatcolor", tagsnormfloatcolor); + XRDB_LOAD_COLOR("dwm.tagsselfgcolor", tagsselfgcolor); + XRDB_LOAD_COLOR("dwm.tagsselbgcolor", tagsselbgcolor); + XRDB_LOAD_COLOR("dwm.tagsselbordercolor", tagsselbordercolor); + XRDB_LOAD_COLOR("dwm.tagsselfloatcolor", tagsselfloatcolor); + XRDB_LOAD_COLOR("dwm.hidnormfgcolor", hidnormfgcolor); + XRDB_LOAD_COLOR("dwm.hidnormbgcolor", hidnormbgcolor); + XRDB_LOAD_COLOR("dwm.hidselfgcolor", hidselfgcolor); + XRDB_LOAD_COLOR("dwm.hidselbgcolor", hidselbgcolor); + XRDB_LOAD_COLOR("dwm.urgfgcolor", urgfgcolor); + XRDB_LOAD_COLOR("dwm.urgbgcolor", urgbgcolor); + XRDB_LOAD_COLOR("dwm.urgbordercolor", urgbordercolor); + XRDB_LOAD_COLOR("dwm.urgfloatcolor", urgfloatcolor); + #if BAR_LTSYMBOL_SCHEME_PATCH + XRDB_LOAD_COLOR("dwm.ltsymbolfgcolor", ltsymbolfgcolor); + XRDB_LOAD_COLOR("dwm.ltsymbolbgcolor", ltsymbolbgcolor); + #endif // BAR_LTSYMBOL_SCHEME_PATCH + #if RENAMED_SCRATCHPADS_PATCH + XRDB_LOAD_COLOR("dwm.scratchselfgcolor", scratchselfgcolor); + XRDB_LOAD_COLOR("dwm.scratchselbgcolor", scratchselbgcolor); + XRDB_LOAD_COLOR("dwm.scratchselbordercolor", scratchselbordercolor); + XRDB_LOAD_COLOR("dwm.scratchselfloatcolor", scratchselfloatcolor); + XRDB_LOAD_COLOR("dwm.scratchnormfgcolor", scratchnormfgcolor); + XRDB_LOAD_COLOR("dwm.scratchnormbgcolor", scratchnormbgcolor); + XRDB_LOAD_COLOR("dwm.scratchnormbordercolor", scratchnormbordercolor); + XRDB_LOAD_COLOR("dwm.scratchnormfloatcolor", scratchnormfloatcolor); + #endif // RENAMED_SCRATCHPADS_PATCH + #if BAR_FLEXWINTITLE_PATCH + XRDB_LOAD_COLOR("dwm.normTTBbgcolor", normTTBbgcolor); + XRDB_LOAD_COLOR("dwm.normLTRbgcolor", normLTRbgcolor); + XRDB_LOAD_COLOR("dwm.normMONObgcolor", normMONObgcolor); + XRDB_LOAD_COLOR("dwm.normGRIDbgcolor", normGRIDbgcolor); + XRDB_LOAD_COLOR("dwm.normGRD1bgcolor", normGRD1bgcolor); + XRDB_LOAD_COLOR("dwm.normGRD2bgcolor", normGRD2bgcolor); + XRDB_LOAD_COLOR("dwm.normGRDMbgcolor", normGRDMbgcolor); + XRDB_LOAD_COLOR("dwm.normHGRDbgcolor", normHGRDbgcolor); + XRDB_LOAD_COLOR("dwm.normDWDLbgcolor", normDWDLbgcolor); + XRDB_LOAD_COLOR("dwm.normSPRLbgcolor", normSPRLbgcolor); + XRDB_LOAD_COLOR("dwm.normfloatbgcolor", normfloatbgcolor); + XRDB_LOAD_COLOR("dwm.actTTBbgcolor", actTTBbgcolor); + XRDB_LOAD_COLOR("dwm.actLTRbgcolor", actLTRbgcolor); + XRDB_LOAD_COLOR("dwm.actMONObgcolor", actMONObgcolor); + XRDB_LOAD_COLOR("dwm.actGRIDbgcolor", actGRIDbgcolor); + XRDB_LOAD_COLOR("dwm.actGRD1bgcolor", actGRD1bgcolor); + XRDB_LOAD_COLOR("dwm.actGRD2bgcolor", actGRD2bgcolor); + XRDB_LOAD_COLOR("dwm.actGRDMbgcolor", actGRDMbgcolor); + XRDB_LOAD_COLOR("dwm.actHGRDbgcolor", actHGRDbgcolor); + XRDB_LOAD_COLOR("dwm.actDWDLbgcolor", actDWDLbgcolor); + XRDB_LOAD_COLOR("dwm.actSPRLbgcolor", actSPRLbgcolor); + XRDB_LOAD_COLOR("dwm.actfloatbgcolor", actfloatbgcolor); + XRDB_LOAD_COLOR("dwm.selTTBbgcolor", selTTBbgcolor); + XRDB_LOAD_COLOR("dwm.selLTRbgcolor", selLTRbgcolor); + XRDB_LOAD_COLOR("dwm.selMONObgcolor", selMONObgcolor); + XRDB_LOAD_COLOR("dwm.selGRIDbgcolor", selGRIDbgcolor); + XRDB_LOAD_COLOR("dwm.selGRD1bgcolor", selGRD1bgcolor); + XRDB_LOAD_COLOR("dwm.selGRD2bgcolor", selGRD2bgcolor); + XRDB_LOAD_COLOR("dwm.selGRDMbgcolor", selGRDMbgcolor); + XRDB_LOAD_COLOR("dwm.selHGRDbgcolor", selHGRDbgcolor); + XRDB_LOAD_COLOR("dwm.selDWDLbgcolor", selDWDLbgcolor); + XRDB_LOAD_COLOR("dwm.selSPRLbgcolor", selSPRLbgcolor); + XRDB_LOAD_COLOR("dwm.selfloatbgcolor", selfloatbgcolor); + #endif // BAR_FLEXWINTITLE_PATCH + #if BAR_STATUS2D_XRDB_TERMCOLORS_PATCH && BAR_STATUS2D_PATCH + XRDB_LOAD_COLOR("color0", termcol0); + XRDB_LOAD_COLOR("color1", termcol1); + XRDB_LOAD_COLOR("color2", termcol2); + XRDB_LOAD_COLOR("color3", termcol3); + XRDB_LOAD_COLOR("color4", termcol4); + XRDB_LOAD_COLOR("color5", termcol5); + XRDB_LOAD_COLOR("color6", termcol6); + XRDB_LOAD_COLOR("color7", termcol7); + XRDB_LOAD_COLOR("color8", termcol8); + XRDB_LOAD_COLOR("color9", termcol9); + XRDB_LOAD_COLOR("color10", termcol10); + XRDB_LOAD_COLOR("color11", termcol11); + XRDB_LOAD_COLOR("color12", termcol12); + XRDB_LOAD_COLOR("color13", termcol13); + XRDB_LOAD_COLOR("color14", termcol14); + XRDB_LOAD_COLOR("color15", termcol15); + #endif // BAR_STATUS2D_XRDB_TERMCOLORS_PATCH + + XrmDestroyDatabase(xrdb); + } + } + } + + XCloseDisplay(display); +} + +void +xrdb(const Arg *arg) +{ + load_xresources(); + int i; + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], + #if BAR_ALPHA_PATCH + alphas[i], + #endif // BAR_ALPHA_PATCH + ColCount + ); + #if BAR_SYSTRAY_PATCH && !BAR_ALPHA_PATCH + if (systray) { + XMoveWindow(dpy, systray->win, -32000, -32000); + } + #endif // BAR_SYSTRAY_PATCH + arrange(NULL); + focus(NULL); +} diff --git a/dwm/patch/xrdb.h b/dwm/patch/xrdb.h new file mode 100755 index 0000000..0b96b3a --- /dev/null +++ b/dwm/patch/xrdb.h @@ -0,0 +1,20 @@ +#include + +#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ + if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ + int i = 1; \ + for (; i <= 6; i++) { \ + if (value.addr[i] < 48) break; \ + if (value.addr[i] > 57 && value.addr[i] < 65) break; \ + if (value.addr[i] > 70 && value.addr[i] < 97) break; \ + if (value.addr[i] > 102) break; \ + } \ + if (i == 7) { \ + strncpy(V, value.addr, 7); \ + V[7] = '\0'; \ + } \ + } \ + } + +static void load_xresources(void); +static void xrdb(const Arg *arg); diff --git a/dwm/patch/xresources.c b/dwm/patch/xresources.c new file mode 100755 index 0000000..1e8eab5 --- /dev/null +++ b/dwm/patch/xresources.c @@ -0,0 +1,74 @@ +void +resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) +{ + char *sdst = NULL; + int *idst = NULL; + float *fdst = NULL; + + sdst = dst; + idst = dst; + fdst = dst; + + char fullname[256]; + char *type; + XrmValue ret; + + snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name); + fullname[sizeof(fullname) - 1] = '\0'; + + XrmGetResource(db, fullname, "*", &type, &ret); + if (!(ret.addr == NULL || strncmp("String", type, 64))) + { + switch (rtype) { + case STRING: + strcpy(sdst, ret.addr); + break; + case INTEGER: + *idst = strtoul(ret.addr, NULL, 10); + break; + case FLOAT: + *fdst = strtof(ret.addr, NULL); + break; + } + } +} + +void +load_xresources(void) +{ + Display *display; + char *resm; + XrmDatabase db; + ResourcePref *p; + + display = XOpenDisplay(NULL); + resm = XResourceManagerString(display); + if (!resm) + return; + + db = XrmGetStringDatabase(resm); + for (p = resources; p < resources + LENGTH(resources); p++) + resource_load(db, p->name, p->type, p->dst); + XCloseDisplay(display); +} + +void +xrdb(const Arg *arg) +{ + int i; + load_xresources(); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], + #if BAR_ALPHA_PATCH + alphas[i], + #endif // BAR_ALPHA_PATCH + ColCount + ); + #if BAR_SYSTRAY_PATCH && !BAR_ALPHA_PATCH + if (systray) { + XMoveWindow(dpy, systray->win, -32000, -32000); + } + #endif // BAR_SYSTRAY_PATCH + arrange(NULL); + focus(NULL); +} diff --git a/dwm/patch/xresources.h b/dwm/patch/xresources.h new file mode 100755 index 0000000..b06e194 --- /dev/null +++ b/dwm/patch/xresources.h @@ -0,0 +1,18 @@ +#include + +/* Xresources preferences */ +enum resource_type { + STRING = 0, + INTEGER = 1, + FLOAT = 2 +}; + +typedef struct { + char *name; + enum resource_type type; + void *dst; +} ResourcePref; + +static void load_xresources(void); +static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); +static void xrdb(const Arg *arg); diff --git a/dwm/patch/zoomswap.c b/dwm/patch/zoomswap.c new file mode 100755 index 0000000..58ee9d4 --- /dev/null +++ b/dwm/patch/zoomswap.c @@ -0,0 +1,14 @@ + +#if !PERTAG_PATCH +static Client *prevzoom = NULL; +#endif // PERTAG_PATCH + +Client * +findbefore(Client *c) { + Client *p; + if (!c || c == c->mon->clients) + return NULL; + for (p = c->mon->clients; p && p->next != c; p = p->next); + return p; +} + diff --git a/dwm/patch/zoomswap.h b/dwm/patch/zoomswap.h new file mode 100755 index 0000000..22c752a --- /dev/null +++ b/dwm/patch/zoomswap.h @@ -0,0 +1,2 @@ +static Client *findbefore(Client *c); + diff --git a/dwm/patches.def.h b/dwm/patches.def.h new file mode 100755 index 0000000..bd275e3 --- /dev/null +++ b/dwm/patches.def.h @@ -0,0 +1,1630 @@ +/* + * This file contains patch control flags. + * + * In principle you should be able to mix and match any patches + * you may want. In cases where patches are logically incompatible + * one patch may take precedence over the other as noted in the + * relevant descriptions. + * + * Although layouts typically come as patches they are differentiated + * here for grouping purposes. + */ + +/** + * Bar modules + */ + +/* Enhanced taskbar that shows the titles of all visible windows in the status + * bar and allows focus / hiding / unhiding of windows by clicking on the status + * bar. Awesomebar takes precedence over fancybar. + * https://dwm.suckless.org/patches/awesomebar/ + */ +#define BAR_AWESOMEBAR_PATCH 0 + +/* This patch depends on statuscmd patch and adds integration with a (patched) + * dwmblocks instance to give a clickable status bar. One must not necessarily + * have to use dwmblocks for this feature, any status updater that has support + * for real-time signals (SIGRTMIN) can be used. + * + * dwmblocks: https://github.com/torrinfail/dwmblocks + * https://dwm.suckless.org/patches/statuscmd/ + */ +#define BAR_DWMBLOCKS_PATCH 0 + +/* Originally the dwmblocks + statuscmd patch used a user defined signal + * (SIGUSR1) for communicating with dwmblocks to indicate update signal and what + * button was pressed. The signalling was later changed to SIGRTMIN instead. + * + * Ultimately this makes dwmblocks instances that were patched with the old + * patch are incompatible with the new dwm patch and vice versa. + * + * This is a compatibility patch that makes dwm use SIGUSR1 instead of SIGRTMIN + * so if button clicks are not working then you may want to try enabling this. + * + * If dwmblocks happen to die like this when clicking on a status + * + * [1] 54355 user-defined signal 1 dwmblocks + * + * then it suggests that dwmblocks does not support user defined signals and + * this patch should be left disabled. + * + * Patch: https://gist.github.com/danbyl/54f7c1d57fc6507242a95b71c3d8fdea + * https://dwm.suckless.org/patches/statuscmd/ + */ +#define BAR_DWMBLOCKS_SIGUSR1_PATCH 0 + +/* This patch shows the titles of all visible windows in the status bar + * (as opposed to showing only the selected one). + * Awesomebar takes precedence over fancybar. Fancybar takes precedence over + * the centeredwindowname patch. + * https://dwm.suckless.org/patches/fancybar/ + */ +#define BAR_FANCYBAR_PATCH 0 + +/* Being an evolution of the bartabgroups patch the flexwintitle patch + * specifically taps into the many layout options that flextile-deluxe offers to + * produce a window title section in the bar that is representative of what is + * shown on screen. + */ +#define BAR_FLEXWINTITLE_PATCH 0 + +/* Adds buttons to the bar that can be used to launch applications. + * https://dwm.suckless.org/patches/launcher/ + */ +#define BAR_LAUNCHER_PATCH 0 + +/* This patch adds a context menu for layout switching. + * - xmenu needs to be installed. + * - Edit layoutmenu.sh with the installed layouts and with correct indexes. + * - Place layoutmenu.sh in PATH. + * - The text of the menu items is for display only. Name them however you + * want. https://dwm.suckless.org/patches/layoutmenu/ + */ +#define BAR_LAYOUTMENU_PATCH 0 + +/* Show layout symbol in bar */ +#define BAR_LTSYMBOL_PATCH 1 + +/* Adds a colour schme for the layout symbol */ +#define BAR_LTSYMBOL_SCHEME_PATCH 0 + +/* Adds powerline arrows for the status. + * This uses statuscolors logic for choosing colors for the powerline. As these + * markers are also control characters there is no explicit statuscmd support + * for this patch. + * + * Powerline separators are defined as: + * |\xXX (creates a hard edge) + * <\xXX (creates a less than arrow) + * /\xXX (creates a diagonal line) + * + * Examples: + * xsetroot -name "$(echo -e '<\x01a<\x02b<\x03c')" + * xsetroot -name "$(echo -e '/\x01d/\x02e/\x03f')" + * + * https://gitlab.com/udiboy1209-suckless/dwm/-/commit/071f5063e8ac4280666828179f92788d893eea40#4b1a539194be7467cefbda22f675a3b7c19ceca7 + * https://dwm.suckless.org/patches/statuscolors/ + */ +#define BAR_POWERLINE_STATUS_PATCH 0 + +/* Adds powerline arrows for the tags. + * https://gitlab.com/udiboy1209-suckless/dwm/-/commit/071f5063e8ac4280666828179f92788d893eea40#4b1a539194be7467cefbda22f675a3b7c19ceca7 + */ +#define BAR_POWERLINE_TAGS_PATCH 0 + +/* Alters the tags powerline to use forward slash instead of arrows */ +#define BAR_POWERLINE_TAGS_SLASH_PATCH 0 + +/* This patch turns the titlebar area into a mfact-respecting tabbar showing + * each client's title. https://dwm.suckless.org/patches/bartabgroups/ + */ +#define BAR_TABGROUPS_PATCH 0 + +/* This patch adds an option to place tags in rows like in many other window + * managers. https://dwm.suckless.org/patches/taggrid/ + */ +#define BAR_TAGGRID_PATCH 0 + +/* Hover tag icons to see a preview of the windows on that tag. + * + * The patch depends on Imlib2 for icon scaling. + * You need to uncomment the corresponding line in config.mk to use the -lImlib2 + * library + * + * Arch Linux: + * sudo pacman -S imlib2 + * Debian: + * sudo apt install libimlib2-dev + * + * As with the winicon patch you may want to consider adding the compiler flags + * of -O3 and -march=native to enable auto loop vectorize for better + * performance. + * + * https://dwm.suckless.org/patches/tag-previews/ + */ +#define BAR_TAGPREVIEW_PATCH 0 + +/* Show status in bar */ +#define BAR_STATUS_PATCH 1 + +/* This patch adds a clickable button to the left hand side of the statusbar. + * https://dwm.suckless.org/patches/statusbutton/ + */ +#define BAR_STATUSBUTTON_PATCH 0 + +/* This patch adds the ability to execute shell commands based on the mouse + * button and position when clicking the status bar. Refer to the website for + * usage. https://dwm.suckless.org/patches/statuscmd/ + */ +#define BAR_STATUSCMD_PATCH 0 + +/* Status2d allows colors and rectangle drawing in your dwm status bar. + * This patch is incompatible with the statuscolors patch which takes + * precedence. This patch is incompatible with the extrabar patch. + * https://dwm.suckless.org/patches/status2d/ + */ +#define BAR_STATUS2D_PATCH 0 + +/* Supplementary patch should you want to disable alpha for the status2d section + */ +#define BAR_STATUS2D_NO_ALPHA_PATCH 0 + +/* Addition to the status2d patch that allows the use of terminal colors (color0 + * through color15) from xrdb in the status, allowing programs like pywal to + * change statusbar colors. This adds the C and B codes to use terminal + * foreground and background colors respectively. E.g. ^B5^ would use color5 as + * the background color. https://dwm.suckless.org/patches/status2d/ + */ +#define BAR_STATUS2D_XRDB_TERMCOLORS_PATCH 0 + +/* The systray patch adds systray for the status bar. + * https://dwm.suckless.org/patches/systray/ + */ +#define BAR_SYSTRAY_PATCH 0 + +/* Show tag symbols in the bar. */ +#define BAR_TAGS_PATCH 1 + +/* Show tag symbols + class of master window in the bar. + * https://dwm.suckless.org/patches/taglabels/ + */ +#define BAR_TAGLABELS_PATCH 0 + +/* This patch underlines the selected tag, or optionally all tags. + * https://dwm.suckless.org/patches/underlinetags/ + */ +#define BAR_UNDERLINETAGS_PATCH 0 + +/* This patch adds the window icon next to the window title in the bar. + * + * The patch depends on Imlib2 for icon scaling. + * You need to uncomment the corresponding line in config.mk to use the -lImlib2 + * library + * + * Arch Linux: + * sudo pacman -S imlib2 + * Debian: + * sudo apt install libimlib2-dev + * + * The author recommends adding the compiler flags of -O3 and -march=native to + * enable auto loop vectorize for better performance. + * + * https://github.com/AdamYuan/dwm-winicon + * https://dwm.suckless.org/patches/winicon + */ +#define BAR_WINICON_PATCH 0 + +/* Show window title in bar */ +#define BAR_WINTITLE_PATCH 1 + +/* Shows window titles in the bar, but only for floating clients. + * This depends on code from the flexwintitle patch. + * Note that the configuration in config.def.h for this is merely an example. If + * combined with the corresponding hidden patch then these two will overlap + * unless the width of the modules are controlled. + */ +#define BAR_WINTITLE_FLOATING_PATCH 0 + +/* Shows window titles in the bar, but only for floating clients. + * This depends on code from the flexwintitle patch. + * Note that the configuration in config.def.h for this is merely an example. If + * combined with the corresponding floating patch then these two will overlap + * unless the width of the modules are controlled. + */ +#define BAR_WINTITLE_HIDDEN_PATCH 0 + +/* Title bar modules such as wintitle (default), fancybar and awesomebar + * do not by default add left and/or right padding as they take up the + * remaining space. These options allow you explicitly add padding should + * you need it. + */ +#define BAR_TITLE_RIGHT_PAD_PATCH 0 +#define BAR_TITLE_LEFT_PAD_PATCH 0 + +/** + * Bar options + */ + +/* This patch changes the rectangle indicating if a tag is used by a client into + * a bar above the tag name for better visibility. Set the tagindicatortype + * variable in config.h to INDICATOR_TOP_BAR to enable this. + * https://dwm.suckless.org/patches/activetagindicatorbar/ + */ +#define BAR_ACTIVETAGINDICATORBAR_PATCH N / A + +/* Alternative patch to the activetagindicatorbar patch, adds the bar below the + * tag icon rather than above. Set the tagindicatortype variable in config.h to + * INDICATOR_BOTTOM_BAR to enable this. + */ +#define BAR_ACTIVETAGINDICATORBAR_ALT1_PATCH N / A + +/* The alpha patch adds transparency for the status bar. + * You need to uncomment the corresponding line in config.mk to use the + * -lXrender library when including this patch. + * https://dwm.suckless.org/patches/alpha/ + */ +#define BAR_ALPHA_PATCH 1 + +/* This patch introduces alternative tags which can be switched on the fly for + * the sole purpose of providing visual aid. + * https://dwm.suckless.org/patches/alternativetags/ + */ +#define BAR_ALTERNATIVE_TAGS_PATCH 0 + +/* This patches provides the ability to use alternative text for tags which + * contain at least one window. + * https://dwm.suckless.org/patches/alttagsdecoration/ + */ +#define BAR_ALTTAGSDECORATION_PATCH 0 + +/* This patch enables dwm to manage external status bars such as lemonbar and + * polybar. dwm treats the external bar as it would its own, so all regular dwm + * commands such as togglebar affect the external bar in the same way. + * + * NB: Unless you want both anybar + dwm bar(s) then the recommendation is to + * disable all bar modules and have { -2 } in the barrules. + * + * https://dwm.suckless.org/patches/anybar/ + */ +#define BAR_ANYBAR_PATCH 0 + +/* Anybar option to place the next bar depending on previous bar's position (top + * or bottom) */ +#define BAR_ANYBAR_TOP_AND_BOTTOM_BARS_PATCH 0 + +/* Anybar option to let dwm manage the width of the bar */ +#define BAR_ANYBAR_MANAGE_WIDTH_PATCH 0 + +/* This patch adds a border around the status bar(s) just like the border of + * client windows. https://codemadness.org/paste/dwm-border-bar.patch + */ +#define BAR_BORDER_PATCH 0 + +/* Optional addon for the border patch. This makes it so that the bar border is + * drawn using the background colour of the bar as opposed to the border colour. + * This allows for the border to have the same transparency as the background + * thus giving a more uniform look. + */ +#define BAR_BORDER_COLBG_PATCH 0 + +/* This patch centers the WM_NAME of the currently selected window on the status + * bar. This is compatible with the wintitle, bartabgroups, flexwintitle and + * awesomebar bar modules. https://dwm.suckless.org/patches/centeredwindowname/ + */ +#define BAR_CENTEREDWINDOWNAME_PATCH 0 + +/* Draws a dot indicator overlayed on each tag icon for each client. The + * selected client is drawn as a larger horizontal line. Set the + * tagindicatortype variable in config.h to INDICATOR_CLIENT_DOTS to enable + * this. https://dwm.suckless.org/patches/clientindicators/ + */ +#define BAR_CLIENTINDICATOR_PATCH N / A + +/* Updates the position of dmenu to match that of the bar. I.e. if topbar is 0 + * then dmenu will appear at the bottom and if 1 then dmenu will appear at the + * top. https://dwm.suckless.org/patches/dmenumatchtop + */ +#define BAR_DMENUMATCHTOP_PATCH 0 + +/* Originally this was the extrabar patch, but as the handling of extra bars is + * now built-in only the splitting of the status by a designated separator + * remains. As such this has been renamed to more accurately reflect what it + * does - creating an extra status. https://dwm.suckless.org/patches/extrabar/ + */ +#define BAR_EXTRASTATUS_PATCH 0 + +/* Adds EWMH support for _NET_NUMBER_OF_DESKTOPS, _NET_CURRENT_DESKTOP, + * _NET_DESKTOP_NAMES and _NET_DESKTOP_VIEWPORT, which allows for compatibility + * with other bars and programs that request workspace information. For example + * polybar's xworkspaces module. + * + * This patch also includes support for adding the _IS_FLOATING property for + * floating windows allowing for compositors to treat floating windows + * differently to tiled windows. + * + * E.g. this setting makes picom only render shadows for floating windows: + * + * shadow-exclude = [ "! _IS_FLOATING@:32c = 1" ]; + * + * https://github.com/bakkeby/dwm-flexipatch/issues/50 (_IS_FLOATING patch) + * https://dwm.suckless.org/patches/ewmhtags/ + */ +#define BAR_EWMHTAGS_PATCH 0 + +/* Allows the bar height to be explicitly set rather than being derived from + * font. https://dwm.suckless.org/patches/bar_height/ + */ +#define BAR_HEIGHT_PATCH 0 + +/* This patch prevents dwm from drawing tags with no clients (i.e. vacant) on + * the bar. https://dwm.suckless.org/patches/hide_vacant_tags/ + */ +#define BAR_HIDEVACANTTAGS_PATCH 0 + +/* With this patch dwm's built-in status bar is only shown when HOLDKEY is + * pressed and the bar will now overlay the display. + * http://dwm.suckless.org/patches/holdbar/ + */ +#define BAR_HOLDBAR_PATCH 0 + +/* Sometimes dwm crashes when it cannot render some glyphs in window titles + * (usually emoji). This patch is essentially a hack to ignore any errors when + * drawing text on the status bar. + * https://groups.google.com/forum/m/#!topic/wmii/7bncCahYIww + * https://docs.google.com/viewer?a=v&pid=forums&srcid=MDAwODA2MTg0MDQyMjE0OTgzMzMBMDQ3ODQzODkyMTU3NTAyMTMxNTYBX2RUMVNtOUtDQUFKATAuMQEBdjI&authuser=0 + */ +#define BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH 0 + +/* This patch adds back in the workaround for a BadLength error in the Xft + * library when color glyphs are used. This is for systems that do not have an + * updated version of the Xft library (or generally prefer monochrome fonts). + */ +#define BAR_NO_COLOR_EMOJI_PATCH 0 + +/* This patch adds vertical and horizontal space between the statusbar and the + * edge of the screen. https://dwm.suckless.org/patches/barpadding/ + */ +#define BAR_PADDING_PATCH 0 + +/* Same as barpadding patch but specifically tailored for the vanitygaps patch + * in that the outer bar padding is derived from the vanitygaps settings. In + * addition to this the bar padding is toggled in unison when vanitygaps are + * toggled. Increasing or decreasing gaps during runtime will not affect the bar + * padding. + */ +#define BAR_PADDING_VANITYGAPS_PATCH 0 + +/* Smart bar padding patch that automatically adjusts the padding when there is + * only one client on the monitor. Works well with vanitygaps and barpadding + * patches. + */ +#define BAR_PADDING_SMART_PATCH 0 + +/* This patch adds simple markup for status messages using pango markup. + * This depends on the pango library v1.44 or greater. + * You need to uncomment the corresponding lines in config.mk to use the pango + * libraries when including this patch. + * + * Note that the pango patch does not protect against the BadLength error from + * Xft when color glyphs are used, which means that dwm will crash if color + * emoji is used. + * + * If you need color emoji then you may want to install this patched library + * from the AUR: https://aur.archlinux.org/packages/libxft-bgra/ + * + * A long term fix for the libXft library is pending approval of this pull + * request: https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1 + * + * Also see: + * https://developer.gnome.org/pygtk/stable/pango-markup-language.html + * https://lists.suckless.org/hackers/2004/17285.html + * https://dwm.suckless.org/patches/pango/ + */ +#define BAR_PANGO_PATCH 0 + +/* This patch allows the status text to be fixed to the bar on a specific + * monitor rather than being drawn on the focused monitor. + * The statusallmons patch takes precedence over this patch. + * https://dwm.suckless.org/patches/staticstatus/ + */ +#define BAR_STATICSTATUS_PATCH 0 + +/* This patch draws and updates the statusbar on all monitors. + * https://dwm.suckless.org/patches/statusallmons/ + */ +#define BAR_STATUSALLMONS_PATCH 0 + +/* This patch enables colored text in the status bar. It changes the way colors + * are defined in config.h allowing multiple color combinations for use in the + * status script. This patch is incompatible with and takes precedence over the + * status2d patch. + * + * This patch is compatible with the statuscmd patch with the caveat that the + * first 16 markers are reserved for status colors restricting block signals to + * 17 through 31. + * + * https://dwm.suckless.org/patches/statuscolors/ + */ +#define BAR_STATUSCOLORS_PATCH 0 + +/* This patch adds configuration options for horizontal and vertical padding in + * the status bar. https://dwm.suckless.org/patches/statuspadding/ + */ +#define BAR_STATUSPADDING_PATCH 0 + +/* This patch adds the ability for dwm to read colors from the linux virtual + * console. /sys/module/vt/parameters/default_{red,grn,blu} Essentially this way + * the colors you use in your regular tty is "mirrored" to dwm. + * https://dwm.suckless.org/patches/vtcolors/ + */ +#define BAR_VTCOLORS_PATCH 0 + +/* This patch allows client windows to be hidden. This code was originally part + * of awesomebar, but has been separated out so that other bar modules can take + * advantage of it. Both awesomebar and bartabgroups patches depend on this + * patch and it will be auto-enabled during compile time if it is needed. Note + * that if using flexipatch-finalizer this must be explicitly enabled. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-barmodules-wintitleactions-6.2.diff + */ +#define BAR_WINTITLEACTIONS_PATCH \ + BAR_AWESOMEBAR_PATCH || BAR_TABGROUPS_PATCH || BAR_FLEXWINTITLE_PATCH + +/*** + * Other patches + */ + +/* Adds a window task switcher toggled using alt-tab. + * https://dwm.suckless.org/patches/alt-tab/ + */ +#define ALT_TAB_PATCH 0 + +/* All floating windows are centered, like the center patch, but without a rule. + * The center patch takes precedence over this patch. + * This patch interferes with the center transient windows patches. + * https://dwm.suckless.org/patches/alwayscenter/ + */ +#define ALWAYSCENTER_PATCH 0 + +/* Allows for floating windows to be toggled to be always on top (aot). + * + * Disclaimer: Some flickering may be expected with this patch when floating and + * aot windows overlap. + * + * https://dwm.suckless.org/patches/alwaysontop/ + */ +#define ALWAYSONTOP_PATCH 0 + +/* This patch allows windows to be resized with its aspect ratio remaining + * constant. https://dwm.suckless.org/patches/aspectresize/ + */ +#define ASPECTRESIZE_PATCH 0 + +/* This patch adds new clients above the selected client, instead of always + * becoming the new master. This behaviour is known from Xmonad. + * This patch takes precedence over ATTACHASIDE_PATCH. + * https://dwm.suckless.org/patches/attachabove/ + */ +#define ATTACHABOVE_PATCH 0 + +/* This patch adds new clients on top of the stack. + * This patch takes precedence over ATTACHBELOW_PATCH. + * https://dwm.suckless.org/patches/attachaside/ + */ +#define ATTACHASIDE_PATCH 1 + +/* This patch adds new clients below the selected client. + * This patch takes precedence over ATTACHBOTTOM_PATCH. + * https://dwm.suckless.org/patches/attachbelow/ + */ +#define ATTACHBELOW_PATCH 0 + +/* This patch adds new clients at the bottom of the stack. + * https://dwm.suckless.org/patches/attachbottom/ + */ +#define ATTACHBOTTOM_PATCH 0 + +/* This patch will make dwm run "~/.local/share/dwm/autostart_blocking.sh" and + * "~/.local/share/dwm/autostart.sh &" before entering the handler loop. One or + * both of these files can be ommited. Note the path inside .local/share rather + * than the original ~/.dwm folder. + * https://dwm.suckless.org/patches/autostart/ + */ +#define AUTOSTART_PATCH 0 + +/* By default, windows that are not visible when requesting a resize/move will + * not get resized/moved. With this patch, they will. + * https://dwm.suckless.org/patches/autoresize/ + */ +#define AUTORESIZE_PATCH 0 + +/* This patch allows for the mouse cursor to automatically hide when the user + * uses the keyboard. + * + * You need to uncomment the corresponding lines in config.mk to use additional + * libraries when including this patch. + * + * This patch depends on the following libraries: + * - libxfixes + * - libxi + * + * https://github.com/bakkeby/patches/wiki/banish + */ +#define BANISH_PATCH 0 + +/* This patch adds proper support for Right-To-Left languages. (such as Farsi, + * Arabic or Hebrew). + * + * You need to uncomment the corresponding lines in config.mk to use the + * -lfribidi library when including this patch. + * + * This patch depends on the following additional library: + * - fribidi + * + * https://dwm.suckless.org/patches/bidi/ + */ +#define BIDI_PATCH 0 + +/* This patch adds a client rule option to allow the border width to be + * specified on a per client basis. + * + * Example rule: + * RULE(.class = "Gimp", .bw = 0) + * + * https://dwm.suckless.org/patches/borderrule/ + */ +#define BORDER_RULE_PATCH 0 + +/* This patch adds an iscentered rule to automatically center clients on the + * current monitor. This patch takes precedence over centeredwindowname, + * alwayscenter and fancybar patches. https://dwm.suckless.org/patches/center/ + */ +#define CENTER_PATCH 0 + +/* A transient window is one that is meant to be short lived and is usually + * raised by a parent window. Such windows are typically dialog boxes and the + * like. It should be noted that in dwm transient windows are not subject to + * normal client rules and they are always floating by default. This patch + * centers transient windows on the screen like the center patch does. Note that + * the 6.2 center patch piggy-backed on the updatewindowtype function to ensure + * that all dialog boxes were centered, transient or not. This function was + * removed in relation to adding wintype as a client rule filter, hence this no + * longer works out of the box. This patch restores previous behaviour with the + * center patch. + */ +#define CENTER_TRANSIENT_WINDOWS_PATCH 0 + +/* As above, except that the transient window is centered within the position of + * the parent window, rather than at the center of the screen. This takes + * precedence over the above patch. + */ +#define CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH 0 + +/* This patch provides the ability to assign different weights to clients in + * their respective stack in tiled layout. + * https://dwm.suckless.org/patches/cfacts/ + */ +#define CFACTS_PATCH 0 + +/* This patch allows color attributes to be set through the command line. + * https://dwm.suckless.org/patches/cmdcustomize/ + */ +#define CMDCUSTOMIZE_PATCH 0 + +/* This patch tweaks the tagging interface so that you can select multiple tags + * for tag or view by pressing all the right keys as a combo. For example to + * view tags 1 and 3, hold MOD and then press and hold 1 and 3 together. + * https://dwm.suckless.org/patches/combo/ + */ +#define COMBO_PATCH 0 + +/* Allow dwm to execute commands from autostart array in your config.h file. + * When dwm exits then all processes from autostart array will be killed. + * https://dwm.suckless.org/patches/cool_autostart/ + */ +#define COOL_AUTOSTART_PATCH 0 + +/* The cyclelayouts patch lets you cycle through all your layouts. + * https://dwm.suckless.org/patches/cyclelayouts/ + */ +#define CYCLELAYOUTS_PATCH 0 + +/* Make dwm respect _MOTIF_WM_HINTS property, and not draw borders around + * windows requesting for it. Some applications use this property to notify + * window managers to not draw window decorations. Not respecting this property + * leads to issues with applications that draw their own borders, like chromium + * (with "Use system title bar and borders" turned off) or vlc in fullscreen + * mode. https://dwm.suckless.org/patches/decoration_hints/ + */ +#define DECORATION_HINTS_PATCH 0 + +/* This feature distributes all clients on the current monitor evenly across all + * tags. It is a variant of the reorganizetags patch. + * https://dwm.suckless.org/patches/reorganizetags/ + */ +#define DISTRIBUTETAGS_PATCH 0 + +/* By default dwm will terminate on color allocation failure and the behaviour + * is intended to catch and inform the user of color configuration issues. + * + * Some patches like status2d and xresources / xrdb can change colours during + * runtime, which means that if a color can't be allocated at this time then the + * window manager will abruptly terminate. + * + * This patch will ignore color allocation failures and continue on as normal. + * The effect of this is that the existing color, that was supposed to be + * replaced, will remain as-is. + */ +#define DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH 0 + +/* Similarly to the dragmfact patch this allows you to click and drag clients to + * change the cfact to adjust the client's size in the stack. This patch depends + * on the cfacts patch. + */ +#define DRAGCFACT_PATCH 0 + +/* This patch lets you resize the split in the tile layout (i.e. modify mfact) + * by holding the modkey and dragging the mouse. This patch can be a bit wonky + * with other layouts, but generally works. + * https://dwm.suckless.org/patches/dragmfact/ + */ +#define DRAGMFACT_PATCH 0 + +/* Simple dwmc client using a fork of fsignal to communicate with dwm. + * To use this either copy the patch/dwmc shell script to somewhere in your path + * or uncomment the following line in Makefile: #cp -f patch/dwmc + * ${DESTDIR}${PREFIX}/bin http://dwm.suckless.org/patches/dwmc/ + */ +#define DWMC_PATCH 0 + +/* This patch allows no tag at all to be selected. The result is that dwm will + * start with no tag selected and when you start a client with no tag rule and + * no tag selected then it will be opened on the first tag. + * https://dwm.suckless.org/patches/emptyview/ + */ +#define EMPTYVIEW_PATCH 0 + +/* This patch allows the user to change size and placement of floating windows + * using only the keyboard. It also allows for temporary vertical and horizontal + * extension of windows similar to other WMs fill command. + * https://dwm.suckless.org/patches/exresize/ + */ +#define EXRESIZE_PATCH 0 + +/* Only allow clients to "fullscreen" into the space currently given to them. + * As an example, this will allow you to view a fullscreen video in your browser + * on one half of the screen, while having the other half available for other + * tasks. This patch takes precedence over the fakefullscreen client patch + * below. https://dwm.suckless.org/patches/fakefullscreen/ + */ +#define FAKEFULLSCREEN_PATCH 0 + +/* Similarly to the fakefullscreen patch this patch only allows clients to + * "fullscreen" into the space currently given to them. The "twist" with this + * patch is that fake fullscreen can be toggled on a per client basis rather + * than applying to all clients globally. Also see the selectivefakefullscreen + * option that adds a rule option to enabled this on client startup. + */ +#define FAKEFULLSCREEN_CLIENT_PATCH 0 + +/* This patch adds a float rule allowing the size and position of floating + * windows to be specified It also allows the size and position of floating + * windows to be controlled similar to the exresize, moveresize, and moveplace + * patches. The size and position can be specified using absolute, relative or + * fixed co-ordinates and https://github.com/bakkeby/patches/wiki/floatpos/ + */ +#define FLOATPOS_PATCH 0 + +/* Add-on functionality for the above: make the float positions respect outer + * (vanity)gaps. */ +#define FLOATPOS_RESPECT_GAPS_PATCH 0 + +/* This patch provides the ability to focus the tag on the immediate left or + * right of the currently focused tag. It also allows to send the focused window + * either on the left or the right tag. + * http://dwm.suckless.org/patches/focusadjacenttag/ + */ +#define FOCUSADJACENTTAG_PATCH 0 + +/* Allows focusing on clients based on direction (up, down, left, right) instead + * of client order. https://github.com/bakkeby/patches/wiki/focusdir/ + */ +#define FOCUSDIR_PATCH 0 + +/* When changing tags, closing windows or moving clients out of view then focus + * will revert to the client window that remains under the mouse cursor rather + * than the most recently focused window. + * https://github.com/bakkeby/patches/wiki/focusfollowmouse + */ +#define FOCUSFOLLOWMOUSE_PATCH 0 + +/* A simple patch that just puts focus back to the master client. + * https://dwm.suckless.org/patches/focusmaster/ + */ +#define FOCUSMASTER_PATCH 0 + +/* A variant of the focusmaster patch that additionally allows the focus to be + * returned to the previously focused client + * https://dwm.suckless.org/patches/focusmaster/ + */ +#define FOCUSMASTER_RETURN_PATCH 0 + +/* Switch focus only by mouse click and not sloppy (focus follows mouse + * pointer). https://dwm.suckless.org/patches/focusonclick/ + */ +#define FOCUSONCLICK_PATCH 0 + +/* Selects the next window having the urgent flag regardless of the tag it is + * on. The urgent flag can be artificially set with the following xdotool + * command on any window: xdotool selectwindow -- set_window --urgency 1 + * https://dwm.suckless.org/patches/focusurgent/ + */ +#define FOCUSURGENT_PATCH 0 + +/* By default, dwm responds to _NET_ACTIVE_WINDOW client messages by setting + * the urgency bit on the named window. This patch activates the window instead. + * https://dwm.suckless.org/patches/focusonnetactive/ + */ +#define FOCUSONNETACTIVE_PATCH 0 + +/* Send "fake signals" to dwm for handling, using xsetroot. This will not + * conflict with the status bar, which also is managed using xsetroot. Also see + * the dwmc patch, which takes precedence over this patch. + * https://dwm.suckless.org/patches/fsignal/ + */ +#define FSIGNAL_PATCH 0 + +/* Applies the monocle layout with the focused client on top and hides the bar. + * When pressed again it shows the bar and restores the layout that was active + * before going fullscreen. https://dwm.suckless.org/patches/fullscreen/ + */ +#define FULLSCREEN_PATCH 0 + +/* Adds a rule identifying clients as a "game" such that if the client is in + * fullscreen and it loses focus (e.g. by moving to another tag) then it will + * automatically be minimized (set to IconicState and unmapped). + * + * When the client receives focus again (e.g. by going back to its tag) then it + * will automatically be unminimized (set to NormalState and mapped). This + * should address many of the black screen or window is tiny issues after having + * moved to another tag and back again. + * + * https://github.com/bakkeby/patches/wiki/steam + */ +#define GAMES_PATCH 0 + +/* This patch provides a keybinding to rotate all clients in the currently + * selected area (master or stack) without affecting the other area. + * https://dwm.suckless.org/patches/inplacerotate/ + */ +#define INPLACEROTATE_PATCH 0 + +/* This patch lets you define custom insets from each edge of the screen. One + * use case would be to arrange space for an external bar. + * https://dwm.suckless.org/patches/insets/ + */ +#define INSETS_PATCH 0 + +/* This patch (v1.5.7) implements inter-process communication through a UNIX + * socket for dwm. This allows for the window manager to be queried for + * information, e.g. listen for events such as tag or layout changes, as well as + * send commands to control the window manager via other programs. + * + * You need to uncomment the corresponding lines in config.mk to use the -lyajl + * library when including this patch. This patch depends on the following + * additional library: + * - yajl + * + * https://github.com/mihirlad55/dwm-ipc + * https://dwm.suckless.org/patches/ipc/ + */ +#define IPC_PATCH 0 + +/* Adds rule option for clients to avoid accidental termination by killclient + * for sticky windows. https://dwm.suckless.org/patches/ispermanent/ + */ +#define ISPERMANENT_PATCH 0 + +/* This patch adds key modes (like in vim or emacs) where chains of keyboard + * shortcuts can be performed. https://dwm.suckless.org/patches/keymodes/ + */ +#define KEYMODES_PATCH 0 + +/* This patch adds a keybinding to kills all visible clients that are not + * selected. https://dwm.suckless.org/patches/killunsel/ + */ +#define KILLUNSEL_PATCH 0 + +/* This changes the window manager name to LG3d instead of dwm as a workaround + * for Java applications that assume that the window manager is using window + * reparenting. Refer to the ISSUES secton of the dwm man page for more details. + */ +#define LG3D_PATCH 0 + +/* By default in dwm it is possible to make an application fullscreen, then use + * the focusstack keybindings to focus on other windows beneath the current + * window. It is also possible to spawn new windows (e.g. a terminal) that end + * up getting focus while the previous window remains in fullscreen. This patch + * ensures that in such scenarios the previous window loses fullscreen. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-losefullscreen-6.2.diff + */ +#define LOSEFULLSCREEN_PATCH 0 + +/* This patch adds helper functions for maximizing, horizontally and vertically, + * floating windows using keybindings. + * https://dwm.suckless.org/patches/maximize/ + */ +#define MAXIMIZE_PATCH 0 + +/* Control Music Player Daemon via keybinds. + * You need to uncomment the corresponding line in config.mk to use the + * -lmpdclient library when including this patch. This patch depends on the + * following additional library: + * - libmpdclient + * https://dwm.suckless.org/patches/mpdcontrol/ + */ +#define MPDCONTROL_PATCH 0 + +/* Adds rules per monitor, e.g. have default layouts per monitor. + * The use case for this is if the second monitor is vertical (i.e. rotated) + * then you may want to use a different default layout for this monitor than + * what is used for the main monitor. E.g. normal vertical split for main + * monitor and horizontal split for the second. + */ +#define MONITOR_RULES_PATCH 0 + +/* Always display the the monocle-symbol as defined in config.h if the + * monocle-layout is activated. Do not display the number of open clients in the + * current tag. https://dwm.suckless.org/patches/monoclesymbol/ + */ +#define MONOCLESYMBOL_PATCH 0 + +/* This patch provides a keybinding to center the focused window. + * https://dwm.suckless.org/patches/movecenter/ + */ +#define MOVECENTER_PATCH 0 + +/* Makes a window floating and 1/3rd the height and 1/3rd the width of the + * screen and is positioned in either the center or one of the 8 cardinal + * directions depending on which key is pressed. + * https://dwm.suckless.org/patches/moveplace/ + */ +#define MOVEPLACE_PATCH 0 + +/* This patch allows you to move and resize dwm's clients using keyboard + * bindings. https://dwm.suckless.org/patches/moveresize/ + */ +#define MOVERESIZE_PATCH 0 + +/* This patch allows you to move clients around in the stack and swap them with + * the master. https://dwm.suckless.org/patches/movestack/ + */ +#define MOVESTACK_PATCH 0 + +/* This patch allows you to change the names of tags during runtime. + * + * This is a bespoke version implemented specifically in relation to tagicons, + * which is integrated into dwm-flexipatch. By default it uses dmenu to retrieve + * the new name, but this can be customised via config along with the maximum + * text length and the format string. + * + * Special behaviour: + * - if more than one tag is selected then the name change applies to all + * selected tags + * - if tagicons is configured to have unique tags per monitor then the + * change only applies for the current monitor + * - the name change applies to the tag set that is active for the current + * tag: + * * if used in combination with BAR_ALTTAGSDECORATION_PATCH and there are + * clients on the given tag then the name change only applies to the + * ALT_TAGS_DECORATION tag set + * * if used in combination with the BAR_ALTERNATIVE_TAGS_PATCH and + * alternative tags are shown then the name change only applies to the + * ALTERNATIVE_TAGS tag set + * * if used in combination with both then BAR_ALTTAGSDECORATION_PATCH + * takes precedence + * * otherwise the name change applies to the DEFAULT_TAGS tag set + * + * https://dwm.suckless.org/patches/nametag/ + */ +#define NAMETAG_PATCH 0 + +/* Variant of the above which prepends the tag number to the given string. + * The toggle does nothing on its own and need to be enabled in combination with + * the above. */ +#define NAMETAG_PREPEND_PATCH 0 + +/* Adds support for the _NET_CLIENT_LIST_STACKING atom, needed by certain + * applications like the Zoom video conferencing application. + * https://github.com/bakkeby/patches/wiki/netclientliststacking/ + */ +#define NET_CLIENT_LIST_STACKING_PATCH 0 + +/* Removes the border when there is only one window visible. + * https://dwm.suckless.org/patches/noborder/ + */ +#define NOBORDER_PATCH 0 + +/* Enable modifying or removing dmenu in config.def.h which resulted previously + * in a compilation error because two lines of code hardcode dmenu into dwm. + * https://dwm.suckless.org/patches/nodmenu/ + */ +#define NODMENU_PATCH 0 + +/* This patch allows for toggleable client button bindings that have no + modifiers. + * This can, for example, allow you to move or resize using the mouse alone + without holding + * down a modifier key. This can be practical if you have extra buttons on your + mouse. + * While you can use button bindings with no modifiers without this patch in a + bare dwm, + * those buttons are then unavailable for use within the application itself so + being able to + * toggle these on and off can be necessary in certain situations (e.g. being + able to use + * back and forward buttons in a browser). + + * Example bindings: + * { ClkClientWin, 0, Button8, movemouse, + {0} }, + * { ClkClientWin, 0, Button9, resizemouse, + {0} }, + */ +#define NO_MOD_BUTTONS_PATCH 0 + +/* When terminals have transparency then their borders also become transparent. + * This patch ensures that borders have no transparency. Note that this patch is + * only relevant if you are not using the alpha patch. + * https://github.com/szatanjl/dwm/commit/1529909466206016f2101457bbf37c67195714c8 + * https://dwm.suckless.org/patches/alpha/dwm-fixborders-6.2.diff + */ +#define NO_TRANSPARENT_BORDERS_PATCH 0 + +/* Port of InstantWM's on_empty_keys functionality allowing keybindings that + * apply only when a tag is empty. An example use case is being able to launch + * applications with first hand keys like "f" to launch firefox. + * + * https://github.com/instantOS/instantWM/ + * https://github.com/bakkeby/dwm-flexipatch/issues/51 + */ +#define ON_EMPTY_KEYS_PATCH 0 + +/* Minor patch that prevents more than one rule being matched for a given + * client. */ +#define ONLY_ONE_RULE_MATCH_PATCH 0 + +/* This patch makes it so dwm will only exit via quit() if no windows are open. + * This is to prevent you accidentally losing all your work. + * https://dwm.suckless.org/patches/onlyquitonempty/ + */ +#define ONLYQUITONEMPTY_PATCH 0 + +/* The pertag patch adds nmaster, mfacts and layouts per tag rather than per + * monitor (default). + * https://dwm.suckless.org/patches/pertag/ + */ +#define PERTAG_PATCH 0 + +/* Option to enable gaps on a per tag basis rather than globally. + * Depends on both pertag and vanitygaps patches being enabled. + */ +#define PERTAG_VANITYGAPS_PATCH 0 + +/* This patch allows configuring vanity gaps on a per-monitor basis rather than + * all monitors (default). + */ +#define PERMON_VANITYGAPS_PATCH 0 + +/* This controls whether or not to also store bar position on a per + * tag basis, or leave it as one bar per monitor. + */ +#define PERTAGBAR_PATCH 0 + +/* Similar to the focusdir patch this patch allow users to move a window in any + * direction in the tiled stack (up, down, left, right). + * https://github.com/bakkeby/patches/wiki/placedir + */ +#define PLACEDIR_PATCH 0 + +/* This patch lets you change the position of a client in the stack using the + * mouse. https://github.com/bakkeby/patches/wiki/placemouse + */ +#define PLACEMOUSE_PATCH 0 + +/* This patch provides a way to move clients up and down inside the client list. + * https://dwm.suckless.org/patches/push/ + */ +#define PUSH_PATCH 0 + +/* This patch provides a way to move clients up and down inside the client list, + * but does not push up or down into the master area (except that it does not + * take nmaster into account). This takes precedence over the push patch above. + * https://dwm.suckless.org/patches/push/ + */ +#define PUSH_NO_MASTER_PATCH 0 + +/* Variant of the named scratchpads patch allowing scratch keys to be added or + * removed on demand, allowing multiple scratchpad windows to be toggled into + * and out of view in unison, as well as including multi-monitor support. + * + * https://github.com/bakkeby/patches/wiki/renamedscratchpads + */ +#define RENAMED_SCRATCHPADS_PATCH 0 + +/* Renamed scratchpads option to auto-hide scratchpads when moving to a + * different tag. This behaviour is similar to that of the (multiple) + * scratchpads patch. */ +#define RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH 0 + +/* Shifts all clients per tag to leftmost unoccupied tags. + * + * For example, if clients A, B, C are tagged on tags 1, 5, 9 respectively, when + * this function is called, they will now be on 1, 2, and 3. The focused client + * will also remain focused. + * + * Clients on multiple tags will be treated as if they only were only on their + * leftmost tag, and will be reduced to one tag after the operation is complete. + * https://dwm.suckless.org/patches/reorganizetags/ + */ +#define REORGANIZETAGS_PATCH 0 + +/* By default, windows only resize from the bottom right corner. With this + * patch the mouse is warped to the nearest corner and you resize from there. + * https://dwm.suckless.org/patches/resizecorners/ + */ +#define RESIZECORNERS_PATCH 0 + +/* Practically the same as resizecorners, but the cursor does not warp to + * corners. This takes precedence over the resizecorners patch. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-resizepoint-6.2.diff + */ +#define RESIZEPOINT_PATCH 0 + +/* Adds a keyboard shortcut to restart dwm or alternatively by using kill -HUP + * dwmpid. Additionally dwm can quit cleanly by using kill -TERM dwmpid. + * https://dwm.suckless.org/patches/restartsig/ + */ +#define RESTARTSIG_PATCH 0 + +/* Adds rio-like drawing to resize the selected client. + * This depends on an external tool slop being installed. + * This patch was backported from instantWM. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-riodraw-6.2.diff + */ +#define RIODRAW_PATCH 0 + +/* This patch let's you rotate through the stack using keyboard shortcuts. + * https://dwm.suckless.org/patches/rotatestack/ + */ +#define ROTATESTACK_PATCH 0 + +/* This patch adds rounded corners to client windows in dwm. + * You need to uncomment the corresponding line in config.mk to use the -lXext + * library when including this patch. You will also want to set "borderpx = 0;" + * in your config.h. + * https://github.com/mitchweaver/suckless/blob/master/dwm/patches/mitch-06-rounded_corners-f04cac6d6e39cd9e3fc4fae526e3d1e8df5e34b2.patch + */ +#define ROUNDED_CORNERS_PATCH 0 + +/* This patch saves size and position of every floating window before it is + * forced into tiled mode. If the window is made floating again then the old + * dimensions will be restored. https://dwm.suckless.org/patches/save_floats/ + */ +#define SAVEFLOATS_PATCH 0 + +/* The scratchpad patch allows you to spawn or restore floating terminal + * windows. It is typically useful when one need to do some short typing. + * + * Note that this patch changes TAGMASK to make room for special scratchpad + * tags, so ~0 does more than select all tags with this patch. Code that relies + * on ~0 to represent all tags should use ~SPTAGMASK instead. + * + * Upgraded to Christian Tenllado's multiple scratchpad version. + * https://lists.suckless.org/hackers/2004/17205.html + * https://dwm.suckless.org/patches/scratchpads/ + */ +#define SCRATCHPADS_PATCH 0 + +/* Minor alteration of the above allowing clients to keep their size and + * position when shown */ +#define SCRATCHPADS_KEEP_POSITION_AND_SIZE_PATCH 0 + +/* This alternative patch enables a scratchpad feature in dwm similar to the + * scratchpad feature in i3wm. https://github.com/GasparVardanyan/dwm-scratchpad + */ +#define SCRATCHPAD_ALT_1_PATCH 0 + +/* This patch persists some settings across window manager restarts. These + * include but are not limited to: + * - client's assigned tag(s) on which monitor + * - the order of clients + * - nmaster + * - selected layout + * - plus various additions depending on what other patches are used + * + * The above is not persisted across reboots, however. + */ +#define SEAMLESS_RESTART_PATCH 0 + +/* As opposed to the original patch this only adds a rule option allowing fake + * fullscreen to be enabled for applications when they start. This is intended + * to be used in combination with the fakefullscreenclient patch and offers no + * practical functionality without it. + * https://dwm.suckless.org/patches/selectivefakefullscreen/ + */ +#define SELECTIVEFAKEFULLSCREEN_PATCH 0 + +/* Allows restarting dwm without the dependency of an external script. + * https://dwm.suckless.org/patches/selfrestart/ + */ +#define SELFRESTART_PATCH 0 + +/* Floating windows being sent to another monitor will be centered. + * https://dwm.suckless.org/patches/sendmoncenter/ + */ +#define SENDMON_CENTER_PATCH 0 + +/* This patch allow clients to keep focus when being sent to another monitor. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-sendmon_keepfocus-6.2.diff + */ +#define SENDMON_KEEPFOCUS_PATCH 0 + +/* This patch allows border pixels to be changed during runtime. + * https://dwm.suckless.org/patches/setborderpx/ + */ +#define SETBORDERPX_PATCH 0 + +/* Combines shifttag and shiftview. Basically moves the window to the next/prev + * tag and follows it. Also see the focusadjacenttag patch. + * https://dwm.suckless.org/patches/shift-tools/ + */ +#define SHIFTBOTH_PATCH 0 + +/* Swaps all the clients on the current tag with all the client on the next/prev + * tag. Depends on the swaptags patch. + * https://dwm.suckless.org/patches/shift-tools/ + */ +#define SHIFTSWAPTAGS_PATCH 0 + +/* Moves the current selected client to the adjacent tag. + * Also see the focusadjacenttag patch. + * https://dwm.suckless.org/patches/shift-tools/ + */ +#define SHIFTTAG_PATCH 0 + +/* Moves the current selected client to the adjacent tag that has at least one + * client, if none then it acts as shifttag. + * https://dwm.suckless.org/patches/shift-tools/ + */ +#define SHIFTTAGCLIENTS_PATCH 0 + +/* This patch adds keybindings for left and right circular shift through tags. + * https://github.com/chau-bao-long/dotfiles/blob/master/suckless/dwm/shiftview.diff + */ +#define SHIFTVIEW_PATCH 1 + +/* This variant of the shiftview patch adds left and right circular shift + * through tags, but skips tags where there are no clients. + */ +#define SHIFTVIEW_CLIENTS_PATCH 0 + +/* This patch makes dwm obey even "soft" sizehints for new clients. Any window + * that requests a specific initial size will be floated and set to that size. + * Unlike with "fixed size" windows, you are able to resize and/or unfloat these + * windows freely - only the initial state is affected. + * This version of the patch is honestly of limited utility since there are many + * clients that will abuse it. + * https://dwm.suckless.org/patches/sizehints/ + */ +#define SIZEHINTS_PATCH 0 + +/* This patch makes dwm obey even "soft" sizehints for new clients. This ruled + * version is essentially the same patch except it obeys the "isfloating" rule + * if it is available in config.h for the given client. + * https://dwm.suckless.org/patches/sizehints/ + */ +#define SIZEHINTS_RULED_PATCH 0 + +/* This patch makes dwm obey even "soft" sizehints for new clients. The + * isfreesize version is similar to the sizehints ruled patch except it allows + * you to specify via client rules which clients this should apply to. Soft + * sizehints applies by default to clients that are not ruled, and will be + * disabled by default for clients that are. + * + * Example client rule enabling soft sizehints: + * - RULE(.wintype = WTYPE "DIALOG", .isfloating = 1, .isfreesize = 1) + * + * https://dwm.suckless.org/patches/sizehints/ + */ +#define SIZEHINTS_ISFREESIZE_PATCH 0 + +/* In a multi-head setup monitor 0 is by default the primary screen, with the + * left and right screen being monitor 1 and 2 respectively. This patch sorts + * screens left to right (or top to bottom in a vertical layout) which aims to + * address some inconsistencies when it comes to focusmon, tagmon and similar + * functionality. + * https://www.mail-archive.com/hackers@suckless.org/msg09400.html + */ +#define SORTSCREENS_PATCH 0 + +/* Spawns programs from currently focused client's working directory. + * https://dwm.suckless.org/patches/spawn_cwd/ + */ +#define SPAWNCMD_PATCH 0 + +/* This patch provides comprehensive utilities for managing the client stack, + * providing keyboard shortcuts for focusing or placing a client at specific + * positions in the stack. Note that the default keybindings for this patch have + * been changed in dwm-flexipatch due to the many conflicts with other patches. + * As it provides similar functionality to the swapfocus patch it also uses the + * MOD+s shortcut to focus the previously selected client, thus note a conflict + * between these two patches. https://dwm.suckless.org/patches/stacker/ + */ +#define STACKER_PATCH 0 + +/* Steam, and steam windows (games), trigger a ConfigureNotify request every + * time the window gets focus. More so, the configure event passed along from + * Steam tends to have the wrong x and y co-ordinates which can make the window, + * if floating, jump around the screen. + * + * This patch works around this age-old issue by ignoring the x and y + * co-ordinates for ConfigureNotify requests relating to Steam windows. + * + * https://github.com/bakkeby/patches/wiki/steam + */ +#define STEAM_PATCH 0 + +/* Adds toggleable keyboard shortcut to make a client 'sticky', i.e. visible on + * all tags. https://dwm.suckless.org/patches/sticky/ + */ +#define STICKY_PATCH 0 + +/* This patch adds "window swallowing" to dwm as known from Plan 9's windowing + * system rio. Clients marked with isterminal in config.h swallow a window + * opened by any child process, e.g. running xclock in a terminal. Closing the + * xclock window restores the terminal window in the current position. + * + * This patch depends on the following additional libraries: + * - libxcb + * - Xlib-libxcb + * - xcb-res + * + * You need to uncomment the corresponding line in config.mk to use the above + * libraries when including this patch. + * + * https://dwm.suckless.org/patches/swallow/ + */ +#define SWALLOW_PATCH 0 + +/* This patch depends on the pertag patch and makes it possible to switch focus + * with a single shortcut (MOD+s) instead of having to think if you should use + * mod-j or mod-k for reaching the previously used window. + * https://dwm.suckless.org/patches/swapfocus/ + */ +#define SWAPFOCUS_PATCH 0 + +/* This patch allows swapping the contents of the currently selected tag with + * another tag using keyboard shortcuts. + * https://dwm.suckless.org/patches/swaptags/ + */ +#define SWAPTAGS_PATCH 0 + +/* Switch focus between the master and stack columns using a single keybinding. + * https://dwm.suckless.org/patches/switchcol/ + */ +#define SWITCHCOL_PATCH 0 + +/* By default dwm allow you to set application specific rules so that you can + * have your browser, for example, start up on tag 9 optionally on a given + * monitor when you open your browser it is then automatically moved to the + * configured tag, but you have to manually enable the tag to see the newly + * opened application. This patch adds an extra configuration option for + * individual rules where: 0 is default behaviour 1 automatically moves you to + * the tag of the newly opened application and 2 enables the tag of the newly + * opened application in addition to your existing enabled tags 3 as 1, but + * closing that window reverts the view back to what it was previously (*) 4 as + * 2, but closing that window reverts the view back to what it was previously + * (*) + * + * (*) except if the client has been moved between tags or to another monitor + * + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-switchtag-6.2.diff + * Also see https://dwm.suckless.org/patches/switchtotag + */ +#define SWITCHTAG_PATCH 0 + +/* This patch transforms the monocle layout into a "tabbed" layout if more than + * one window is present on the monocle view. This patch has been added for + * demonstration purposes only and has limited compatibility with other patches. + * It will conflict space-wise with a second bar. Note that fancybar, + * awesomebar, bartabgroups and similar patches make the tab patch redundant. + * https://dwm.suckless.org/patches/tab/ + */ +#define TAB_PATCH 0 + +/* Adds keyboard shortcuts to move all (or only floating) windows from one tag + * to another. https://dwm.suckless.org/patches/tagall/ + */ +#define TAGALL_PATCH 0 + +/* This patch allows you to move all visible windows on a monitor to an adjacent + * monitor. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-tagallmon-6.2.diff + */ +#define TAGALLMON_PATCH 0 + +/* This patch makes new clients attach into the stack area when you toggle a new + * tag into view. This means your master area will remain unchanged when + * toggling views. The allmaster patch will cause all clients in the master area + * to be left alone. This patch takes precedence over the onemaster tagintostack + * patch. https://dwm.suckless.org/patches/tagintostack/ + */ +#define TAGINTOSTACK_ALLMASTER_PATCH 0 + +/* This patch makes new clients attach into the stack area when you toggle a new + * tag into view. This means your master area will remain unchanged when + * toggling views. The onemaster patch will cause the first client in the master + * area to be left alone. https://dwm.suckless.org/patches/tagintostack/ + */ +#define TAGINTOSTACK_ONEMASTER_PATCH 0 + +/* If you try to send a fullscreen window to an adjacent monitor using tagmon + * then the window is moved behind the scenes, but it remains in fullscreen on + * the original monitor until you exit fullscreen view (at which point it will + * appear on the adjacent monitor). This patch allows a fullscreen window to be + * moved to an adjacent monitor while remaining in fullscreen. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-tagmonfixfs-6.2.diff + */ +#define TAGMONFIXFS_PATCH 0 + +/* Add functions and keybindings to tag a window to a desired tag on the next + * (right) or previous (left) monitor from the currently selected monitor. + * https://dwm.suckless.org/patches/tagothermonitor/ + */ +#define TAGOTHERMONITOR_PATCH 0 + +/* This patch allows you to swap all visible windows on one monitor with those + * of an adjacent monitor. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-tagswapmon-6.2.diff + */ +#define TAGSWAPMON_PATCH 0 + +/* Sync tag actions across all monitors. + * This is comparable to a sort of pseudo-desktop environment. + * Also refer to the desktop patch: + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-desktop-6.3.diff + */ +#define TAGSYNC_PATCH 0 + +/* This patch can be useful to the touchpad users because it allows to + * resize windows using Mod + two-finger scroll. It is useful when + * two-finger scrolling is configured in libinput. + * https://dwm.suckless.org/patches/tapresize/ + */ +#define TAPRESIZE_PATCH 0 + +/* This patch allows you to toggle fullscreen on and off using a single shortcut + * key. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-togglefullscreen-6.2.diff + */ +#define TOGGLEFULLSCREEN_PATCH 0 + +/* This patch allows for the bar position (top or bottom) to be toggled during + * runtime. https://dwm.suckless.org/patches/toggletopbar/ + */ +#define TOGGLETOPBAR_PATCH 0 + +/* Minor patch that lets you use the same keyboard shortcut to toggle to the + * previous layout if the designated layout is already active. + * + * This allows you to use e.g. MOD+m to change to the monocle layout and use the + * same keybinding to toggle back to what it was previously. The default + * behaviour in dwm forces you to use either MOD+space or MOD+t to change back + * to tiled layout. + * + * https://github.com/bakkeby/patches/wiki/togglelayout + */ + +#define TOGGLELAYOUT_PATCH 0 + +/* Minor patch that lets you use the same keyboard shortcut to toggle to the + * previous tag if the designated tag is already active. + * + * This allows you to use e.g. MOD+4 to quickly view the 4th tag and use the + * same keybinding to toggle back to what it was previously. The default + * behaviour in dwm forces you to use either MOD+tab or MOD+1 to change back to + * the previous tag. + * + * Idea ref. + * https://www.reddit.com/r/suckless/comments/ik27vd/key_toggle_between_next_and_previous_tag_dwm/ + * https://github.com/bakkeby/patches/wiki/toggletag + */ +#define TOGGLETAG_PATCH 0 + +/* Lets you transfer the currently focused client between the master and stack + * area while increasing or decreasing the master area (nmaster) accordingly. + * https://dwm.suckless.org/patches/transfer/ + */ +#define TRANSFER_PATCH 0 + +/* Lets you transfer all clients between the master and stack area + * while increasing or decreasing the master area (nmaster) accordingly. + * https://dwm.suckless.org/patches/transfer/ + */ +#define TRANSFER_ALL_PATCH 0 + +/* This patch resets isfloating on any visible windows that have it set. + * Optionally also applies a layout. + * https://dwm.suckless.org/patches/unfloatvisible/ + */ +#define UNFLOATVISIBLE_PATCH 0 + +/* This patch adds a client rule that allows for windows that do not specify the + * override-redirect to not be managed by the window manager. This can be useful + * for external bars, widgets, launchers, docks, desktop icons and more. + * https://github.com/bakkeby/patches/wiki/unmanaged + */ +#define UNMANAGED_PATCH 0 + +/* This patch adds configurable gaps between windows differentiating between + * outer, inner, horizontal and vertical gaps. + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-vanitygaps-6.2.diff + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-cfacts-vanitygaps-6.2.diff + */ +#define VANITYGAPS_PATCH 1 + +/* This patch adds outer gaps for the monocle layout. + * Most gaps patches tries to avoid gaps on the monocle layout, as it is often + * used as a fullscreen mode, hence this is enabled separately from the main + * vanitygaps patch. + */ +#define VANITYGAPS_MONOCLE_PATCH 0 + +/* By default MOD+Tab will take the user back to the previous tag only. If the + * user keeps using MOD+Tab then the view will switch back and forth between the + * current and previous tag. This patch allows dwm to keep a longer history of + * previous tag changes such that MOD+Tab can be pressed multiple times to go + * further back to earlier tag selections. + * + * The number of history elements is defined by the NUMVIEWHIST macro in dwm.c + * and defaults to the number of tags in the system. + */ +#define VIEW_HISTORY_PATCH 0 + +/* Follow a window to the tag it is being moved to. + * https://dwm.suckless.org/patches/viewontag/ + */ +#define VIEWONTAG_PATCH 0 + +/* This patch warps the mouse cursor to the center of the currently focused + * window or screen when the mouse cursor is (a) on a different screen or (b) on + * top of a different window. https://dwm.suckless.org/patches/warp/ + */ +#define WARP_PATCH 0 + +/* Sometimes a single application opens different windows depending on the task + * at hand and this is often reflected in the WM_WINDOW_ROLE(STRING) x property. + * This patch adds the role field to the rule configuration so that one can + * differentiate between, say, Firefox "browser" vs "Preferences" vs "Manager" + * or Google-chrome "browser" vs "pop-up". + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-windowrolerule-6.2.diff + */ +#define WINDOWROLERULE_PATCH 0 + +/* The winview patch allows switching the view to that of a given client from + * the all-window view (Mod-0) using a keyboard shortcut. + * http://dwm.suckless.org/patches/winview/ + */ +#define WINVIEW_PATCH 0 + +/* Remember keyboard layout per client. + * It is recommended that you configure xkb before using this patch as described + * in https://www.x.org/archive/X11R7.5/doc/input/XKB-Config.html + * https://dwm.suckless.org/patches/xkb/ + */ +#define XKB_PATCH 0 + +/* Allows dwm to read colors from xrdb (.Xresources) during runtime. Compatible + * with the float border color, awesomebar, urgentborder and titlecolor patches. + * https://dwm.suckless.org/patches/xrdb/ + */ +#define XRDB_PATCH 0 + +/* This patch allows for integer, float and string settings to be loaded from + * Xresources. Xresources takes precedence over xrdb. + * https://dwm.suckless.org/patches/xresources/ + */ +#define XRESOURCES_PATCH 0 + +/* Simple patch that allows floating windows to be zoomed into the master stack + * position. + * https://www.reddit.com/r/suckless/comments/ie5fe3/zoomfloating_my_own_simple_original_patch/ + */ +#define ZOOMFLOATING_PATCH 0 + +/* The zoomswap patch allows a master and a stack window to swap places + * rather than every window on the screen changing position. + * https://dwm.suckless.org/patches/zoomswap/ + */ +#define ZOOMSWAP_PATCH 0 + +/** + * Layouts + */ + +/* Bottomstack layout. + * https://dwm.suckless.org/patches/bottomstack/ + */ +#define BSTACK_LAYOUT 0 + +/* Bottomstack horizontal layout. + * https://dwm.suckless.org/patches/bottomstack/ + */ +#define BSTACKHORIZ_LAYOUT 0 + +/* Centered master layout. + * https://dwm.suckless.org/patches/centeredmaster/ + */ +#define CENTEREDMASTER_LAYOUT 0 + +/* Centered floating master layout. + * https://dwm.suckless.org/patches/centeredmaster/ + */ +#define CENTEREDFLOATINGMASTER_LAYOUT 0 + +/* Same as the default tile layout except clients in the master area are + * arranged in columns (i.e. left to right). + * https://dwm.suckless.org/patches/columns/ + */ +#define COLUMNS_LAYOUT 0 + +/* Deck layout. + * https://dwm.suckless.org/patches/deck/ + */ +#define DECK_LAYOUT 0 + +/* Fibonacci dwindle layout. + * https://dwm.suckless.org/patches/fibonacci/ + */ +#define FIBONACCI_DWINDLE_LAYOUT 0 + +/* Fibonacci spiral layout. + * https://dwm.suckless.org/patches/fibonacci/ + */ +#define FIBONACCI_SPIRAL_LAYOUT 0 + +/* Flextile deluxe layout. + * A revamped, more flexible, and over-the-top version of the original flextile + * layout. https://dwm.suckless.org/patches/flextile/ (original) + */ +#define FLEXTILE_DELUXE_LAYOUT 0 + +/* Gappless grid layout. + * https://dwm.suckless.org/patches/gaplessgrid/ + */ +#define GAPPLESSGRID_LAYOUT 0 + +/* Gridmode (grid) layout. + * https://dwm.suckless.org/patches/gridmode/ + */ +#define GRIDMODE_LAYOUT 0 + +/* Horizontal grid (horizgrid) layout. + * https://dwm.suckless.org/patches/horizgrid/ + */ +#define HORIZGRID_LAYOUT 0 + +/* Grid layout where nmaster controls the number of rows. + * https://dwm.suckless.org/patches/nrowgrid/ + */ +#define NROWGRID_LAYOUT 0 + +/* The default tile layout. + * This can be optionally disabled in favour of other layouts. + */ +#define TILE_LAYOUT 1 + +/* Monocle layout (default). + * This can be optionally disabled in favour of other layouts. + */ +#define MONOCLE_LAYOUT 1 diff --git a/dwm/transient.c b/dwm/transient.c new file mode 100755 index 0000000..158460f --- /dev/null +++ b/dwm/transient.c @@ -0,0 +1,43 @@ +/* cc transient.c -o transient -lX11 */ + +#include +#include +#include +#include + +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/util.c b/dwm/util.c new file mode 100755 index 0000000..0cdc035 --- /dev/null +++ b/dwm/util.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#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/util.h b/dwm/util.h new file mode 100755 index 0000000..72ba202 --- /dev/null +++ b/dwm/util.h @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) + +#ifdef _DEBUG +#define DEBUG(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG(...) +#endif + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); + diff --git a/local/bin/README.md b/local/bin/README.md new file mode 100755 index 0000000..ea5b2c9 --- /dev/null +++ b/local/bin/README.md @@ -0,0 +1,3 @@ +Credits to *Swindles McCoop* for **edsc**, **sb-liisten, sb-memory, sb-volume, sb-cputemp, sb-cpuusage, sb-network, and sb-battery**. Really useful tools. + +(same username on [https://git.cbps.xyz/swindlesmccoop](git.cbps.xyz) he's my daddy btw i love him) \ No newline at end of file diff --git a/local/bin/Xrec b/local/bin/Xrec new file mode 100755 index 0000000..1d7e956 --- /dev/null +++ b/local/bin/Xrec @@ -0,0 +1,32 @@ +#!/usr/bin/env sh +VIDEO_SIZE="1920x1080" +DISPLAY_NUM=":0.0" +AUDIO_SOURCE="default" +FPS="60" +OUTPUT_FILE="recording_$(date +%Y%m%d_%H%M%S).mkv" +AUDIO_BITRATE="128k" +record() { + local out_file="${1:-$OUTPUT_FILE}" + echo "Starting screen + mic recording..." + echo "Resolution: $VIDEO_SIZE @ ${FPS}fps" + echo "Audio source: $AUDIO_SOURCE" + echo "Output: $out_file" + ffmpeg -y \ + -thread_queue_size 1024 \ + -f x11grab -framerate "$FPS" -video_size "$VIDEO_SIZE" -i "$DISPLAY_NUM" \ + -thread_queue_size 1024 \ + -f pulse -i "$AUDIO_SOURCE" \ + -c:v h264_nvenc -preset p1 -rc vbr -cq 23 \ + -pix_fmt yuv420p \ + -c:a aac -b:a "$AUDIO_BITRATE" \ + -vsync 1 \ + "$out_file" +} +show_help() { + echo "Usage: $0 record [output_file]" +} +if [ "$1" = "--record" ]; then + record "$2" +else + show_help +fi diff --git a/local/bin/aurtest.sh b/local/bin/aurtest.sh new file mode 100755 index 0000000..d26ca37 --- /dev/null +++ b/local/bin/aurtest.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +AUR_URL="https://aur.archlinux.org" +TIMEOUT=5 + +if curl -s --head --fail --max-time "$TIMEOUT" "$AUR_URL" > /dev/null; then + echo "Unfortunately, the AUR is up." +else + echo "AUR IS DOWN" +fi diff --git a/local/bin/bat-symbol b/local/bin/bat-symbol new file mode 100755 index 0000000..1ae28f8 --- /dev/null +++ b/local/bin/bat-symbol @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +def read_file(path): + try: + with open(path, "r") as f: + return f.read().strip() + except: + return None + +def get_battery_info(): + capacity = read_file("/sys/class/power_supply/BAT1/capacity") + status = read_file("/sys/class/power_supply/BAT1/status") + ac_online = read_file("/sys/class/power_supply/ACAD/online") + + try: + percent = int(capacity) + except (TypeError, ValueError): + percent = None + + charging = (status == "Charging") or (ac_online == "1") + return charging, percent + +def print_symbol(): + charging, percent = get_battery_info() + + if percent is None: + print("[?]") + return + + if charging and percent >= 90: + print("[++]") + elif charging and percent < 30: + print("[-+]") + elif charging: + print("[+]") + elif not charging and percent < 30: + print("[--]") + else: + print("[-]") + +if __name__ == "__main__": + print_symbol() diff --git a/local/bin/brwmenu b/local/bin/brwmenu new file mode 100755 index 0000000..11628eb --- /dev/null +++ b/local/bin/brwmenu @@ -0,0 +1,118 @@ +#!/bin/sh + +WMENU="wmenu" +DMENU="dmenu" +BROWSER="firefox-bin" +NOTIFY="notify-send" + +CHOICES="Paulgo +URL +Incognito URL +YouTube +Codeberg +Tildegit +IPLeak +Safebooru +Wikipedia" + +notify() { + "$NOTIFY" "$1" "$2" 2>/dev/null +} + +run_wmenu() { + printf '%s\n' "$1" | $WMENU -p "$2" +} + +run_dmenu() { + printf '' | $DMENU -p "$1" +} + +urlencode() { + python3 -c "import sys, urllib.parse as ul; print(ul.quote_plus(sys.argv[1]))" "$1" +} + +open_url() { + url="$1" + if pgrep -x "$BROWSER" >/dev/null; then + "$BROWSER" --new-tab "$url" & + else + "$BROWSER" "$url" & + fi +} + +main() { + choice=$(run_wmenu "$CHOICES" "Where to?") + [ -z "$choice" ] && notify "Error" "No selection made" && exit 1 + + case "$choice" in + Codeberg) + repo=$(run_dmenu "Username & repo (user/repo):") + [ -z "$repo" ] && notify "Error" "No input" && exit 1 + open_url "https://codeberg.org/$repo" + ;; + Tildegit) + repo=$(run_dmenu "Username & repo (user/repo):") + [ -z "$repo" ] && notify "Error" "No input" && exit 1 + open_url "https://tildegit.org/$repo" + ;; + IPLeak) + open_url "https://ipleak.net" + ;; + Paulgo) + query=$(run_dmenu "Search Paulgo:") + [ -z "$query" ] && notify "Error" "No input" && exit 1 + qenc=$(urlencode "$query") + open_url "https://paulgo.io/search?q=$qenc" + ;; + Wikipedia) + query=$(run_dmenu "Search Wikipedia:") + [ -z "$query" ] && notify "Error" "No input" && exit 1 + qenc=$(urlencode "$query") + open_url "https://en.wikipedia.org/wiki/Special:Search?search=$qenc" + ;; + URL) + url=$(run_dmenu "Enter URL:") + [ -z "$url" ] && notify "Error" "No URL entered" && exit 1 + case "$url" in + http*) ;; + *) url="https://$url" ;; + esac + open_url "$url" + ;; + "Incognito URL") + url=$(run_dmenu "Enter incognito URL:") + [ -z "$url" ] && notify "Error" "No URL entered" && exit 1 + case "$url" in + http*) ;; + *) url="https://$url" ;; + esac + "$BROWSER" --private-window "$url" & + ;; + YouTube) + query=$(run_dmenu "Search YouTube:") + [ -z "$query" ] && notify "Error" "No input" && exit 1 + qenc=$(urlencode "$query") + open_url "https://youtube.com/results?search_query=$qenc" + ;; + Safebooru) + query=$(run_dmenu "Search Safebooru:") + [ -z "$query" ] && notify "Error" "No input" && exit 1 + qenc=$(urlencode "$query") + open_url "https://safebooru.org/index.php?page=post&s=list&tags=$qenc" + ;; + *) + notify "Error" "Invalid selection: $choice" + exit 1 + ;; + esac +} + +for cmd in "$WMENU" "$DMENU" "$BROWSER" "$NOTIFY"; do + if ! command -v "$cmd" >/dev/null 2>&1; then + echo "Error: required command '$cmd' not found" >&2 + exit 1 + fi +done + +main + diff --git a/local/bin/cotray b/local/bin/cotray new file mode 100755 index 0000000..d9802c7 Binary files /dev/null and b/local/bin/cotray differ diff --git a/local/bin/define b/local/bin/define new file mode 100755 index 0000000..6d9b2dc --- /dev/null +++ b/local/bin/define @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +word=${1:-$(xclip -o -selection primary 2>/dev/null || wl-paste 2>/dev/null)} + +# Check for empty word or special characters +[[ -z "$word" || "$word" =~ [\/] ]] && notify-send -h string:bgcolor:#bf616a -t 3000 "Invalid input." && exit 0 + +query=$(curl -s --connect-timeout 5 --max-time 10 "https://api.dictionaryapi.dev/api/v2/entries/en_US/$word") + +# Check for connection error (curl exit status stored in $?) +[ $? -ne 0 ] && notify-send -h string:bgcolor:#bf616a -t 3000 "Connection error." && exit 1 + +# Check for invalid word response +[[ "$query" == *"No Definitions Found"* ]] && notify-send -h string:bgcolor:#bf616a -t 3000 "Invalid word." && exit 0 + +# Show only first 3 definitions +def=$(echo "$query" | jq -r '[.[].meanings[] | {pos: .partOfSpeech, def: .definitions[].definition}] | .[:3].[] | "\n\(.pos). \(.def)"') + +# Requires a notification daemon to be installed +notify-send "$word -" "$def" + + +### MORE OPTIONS :) + +# Show first definition for each part of speech (thanks @morgengabe1 on youtube) +# def=$(echo "$query" | jq -r '.[0].meanings[] | "\(.partOfSpeech): \(.definitions[0].definition)\n"') + +# Show all definitions +# def=$(echo "$query" | jq -r '.[].meanings[] | "\n\(.partOfSpeech). \(.definitions[].definition)"') + +# Regex + grep for just definition, if anyone prefers that to jq +# def=$(grep -Po '"definition":"\K(.*?)(?=")' <<< "$query") + +# bold=$(tput bold) # Print text bold with echo, for visual clarity +# normal=$(tput sgr0) # Reset text to normal +# echo "${bold}Definition of $word" +# echo "${normal}$def" diff --git a/local/bin/discord b/local/bin/discord new file mode 100755 index 0000000..324caf1 --- /dev/null +++ b/local/bin/discord @@ -0,0 +1,39 @@ +#!/bin/sh + +RUN_WITH_PROXY() { + BINARY=$1 + shift + if [ -n "$BINARY" ]; then + exec "$BINARY" --proxy-server="socks5://127.0.0.1:65000" "$@" + fi +} + +GET_VESKTOP() { + if command -v vesktop >/dev/null 2>&1; then + echo "$(command -v vesktop)" + elif command -v vesktop-bin >/dev/null 2>&1; then + echo "$(command -v vesktop-bin)" + elif command -v flatpak >/dev/null 2>&1 && flatpak list --ids | grep -q "dev.vencord.Vesktop"; then + echo "flatpak run dev.vencord.Vesktop" + fi +} + +GET_DISCORD() { + if command -v linux-discord >/dev/null 2>&1; then + echo "$(command -v linux-discord)" + elif command -v flatpak >/dev/null 2>&1 && flatpak list --ids | grep -q "com.discordapp.Discord"; then + echo "flatpak run com.discordapp.Discord" + fi +} + +OS=$(uname -s) + +if [ "$OS" = "FreeBSD" ]; then + CMD=$(GET_DISCORD) + RUN_WITH_PROXY $CMD "$@" +elif [ "$OS" = "Linux" ]; then + CMD=$(GET_VESKTOP) + RUN_WITH_PROXY $CMD "$@" +else + linux-discord --proxy-server="socks5://127.0.0.1:65000" "$@" +fi diff --git a/local/bin/dmenu.py b/local/bin/dmenu.py new file mode 100755 index 0000000..948dbd8 --- /dev/null +++ b/local/bin/dmenu.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import sys +from pathlib import Path + + +DMENU_ARGS = [ + "dmenu", + "-i", + "-fn", "JetBrainsMono Nerd Font-10", + "-nb", "#121212", + "-nf", "#e0e0e0", + "-sb", "#222222", + "-sf", "#e0e0e0", + "-l", "10", + "-p", "Launch:", +] + +DESKTOP_DIRS = [ + Path.home() / ".local/share/applications", + Path.home() / ".local/share/flatpak/exports/share/applications", + Path("/var/lib/flatpak/exports/share/applications"), + Path("/usr/share/applications"), + Path("/usr/local/share/applications"), +] + +INVALID_EXEC_PREFIXES = ("wine", "wscript", "rundll32", "winhlp32", "hh ") + + +def parse_desktop_file(path: Path): + """ + Returns (name, exec_cmd) or (None, None) if the file should be skipped. + Handles: NoDisplay=true, Hidden=true, missing Name/Exec, field codes, env wrappers. + """ + props = {} + in_desktop_entry = False + + try: + with path.open(encoding="utf-8", errors="replace") as f: + for line in f: + line = line.rstrip("\n") + if line.startswith("["): + in_desktop_entry = line == "[Desktop Entry]" + continue + if not in_desktop_entry or "=" not in line: + continue + key, _, value = line.partition("=") + key = key.strip() + if key not in props: + props[key] = value.strip() + except OSError: + return None, None + + if props.get("NoDisplay", "").lower() == "true": + return None, None + if props.get("Hidden", "").lower() == "true": + return None, None + if props.get("Type", "") != "Application": + return None, None + + name = props.get("Name") + exec_raw = props.get("Exec") + + if not name or not exec_raw: + return None, None + + exec_cmd = clean_exec(exec_raw) + + if not exec_cmd: + return None, None + + lower = exec_cmd.lower() + if any(lower.startswith(p) for p in INVALID_EXEC_PREFIXES): + return None, None + + terminal = props.get("Terminal", "").lower() == "true" + if terminal: + term = os.environ.get("TERMINAL", "xterm") + exec_cmd = f"{term} -e {exec_cmd}" + + return name, exec_cmd + + +def clean_exec(exec_raw: str) -> str: + tokens = exec_raw.split() + cleaned = [] + for token in tokens: + if token.startswith("%") and len(token) == 2 and token[1].isalpha(): + continue + cleaned.append(token) + return " ".join(cleaned).strip() + + +def collect_apps(): + seen_stems = {} + for directory in DESKTOP_DIRS: + if not directory.is_dir(): + continue + for desktop_file in sorted(directory.glob("*.desktop")): + stem = desktop_file.stem.lower() + if stem not in seen_stems: + seen_stems[stem] = desktop_file + + apps = {} + for desktop_file in seen_stems.values(): + name, cmd = parse_desktop_file(desktop_file) + if name and cmd and name not in apps: + apps[name] = cmd + return apps + + +def run_dmenu(app_names: list[str]) -> str | None: + names_input = "\n".join(sorted(app_names, key=str.casefold)).encode() + try: + result = subprocess.run( + DMENU_ARGS, + input=names_input, + capture_output=True, + ) + except FileNotFoundError: + sys.exit("error: dmenu not found in PATH") + + if result.returncode != 0: + return None + + return result.stdout.decode().strip() + + +def launch(cmd: str): + subprocess.Popen( + cmd, + shell=True, + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + start_new_session=True, + ) + + +def main(): + apps = collect_apps() + + if not apps: + sys.exit("error: no applications found") + + selected = run_dmenu(list(apps.keys())) + + if not selected: + return + + cmd = apps.get(selected) + if not cmd: + sys.exit(f"error: no command found for '{selected}'") + + launch(cmd) + + +if __name__ == "__main__": + main() diff --git a/local/bin/ecop b/local/bin/ecop new file mode 100755 index 0000000..6bdb7c3 --- /dev/null +++ b/local/bin/ecop @@ -0,0 +1,2 @@ +#!/bin/zsh +xclip -sel clipboard diff --git a/local/bin/edsc b/local/bin/edsc new file mode 100755 index 0000000..e25e94c --- /dev/null +++ b/local/bin/edsc @@ -0,0 +1,13 @@ +#!/bin/sh +if [ -z "$1" ]; then + SCRIPT=$(find . -type f | fzfse) +else + SCRIPT="$1" +fi + +if [ -z "$SCRIPT" ]; then + echo 'Usage: edsc [file]' + exit 1 +fi + +emacsclient -c -nw "$SCRIPT" diff --git a/local/bin/emacsd b/local/bin/emacsd new file mode 100755 index 0000000..34944c4 --- /dev/null +++ b/local/bin/emacsd @@ -0,0 +1,2 @@ +#!/bin/sh +kitty -e emacsclient -c $1 diff --git a/local/bin/emacsd~ b/local/bin/emacsd~ new file mode 100755 index 0000000..e29cb1d --- /dev/null +++ b/local/bin/emacsd~ @@ -0,0 +1,2 @@ +#!/bin/sh +emacsclient -c $1 \ No newline at end of file diff --git a/local/bin/f2py b/local/bin/f2py new file mode 100755 index 0000000..8eeab20 --- /dev/null +++ b/local/bin/f2py @@ -0,0 +1,8 @@ +#!/usr/bin/python3.13 +# -*- coding: utf-8 -*- +import re +import sys +if __name__ == '__main__': + from numpy.f2py.f2py2e import main + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/local/bin/firemenu b/local/bin/firemenu new file mode 100755 index 0000000..69b9b18 --- /dev/null +++ b/local/bin/firemenu @@ -0,0 +1,43 @@ +#!/bin/sh +# Credits to Swindles McCoop +# Coast's configuration of Firemenu +# ## Bravemenu +set -e +DMENU_CMD="dmenu -i -fn Cozette:size=13 -nb #151821 -nf #a9b1d6 -sb #414868 -sf #c0caf5" +CHOICES="URL +Google +YouTube +Spotify +Discord +Git.gay +Github +DeepSeek +ChatGPT +4chan +Proton Inbox +Proton Drive +Google Inbox +Ente Auth" + +CHOICE=$(printf "$CHOICES" | $DMENU_CMD -p "Bravemenu ") +SWALLOW= + +case $CHOICE in + "URL") printf '' | $DMENU_CMD -p 'Enter URL(s):' | xargs $SWALLOW brave > /dev/null ;; + "Discord") $SWALLOW brave https://discord.com/app/ > /dev/null ;; + "Spotify") $SWALLOW brave https://open.spotify.com/ > /dev/null ;; + "DeepSeek") $SWALLOW brave https://chat.deepseek.com/ > /dev/null ;; + "ChatGPT") $SWALLOW brave https://chatgpt.com/ > /dev/null ;; + #"Github") $SWALLOW brave https://github.com/ > /dev/null ;; + "Github") printf '' | $DMENU_CMD -p 'Repository:' | sed 's|^|https://github.com/|' | sed 's/ /%20/g' | xargs $SWALLOW brave > /dev/null ;; + "Git.gay") printf '' | $DMENU_CMD -p 'Repository:' | sed 's|^|https://git.gay/|' | sed 's/ /%20/g' | xargs $SWALLOW brave > /dev/null ;; + #"Git.gay") $SWALLOW brave https://git.gay/ > /dev/null ;; + "Google") printf '' | $DMENU_CMD -p 'Search:' | sed 's|^|https://google.com/search?q=|' | sed 's/ /%20/g' | xargs $SWALLOW brave > /dev/null ;; + "Link") printf '' | $DMENU_CMD -p 'Enter URL(s):' | xargs $SWALLOW brave > /dev/null ;; + "YouTube") printf '' | $DMENU_CMD -p 'Search:' | sed 's|^|https://youtube.com/results?search_query=|' | sed 's/ /%20/g' | xargs $SWALLOW brave > /dev/null ;; + "4chan") printf '3\na\naco\nadv\nan\nb\nbant\nbiz\nc\ncgl\nck\ncm\nco\nd\ndiy\ne\nf\nfa\nfit\ng\ngd\ngif\nh\nhc\nhis\nhm\nhr\ni\nic\nint\njp\nk\nlgbt\nlit\nm\nmlp\nmu\nn\nnews\no\nout\np\npo\npol\npw\nqa\nqst\nr\nr9k\ns\ns4s\nsci\nsoc\nsp\nt\ntg\ntoy\ntrv\ntv\nu\nv\nvg\nvip\nvm\nvmg\nvp\nvr\nvrpg\nvst\nvt\nw\nwg\nwsg\nwsr\nx\nxs\ny' | $DMENU_CMD -p 'Board letter:' | sed 's|^|https://4chan.org/|' | xargs $SWALLOW brave > /dev/null ;; + "Proton Inbox") printf '' | $SWALLOW brave https://mail.proton.me/u/0/inbox > /dev/null ;; + "Proton Drive") printf '' | $SWALLOW brave https://drive.proton.me/ > /dev/null ;; + "Google Inbox") printf '' | $SWALLOW brave https://mail.google.com/mail/u/0/ ;; + "Ente Auth") printf '' | $SWALLOW brave https://auth.ente.io/auth ;; +esac diff --git a/local/bin/fzfse b/local/bin/fzfse new file mode 100755 index 0000000..f580569 --- /dev/null +++ b/local/bin/fzfse @@ -0,0 +1,3 @@ +#!/bin/sh + +fzf --layout=reverse --height 40% diff --git a/local/bin/grubfk b/local/bin/grubfk new file mode 100755 index 0000000..06a87f5 --- /dev/null +++ b/local/bin/grubfk @@ -0,0 +1,29 @@ +#!/bin/zsh + +grub_screen() { + clear + echo -e "\n\n\t GNU GRUB 2.06" + echo -e "\n" + echo -e "\t Minimal BASH-like line editing is supported. For the first word, TAB" + echo -e "\t lists possible command completions. Anywhere else TAB lists possible" + echo -e "\t device or file completions." + echo -e "\n" +} + +grub_screen + +# Fake GRUB prompt +while true; do + echo -ne " grub> " + read -r command + case $command in + exit|quit) + clear + break + ;; + *) + echo -e "\t Unknown command. Press a key to continue..." + read -r dummy + ;; + esac +done diff --git a/local/bin/hyfetch b/local/bin/hyfetch new file mode 100755 index 0000000..75b46c2 --- /dev/null +++ b/local/bin/hyfetch @@ -0,0 +1,7 @@ +#!/usr/bin/python3 +import sys +from hyfetch.__main__ import run_rust +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(run_rust()) diff --git a/local/bin/hyfetch.rs b/local/bin/hyfetch.rs new file mode 100755 index 0000000..75b46c2 --- /dev/null +++ b/local/bin/hyfetch.rs @@ -0,0 +1,7 @@ +#!/usr/bin/python3 +import sys +from hyfetch.__main__ import run_rust +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(run_rust()) diff --git a/local/bin/hyfetch.v1 b/local/bin/hyfetch.v1 new file mode 100755 index 0000000..547f291 --- /dev/null +++ b/local/bin/hyfetch.v1 @@ -0,0 +1,7 @@ +#!/usr/bin/python3 +import sys +from hyfetch.__main__ import run_py +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(run_py()) diff --git a/local/bin/killradio b/local/bin/killradio new file mode 100755 index 0000000..46e7d6e --- /dev/null +++ b/local/bin/killradio @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +import subprocess +import sys +import signal + +try: + # Find PID(s) of running 'radio' process (matching name) + out = subprocess.check_output(["pgrep", "-f", "radio"]) + pids = [int(pid) for pid in out.decode().strip().split()] +except subprocess.CalledProcessError: + print("No running 'radio' process found.") + sys.exit(1) + +for pid in pids: + try: + # Send SIGKILL (kill -9) to each found pid + subprocess.run(["kill", "-9", str(pid)]) + print(f"Killed PID {pid}") + except Exception as e: + print(f"Failed to kill PID {pid}: {e}") diff --git a/local/bin/math b/local/bin/math new file mode 100755 index 0000000..a817382 --- /dev/null +++ b/local/bin/math @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +import ast +import operator +import math +import sys + +_OPERATORS = { + ast.Add: operator.add, + ast.Sub: operator.sub, + ast.Mult: operator.mul, + ast.Div: operator.truediv, + ast.Mod: operator.mod, + ast.Pow: operator.pow, + ast.USub: operator.neg, + ast.UAdd: operator.pos, + ast.FloorDiv: operator.floordiv, +} + +_MATH_FUNCS = {name: getattr(math, name) for name in dir(math) if not name.startswith("_") and callable(getattr(math, name))} +_MATH_FUNCS.update({ + "abs": abs, + "round": round, + "factorial": math.factorial, + "degrees": math.degrees, + "radians": math.radians, + "isclose": math.isclose, + "isfinite": math.isfinite, + "isinf": math.isinf, + "isnan": math.isnan, + "log2": math.log2, + "log10": math.log10, + "log": math.log, + "exp": math.exp, + "expm1": math.expm1, + "fsum": math.fsum, + "gamma": math.gamma, + "lgamma": math.lgamma, + "trunc": math.trunc, + "max": max, + "min": min, + "sum": sum, +}) + +_CONSTANTS = { + "pi": math.pi, + "e": math.e, + "tau": math.tau, + "inf": math.inf, + "nan": math.nan, +} + +class matheval(ast.NodeVisitor): + def visit(self, node): + if isinstance(node, ast.Expression): + return self.visit(node.body) + return super().visit(node) + + def visit_BinOp(self, node): + left = self.visit(node.left) + right = self.visit(node.right) + op_type = type(node.op) + if op_type in _OPERATORS: + return _OPERATORS[op_type](left, right) + raise ValueError(f"Unsupported binary operator {op_type.__name__}") + + def visit_UnaryOp(self, node): + operand = self.visit(node.operand) + op_type = type(node.op) + if op_type in _OPERATORS: + return _OPERATORS[op_type](operand) + raise ValueError(f"Unsupported unary operator {op_type.__name__}") + + def visit_Call(self, node): + if not isinstance(node.func, ast.Name): + raise ValueError("Only simple function calls allowed") + func_name = node.func.id + if func_name not in _MATH_FUNCS: + raise ValueError(f"Unknown function '{func_name}'") + args = [self.visit(arg) for arg in node.args] + return _MATH_FUNCS[func_name](*args) + + def visit_Name(self, node): + if node.id in _CONSTANTS: + return _CONSTANTS[node.id] + raise ValueError(f"Unknown identifier '{node.id}'") + + def visit_Constant(self, node): + if isinstance(node.value, (int, float)): + return node.value + raise ValueError(f"Unsupported constant type: {type(node.value).__name__}") + + def visit_List(self, node): + return [self.visit(el) for el in node.elts] + + def visit_Tuple(self, node): + return tuple(self.visit(el) for el in node.elts) + + def generic_visit(self, node): + raise ValueError(f"Unsupported expression: {type(node).__name__}") + +def main(): + if len(sys.argv) < 2: + print("Usage: math ''") + print("Example: math 'sin(pi/2) + 2^3'") + sys.exit(1) + + expr = " ".join(sys.argv[1:]) + expr = expr.replace("^", "**") + expr = expr.replace("\n", "") + + try: + tree = ast.parse(expr, mode="eval") + evaluator = matheval() + result = evaluator.visit(tree) + if isinstance(result, float) and result.is_integer(): + print(int(result)) + else: + print(result) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/local/bin/mksymlink b/local/bin/mksymlink new file mode 100755 index 0000000..54ecd4c --- /dev/null +++ b/local/bin/mksymlink @@ -0,0 +1,57 @@ +#!/bin/sh + +CONFIG_FILE="${HOME}/.config/mksymlink.conf" +TARGET_BASE="${HOME}/.config" + +usage() { + echo "Usage: $0 [-c config_file] [-t target_base]" + exit 1 +} + +while getopts "c:t:h" opt; do + case "$opt" in + c) CONFIG_FILE="$OPTARG" ;; + t) TARGET_BASE="$OPTARG" ;; + h) usage ;; + *) usage ;; + esac +done + +if [ ! -f "$CONFIG_FILE" ]; then + echo "Error: config file '$CONFIG_FILE' does not exist" 1>&2 + exit 2 +fi + +. "$CONFIG_FILE" + +if [ -z "$MAIN" ]; then + echo "Error: MAIN is not set in config file" 1>&2 + exit 3 +fi + +mkdir -p "$TARGET_BASE" + +for entry in $list; do + TARGET=$(echo "$entry" | cut -d= -f1) + SRC_REL=$(echo "$entry" | cut -d= -f2) + SRC="$MAIN/$SRC_REL" + TARGET_PATH="$TARGET_BASE/$TARGET" + + if [ ! -e "$SRC" ]; then + echo "Warning: source '$SRC' does not exist, skipping" 1>&2 + continue + fi + + mkdir -p "$(dirname "$TARGET_PATH")" + + if [ -L "$TARGET_PATH" ]; then + rm "$TARGET_PATH" + elif [ -e "$TARGET_PATH" ]; then + echo "Warning: target '$TARGET_PATH' exists and is not a symlink, skipping" 1>&2 + continue + fi + + ln -s "$SRC" "$TARGET_PATH" + echo "Created symlink: $TARGET_PATH -> $SRC" +done + diff --git a/local/bin/mpc-shuf.sh b/local/bin/mpc-shuf.sh new file mode 100755 index 0000000..c0ebafe --- /dev/null +++ b/local/bin/mpc-shuf.sh @@ -0,0 +1,126 @@ +#!/usr/bin/env lua + +local launcher = "dmenu" + +local dmenu_args = { + "-i", + "-fn", "JetBrainsMono Nerd Font-10", + "-nb", "#121212", + "-nf", "#e0e0e0", + "-sb", "#222222", + "-sf", "#e0e0e0", + "-l", "10", +} + +local music_dir = "/home/coast/Music" +local max_length = 30 +local default_icon = "/usr/share/icons/hicolor/48x48/apps/musical-note.png" + +local function build_menu(prompt) + if launcher == "rofi" then + return string.format("rofi -dmenu -i -p '%s'", prompt) + else + local args = "dmenu" + for _, v in ipairs(dmenu_args) do + args = args .. " '" .. v .. "'" + end + args = args .. string.format(" -p '%s'", prompt) + return args + end +end + +local function escape(str) + return str:gsub("'", "'\\''") +end + +local function capture(cmd) + local f = io.popen(cmd, 'r') + local s = f:read('*a') + f:close() + return s:gsub("^%s*(.-)%s*$", "%1") +end + +local function truncate(str, len) + if #str > len then + return str:sub(1, len) .. "..." + end + return str +end + +local function get_cover(song_file) + if not song_file or song_file == "" then return default_icon end + local full_path = music_dir .. "/" .. song_file + local dir = full_path:match("(.*[/\\])") or music_dir + local names = {"cover.jpg", "cover.png", "folder.jpg", "folder.png", "front.jpg", "front.png"} + for _, name in ipairs(names) do + local path = dir .. name + local f = io.open(path, "r") + if f then + f:close() + return path + end + end + return default_icon +end + +local action = arg[1] + +if action == "shuf" then + os.execute("mpc random on >/dev/null && notify-send 'Shuffle enabled'") + os.exit(0) +elseif action == "shufno" then + os.execute("mpc random off >/dev/null && notify-send 'Shuffle disabled'") + os.exit(0) +elseif action == "next" then + os.execute("mpc next >/dev/null") + os.exit(0) +elseif action == "prev" then + os.execute("mpc prev >/dev/null") + os.exit(0) +elseif action == "toggle" then + os.execute("mpc toggle >/dev/null") + os.exit(0) +elseif action == "current" then + local current = capture("mpc current") + if current ~= "" then io.write(current .. "\n") end + os.exit(0) +elseif action == "info" then + local file = capture("mpc --format '%file%' current") + local title = capture("mpc current") + local cover = get_cover(file) + os.execute(string.format("notify-send 'Currently Playing' '%s' -i '%s'", escape(title), cover)) + os.exit(0) +elseif action == "album" then + local album = capture("mpc list album | " .. build_menu("Select Album")) + if album ~= "" then + os.execute(string.format("mpc clear >/dev/null && mpc find album '%s' | mpc add && mpc play >/dev/null", escape(album))) + end + os.exit(0) +elseif action == "artist" then + local artist = capture("mpc list artist | " .. build_menu("Select Artist")) + if artist ~= "" then + os.execute(string.format("mpc clear >/dev/null && mpc find artist '%s' | mpc add && mpc play >/dev/null", escape(artist))) + end + os.exit(0) +elseif action == "search" then + local menu = "mpc --format '%title% - %artist% - %album%\t%file%' search any '' | " .. build_menu("Search music") + local choice = capture(menu) + if choice == "" then os.exit(0) end + local file = choice:match("\t(.-)$") + if file then + os.execute(string.format("mpc clear >/dev/null && mpc add '%s' >/dev/null && mpc play >/dev/null", escape(file))) + os.exit(0) + end +elseif action == "reload" then + os.execute("mpc update && mpc clear && mpc add / && mpc play >/dev/null") + os.execute("notify-send 'Library refreshed. Now playing...'") + os.exit(0) +end + +os.execute("mpc play >/dev/null 2>&1") +os.execute("mpc volume 15 >/dev/null 2>&1") +local file = capture("mpc --format '%file%' current") +local title = capture("mpc current") +local cover = get_cover(file) +local display = truncate(title, max_length) +os.execute(string.format("notify-send 'Now playing...' '%s' -i '%s'", escape(display), cover)) diff --git a/local/bin/nodeenv b/local/bin/nodeenv new file mode 100755 index 0000000..075fc9b --- /dev/null +++ b/local/bin/nodeenv @@ -0,0 +1,7 @@ +#!/usr/bin/python3.13 +import sys +from nodeenv import main +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(main()) diff --git a/local/bin/numpy-config b/local/bin/numpy-config new file mode 100755 index 0000000..399eb6f --- /dev/null +++ b/local/bin/numpy-config @@ -0,0 +1,8 @@ +#!/usr/bin/python3.13 +# -*- coding: utf-8 -*- +import re +import sys +if __name__ == '__main__': + from numpy._configtool import main + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/local/bin/pyright b/local/bin/pyright new file mode 100755 index 0000000..9c5770d --- /dev/null +++ b/local/bin/pyright @@ -0,0 +1,7 @@ +#!/usr/bin/python3.13 +import sys +from pyright.cli import entrypoint +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(entrypoint()) diff --git a/local/bin/pyright-langserver b/local/bin/pyright-langserver new file mode 100755 index 0000000..e206592 --- /dev/null +++ b/local/bin/pyright-langserver @@ -0,0 +1,7 @@ +#!/usr/bin/python3.13 +import sys +from pyright.langserver import entrypoint +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(entrypoint()) diff --git a/local/bin/pyright-python b/local/bin/pyright-python new file mode 100755 index 0000000..9c5770d --- /dev/null +++ b/local/bin/pyright-python @@ -0,0 +1,7 @@ +#!/usr/bin/python3.13 +import sys +from pyright.cli import entrypoint +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(entrypoint()) diff --git a/local/bin/pyright-python-langserver b/local/bin/pyright-python-langserver new file mode 100755 index 0000000..e206592 --- /dev/null +++ b/local/bin/pyright-python-langserver @@ -0,0 +1,7 @@ +#!/usr/bin/python3.13 +import sys +from pyright.langserver import entrypoint +if __name__ == '__main__': + if sys.argv[0].endswith('.exe'): + sys.argv[0] = sys.argv[0][:-4] + sys.exit(entrypoint()) diff --git a/local/bin/qr b/local/bin/qr new file mode 100755 index 0000000..650c903 --- /dev/null +++ b/local/bin/qr @@ -0,0 +1,8 @@ +#!/nix/store/1ki8jq5sax0hm1sqbw0jk6qnqpy417zx-python3-3.13.5/bin/python3.13 +# -*- coding: utf-8 -*- +import re +import sys +from qrcode.console_scripts import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/local/bin/radio b/local/bin/radio new file mode 100755 index 0000000..20c369a --- /dev/null +++ b/local/bin/radio @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +import subprocess +import time +from pathlib import Path +import threading +import json +import tempfile +import urllib.request +import websocket +# 128kbps Opus +URL="https://radio.animebits.moe/stream/stream128.ogg" +# 256kbps Opus +#URL="https://radio.animebits.moe/stream/stream256.ogg" +# ~148kbps VBR AAC +#URL="https://radio.animebits.moe/stream/stream128.aac" +# ~192kbps VBR MP3 +#URL="https://radio.animebits.moe/stream/stream192.mp3" +# Lossless FLAC +#URL="https://radio.animebits.moe/stream/stream.flac" +#config file & pid +CONF = Path.home() / ".config" / "radiorc" +PID = Path.home() / ".config" / "radio-pid" +with open(CONF) as f: + VOL = f.read().strip() +def notify(title, image_url=None): + icon_path = None + if image_url: + try: + tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png") + urllib.request.urlretrieve(image_url, tmp.name) + icon_path = tmp.name + except: + icon_path = None + args = ["notify-send", title] + if icon_path: + args += ["-i", icon_path] + subprocess.run(args) +def ws_listener(): + def on_message(ws, message): + data = json.loads(message) + if "data" in data and "title" in data["data"]: + title = data["data"]["title"] + image = data["data"].get("album_cover") + notify(title, image) + def on_error(ws, error): + pass + def on_close(ws, close_status_code, close_msg): + time.sleep(1) + run_ws() + def on_open(ws): + pass + def run_ws(): + ws = websocket.WebSocketApp("wss://radio.animebits.moe/api/events/basic", + on_message=on_message, + on_error=on_error, + on_close=on_close, + on_open=on_open) + ws.run_forever() + run_ws() +threading.Thread(target=ws_listener, daemon=True).start() +while True: + try: + print("Playing now...") + subprocess.run(["notify-send", "Playing now..."]) + proc = subprocess.Popen(["mpv", "--no-video", f"--volume={VOL}", URL]) + with open(PID, "w") as f: + f.write(str(proc.pid)) + proc.wait() + except KeyboardInterrupt: + subprocess.run(["notify-send", "Stopping now..."]) + print("\nStopping now...") + break + except Exception as e: + print(f"Something broke... trying again... Error: {e}") + time.sleep(2) diff --git a/local/bin/resmacs b/local/bin/resmacs new file mode 100755 index 0000000..8be929c --- /dev/null +++ b/local/bin/resmacs @@ -0,0 +1,2 @@ +#!/bin/sh +systemctl restart --user emacs.service diff --git a/local/bin/rimworld b/local/bin/rimworld new file mode 100755 index 0000000..e776f9b --- /dev/null +++ b/local/bin/rimworld @@ -0,0 +1,3 @@ +#!/bin/sh +WINEPREFIX=$HOME/.wine +prime-run wine /home/coast/files/rimworld/RimWorldWin64.exe diff --git a/local/bin/sb-battery b/local/bin/sb-battery new file mode 100755 index 0000000..5e0a9fc --- /dev/null +++ b/local/bin/sb-battery @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +batteries=(/sys/class/power_supply/BAT*) +# Check if any battery directories exist +found=false +for b in "${batteries[@]}"; do + if [ -d "$b" ]; then + found=true + break + fi +done + +if [ "$found" = false ]; then + echo "None" + exit 1 +fi + +first=true +for battery in /sys/class/power_supply/BAT*; do + if [ -d "$battery" ]; then + if [ -r "$battery/capacity" ]; then + capacity=$(<"$battery/capacity") + else + capacity=0 + fi + if [ "$first" = true ]; then + echo -n "${capacity}%" + first=false + else + echo -n " ${capacity}%" + fi + fi +done +echo + diff --git a/local/bin/sb-cputemp b/local/bin/sb-cputemp new file mode 100755 index 0000000..5cbe975 --- /dev/null +++ b/local/bin/sb-cputemp @@ -0,0 +1,20 @@ +#!/bin/sh + +_linux() { + sensors $1 | awk '/^temp1/ {print $2}' | sed 's/+//' +} + +_openbsd() { + [ "$1" = "-f" ] && printf "$(expr $(sysctl | grep hw.sensors.cpu0.temp0 | sed 's/\.00.*//' | sed 's/.*=//') \* 9 / 5 + 32 2> /dev/null)°F" || sysctl | grep hw.sensors.cpu0.temp0 | sed 's/.*=//' | sed 's/\.00//' | sed 's/ deg/°/' +} + +_freebsd() { + C_TEMP=$(sysctl hw.acpi.thermal.tz0.temperature | sed 's/^.* //' ) + [ "$1" = "-f" ] && printf "$(expr $(printf $C_TEMP | sed 's/\..C//') \* 9 / 5 + 32)°F" || printf "$C_TEMP" | sed 's/C/°C/' +} + +case $(uname) in + Linux) _linux "$@" ;; + OpenBSD) _openbsd "$@" ;; + FreeBSD) _freebsd "$@" ;; +esac diff --git a/local/bin/sb-cpuusage b/local/bin/sb-cpuusage new file mode 100755 index 0000000..c05576b --- /dev/null +++ b/local/bin/sb-cpuusage @@ -0,0 +1,30 @@ +#!/bin/sh +#Display CPU usage percentage + +_openbsd() { + CPUS=$(sysctl | grep 'hw.ncpuonline' | sed 's/^.*=//') + TOTALUSAGE=$(ps aux | awk '{print $3}' | sed '1d' | sort | paste -s -d+ - | bc) + USAGE=$(printf "$TOTALUSAGE / $CPUS\n" | bc -l) + printf "$USAGE" | grep "^\.[0-9]" > /dev/null && printf "0$(printf $USAGE | cut -c1-3)%%" || printf "$(printf "$USAGE" | cut -c1-4)%%\n" +} + +_freebsd() { + CPUS="$(sysctl hw.ncpu | sed 's/^.*: //')" + FREE=$(ps -o %cpu -p $(pgrep -S idle) | tail -n 1) + TPP=$(expr $CPUS \* 100) + TOTALUSAGE=$(printf "$TPP - $FREE" | bc -l) + USAGE=$(printf "$TOTALUSAGE / $CPUS" | bc -l | cut -c -4) + printf "$USAGE" | egrep "\.[0-9]{3}" > /dev/null && printf "0$(printf $USAGE | cut -c -3)%%\n" || printf -- "$USAGE%%\n" +} + +_linux() { + TOTALUSAGE="$(ps axch -o cmd,%cpu --sort=-%cpu | sed 's/ //' | grep -E -o " [0-9].*" | sed 's/ //' | paste -s -d+ - | bc)" + USAGE="$(printf "$(printf "$TOTALUSAGE / $(nproc)\n" | bc -l | cut -c1-4)%%\n")" + printf -- "$USAGE%" | grep "^\.[0-9]" > /dev/null && printf -- "0$(printf -- $USAGE% | cut -c1-3)%%" || printf -- "$(printf -- "$USAGE%" | cut -c1-4)%%\n" +} + +case $(uname) in + Linux) _linux ;; + OpenBSD) _openbsd ;; + FreeBSD) _freebsd ;; +esac diff --git a/local/bin/sb-liisten b/local/bin/sb-liisten new file mode 100755 index 0000000..ff9b420 --- /dev/null +++ b/local/bin/sb-liisten @@ -0,0 +1,38 @@ +#!/bin/sh +#Liisten for the status bar + +#options +LOOPCOUNT=1 #however many times you want the song to play minus one (for technical reasons) +SONGDIR="$HOME/music/brstm" +cd "$SONGDIR" + +MODE=$(printf "Random\nForever" | dmenu -i) + +playsong () { + vgmstream-cli -m "$SONG" > /tmp/brstminfo.txt + STARTLOOP="$(grep "seconds" /tmp/brstminfo.txt | head -n 1 | sed 's/.*(//' | sed 's/ seconds)//')" + ENDLOOP="$(grep "seconds" /tmp/brstminfo.txt | tail -n 1 | sed 's/.*(//' | sed 's/ seconds)//')" + echo "Now playing: \"$(echo $SONG | sed 's/\.brstm//')\"" + mpv --ab-loop-a="$STARTLOOP" --ab-loop-b="$ENDLOOP" --ab-loop-count="$LOOPCOUNT" "$SONG" +} + +forever () { + SONG="$(command ls -1 | dmenu -i)" + vgmstream-cli -m "$SONG" > /tmp/brstminfo.txt + STARTLOOP="$(grep "seconds" /tmp/brstminfo.txt | head -n 1 | sed 's/.*(//' | sed 's/ seconds)//')" + ENDLOOP="$(grep "seconds" /tmp/brstminfo.txt | tail -n 1 | sed 's/.*(//' | sed 's/ seconds)//')" + mpv --ab-loop-a="$STARTLOOP" --ab-loop-b="$ENDLOOP" --loop-file=inf "$SONG" +} + +random () { + while true; do + RANDNUM=$(shuf -i 1-$(ls -1 | wc -l) -n 1) + SONG="$(command ls | head -n $RANDNUM | tail -n 1)" + playsong + done +} + +case "$MODE" in + Forever) forever ;; + Random) random ;; +esac diff --git a/local/bin/sb-memory b/local/bin/sb-memory new file mode 100755 index 0000000..282d6f7 --- /dev/null +++ b/local/bin/sb-memory @@ -0,0 +1,27 @@ +#!/bin/sh + +_openbsd() { + TOTAL="$(free | awk '/^Mem:/ {print $2}')" + MUSED="$(top -b -n 1 | grep -o 'Real.*' | sed 's/Real: //' | sed 's/\/.*//')" + printf "$MUSED" | egrep "[0-9]{4}" > /dev/null && FUSED="$(printf "$MUSED" | cut -c -2 | sed 's/./.&/2')G" || FUSED=$MUSED + printf "$FUSED/$TOTAL\n" +} + +_freebsd() { + TOTAL="$(freecolor -om | awk '/^Mem:/ {print $2}')" + MUSED="$(freecolor -om | awk '/^Mem:/ {print $3}')" + printf "$MUSED" | egrep "[0-9]{4}" > /dev/null && FUSED="$(printf "$MUSED" | cut -c -2 | sed 's/./.&/2')G" || FUSED=""$MUSED"M" + printf "$TOTAL" | egrep "[0-9]{4}" > /dev/null && TOTAL="$(printf "$TOTAL" | cut -c -2 | sed 's/./.&/2')G" || FUSED=$TOTAL + printf "$FUSED/$TOTAL\n" +} + +_linux() { + MUSED="$(free -m | awk '/^Mem:/ {print $3}')" + echo "$MUSED" +} + +case $(uname) in + Linux) _linux ;; + OpenBSD) _openbsd ;; + FreeBSD) _freebsd ;; +esac diff --git a/local/bin/sb-network b/local/bin/sb-network new file mode 100755 index 0000000..0937126 --- /dev/null +++ b/local/bin/sb-network @@ -0,0 +1,8 @@ +#!/bin/sh +# Show local IP and transfer if connected to the internet. Opens $NETWORKMANAGER on click +NETWORKMANAGER=connman-gtk +ifconfig | grep ".*inet.*netmask" | tail -n 1 | sed 's/inet //g' | sed 's/ netmask.*//g' | sed 's/ //g' | sed 's/ //g' + +case $BLOCK_BUTTON in + 1) $NETWORKMANAGER ;; +esac diff --git a/local/bin/sb-swap b/local/bin/sb-swap new file mode 100755 index 0000000..096e308 --- /dev/null +++ b/local/bin/sb-swap @@ -0,0 +1,7 @@ +#!/bin/sh + +swap_used_kib=$(awk '/SwapTotal/ {total=$2} /SwapFree/ {free=$2} END {print total - free}' /proc/meminfo) + +swap_used_mib=$((swap_used_kib / 1024)) + +echo "${swap_used_mib}" diff --git a/local/bin/sb-volume b/local/bin/sb-volume new file mode 100755 index 0000000..0736259 --- /dev/null +++ b/local/bin/sb-volume @@ -0,0 +1,14 @@ +#!/bin/sh + +_bsd() { + sndioctl -n output.level | sed 's/0\.//' | sed 's/.$/%/' | sed 's/\.//' +} + +_linux() { + printf "$(pamixer --get-volume)%%\n" +} + +case $(uname) in + Linux) _linux ;; + *BSD) _bsd ;; +esac diff --git a/local/bin/screencast b/local/bin/screencast new file mode 100755 index 0000000..9ea3683 --- /dev/null +++ b/local/bin/screencast @@ -0,0 +1,22 @@ +#!/bin/sh +set -e + +printf "Title: " +read TITLE +printf "Sound device (ex: default, 1, 2): " +read SNDDEV + +TITLE="$(echo $TITLE | sed 's/ /_/g')" +DIRNAME="$TITLE-$(date '+%s')" +mkdir -p "$HOME/videos/screencasts/$DIRNAME" + +ffmpeg -loglevel fatal -video_size 1600x900 -framerate 30 -f x11grab -i :0.0 -c:v libx264 -preset veryfast "$HOME/videos/screencasts/$DIRNAME/video.mkv" & printf "Video recording started.\n" +aucat -f snd/$SNDDEV -o "$HOME/videos/screencasts/$DIRNAME/audio.wav" > /dev/null & printf "Audio recording started.\n\n" + +printf "Press enter to stop recording" +read lol +kill $(pgrep ffmpeg) +kill $(pgrep aucat) + +cd "$HOME/videos/screencasts/$DIRNAME" +ffmpeg -loglevel fatal -i video.mkv -i audio.wav -c copy final.mkv diff --git a/local/bin/screenie b/local/bin/screenie new file mode 100755 index 0000000..5dcf99b --- /dev/null +++ b/local/bin/screenie @@ -0,0 +1,8 @@ +#!/bin/sh +DIR="$HOME/Pictures/Screenshots" +FILE="$DIR/shot_$(date +%s).png" + +mkdir -p "$DIR" +maim -s "$FILE" +xclip -selection clipboard -t image/png -i "$FILE" +notify-send "Region Captured" "Saved and copied to clipboard" diff --git a/local/bin/screenie-active b/local/bin/screenie-active new file mode 100755 index 0000000..eab9f1b --- /dev/null +++ b/local/bin/screenie-active @@ -0,0 +1,3 @@ +#!/bin/sh +maim -i "$(xdotool getactivewindow)" /tmp/shot.png +xclip -selection clipboard -t image/png -i /tmp/shot.png diff --git a/local/bin/screenie-wlr b/local/bin/screenie-wlr new file mode 100755 index 0000000..a478ab3 --- /dev/null +++ b/local/bin/screenie-wlr @@ -0,0 +1,13 @@ +#!/bin/sh +DIR="$HOME/Pictures/Screenshots" +mkdir -p "$DIR" +TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") +FINAL_FILE="$DIR/screenshot_$TIMESTAMP.png" +TEMP_FULLSCREEN=$(mktemp /tmp/fullscreen_XXXXXX.png) +grim "$TEMP_FULLSCREEN" +TEMP_FILE=$(mktemp /tmp/screenshot_XXXXXX.png) +grim -g "$(slurp)" "$TEMP_FILE" +cp "$TEMP_FILE" "$FINAL_FILE" +wl-copy < "$TEMP_FILE" +notify-send "Screenshot" "Saved to $FINAL_FILE" -i "$TEMP_FILE" +rm "$TEMP_FILE" "$TEMP_FULLSCREEN" diff --git a/local/bin/setwall.py b/local/bin/setwall.py new file mode 100755 index 0000000..0126288 --- /dev/null +++ b/local/bin/setwall.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +import os +import secrets +import subprocess + +BASE_DIR = "/home/coast/.local/src/wall" + +wallpapers = [] +for root, dirs, files in os.walk(BASE_DIR): + for file in files: + if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif')): + wallpapers.append(os.path.join(root, file)) + +if not wallpapers: + print("No wallpapers found!") + exit(1) + +chosen_wallpaper = secrets.choice(wallpapers) +print(chosen_wallpaper) +subprocess.run(["swaybg", "-i", chosen_wallpaper, "-m", "fill"]) diff --git a/local/bin/setwall.sh b/local/bin/setwall.sh new file mode 100755 index 0000000..548d281 --- /dev/null +++ b/local/bin/setwall.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail +WALL_DIR="/home/coast/.local/src/wall" +SUBDIR=$(find "$WALL_DIR" -mindepth 1 -maxdepth 1 -type d | shuf -n1) +FILE=$(find "$SUBDIR" -type f \( -iname '*.jpg' -o -iname '*.png' -o -iname '*.jpeg' \) | shuf -n1) +if [[ -n "$FILE" ]]; then + swaymsg output '*' bg "$FILE" fill +fi diff --git a/local/bin/sober b/local/bin/sober new file mode 100644 index 0000000..69593c7 --- /dev/null +++ b/local/bin/sober @@ -0,0 +1,2 @@ +#!sh +flatpak run org.vinegarhq.Sober diff --git a/local/bin/stacki3 b/local/bin/stacki3 new file mode 100755 index 0000000..ad65f02 --- /dev/null +++ b/local/bin/stacki3 @@ -0,0 +1,8 @@ +#!/usr/bin/python3.13 +# -*- coding: utf-8 -*- +import re +import sys +if __name__ == '__main__': + from stacki3 import main + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/local/bin/start-meowgun.sh b/local/bin/start-meowgun.sh new file mode 100755 index 0000000..bcdd9e9 --- /dev/null +++ b/local/bin/start-meowgun.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cd "$HOME/Downloads/MeowGun" && wine meowgun.exe diff --git a/local/bin/start-wq.sh b/local/bin/start-wq.sh new file mode 100755 index 0000000..4c8563e --- /dev/null +++ b/local/bin/start-wq.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cd "/home/coast/.wine/drive_c/WolfQuest/" && env WINEDLLOVERRIDES="winhttp=n,b" wine64.bin WolfQuestAE.exe diff --git a/local/bin/start_qtile.sh b/local/bin/start_qtile.sh new file mode 100755 index 0000000..0b4758f --- /dev/null +++ b/local/bin/start_qtile.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +wlr-randr --output eDP-1 --off & + +( + if ! pgrep -x foot >/dev/null; then + foot -s + fi +) & + +( + if ! pgrep -x udiskie >/dev/null; then + /usr/bin/udiskie + fi +) & + + +( + if ! pgrep -x swaybg >/dev/null; then + swaybg -i "/home/coast/.local/src/wall/landscapes/1685466762541384.jpg" & + fi +) & + +( + if ! pgrep -x polkit-gnome-authentication-agent >/dev/null; then + /usr/libexec/polkit-gnome-authentication-agent-1 + fi +) & + +( + if ! pgrep -x eww >/dev/null; then + eww daemon & + eww open-many year month day & + else + pkill eww + eww daemon & + eww open-many year month day & + fi +) & diff --git a/local/bin/startniri b/local/bin/startniri new file mode 100755 index 0000000..a20c6cb --- /dev/null +++ b/local/bin/startniri @@ -0,0 +1,8 @@ +#!/bin/sh +export WAYLAND_DISPLAY=wayland-0 +export XDG_CURRENT_DESKTOP=niri +export XDG_SESSION_TYPE=wayland +export XWAYLAND_DISPLAY=:1 + +xwayland-satellite & +niri & diff --git a/local/bin/startw b/local/bin/startw new file mode 100755 index 0000000..348618c --- /dev/null +++ b/local/bin/startw @@ -0,0 +1,3 @@ +#!/bin/sh +dbus-run-session qtile start -b wayland + diff --git a/local/bin/swallow b/local/bin/swallow new file mode 100755 index 0000000..38756f9 --- /dev/null +++ b/local/bin/swallow @@ -0,0 +1,13 @@ +#!/bin/sh +COMMAND="$*" +BINARY="$(printf "$COMMAND" | sed 's/ .*//')" +ARGS="$(printf "$COMMAND" | sed "s/$BINARY //")" + +main() { + WINID=$(xdo id) + xdo hide $WINID + $BINARY "$ARGS" || $BINARY $ARGS + xdo show $WINID +} + +[ "$1" = "" ] && printf "Error: You must provide at least one argument.\nExample usage: swallow mpv ~/videos/AmericanPsycho.mkv\n" || main "$@" diff --git a/local/bin/swap.start b/local/bin/swap.start new file mode 100755 index 0000000..585568e --- /dev/null +++ b/local/bin/swap.start @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +# Open encrypted swap manually + +/usr/bin/cryptsetup open /dev/nvme0n1p2 cryptswap +/usr/sbin/swapon /dev/dm-1 diff --git a/local/bin/swap.stop b/local/bin/swap.stop new file mode 100755 index 0000000..b5294b1 --- /dev/null +++ b/local/bin/swap.stop @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +# Close encrypted swap manually + +swapoff /dev/dm-1 +cryptsetup close cryptswap diff --git a/local/bin/sway-status b/local/bin/sway-status new file mode 100755 index 0000000..064e181 --- /dev/null +++ b/local/bin/sway-status @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Date +date=$(date "+%I:%M %p") + +# CPU temp +cpu=$(sensors | grep "Package" | cut -f 1-3,5 -d " ") + +# Alsa master volume +volume=$(amixer get Master | grep "Right:" | cut -f 7,8 -d " ") + +# Battery percentage +batt="" +for b in /sys/class/power_supply/BAT*; do + if [ -d "$b" ]; then + if [ -r "$b/capacity" ]; then + cap=$(<"$b/capacity") + else + cap=0 + fi + if [ -z "$batt" ]; then + batt="${cap}%" + else + batt="$batt ${cap}%" + fi + fi +done +# If no battery found +if [ -z "$batt" ]; then + batt="None" +fi + +# Status bar +echo "BAT: $batt | $date" + diff --git a/local/bin/tabulate b/local/bin/tabulate new file mode 100755 index 0000000..ed4064c --- /dev/null +++ b/local/bin/tabulate @@ -0,0 +1,8 @@ +#!/usr/lib/python-exec/python3.13/python +# -*- coding: utf-8 -*- +import re +import sys +if __name__ == '__main__': + from tabulate import _main + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(_main()) diff --git a/local/bin/toggle-screens.sh b/local/bin/toggle-screens.sh new file mode 100755 index 0000000..dcda9f3 --- /dev/null +++ b/local/bin/toggle-screens.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +outputs_json="$(niri msg --json outputs)" + +echo "$outputs_json" | jq -c '.[]' | while read -r out; do + name=$(echo "$out" | jq -r '.name') + dpms=$(echo "$out" | jq -r '.dpms') + + if [ "$dpms" = "On" ]; then + echo "Turning off $name" + niri msg output "$name" dpms off + fi +done diff --git a/local/bin/tun2socks b/local/bin/tun2socks new file mode 100755 index 0000000..2f8db64 Binary files /dev/null and b/local/bin/tun2socks differ diff --git a/local/bin/updateriver b/local/bin/updateriver new file mode 100755 index 0000000..3632cea --- /dev/null +++ b/local/bin/updateriver @@ -0,0 +1,79 @@ +#!/usr/bin/env lua + +local home = os.getenv("home") or os.getenv("HOME") +local cache_dir = home .. "/.cache" +local zig_cache = cache_dir .. "/zig" +local proxy_cmd = "ssh -o ProxyCommand='nc -X 5 -x 127.0.0.1:65000 %h %p'" + +local project_dir = arg[1] or (home .. "/Projects/river/river") + +local function run(cmd) + local ok = os.execute(cmd) + if not ok then + io.stderr:write("failed: " .. cmd .. "\n") + os.exit(1) + end +end + +local function fetch_git_dep(path, commit) + local name = path:match("([^/]+)$"):gsub("^zig%-", "") + local tmp = cache_dir .. "/" .. name .. "-tmp" + local tarball = cache_dir .. "/" .. name .. ".tar.gz" + + run("rm -rf " .. tmp) + run('GIT_SSH_COMMAND="' .. proxy_cmd .. '" git clone git@codeberg.org:' .. path .. ".git " .. tmp) + run("git -C " .. tmp .. " checkout " .. commit) + run("tar -czf " .. tarball .. " -C " .. cache_dir .. " " .. name .. "-tmp") + run("zig fetch --global-cache-dir " .. zig_cache .. " file://" .. tarball) + run( + "sed -i '/\\." + .. name + .. ' = /,/\\.hash/{s|.url = "[^"]*"|.url = "file://' + .. tarball + .. "\"|}' " + .. project_dir + .. "/build.zig.zon" + ) +end + +local function fetch_https_dep(url) + local filename = url:match("([^/]+)$") + local name = filename:gsub("^zig%-", ""):gsub("%-v?[0-9].*$", ""):gsub("%.tar%.gz$", "") + local tarball = cache_dir .. "/" .. filename + + run('GIT_SSH_COMMAND="' .. proxy_cmd .. '" curl -x socks5h://127.0.0.1:65000 -Lo ' .. tarball .. " " .. url) + run("zig fetch --global-cache-dir " .. zig_cache .. " file://" .. tarball) + run( + "sed -i '/\\." + .. name + .. ' = /,/\\.hash/{s|.url = "[^"]*"|.url = "file://' + .. tarball + .. "\"|}' " + .. project_dir + .. "/build.zig.zon" + ) +end + +run("git -C " .. project_dir .. " pull") + +local zon = io.open(project_dir .. "/build.zig.zon", "r") +if not zon then + io.stderr:write("cant open build.zig.zon\n") + os.exit(1) +end + +for line in zon:lines() do + local path, commit = line:match("git%+https://codeberg%.org/([^?]+)%?ref=[^#]+#([a-f0-9]+)") + if path and commit then + fetch_git_dep(path, commit) + else + local url = line:match('"(https://codeberg%.org/[^"]+%.tar%.gz)"') + if url then + fetch_https_dep(url) + end + end +end + +zon:close() + +run("cd " .. project_dir .. " && zig build -Doptimize=ReleaseSafe --prefix " .. home .. "/.local install") diff --git a/local/bin/upim b/local/bin/upim new file mode 100755 index 0000000..cbd07d1 --- /dev/null +++ b/local/bin/upim @@ -0,0 +1,21 @@ +#!/usr/bin/env sh +if [ -z "$1" ]; then + echo "usage: $0 " + exit 1 +fi +FILE="$1" +RESPONSE=$(curl -s -X POST \ + -F "file=@${FILE}" \ + https://coast.is-terrible.com/api/files/create) +URL=$(echo "$RESPONSE" | jq -r '.url') +THUMBNAIL_URL=$(echo "$RESPONSE" | jq -r '.thumb') +DELETION_URL=$(echo "$RESPONSE" | jq -r '.del_url') +ERROR=$(echo "$RESPONSE" | jq -r '.error') +if [ "$ERROR" != "null" ]; then + echo "Error uploading file: $ERROR" + exit 1 +fi +echo "file uploaded successfully!" +echo "url: $URL" +echo "thumbnail url: $THUMBNAIL_URL" +echo "deletion url: $DELETION_URL" diff --git a/local/bin/usbmount b/local/bin/usbmount new file mode 100755 index 0000000..81ba1a5 --- /dev/null +++ b/local/bin/usbmount @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import sys + +RED = "\033[0;31m" +RESET = "\033[0m" + +def main(): + if os.geteuid() != 0: + print(f"{RED}[!] Superuser access is required{RESET}") + sys.exit(1) + + if not os.path.exists("/dev/sda"): + print(f"{RED}[!] USB not found!{RESET}") + sys.exit(1) + + print(f"{RED}[*] Decrypting /dev/sda1...{RESET}") + try: + subprocess.run(["cryptsetup", "open", "/dev/sda1", "sda1_crypt"], check=True) + subprocess.run(["mount", "/dev/mapper/sda1_crypt", "/mnt/usb", "--mkdir"], check=True) + print(f"{RED}[*] Decrypted and mounted to /mnt/usb!{RESET}") + except subprocess.CalledProcessError as e: + print(f"{RED}[!] Error: {e}{RESET}") + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/local/bin/usbumount b/local/bin/usbumount new file mode 100755 index 0000000..ffe68bc --- /dev/null +++ b/local/bin/usbumount @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import sys + +RED = "\033[0;31m" +RESET = "\033[0m" + +def run(cmd, fail_msg): + try: + subprocess.run(cmd, check=True) + except subprocess.CalledProcessError: + print(f"{RED}[!] {fail_msg}{RESET}") + sys.exit(1) + +def main(): + if os.geteuid() != 0: + print(f"{RED}[!] Superuser access is required{RESET}") + sys.exit(1) + + print(f"{RED}[*] Unmounting /mnt/usb...{RESET}") + run(["umount", "/mnt/usb"], "Failed to unmount /mnt/usb") + + print(f"{RED}[*] Closing encrypted device...{RESET}") + run(["cryptsetup", "close", "sda1_crypt"], "Failed to close mapper device") + + print(f"{RED}[*] Unmounted and closed successfully!{RESET}") + +if __name__ == "__main__": + main() diff --git a/local/bin/uwuify.awk b/local/bin/uwuify.awk new file mode 100755 index 0000000..7b42027 --- /dev/null +++ b/local/bin/uwuify.awk @@ -0,0 +1,75 @@ +#!awk -f + +function uwuify(s, o) { + o = s + + # r/l -> w/W + o = gensub(/[rl]/, "w", "g", o) + o = gensub(/[RL]/, "W", "g", o) + + # n + vowel -> ny + o = gensub(/N([AEIOU])/, "NY\\1", "g", o) + o = gensub(/([nN])([aeiouAEIOU])/, "\\1y\\2", "g", o) + + # soft c before e/i + o = gensub(/c([ie])/, "sh\\1", "g", o) + o = gensub(/C([ie])/, "Sh\\1", "g", o) + o = gensub(/C([IE])/, "SH\\1", "g", o) + + # th -> d + o = gensub(/th/, "d", "g", o) + o = gensub(/Th/, "D", "g", o) + o = gensub(/TH/, "D", "g", o) + + # ove -> uv + o = gensub(/ove/, "uv", "g", o) + o = gensub(/OVE/, "UV", "g", o) + + # ing -> in’ + o = gensub(/ing\b/, "in’", "g", o) + o = gensub(/ING\b/, "IN’", "g", o) + + # punctuation uwuifier + o = gensub(/!+/, " owo~ ", "g", o) + o = gensub(/\?+/, " uwu?", "g", o) + o = gensub(/\.{3}/, "… >w< ", "g", o) + + return o +} + +function uwuify_line(line, pre, post, uw_pre, diff, fullseq, num, newnum, newseq) { + if (match(line, /^(.*:)/)) { + pre = substr(line, 1, RLENGTH) + post = substr(line, RLENGTH + 1) + + uw_pre = uwuify(pre) + diff = length(uw_pre) - length(pre) + + if (match(uw_pre, /\033\[[0-9]+C/)) { + fullseq = substr(uw_pre, RSTART, RLENGTH) + if (match(fullseq, /\033\[([0-9]+)C/, m)) { + num = m[1] + newnum = num - diff + if (newnum < 0) newnum = 0 + newseq = "\033[" newnum "C" + uw_pre = substr(uw_pre, 1, RSTART - 1) newseq substr(uw_pre, RSTART + RLENGTH) + } + } + + return uw_pre uwuify(post) + } + return uwuify(line) +} + +{ + # Kitty image protocol lines stay raw + if ($0 ~ /\033_G/) { + print $0 + } else if ($0 ~ /\033\[[0-9]+C/) { + out = uwuify_line($0) + print out + } else { + out = uwuify($0) + print out + } +} diff --git a/local/bin/vesktop.sh b/local/bin/vesktop.sh new file mode 100755 index 0000000..5fa9d93 --- /dev/null +++ b/local/bin/vesktop.sh @@ -0,0 +1,2 @@ +#!/bin/sh +vesktop --ozone-platform=wayland diff --git a/local/bin/win2xcur b/local/bin/win2xcur new file mode 100755 index 0000000..ef5b208 --- /dev/null +++ b/local/bin/win2xcur @@ -0,0 +1,8 @@ +#!/usr/bin/python3.13 +# -*- coding: utf-8 -*- +import re +import sys +if __name__ == '__main__': + from win2xcur.main.win2xcur import main + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/local/bin/wsdump b/local/bin/wsdump new file mode 100755 index 0000000..e047f13 --- /dev/null +++ b/local/bin/wsdump @@ -0,0 +1,8 @@ +#!/usr/lib/python-exec/python3.13/python +# -*- coding: utf-8 -*- +import re +import sys +if __name__ == '__main__': + from websocket._wsdump import main + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/local/bin/x2wincur b/local/bin/x2wincur new file mode 100755 index 0000000..68e4a97 --- /dev/null +++ b/local/bin/x2wincur @@ -0,0 +1,8 @@ +#!/usr/bin/python3.13 +# -*- coding: utf-8 -*- +import re +import sys +if __name__ == '__main__': + from win2xcur.main.x2wincur import main + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/local/bin/yellusb b/local/bin/yellusb new file mode 100755 index 0000000..1f53ecd --- /dev/null +++ b/local/bin/yellusb @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import pyudev +import subprocess + +context = pyudev.Context() +monitor = pyudev.Monitor.from_netlink(context) +monitor.filter_by(subsystem='block') + +for device in iter(monitor.poll, None): + if device.action == 'add': + print(f"New device detected: {device.device_node}") + subprocess.run(f"notify-send 'New device connected: {device.device_node}'", shell=True) \ No newline at end of file diff --git a/local/share/color-schemes/Monochrome.colors b/local/share/color-schemes/Monochrome.colors new file mode 100755 index 0000000..871b18c --- /dev/null +++ b/local/share/color-schemes/Monochrome.colors @@ -0,0 +1,123 @@ +[ColorEffects:Disabled] +Color=56,56,56 +ColorAmount=0 +ColorEffect=0 +ContrastAmount=0.4 +ContrastEffect=1 +IntensityAmount=0.1 +IntensityEffect=2 + +[ColorEffects:Inactive] +ChangeSelectionColor=true +Color=112,111,110 +ColorAmount=0.025 +ColorEffect=2 +ContrastAmount=0.1 +ContrastEffect=2 +Enable=false +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=189,195,199 +BackgroundNormal=30,30,32 +DecorationFocus=80,80,82 +DecorationHover=110,110,112 +ForegroundActive=61,174,233 +ForegroundInactive=127,140,141 +ForegroundLink=100,100,100 +ForegroundNegative=218,68,83 +ForegroundNeutral=246,116,0 +ForegroundNormal=170,170,172 +ForegroundPositive=85,255,255 +ForegroundVisited=127,140,141 + +[Colors:Complementary] +BackgroundAlternate=59,64,69 +BackgroundNormal=49,54,59 +DecorationFocus=80,80,82 +DecorationHover=80,80,82 +ForegroundActive=246,116,0 +ForegroundInactive=175,176,179 +ForegroundLink=61,174,230 +ForegroundNegative=237,21,21 +ForegroundNeutral=201,206,59 +ForegroundNormal=218,218,220 +ForegroundPositive=17,209,22 +ForegroundVisited=61,174,230 + +[Colors:Selection] +BackgroundAlternate=29,153,243 +BackgroundNormal=114,114,116 +DecorationFocus=80,80,82 +DecorationHover=110,110,112 +ForegroundActive=252,252,252 +ForegroundInactive=218,218,220 +ForegroundLink=200,200,200 +ForegroundNegative=218,68,83 +ForegroundNeutral=246,116,0 +ForegroundNormal=218,218,220 +ForegroundPositive=85,255,255 +ForegroundVisited=189,195,199 + +[Colors:Tooltip] +BackgroundAlternate=77,77,77 +BackgroundNormal=30,30,32 +DecorationFocus=80,80,82 +DecorationHover=110,110,112 +ForegroundActive=61,174,233 +ForegroundInactive=189,195,199 +ForegroundLink=100,100,100 +ForegroundNegative=218,68,83 +ForegroundNeutral=246,116,0 +ForegroundNormal=170,170,172 +ForegroundPositive=85,255,255 +ForegroundVisited=127,140,141 + +[Colors:View] +BackgroundAlternate=30,30,32 +BackgroundNormal=30,30,32 +DecorationFocus=80,80,82 +DecorationHover=110,110,112 +ForegroundActive=61,174,233 +ForegroundInactive=127,140,141 +ForegroundLink=100,100,100 +ForegroundNegative=218,68,83 +ForegroundNeutral=246,116,0 +ForegroundNormal=170,170,172 +ForegroundPositive=85,255,255 +ForegroundVisited=127,140,141 + +[Colors:Window] +BackgroundAlternate=189,195,199 +BackgroundNormal=30,30,32 +DecorationFocus=80,80,82 +DecorationHover=110,110,112 +ForegroundActive=61,174,233 +ForegroundInactive=127,140,141 +ForegroundLink=100,100,100 +ForegroundNegative=218,68,83 +ForegroundNeutral=246,116,0 +ForegroundNormal=170,170,172 +ForegroundPositive=85,255,255 +ForegroundVisited=127,140,141 + +[General] +ColorScheme=Monochrome +Name=Monochrome +shadeSortColumn=true + +[KDE] +contrast=4 + +[WM] +activeBackground=30,30,32 +activeBlend=255,255,255 +activeForeground=170,170,172 +inactiveBackground=30,30,32 +inactiveBlend=154,169,200 +inactiveForeground=120,120,122 + +[Colors:Panel] +BackgroundNormal=0,0,0 +ForegroundNormal=255,255,255 diff --git a/local/share/emoji b/local/share/emoji new file mode 100755 index 0000000..eab9658 --- /dev/null +++ b/local/share/emoji @@ -0,0 +1,1630 @@ +😀 grinning face +😃 grinning face with big eyes +😄 grinning face with smiling eyes +😁 beaming face with smiling eyes +😆 grinning squinting face +😅 grinning face with sweat +🤣 rolling on the floor laughing +😂 face with tears of joy +🙂 slightly smiling face +🙃 upside-down face +🫠 melting face +😉 winking face +😊 smiling face with smiling eyes +😇 smiling face with halo +🥰 smiling face with hearts +😍 smiling face with heart-eyes +🤩 star-struck +😘 face blowing a kiss +😗 kissing face +☺️ smiling face +😚 kissing face with closed eyes +😙 kissing face with smiling eyes +🥲 smiling face with tear +😋 face savoring food +😛 face with tongue +😜 winking face with tongue +🤪 zany face +😝 squinting face with tongue +🤑 money-mouth face +🤗 smiling face with open hands +🤭 face with hand over mouth +🫢 face with open eyes and hand over mouth +🫣 face with peeking eye +🤫 shushing face +🤔 thinking face +🫡 saluting face +🤐 zipper-mouth face +🤨 face with raised eyebrow +😐 neutral face +😑 expressionless face +😶 face without mouth +🫥 dotted line face +😏 smirking face +😒 unamused face +🙄 face with rolling eyes +😬 grimacing face +🤥 lying face +😌 relieved face +😔 pensive face +😪 sleepy face +🤤 drooling face +😴 sleeping face +😷 face with medical mask +🤒 face with thermometer +🤕 face with head-bandage +🤢 nauseated face +🤮 face vomiting +🤧 sneezing face +🥵 hot face +🥶 cold face +🥴 woozy face +😵 face with crossed-out eyes +🤯 exploding head +🤠 cowboy hat face +🥳 partying face +🥸 disguised face +😎 smiling face with sunglasses +🤓 nerd face +🧐 face with monocle +😕 confused face +🫤 face with diagonal mouth +😟 worried face +🙁 slightly frowning face +☹️ frowning face +😮 face with open mouth +😯 hushed face +😲 astonished face +😳 flushed face +🥺 pleading face +🥹 face holding back tears +😦 frowning face with open mouth +😧 anguished face +😨 fearful face +😰 anxious face with sweat +😥 sad but relieved face +😢 crying face +😭 loudly crying face +😱 face screaming in fear +😖 confounded face +😣 persevering face +😞 disappointed face +😓 downcast face with sweat +😩 weary face +😫 tired face +🥱 yawning face +😤 face with steam from nose +😡 pouting face +😠 angry face +🤬 face with symbols on mouth +😈 smiling face with horns +👿 angry face with horns +💀 skull +☠️ skull and crossbones +💩 pile of poo +🤡 clown face +👹 ogre +👺 goblin +👻 ghost +👽 alien +👾 alien monster +🤖 robot +😺 grinning cat +😸 grinning cat with smiling eyes +😹 cat with tears of joy +😻 smiling cat with heart-eyes +😼 cat with wry smile +😽 kissing cat +🙀 weary cat +😿 crying cat +😾 pouting cat +🙈 see-no-evil monkey +🙉 hear-no-evil monkey +🙊 speak-no-evil monkey +💋 kiss mark +💌 love letter +💘 heart with arrow +💝 heart with ribbon +💖 sparkling heart +💗 growing heart +💓 beating heart +💞 revolving hearts +💕 two hearts +💟 heart decoration +❣️ heart exclamation +💔 broken heart +❤️ red heart +🧡 orange heart +💛 yellow heart +💚 green heart +💙 blue heart +💜 purple heart +🤎 brown heart +🖤 black heart +🤍 white heart +💯 hundred points +💢 anger symbol +💥 collision +💫 dizzy +💦 sweat droplets +💨 dashing away +🕳️ hole +💣 bomb +💬 speech balloon +🗨️ left speech bubble +🗯️ right anger bubble +💭 thought balloon +💤 zzz +👋 waving hand +🤚 raised back of hand +🖐️ hand with fingers splayed +✋ raised hand +🖖 vulcan salute +🫱 rightwards hand +🫲 leftwards hand +🫳 palm down hand +🫴 palm up hand +👌 OK hand +🤌 pinched fingers +🤏 pinching hand +✌️ victory hand +🤞 crossed fingers +🫰 hand with index finger and thumb crossed +🤟 love-you gesture +🤘 sign of the horns +🤙 call me hand +👈 backhand index pointing left +👉 backhand index pointing right +👆 backhand index pointing up +🖕 middle finger +👇 backhand index pointing down +☝️ index pointing up +🫵 index pointing at the viewer +👍 thumbs up +👎 thumbs down +✊ raised fist +👊 oncoming fist +🤛 left-facing fist +🤜 right-facing fist +👏 clapping hands +🙌 raising hands +🫶 heart hands +👐 open hands +🤲 palms up together +🤝 handshake +🙏 folded hands +✍️ writing hand +💅 nail polish +🤳 selfie +💪 flexed biceps +🦾 mechanical arm +🦿 mechanical leg +🦵 leg +🦶 foot +👂 ear +🦻 ear with hearing aid +👃 nose +🧠 brain +🫀 anatomical heart +🫁 lungs +🦷 tooth +🦴 bone +👀 eyes +👁️ eye +👅 tongue +👄 mouth +🫦 biting lip +👶 baby +🧒 child +👦 boy +👧 girl +🧑 person +👱 person: blond hair +👨 man +🧔 person: beard +👩 woman +🧓 older person +👴 old man +👵 old woman +🙍 person frowning +🙎 person pouting +🙅 person gesturing NO +🙆 person gesturing OK +💁 person tipping hand +🙋 person raising hand +🧏 deaf person +🙇 person bowing +🤦 person facepalming +🤷 person shrugging +👮 police officer +🕵️ detective +💂 guard +🥷 ninja +👷 construction worker +🫅 person with crown +🤴 prince +👸 princess +👳 person wearing turban +👲 person with skullcap +🧕 woman with headscarf +🤵 person in tuxedo +👰 person with veil +🤰 pregnant woman +🫃 pregnant man +🫄 pregnant person +🤱 breast-feeding +👼 baby angel +🎅 Santa Claus +🤶 Mrs. Claus +🦸 superhero +🦹 supervillain +🧙 mage +🧚 fairy +🧛 vampire +🧜 merperson +🧝 elf +🧞 genie +🧟 zombie +🧌 troll +💆 person getting massage +💇 person getting haircut +🚶 person walking +🧍 person standing +🧎 person kneeling +🏃 person running +💃 woman dancing +🕺 man dancing +🕴️ person in suit levitating +👯 people with bunny ears +🧖 person in steamy room +🧗 person climbing +🤺 person fencing +🏇 horse racing +⛷️ skier +🏂 snowboarder +🏌️ person golfing +🏄 person surfing +🚣 person rowing boat +🏊 person swimming +⛹️ person bouncing ball +🏋️ person lifting weights +🚴 person biking +🚵 person mountain biking +🤸 person cartwheeling +🤼 people wrestling +🤽 person playing water polo +🤾 person playing handball +🤹 person juggling +🧘 person in lotus position +🛀 person taking bath +🛌 person in bed +👭 women holding hands +👫 woman and man holding hands +👬 men holding hands +💏 kiss +💑 couple with heart +👪 family +🗣️ speaking head +👤 bust in silhouette +👥 busts in silhouette +🫂 people hugging +👣 footprints +🐵 monkey face +🐒 monkey +🦍 gorilla +🦧 orangutan +🐶 dog face +🐕 dog +🦮 guide dog +🐩 poodle +🐺 wolf +🦊 fox +🦝 raccoon +🐱 cat face +🐈 cat +🦁 lion +🐯 tiger face +🐅 tiger +🐆 leopard +🐴 horse face +🐎 horse +🦄 unicorn +🦓 zebra +🦌 deer +🦬 bison +🐮 cow face +🐂 ox +🐃 water buffalo +🐄 cow +🐷 pig face +🐖 pig +🐗 boar +🐽 pig nose +🐏 ram +🐑 ewe +🐐 goat +🐪 camel +🐫 two-hump camel +🦙 llama +🦒 giraffe +🐘 elephant +🦣 mammoth +🦏 rhinoceros +🦛 hippopotamus +🐭 mouse face +🐁 mouse +🐀 rat +🐹 hamster +🐰 rabbit face +🐇 rabbit +🐿️ chipmunk +🦫 beaver +🦔 hedgehog +🦇 bat +🐻 bear +🐨 koala +🐼 panda +🦥 sloth +🦦 otter +🦨 skunk +🦘 kangaroo +🦡 badger +🐾 paw prints +🦃 turkey +🐔 chicken +🐓 rooster +🐣 hatching chick +🐤 baby chick +🐥 front-facing baby chick +🐦 bird +🐧 penguin +🕊️ dove +🦅 eagle +🦆 duck +🦢 swan +🦉 owl +🦤 dodo +🪶 feather +🦩 flamingo +🦚 peacock +🦜 parrot +🐸 frog +🐊 crocodile +🐢 turtle +🦎 lizard +🐍 snake +🐲 dragon face +🐉 dragon +🦕 sauropod +🦖 T-Rex +🐳 spouting whale +🐋 whale +🐬 dolphin +🦭 seal +🐟 fish +🐠 tropical fish +🐡 blowfish +🦈 shark +🐙 octopus +🐚 spiral shell +🪸 coral +🐌 snail +🦋 butterfly +🐛 bug +🐜 ant +🐝 honeybee +🪲 beetle +🐞 lady beetle +🦗 cricket +🪳 cockroach +🕷️ spider +🕸️ spider web +🦂 scorpion +🦟 mosquito +🪰 fly +🪱 worm +🦠 microbe +💐 bouquet +🌸 cherry blossom +💮 white flower +🪷 lotus +🏵️ rosette +🌹 rose +🥀 wilted flower +🌺 hibiscus +🌻 sunflower +🌼 blossom +🌷 tulip +🌱 seedling +🪴 potted plant +🌲 evergreen tree +🌳 deciduous tree +🌴 palm tree +🌵 cactus +🌾 sheaf of rice +🌿 herb +☘️ shamrock +🍀 four leaf clover +🍁 maple leaf +🍂 fallen leaf +🍃 leaf fluttering in wind +🪹 empty nest +🪺 nest with eggs +🍇 grapes +🍈 melon +🍉 watermelon +🍊 tangerine +🍋 lemon +🍌 banana +🍍 pineapple +🥭 mango +🍎 red apple +🍏 green apple +🍐 pear +🍑 peach +🍒 cherries +🍓 strawberry +🫐 blueberries +🥝 kiwi fruit +🍅 tomato +🫒 olive +🥥 coconut +🥑 avocado +🍆 eggplant +🥔 potato +🥕 carrot +🌽 ear of corn +🌶️ hot pepper +🫑 bell pepper +🥒 cucumber +🥬 leafy green +🥦 broccoli +🧄 garlic +🧅 onion +🍄 mushroom +🥜 peanuts +🫘 beans +🌰 chestnut +🍞 bread +🥐 croissant +🥖 baguette bread +🫓 flatbread +🥨 pretzel +🥯 bagel +🥞 pancakes +🧇 waffle +🧀 cheese wedge +🍖 meat on bone +🍗 poultry leg +🥩 cut of meat +🥓 bacon +🍔 hamburger +🍟 french fries +🍕 pizza +🌭 hot dog +🥪 sandwich +🌮 taco +🌯 burrito +🫔 tamale +🥙 stuffed flatbread +🧆 falafel +🥚 egg +🍳 cooking +🥘 shallow pan of food +🍲 pot of food +🫕 fondue +🥣 bowl with spoon +🥗 green salad +🍿 popcorn +🧈 butter +🧂 salt +🥫 canned food +🍱 bento box +🍘 rice cracker +🍙 rice ball +🍚 cooked rice +🍛 curry rice +🍜 steaming bowl +🍝 spaghetti +🍠 roasted sweet potato +🍢 oden +🍣 sushi +🍤 fried shrimp +🍥 fish cake with swirl +🥮 moon cake +🍡 dango +🥟 dumpling +🥠 fortune cookie +🥡 takeout box +🦀 crab +🦞 lobster +🦐 shrimp +🦑 squid +🦪 oyster +🍦 soft ice cream +🍧 shaved ice +🍨 ice cream +🍩 doughnut +🍪 cookie +🎂 birthday cake +🍰 shortcake +🧁 cupcake +🥧 pie +🍫 chocolate bar +🍬 candy +🍭 lollipop +🍮 custard +🍯 honey pot +🍼 baby bottle +🥛 glass of milk +☕ hot beverage +🫖 teapot +🍵 teacup without handle +🍶 sake +🍾 bottle with popping cork +🍷 wine glass +🍸 cocktail glass +🍹 tropical drink +🍺 beer mug +🍻 clinking beer mugs +🥂 clinking glasses +🥃 tumbler glass +🫗 pouring liquid +🥤 cup with straw +🧋 bubble tea +🧃 beverage box +🧉 mate +🧊 ice +🥢 chopsticks +🍽️ fork and knife with plate +🍴 fork and knife +🥄 spoon +🔪 kitchen knife +🫙 jar +🏺 amphora +🌍 globe showing Europe-Africa +🌎 globe showing Americas +🌏 globe showing Asia-Australia +🌐 globe with meridians +🗺️ world map +🗾 map of Japan +🧭 compass +🏔️ snow-capped mountain +⛰️ mountain +🌋 volcano +🗻 mount fuji +🏕️ camping +🏖️ beach with umbrella +🏜️ desert +🏝️ desert island +🏞️ national park +🏟️ stadium +🏛️ classical building +🏗️ building construction +🧱 brick +🪨 rock +🪵 wood +🛖 hut +🏘️ houses +🏚️ derelict house +🏠 house +🏡 house with garden +🏢 office building +🏣 Japanese post office +🏤 post office +🏥 hospital +🏦 bank +🏨 hotel +🏩 love hotel +🏪 convenience store +🏫 school +🏬 department store +🏭 factory +🏯 Japanese castle +🏰 castle +💒 wedding +🗼 Tokyo tower +🗽 Statue of Liberty +⛪ church +🕌 mosque +🛕 hindu temple +🕍 synagogue +⛩️ shinto shrine +🕋 kaaba +⛲ fountain +⛺ tent +🌁 foggy +🌃 night with stars +🏙️ cityscape +🌄 sunrise over mountains +🌅 sunrise +🌆 cityscape at dusk +🌇 sunset +🌉 bridge at night +♨️ hot springs +🎠 carousel horse +🛝 playground slide +🎡 ferris wheel +🎢 roller coaster +💈 barber pole +🎪 circus tent +🚂 locomotive +🚃 railway car +🚄 high-speed train +🚅 bullet train +🚆 train +🚇 metro +🚈 light rail +🚉 station +🚊 tram +🚝 monorail +🚞 mountain railway +🚋 tram car +🚌 bus +🚍 oncoming bus +🚎 trolleybus +🚐 minibus +🚑 ambulance +🚒 fire engine +🚓 police car +🚔 oncoming police car +🚕 taxi +🚖 oncoming taxi +🚗 automobile +🚘 oncoming automobile +🚙 sport utility vehicle +🛻 pickup truck +🚚 delivery truck +🚛 articulated lorry +🚜 tractor +🏎️ racing car +🏍️ motorcycle +🛵 motor scooter +🦽 manual wheelchair +🦼 motorized wheelchair +🛺 auto rickshaw +🚲 bicycle +🛴 kick scooter +🛹 skateboard +🛼 roller skate +🚏 bus stop +🛣️ motorway +🛤️ railway track +🛢️ oil drum +⛽ fuel pump +🛞 wheel +🚨 police car light +🚥 horizontal traffic light +🚦 vertical traffic light +🛑 stop sign +🚧 construction +⚓ anchor +🛟 ring buoy +⛵ sailboat +🛶 canoe +🚤 speedboat +🛳️ passenger ship +⛴️ ferry +🛥️ motor boat +🚢 ship +✈️ airplane +🛩️ small airplane +🛫 airplane departure +🛬 airplane arrival +🪂 parachute +💺 seat +🚁 helicopter +🚟 suspension railway +🚠 mountain cableway +🚡 aerial tramway +🛰️ satellite +🚀 rocket +🛸 flying saucer +🛎️ bellhop bell +🧳 luggage +⌛ hourglass done +⏳ hourglass not done +⌚ watch +⏰ alarm clock +⏱️ stopwatch +⏲️ timer clock +🕰️ mantelpiece clock +🕛 twelve o’clock +🕧 twelve-thirty +🕐 one o’clock +🕜 one-thirty +🕑 two o’clock +🕝 two-thirty +🕒 three o’clock +🕞 three-thirty +🕓 four o’clock +🕟 four-thirty +🕔 five o’clock +🕠 five-thirty +🕕 six o’clock +🕡 six-thirty +🕖 seven o’clock +🕢 seven-thirty +🕗 eight o’clock +🕣 eight-thirty +🕘 nine o’clock +🕤 nine-thirty +🕙 ten o’clock +🕥 ten-thirty +🕚 eleven o’clock +🕦 eleven-thirty +🌑 new moon +🌒 waxing crescent moon +🌓 first quarter moon +🌔 waxing gibbous moon +🌕 full moon +🌖 waning gibbous moon +🌗 last quarter moon +🌘 waning crescent moon +🌙 crescent moon +🌚 new moon face +🌛 first quarter moon face +🌜 last quarter moon face +🌡️ thermometer +☀️ sun +🌝 full moon face +🌞 sun with face +🪐 ringed planet +⭐ star +🌟 glowing star +🌠 shooting star +🌌 milky way +☁️ cloud +⛅ sun behind cloud +⛈️ cloud with lightning and rain +🌤️ sun behind small cloud +🌥️ sun behind large cloud +🌦️ sun behind rain cloud +🌧️ cloud with rain +🌨️ cloud with snow +🌩️ cloud with lightning +🌪️ tornado +🌫️ fog +🌬️ wind face +🌀 cyclone +🌈 rainbow +🌂 closed umbrella +☂️ umbrella +☔ umbrella with rain drops +⛱️ umbrella on ground +⚡ high voltage +❄️ snowflake +☃️ snowman +⛄ snowman without snow +☄️ comet +🔥 fire +💧 droplet +🌊 water wave +🎃 jack-o-lantern +🎄 Christmas tree +🎆 fireworks +🎇 sparkler +🧨 firecracker +✨ sparkles +🎈 balloon +🎉 party popper +🎊 confetti ball +🎋 tanabata tree +🎍 pine decoration +🎎 Japanese dolls +🎏 carp streamer +🎐 wind chime +🎑 moon viewing ceremony +🧧 red envelope +🎀 ribbon +🎁 wrapped gift +🎗️ reminder ribbon +🎟️ admission tickets +🎫 ticket +🎖️ military medal +🏆 trophy +🏅 sports medal +🥇 1st place medal +🥈 2nd place medal +🥉 3rd place medal +⚽ soccer ball +⚾ baseball +🥎 softball +🏀 basketball +🏐 volleyball +🏈 american football +🏉 rugby football +🎾 tennis +🥏 flying disc +🎳 bowling +🏏 cricket game +🏑 field hockey +🏒 ice hockey +🥍 lacrosse +🏓 ping pong +🏸 badminton +🥊 boxing glove +🥋 martial arts uniform +🥅 goal net +⛳ flag in hole +⛸️ ice skate +🎣 fishing pole +🤿 diving mask +🎽 running shirt +🎿 skis +🛷 sled +🥌 curling stone +🎯 bullseye +🪀 yo-yo +🪁 kite +🎱 pool 8 ball +🔮 crystal ball +🪄 magic wand +🧿 nazar amulet +🪬 hamsa +🎮 video game +🕹️ joystick +🎰 slot machine +🎲 game die +🧩 puzzle piece +🧸 teddy bear +🪅 piñata +🪩 mirror ball +🪆 nesting dolls +♠️ spade suit +♥️ heart suit +♦️ diamond suit +♣️ club suit +♟️ chess pawn +🃏 joker +🀄 mahjong red dragon +🎴 flower playing cards +🎭 performing arts +🖼️ framed picture +🎨 artist palette +🧵 thread +🪡 sewing needle +🧶 yarn +🪢 knot +👓 glasses +🕶️ sunglasses +🥽 goggles +🥼 lab coat +🦺 safety vest +👔 necktie +👕 t-shirt +👖 jeans +🧣 scarf +🧤 gloves +🧥 coat +🧦 socks +👗 dress +👘 kimono +🥻 sari +🩱 one-piece swimsuit +🩲 briefs +🩳 shorts +👙 bikini +👚 woman’s clothes +👛 purse +👜 handbag +👝 clutch bag +🛍️ shopping bags +🎒 backpack +🩴 thong sandal +👞 man’s shoe +👟 running shoe +🥾 hiking boot +🥿 flat shoe +👠 high-heeled shoe +👡 woman’s sandal +🩰 ballet shoes +👢 woman’s boot +👑 crown +👒 woman’s hat +🎩 top hat +🎓 graduation cap +🧢 billed cap +🪖 military helmet +⛑️ rescue worker’s helmet +📿 prayer beads +💄 lipstick +💍 ring +💎 gem stone +🔇 muted speaker +🔈 speaker low volume +🔉 speaker medium volume +🔊 speaker high volume +📢 loudspeaker +📣 megaphone +📯 postal horn +🔔 bell +🔕 bell with slash +🎼 musical score +🎵 musical note +🎶 musical notes +🎙️ studio microphone +🎚️ level slider +🎛️ control knobs +🎤 microphone +🎧 headphone +📻 radio +🎷 saxophone +🪗 accordion +🎸 guitar +🎹 musical keyboard +🎺 trumpet +🎻 violin +🪕 banjo +🥁 drum +🪘 long drum +📱 mobile phone +📲 mobile phone with arrow +☎️ telephone +📞 telephone receiver +📟 pager +📠 fax machine +🔋 battery +🪫 low battery +🔌 electric plug +💻 laptop +🖥️ desktop computer +🖨️ printer +⌨️ keyboard +🖱️ computer mouse +🖲️ trackball +💽 computer disk +💾 floppy disk +💿 optical disk +📀 dvd +🧮 abacus +🎥 movie camera +🎞️ film frames +📽️ film projector +🎬 clapper board +📺 television +📷 camera +📸 camera with flash +📹 video camera +📼 videocassette +🔍 magnifying glass tilted left +🔎 magnifying glass tilted right +🕯️ candle +💡 light bulb +🔦 flashlight +🏮 red paper lantern +🪔 diya lamp +📔 notebook with decorative cover +📕 closed book +📖 open book +📗 green book +📘 blue book +📙 orange book +📚 books +📓 notebook +📒 ledger +📃 page with curl +📜 scroll +📄 page facing up +📰 newspaper +🗞️ rolled-up newspaper +📑 bookmark tabs +🔖 bookmark +🏷️ label +💰 money bag +🪙 coin +💴 yen banknote +💵 dollar banknote +💶 euro banknote +💷 pound banknote +💸 money with wings +💳 credit card +🧾 receipt +💹 chart increasing with yen +✉️ envelope +📧 e-mail +📨 incoming envelope +📩 envelope with arrow +📤 outbox tray +📥 inbox tray +📦 package +📫 closed mailbox with raised flag +📪 closed mailbox with lowered flag +📬 open mailbox with raised flag +📭 open mailbox with lowered flag +📮 postbox +🗳️ ballot box with ballot +✏️ pencil +✒️ black nib +🖋️ fountain pen +🖊️ pen +🖌️ paintbrush +🖍️ crayon +📝 memo +💼 briefcase +📁 file folder +📂 open file folder +🗂️ card index dividers +📅 calendar +📆 tear-off calendar +🗒️ spiral notepad +🗓️ spiral calendar +📇 card index +📈 chart increasing +📉 chart decreasing +📊 bar chart +📋 clipboard +📌 pushpin +📍 round pushpin +📎 paperclip +🖇️ linked paperclips +📏 straight ruler +📐 triangular ruler +✂️ scissors +🗃️ card file box +🗄️ file cabinet +🗑️ wastebasket +🔒 locked +🔓 unlocked +🔏 locked with pen +🔐 locked with key +🔑 key +🗝️ old key +🔨 hammer +🪓 axe +⛏️ pick +⚒️ hammer and pick +🛠️ hammer and wrench +🗡️ dagger +⚔️ crossed swords +🔫 water pistol +🪃 boomerang +🏹 bow and arrow +🛡️ shield +🪚 carpentry saw +🔧 wrench +🪛 screwdriver +🔩 nut and bolt +⚙️ gear +🗜️ clamp +⚖️ balance scale +🦯 white cane +🔗 link +⛓️ chains +🪝 hook +🧰 toolbox +🧲 magnet +🪜 ladder +⚗️ alembic +🧪 test tube +🧫 petri dish +🧬 dna +🔬 microscope +🔭 telescope +📡 satellite antenna +💉 syringe +🩸 drop of blood +💊 pill +🩹 adhesive bandage +🩼 crutch +🩺 stethoscope +🩻 x-ray +🚪 door +🛗 elevator +🪞 mirror +🪟 window +🛏️ bed +🛋️ couch and lamp +🪑 chair +🚽 toilet +🪠 plunger +🚿 shower +🛁 bathtub +🪤 mouse trap +🪒 razor +🧴 lotion bottle +🧷 safety pin +🧹 broom +🧺 basket +🧻 roll of paper +🪣 bucket +🧼 soap +🫧 bubbles +🪥 toothbrush +🧽 sponge +🧯 fire extinguisher +🛒 shopping cart +🚬 cigarette +⚰️ coffin +🪦 headstone +⚱️ funeral urn +🗿 moai +🪧 placard +🪪 identification card +🏧 ATM sign +🚮 litter in bin sign +🚰 potable water +♿ wheelchair symbol +🚹 men’s room +🚺 women’s room +🚻 restroom +🚼 baby symbol +🚾 water closet +🛂 passport control +🛃 customs +🛄 baggage claim +🛅 left luggage +⚠️ warning +🚸 children crossing +⛔ no entry +🚫 prohibited +🚳 no bicycles +🚭 no smoking +🚯 no littering +🚱 non-potable water +🚷 no pedestrians +📵 no mobile phones +🔞 no one under eighteen +☢️ radioactive +☣️ biohazard +⬆️ up arrow +↗️ up-right arrow +➡️ right arrow +↘️ down-right arrow +⬇️ down arrow +↙️ down-left arrow +⬅️ left arrow +↖️ up-left arrow +↕️ up-down arrow +↔️ left-right arrow +↩️ right arrow curving left +↪️ left arrow curving right +⤴️ right arrow curving up +⤵️ right arrow curving down +🔃 clockwise vertical arrows +🔄 counterclockwise arrows button +🔙 BACK arrow +🔚 END arrow +🔛 ON! arrow +🔜 SOON arrow +🔝 TOP arrow +🛐 place of worship +⚛️ atom symbol +🕉️ om +✡️ star of David +☸️ wheel of dharma +☯️ yin yang +✝️ latin cross +☦️ orthodox cross +☪️ star and crescent +☮️ peace symbol +🕎 menorah +🔯 dotted six-pointed star +♈ Aries +♉ Taurus +♊ Gemini +♋ Cancer +♌ Leo +♍ Virgo +♎ Libra +♏ Scorpio +♐ Sagittarius +♑ Capricorn +♒ Aquarius +♓ Pisces +⛎ Ophiuchus +🔀 shuffle tracks button +🔁 repeat button +🔂 repeat single button +▶️ play button +⏩ fast-forward button +⏭️ next track button +⏯️ play or pause button +◀️ reverse button +⏪ fast reverse button +⏮️ last track button +🔼 upwards button +⏫ fast up button +🔽 downwards button +⏬ fast down button +⏸️ pause button +⏹️ stop button +⏺️ record button +⏏️ eject button +🎦 cinema +🔅 dim button +🔆 bright button +📶 antenna bars +📳 vibration mode +📴 mobile phone off +♀️ female sign +♂️ male sign +⚧️ transgender symbol +✖️ multiply +➕ plus +➖ minus +➗ divide +🟰 heavy equals sign +♾️ infinity +‼️ double exclamation mark +⁉️ exclamation question mark +❓ red question mark +❔ white question mark +❕ white exclamation mark +❗ red exclamation mark +〰️ wavy dash +💱 currency exchange +💲 heavy dollar sign +⚕️ medical symbol +♻️ recycling symbol +⚜️ fleur-de-lis +🔱 trident emblem +📛 name badge +🔰 Japanese symbol for beginner +⭕ hollow red circle +✅ check mark button +☑️ check box with check +✔️ check mark +❌ cross mark +❎ cross mark button +➰ curly loop +➿ double curly loop +〽️ part alternation mark +✳️ eight-spoked asterisk +✴️ eight-pointed star +❇️ sparkle +©️ copyright +®️ registered +™️ trade mark +#️⃣ keycap: # +*️⃣ keycap: * +0️⃣ keycap: 0 +1️⃣ keycap: 1 +2️⃣ keycap: 2 +3️⃣ keycap: 3 +4️⃣ keycap: 4 +5️⃣ keycap: 5 +6️⃣ keycap: 6 +7️⃣ keycap: 7 +8️⃣ keycap: 8 +9️⃣ keycap: 9 +🔟 keycap: 10 +🔠 input latin uppercase +🔡 input latin lowercase +🔢 input numbers +🔣 input symbols +🔤 input latin letters +🅰️ A button (blood type) +🆎 AB button (blood type) +🅱️ B button (blood type) +🆑 CL button +🆒 COOL button +🆓 FREE button +ℹ️ information +🆔 ID button +Ⓜ️ circled M +🆕 NEW button +🆖 NG button +🅾️ O button (blood type) +🆗 OK button +🅿️ P button +🆘 SOS button +🆙 UP! button +🆚 VS button +🈁 Japanese “here” button +🈂️ Japanese “service charge” button +🈷️ Japanese “monthly amount” button +🈶 Japanese “not free of charge” button +🈯 Japanese “reserved” button +🉐 Japanese “bargain” button +🈹 Japanese “discount” button +🈚 Japanese “free of charge” button +🈲 Japanese “prohibited” button +🉑 Japanese “acceptable” button +🈸 Japanese “application” button +🈴 Japanese “passing grade” button +🈳 Japanese “vacancy” button +㊗️ Japanese “congratulations” button +㊙️ Japanese “secret” button +🈺 Japanese “open for business” button +🈵 Japanese “no vacancy” button +🔴 red circle +🟠 orange circle +🟡 yellow circle +🟢 green circle +🔵 blue circle +🟣 purple circle +🟤 brown circle +⚫ black circle +⚪ white circle +🟥 red square +🟧 orange square +🟨 yellow square +🟩 green square +🟦 blue square +🟪 purple square +🟫 brown square +⬛ black large square +⬜ white large square +◼️ black medium square +◻️ white medium square +◾ black medium-small square +◽ white medium-small square +▪️ black small square +▫️ white small square +🔶 large orange diamond +🔷 large blue diamond +🔸 small orange diamond +🔹 small blue diamond +🔺 red triangle pointed up +🔻 red triangle pointed down +💠 diamond with a dot +🔘 radio button +🔳 white square button +🔲 black square button +🏁 chequered flag +🚩 triangular flag +🎌 crossed flags +🏴 black flag +🏳️ white flag +🇦🇨 flag: Ascension Island +🇦🇩 flag: Andorra +🇦🇪 flag: United Arab Emirates +🇦🇫 flag: Afghanistan +🇦🇬 flag: Antigua & Barbuda +🇦🇮 flag: Anguilla +🇦🇱 flag: Albania +🇦🇲 flag: Armenia +🇦🇴 flag: Angola +🇦🇶 flag: Antarctica +🇦🇷 flag: Argentina +🇦🇸 flag: American Samoa +🇦🇹 flag: Austria +🇦🇺 flag: Australia +🇦🇼 flag: Aruba +🇦🇽 flag: Åland Islands +🇦🇿 flag: Azerbaijan +🇧🇦 flag: Bosnia & Herzegovina +🇧🇧 flag: Barbados +🇧🇩 flag: Bangladesh +🇧🇪 flag: Belgium +🇧🇫 flag: Burkina Faso +🇧🇬 flag: Bulgaria +🇧🇭 flag: Bahrain +🇧🇮 flag: Burundi +🇧🇯 flag: Benin +🇧🇱 flag: St. Barthélemy +🇧🇲 flag: Bermuda +🇧🇳 flag: Brunei +🇧🇴 flag: Bolivia +🇧🇶 flag: Caribbean Netherlands +🇧🇷 flag: Brazil +🇧🇸 flag: Bahamas +🇧🇹 flag: Bhutan +🇧🇻 flag: Bouvet Island +🇧🇼 flag: Botswana +🇧🇾 flag: Belarus +🇧🇿 flag: Belize +🇨🇦 flag: Canada +🇨🇨 flag: Cocos (Keeling) Islands +🇨🇩 flag: Congo - Kinshasa +🇨🇫 flag: Central African Republic +🇨🇬 flag: Congo - Brazzaville +🇨🇭 flag: Switzerland +🇨🇮 flag: Côte d’Ivoire +🇨🇰 flag: Cook Islands +🇨🇱 flag: Chile +🇨🇲 flag: Cameroon +🇨🇳 flag: China +🇨🇴 flag: Colombia +🇨🇵 flag: Clipperton Island +🇨🇷 flag: Costa Rica +🇨🇺 flag: Cuba +🇨🇻 flag: Cape Verde +🇨🇼 flag: Curaçao +🇨🇽 flag: Christmas Island +🇨🇾 flag: Cyprus +🇨🇿 flag: Czechia +🇩🇪 flag: Germany +🇩🇬 flag: Diego Garcia +🇩🇯 flag: Djibouti +🇩🇰 flag: Denmark +🇩🇲 flag: Dominica +🇩🇴 flag: Dominican Republic +🇩🇿 flag: Algeria +🇪🇦 flag: Ceuta & Melilla +🇪🇨 flag: Ecuador +🇪🇪 flag: Estonia +🇪🇬 flag: Egypt +🇪🇭 flag: Western Sahara +🇪🇷 flag: Eritrea +🇪🇸 flag: Spain +🇪🇹 flag: Ethiopia +🇪🇺 flag: European Union +🇫🇮 flag: Finland +🇫🇯 flag: Fiji +🇫🇰 flag: Falkland Islands +🇫🇲 flag: Micronesia +🇫🇴 flag: Faroe Islands +🇫🇷 flag: France +🇬🇦 flag: Gabon +🇬🇧 flag: United Kingdom +🇬🇩 flag: Grenada +🇬🇪 flag: Georgia +🇬🇫 flag: French Guiana +🇬🇬 flag: Guernsey +🇬🇭 flag: Ghana +🇬🇮 flag: Gibraltar +🇬🇱 flag: Greenland +🇬🇲 flag: Gambia +🇬🇳 flag: Guinea +🇬🇵 flag: Guadeloupe +🇬🇶 flag: Equatorial Guinea +🇬🇷 flag: Greece +🇬🇸 flag: South Georgia & South Sandwich Islands +🇬🇹 flag: Guatemala +🇬🇺 flag: Guam +🇬🇼 flag: Guinea-Bissau +🇬🇾 flag: Guyana +🇭🇰 flag: Hong Kong SAR China +🇭🇲 flag: Heard & McDonald Islands +🇭🇳 flag: Honduras +🇭🇷 flag: Croatia +🇭🇹 flag: Haiti +🇭🇺 flag: Hungary +🇮🇨 flag: Canary Islands +🇮🇩 flag: Indonesia +🇮🇪 flag: Ireland +🇮🇱 flag: Israel +🇮🇲 flag: Isle of Man +🇮🇳 flag: India +🇮🇴 flag: British Indian Ocean Territory +🇮🇶 flag: Iraq +🇮🇷 flag: Iran +🇮🇸 flag: Iceland +🇮🇹 flag: Italy +🇯🇪 flag: Jersey +🇯🇲 flag: Jamaica +🇯🇴 flag: Jordan +🇯🇵 flag: Japan +🇰🇪 flag: Kenya +🇰🇬 flag: Kyrgyzstan +🇰🇭 flag: Cambodia +🇰🇮 flag: Kiribati +🇰🇲 flag: Comoros +🇰🇳 flag: St. Kitts & Nevis +🇰🇵 flag: North Korea +🇰🇷 flag: South Korea +🇰🇼 flag: Kuwait +🇰🇾 flag: Cayman Islands +🇰🇿 flag: Kazakhstan +🇱🇦 flag: Laos +🇱🇧 flag: Lebanon +🇱🇨 flag: St. Lucia +🇱🇮 flag: Liechtenstein +🇱🇰 flag: Sri Lanka +🇱🇷 flag: Liberia +🇱🇸 flag: Lesotho +🇱🇹 flag: Lithuania +🇱🇺 flag: Luxembourg +🇱🇻 flag: Latvia +🇱🇾 flag: Libya +🇲🇦 flag: Morocco +🇲🇨 flag: Monaco +🇲🇩 flag: Moldova +🇲🇪 flag: Montenegro +🇲🇫 flag: St. Martin +🇲🇬 flag: Madagascar +🇲🇭 flag: Marshall Islands +🇲🇰 flag: North Macedonia +🇲🇱 flag: Mali +🇲🇲 flag: Myanmar (Burma) +🇲🇳 flag: Mongolia +🇲🇴 flag: Macao SAR China +🇲🇵 flag: Northern Mariana Islands +🇲🇶 flag: Martinique +🇲🇷 flag: Mauritania +🇲🇸 flag: Montserrat +🇲🇹 flag: Malta +🇲🇺 flag: Mauritius +🇲🇻 flag: Maldives +🇲🇼 flag: Malawi +🇲🇽 flag: Mexico +🇲🇾 flag: Malaysia +🇲🇿 flag: Mozambique +🇳🇦 flag: Namibia +🇳🇨 flag: New Caledonia +🇳🇪 flag: Niger +🇳🇫 flag: Norfolk Island +🇳🇬 flag: Nigeria +🇳🇮 flag: Nicaragua +🇳🇱 flag: Netherlands +🇳🇴 flag: Norway +🇳🇵 flag: Nepal +🇳🇷 flag: Nauru +🇳🇺 flag: Niue +🇳🇿 flag: New Zealand +🇴🇲 flag: Oman +🇵🇦 flag: Panama +🇵🇪 flag: Peru +🇵🇫 flag: French Polynesia +🇵🇬 flag: Papua New Guinea +🇵🇭 flag: Philippines +🇵🇰 flag: Pakistan +🇵🇱 flag: Poland +🇵🇲 flag: St. Pierre & Miquelon +🇵🇳 flag: Pitcairn Islands +🇵🇷 flag: Puerto Rico +🇵🇸 flag: Palestinian Territories +🇵🇹 flag: Portugal +🇵🇼 flag: Palau +🇵🇾 flag: Paraguay +🇶🇦 flag: Qatar +🇷🇪 flag: Réunion +🇷🇴 flag: Romania +🇷🇸 flag: Serbia +🇷🇺 flag: Russia +🇷🇼 flag: Rwanda +🇸🇦 flag: Saudi Arabia +🇸🇧 flag: Solomon Islands +🇸🇨 flag: Seychelles +🇸🇩 flag: Sudan +🇸🇪 flag: Sweden +🇸🇬 flag: Singapore +🇸🇭 flag: St. Helena +🇸🇮 flag: Slovenia +🇸🇯 flag: Svalbard & Jan Mayen +🇸🇰 flag: Slovakia +🇸🇱 flag: Sierra Leone +🇸🇲 flag: San Marino +🇸🇳 flag: Senegal +🇸🇴 flag: Somalia +🇸🇷 flag: Suriname +🇸🇸 flag: South Sudan +🇸🇹 flag: São Tomé & Príncipe +🇸🇻 flag: El Salvador +🇸🇽 flag: Sint Maarten +🇸🇾 flag: Syria +🇸🇿 flag: Eswatini +🇹🇦 flag: Tristan da Cunha +🇹🇨 flag: Turks & Caicos Islands +🇹🇩 flag: Chad +🇹🇫 flag: French Southern Territories +🇹🇬 flag: Togo +🇹🇭 flag: Thailand +🇹🇯 flag: Tajikistan +🇹🇰 flag: Tokelau +🇹🇱 flag: Timor-Leste +🇹🇲 flag: Turkmenistan +🇹🇳 flag: Tunisia +🇹🇴 flag: Tonga +🇹🇷 flag: Turkey +🇹🇹 flag: Trinidad & Tobago +🇹🇻 flag: Tuvalu +🇹🇼 flag: Taiwan +🇹🇿 flag: Tanzania +🇺🇦 flag: Ukraine +🇺🇬 flag: Uganda +🇺🇲 flag: U.S. Outlying Islands +🇺🇳 flag: United Nations +🇺🇸 flag: United States +🇺🇾 flag: Uruguay +🇺🇿 flag: Uzbekistan +🇻🇦 flag: Vatican City +🇻🇨 flag: St. Vincent & Grenadines +🇻🇪 flag: Venezuela +🇻🇬 flag: British Virgin Islands +🇻🇮 flag: U.S. Virgin Islands +🇻🇳 flag: Vietnam +🇻🇺 flag: Vanuatu +🇼🇫 flag: Wallis & Futuna +🇼🇸 flag: Samoa +🇽🇰 flag: Kosovo +🇾🇪 flag: Yemen +🇾🇹 flag: Mayotte +🇿🇦 flag: South Africa +🇿🇲 flag: Zambia +🇿🇼 flag: Zimbabwe +🏴󠁧󠁢󠁥󠁮󠁧󠁿 flag: England +🏴󠁧󠁢󠁳󠁣󠁴󠁿 flag: Scotland +🏴󠁧󠁢󠁷󠁬󠁳󠁿 flag: Wales \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-active.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-active.svg new file mode 100755 index 0000000..289ad6c --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-active.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-hover.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-hover.svg new file mode 100755 index 0000000..8a1d351 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace-hover.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace.svg new file mode 100755 index 0000000..8dba5df --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/add-workspace.svg @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-left.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-left.svg new file mode 100755 index 0000000..dcf8298 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-left.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-right.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-right.svg new file mode 100755 index 0000000..ed66559 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/calendar-arrow-right.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-dark.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-dark.svg new file mode 100755 index 0000000..d1cc25f --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-dark.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-off.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-off.svg new file mode 100755 index 0000000..b00efa6 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox-off.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox.svg new file mode 100755 index 0000000..3e6bb2e --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/checkbox.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-active.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-active.svg new file mode 100755 index 0000000..06bc45b --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-active.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-hover.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-hover.svg new file mode 100755 index 0000000..65499ad --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close-hover.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close.svg new file mode 100755 index 0000000..b496e8f --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/close.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/corner-ripple.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/corner-ripple.svg new file mode 100755 index 0000000..da71e7e --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/corner-ripple.svg @@ -0,0 +1,46 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-dark.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-dark.svg new file mode 100755 index 0000000..e4f4671 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-dark.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-off.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-off.svg new file mode 100755 index 0000000..b00efa6 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton-off.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton.svg new file mode 100755 index 0000000..8d9052e --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/radiobutton.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-off.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-off.svg new file mode 100755 index 0000000..d09c478 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-off.svg @@ -0,0 +1,65 @@ + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on-dark.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on-dark.svg new file mode 100755 index 0000000..d4a0ceb --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on-dark.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on.svg new file mode 100755 index 0000000..8f02606 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/toggle-on.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/trash-icon.svg b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/trash-icon.svg new file mode 100755 index 0000000..d78a123 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/assets/trash-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/cinnamon.css b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/cinnamon.css new file mode 100755 index 0000000..8f431fe --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/cinnamon.css @@ -0,0 +1,2594 @@ +/* General Typography */ +.dialog .confirm-dialog-title, +.modal-dialog .confirm-dialog-title { + font-weight: 800; + font-size: 15ptpt; +} + +.workspace-switch-osd, .media-keys-osd { + font-weight: 700; + font-size: 13ptpt; +} + +.polkit-dialog-user-combo { + font-weight: 700; + font-size: 11ptpt; +} + +.prompt-dialog-error-label, .prompt-dialog-info-label, .prompt-dialog-null-label { + font-weight: 400; + font-size: 9ptpt; +} + +stage { + color: #eff1f5; +} + +.label-shadow { + color: rgba(0, 0, 0, 0); +} + +.sound-button, .dialog .dialog-button, +.modal-dialog .dialog-button { + min-height: 24px; + padding: 5px 32px; + transition-duration: 100ms; + border-radius: 12px; + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.04); +} + +.sound-button:focus, .dialog .dialog-button:focus, +.modal-dialog .dialog-button:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.sound-button:hover, .dialog .dialog-button:hover, +.modal-dialog .dialog-button:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + border-radius: 12px; + color: #89b4fa; +} + +.sound-button:hover:focus, .dialog .dialog-button:hover:focus, +.modal-dialog .dialog-button:hover:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.3); + border-radius: 12px; +} + +.sound-button:active, .dialog .dialog-button:active, +.modal-dialog .dialog-button:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.3); + border-radius: 12px; +} + +.sound-button:insensitive, .dialog .dialog-button:insensitive, +.modal-dialog .dialog-button:insensitive { + color: rgba(239, 241, 245, 0.5); + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; +} + +.polkit-dialog-user-combo, .dialog .dialog-button:destructive-action, +.modal-dialog .dialog-button:destructive-action, .dialog .dialog-button:default, +.modal-dialog .dialog-button:default, .notification-button, .notification-icon-button, .menu #notification .notification-button, +.menu #notification .notification-icon-button, .popup-menu #notification .notification-button, +.popup-menu #notification .notification-icon-button, #notification .notification-button, +#notification .notification-icon-button, .calendar-today-home-button, +.calendar-today-home-button-enabled { + border-radius: 12px; + color: rgba(239, 241, 245, 0.7); + background-color: transparent; +} + +.polkit-dialog-user-combo:hover, .dialog .dialog-button:hover:destructive-action, +.modal-dialog .dialog-button:hover:destructive-action, .dialog .dialog-button:hover:default, +.modal-dialog .dialog-button:hover:default, .notification-button:hover, .notification-icon-button:hover, #notification .notification-button:hover, +#notification .notification-icon-button:hover, .calendar-today-home-button:hover, +.calendar-today-home-button-enabled:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.polkit-dialog-user-combo:active, .dialog .dialog-button:active:destructive-action, +.modal-dialog .dialog-button:active:destructive-action, .dialog .dialog-button:active:default, +.modal-dialog .dialog-button:active:default, .notification-button:active, .notification-icon-button:active, #notification .notification-button:active, +#notification .notification-icon-button:active, .calendar-today-home-button:active, +.calendar-today-home-button-enabled:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.3); + border-radius: 12px; +} + +.polkit-dialog-user-combo:insensitive, .dialog .dialog-button:insensitive:destructive-action, +.modal-dialog .dialog-button:insensitive:destructive-action, .dialog .dialog-button:insensitive:default, +.modal-dialog .dialog-button:insensitive:default, .notification-button:insensitive, .notification-icon-button:insensitive, #notification .notification-button:insensitive, +#notification .notification-icon-button:insensitive, .calendar-today-home-button:insensitive, +.calendar-today-home-button-enabled:insensitive { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; + border-radius: 12px; +} + +.dialog-button-box .modal-dialog-button, +.modal-dialog-button-box .modal-dialog-button { + min-height: 24px; + padding: 6px 30px; + transition-duration: 100ms; + border-radius: 12px; + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.04); +} + +.dialog-button-box .modal-dialog-button:hover, +.modal-dialog-button-box .modal-dialog-button:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.dialog-button-box .modal-dialog-button:focus, +.modal-dialog-button-box .modal-dialog-button:focus { + color: #89b4fa; +} + +.dialog-button-box .modal-dialog-button:active, +.modal-dialog-button-box .modal-dialog-button:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.3); +} + +.dialog-button-box .modal-dialog-button:insensitive, +.modal-dialog-button-box .modal-dialog-button:insensitive { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +#menu-search-entry, .prompt-dialog-password-entry, .notification StEntry, .menu #notification StEntry, .popup-menu #notification StEntry, #notification StEntry { + padding: 3px 12px; + min-height: 24px; + caret-size: 1px; + selection-background-color: #89b4fa; + selected-color: rgba(30, 30, 46, 0.87); + transition-duration: 300ms; + border-radius: 12px; + color: #eff1f5; + border: 2px solid transparent; + background-color: rgba(239, 241, 245, 0.04); +} + +#menu-search-entry:focus, .prompt-dialog-password-entry:focus, .notification StEntry:focus, .menu #notification StEntry:focus, .popup-menu #notification StEntry:focus, #notification StEntry:focus, #menu-search-entry:hover, .prompt-dialog-password-entry:hover, .notification StEntry:hover, .menu #notification StEntry:hover, .popup-menu #notification StEntry:hover, #notification StEntry:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + border: 2px solid #89b4fa; +} + +#menu-search-entry:insensitive, .prompt-dialog-password-entry:insensitive, .notification StEntry:insensitive, .menu #notification StEntry:insensitive, .popup-menu #notification StEntry:insensitive, #notification StEntry:insensitive { + border: 2px solid transparent; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +#menu-search-entry StIcon.capslock-warning, .prompt-dialog-password-entry StIcon.capslock-warning, .notification StEntry StIcon.capslock-warning, .menu #notification StEntry StIcon.capslock-warning, .popup-menu #notification StEntry StIcon.capslock-warning, #notification StEntry StIcon.capslock-warning { + icon-size: 16px; + warning-color: #df8e1d; + padding: 0 6px; +} + +StScrollView.vfade { + -st-vfade-offset: 0px; +} + +StScrollView.hfade { + -st-hfade-offset: 0px; +} + +StScrollBar { + padding: 8px; +} + +StScrollView StScrollBar { + min-width: 5px; + min-height: 5px; +} + +StScrollBar StBin#trough { + background-color: rgba(49, 50, 68, 0.1); + border-radius: 9999px; +} + +StScrollBar StButton#vhandle, +StScrollBar StButton#hhandle { + border-radius: 9999px; + background-color: #72727e; + border: 0px solid; + margin: 0px; +} + +StScrollBar StButton#vhandle:hover, +StScrollBar StButton#hhandle:hover { + background-color: #5d5d6a; +} + +StScrollBar StButton#vhandle:active, +StScrollBar StButton#hhandle:active { + background-color: #89b4fa; +} + +.separator { + -gradient-height: 1px; + -gradient-start: rgba(0, 0, 0, 0); + -gradient-end: rgba(0, 0, 0, 0); + -margin-horizontal: 1.5em; + height: 1em; +} + +.popup-slider-menu-item, +.slider { + -slider-height: 4px; + -slider-background-color: rgba(239, 241, 245, 0.12); + -slider-border-color: transparent; + -slider-active-background-color: #89b4fa; + -slider-active-border-color: transparent; + -slider-border-width: 0; + -slider-handle-radius: 4px; + height: 18px; + min-width: 15em; + border: 0 solid transparent; + border-right-width: 1px; + border-left-width: 5px; + color: transparent; +} + +.check-box CinnamonGenericContainer { + spacing: 0.2em; + min-height: 30px; + padding-top: 2px; +} + +.check-box StLabel { + font-weight: normal; +} + +.check-box StBin { + width: 24px; + height: 24px; +} + +.check-box StBin, .check-box:focus StBin { + background-image: url("assets/checkbox-off.svg"); +} + +.check-box:checked StBin, .check-box:focus:checked StBin { + background-image: url("assets/checkbox-dark.svg"); +} + +.radiobutton CinnamonGenericContainer { + spacing: 0.2em; + min-height: 30px; + padding-top: 2px; +} + +.radiobutton StLabel { + padding-top: 4px; + font-size: 0.9em; + box-shadow: none; +} + +.radiobutton StBin { + width: 24px; + height: 24px; +} + +.radiobutton StBin, .radiobutton:focus StBin { + background-image: url("assets/radiobutton-off.svg"); +} + +.radiobutton:checked StBin, .radiobutton:focus:checked StBin { + background-image: url("assets/radiobutton-dark.svg"); +} + +.toggle-switch { + width: 46px; + height: 24px; + background-size: contain; +} + +.toggle-switch, .popup-menu-item:active .toggle-switch { + background-image: url("assets/toggle-off.svg"); +} + +.toggle-switch:checked, .popup-menu-item:active .toggle-switch:checked { + background-image: url("assets/toggle-on-dark.svg"); +} + +.cinnamon-link { + color: #8fcbe8; + text-decoration: underline; +} + +.cinnamon-link:hover { + color: #b9dff1; +} + +#Tooltip { + border-radius: 9999px; + padding: 6px 12px; + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; + margin: 6px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12); + font-size: 1em; + font-weight: normal; + text-align: center; +} + +.menu, +.popup-menu, +.popup-combo-menu { + padding: 0; + color: #eff1f5; + border-radius: 12px; + margin: 6px; + box-shadow: none; + /* @if $outline == 'true' { + border: 2px solid $primary; + } */ +} + +.menu-arrow, +.popup-menu-arrow { + icon-size: 16px; +} + +.menu .popup-sub-menu, +.popup-menu .popup-sub-menu, +.popup-combo-menu .popup-sub-menu { + border-radius: 12px; + background-gradient-direction: none; + box-shadow: none; + background-color: #3d404f; + color: rgba(239, 241, 245, 0.7); +} + +.menu .popup-sub-menu .popup-menu-item:active, +.popup-menu .popup-sub-menu .popup-menu-item:active, +.popup-combo-menu .popup-sub-menu .popup-menu-item:active { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.menu .popup-sub-menu StScrollBar, +.popup-menu .popup-sub-menu StScrollBar, +.popup-combo-menu .popup-sub-menu StScrollBar { + padding: 4px; +} + +.menu .popup-sub-menu StScrollBar StBin#trough, +.menu .popup-sub-menu StScrollBar StBin#vhandle, +.popup-menu .popup-sub-menu StScrollBar StBin#trough, +.popup-menu .popup-sub-menu StScrollBar StBin#vhandle, +.popup-combo-menu .popup-sub-menu StScrollBar StBin#trough, +.popup-combo-menu .popup-sub-menu StScrollBar StBin#vhandle { + border-width: 0; +} + +.menu .popup-menu-content, +.popup-menu .popup-menu-content, +.popup-combo-menu .popup-menu-content { + padding: 6px; + border-radius: 12px; + background-color: #292c3c; + box-shadow: 0 5px 12px rgba(0, 0, 0, 0.35); + border: 2px solid #89b4fa; + background-clip: border-box; +} + +.menu .popup-menu-item, +.popup-menu .popup-menu-item, +.popup-combo-menu .popup-menu-item { + padding: 6px 12px; + spacing: 12px; + border-radius: 12px; +} + +.menu .popup-menu-item:hover, .menu .popup-menu-item:active, +.popup-menu .popup-menu-item:hover, +.popup-menu .popup-menu-item:active, +.popup-combo-menu .popup-menu-item:hover, +.popup-combo-menu .popup-menu-item:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.menu .popup-menu-item:insensitive, +.popup-menu .popup-menu-item:insensitive, +.popup-combo-menu .popup-menu-item:insensitive { + color: rgba(239, 241, 245, 0.5); + background: none; +} + +.menu .popup-inactive-menu-item, +.popup-menu .popup-inactive-menu-item, +.popup-combo-menu .popup-inactive-menu-item { + color: rgba(239, 241, 245, 0.5); +} + +.menu .popup-inactive-menu-item:insensitive, +.popup-menu .popup-inactive-menu-item:insensitive, +.popup-combo-menu .popup-inactive-menu-item:insensitive { + color: rgba(239, 241, 245, 0.12); +} + +.menu .popup-menu-item:active .popup-inactive-menu-item, +.popup-menu .popup-menu-item:active .popup-inactive-menu-item, +.popup-combo-menu .popup-menu-item:active .popup-inactive-menu-item { + color: rgba(239, 241, 245, 0.5); +} + +.menu-icon, +.popup-menu-icon { + icon-size: 16px; +} + +.popup-menu-boxpointer { + -arrow-border-radius: 12px; + -arrow-background-color: rgba(0, 0, 0, 0); + -arrow-border-width: 0; + -arrow-border-color: rgba(0, 0, 0, 0); + -arrow-base: 0; + -arrow-rise: 0; +} + +.popup-combo-menu { + padding: 6px; + border: 2px solid #89b4fa; +} + +.popup-combobox-item { + spacing: 1em; +} + +.popup-separator-menu-item { + -gradient-height: 0; + -gradient-start: transparent; + -gradient-end: transparent; + -margin-horizontal: 1.5em; + height: 0; + margin: 0; + padding: 0; + border-color: rgba(239, 241, 245, 0.12); + border-bottom-width: 0; + border-bottom-style: solid; + background-color: transparent; +} + +.popup-alternating-menu-item:alternate { + font-weight: normal; +} + +.popup-device-menu-item { + spacing: 0.5em; +} + +.popup-subtitle-menu-item { + font-weight: normal; +} + +.nm-menu-item-icons { + spacing: 0.5em; +} + +#panel { + font-weight: bold; + height: 34px; + width: 40px; +} + +#panel:highlight { + border-image: none; + background-color: rgba(210, 15, 57, 0.5); +} + +#panelLeft { + spacing: 4px; +} + +#panelLeft:dnd { + background-gradient-direction: vertical; + background-gradient-start: rgba(210, 15, 57, 0.35); + background-gradient-end: rgba(210, 15, 57, 0.35); +} + +#panelLeft:ltr { + padding-right: 4px; +} + +#panelLeft:rtl { + padding-left: 4px; +} + +#panelLeft.vertical { + padding: 0; +} + +#panelLeft.vertical:ltr { + padding-right: 0px; +} + +#panelLeft.vertical:rtl { + padding-left: 0px; +} + +#panelRight:dnd { + background-gradient-direction: vertical; + background-gradient-start: rgba(30, 102, 245, 0.35); + background-gradient-end: rgba(30, 102, 245, 0.35); +} + +#panelRight:ltr { + padding-left: 6px; + spacing: 0px; +} + +#panelRight:rtl { + padding-right: 6px; + spacing: 0px; +} + +#panelRight.vertical { + padding: 0; +} + +#panelRight.vertical:ltr { + padding-right: 0px; +} + +#panelRight.vertical:rtl { + padding-left: 0px; +} + +#panelCenter { + spacing: 4px; +} + +#panelCenter:dnd { + background-gradient-direction: vertical; + background-gradient-start: rgba(64, 160, 43, 0.35); + background-gradient-end: rgba(64, 160, 43, 0.35); +} + +.panel-top, .panel-bottom, .panel-left, .panel-right { + color: rgba(239, 241, 245, 0.7); + font-size: 1em; + padding: 0px; + background-color: rgba(30, 30, 46, 0.75); + box-shadow: 0 0 5px rgba(0, 0, 0, 0.5), 0 0 16px rgba(0, 0, 0, 0.24); +} + +.panel-top .panel-button:hover, +.panel-top .panel-status-button:hover, .panel-bottom .panel-button:hover, +.panel-bottom .panel-status-button:hover, .panel-left .panel-button:hover, +.panel-left .panel-status-button:hover, .panel-right .panel-button:hover, +.panel-right .panel-status-button:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); +} + +.panel-top .panel-button:active, +.panel-top .panel-status-button:active, .panel-bottom .panel-button:active, +.panel-bottom .panel-status-button:active, .panel-left .panel-button:active, +.panel-left .panel-status-button:active, .panel-right .panel-button:active, +.panel-right .panel-status-button:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.panel-dummy { + background-color: rgba(210, 15, 57, 0.5); +} + +.panel-dummy:entered { + background-color: rgba(210, 15, 57, 0.6); +} + +.panel-status-button { + border-width: 0; + -natural-hpadding: 3px; + -minimum-hpadding: 3px; + font-weight: bold; + height: 22px; + color: rgba(239, 241, 245, 0.7); +} + +.panel-button { + -natural-hpadding: 6px; + -minimum-hpadding: 2px; + font-weight: bold; + transition-duration: 100ms; + color: rgba(239, 241, 245, 0.7); +} + +.system-status-icon { + icon-size: 16px; + padding: 0 1px; +} + +#overview { + spacing: 12px; +} + +.window-caption { + background-color: rgba(24, 24, 37, 0.9); + border: 1px solid rgba(24, 24, 37, 0.9); + color: #eff1f5; + spacing: 25px; + border-radius: 12px; + font-size: 9pt; + padding: 5px 8px; + -cinnamon-caption-spacing: 4px; +} + +.window-caption#selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + border: 1px solid #89b4fa; + spacing: 25px; +} + +.expo-workspaces-name-entry, +.expo-workspaces-name-entry#selected { + height: 15px; + border-radius: 12px; + font-size: 9pt; + padding: 5px 8px; + -cinnamon-caption-spacing: 4px; + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + border: 2px solid transparent; +} + +.expo-workspaces-name-entry:focus, +.expo-workspaces-name-entry#selected:focus { + border: 1px solid #89b4fa; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + font-style: italic; + transition-duration: 300; + selection-background-color: rgba(30, 30, 46, 0.87); + selected-color: #89b4fa; +} + +.expo-workspace-thumbnail-frame { + border: 4px solid rgba(255, 255, 255, 0); + background-color: rgba(255, 255, 255, 0); + border-radius: 0; +} + +.expo-workspace-thumbnail-frame#active { + border: 4px solid #89b4fa; + background-color: black; + border-radius: 0; +} + +.expo-background { + background-color: #181825; +} + +.workspace-thumbnails { + spacing: 26px; +} + +.workspace-thumbnails-background, .workspace-thumbnails-background:rtl { + padding: 8px; +} + +.workspace-add-button { + background-image: url("assets/add-workspace.svg"); + height: 200px; + width: 35px; + transition-duration: 100; +} + +.workspace-add-button:hover { + background-image: url("assets/add-workspace-hover.svg"); + transition-duration: 100; +} + +.workspace-add-button:active { + background-image: url("assets/add-workspace-active.svg"); + transition-duration: 100; +} + +.workspace-overview-background-shade { + background-color: rgba(0, 0, 0, 0.5); +} + +.workspace-close-button, +.window-close { + background-image: url("assets/close.svg"); + background-size: 26px; + height: 26px; + width: 26px; + -cinnamon-close-overlap: 13px; +} + +.workspace-close-button:hover, +.window-close:hover { + background-image: url("assets/close-hover.svg"); + background-size: 26px; + height: 26px; + width: 26px; +} + +.workspace-close-button:active, +.window-close:active { + background-image: url("assets/close-active.svg"); + background-size: 26px; + height: 26px; + width: 26px; +} + +.workspace-thumbnail-indicator { + outline: 2px solid red; + border: 1px solid green; +} + +.window-close:rtl { + -st-background-image-shadow: 2px 2px 6px rgba(0, 0, 0, 0.5); +} + +.window-close-area { + background-image: url("assets/trash-icon.svg"); + height: 120px; + width: 400px; +} + +.about-content { + width: 550px; + height: 250px; + spacing: 8px; + padding-bottom: 10px; +} + +.about-title { + font-size: 2em; + font-weight: bold; +} + +.about-uuid { + font-size: 10px; + color: #888; +} + +.about-icon { + padding-right: 20px; + padding-bottom: 14px; +} + +.about-scrollBox { + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 12px; + background-color: #313244; + padding: 4px; + padding-right: 0; + border-radius: 0; +} + +.about-scrollBox-innerBox { + padding: 1.2em; + spacing: 1.2em; +} + +.about-description { + padding-top: 4px; + padding-bottom: 16px; +} + +.about-version { + padding-left: 7px; + font-size: 10px; + color: #888; +} + +#LookingGlassDialog { + background-color: #313244; + spacing: 6px; + padding: 6px; + margin: 32px; + border-radius: 12px; + color: #eff1f5; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); + border: none; +} + +.calendar-main-box { + margin: 0 0.8em; +} + +.calendar { + spacing-rows: 0px; + spacing-columns: 0px; +} + +.calendar-today-home-button, +.calendar-today-home-button-enabled { + margin: 6px 0; + padding: 6px; +} + +.calendar-today-day-label { + font-size: 1.75em; + color: rgba(239, 241, 245, 0.7); + font-weight: bold; + text-align: center; + padding-bottom: 0.1em; +} + +.calendar-today-date-label { + font-size: 1.1em; + color: rgba(239, 241, 245, 0.5); + font-weight: bold; + text-align: center; +} + +.calendar-month-label { + color: #eff1f5; + font-weight: bold; + padding-bottom: 8px; + padding-top: 8px; +} + +.calendar-change-month-back, +.calendar-change-month-forward { + width: 2.4em; + height: 2.4em; + margin: 2px 0; + padding: 0; + border-radius: 9999px; +} + +.calendar-change-month-back:focus, .calendar-change-month-back:hover, +.calendar-change-month-forward:focus, +.calendar-change-month-forward:hover { + background-color: rgba(239, 241, 245, 0.1); +} + +.calendar-change-month-back:active, +.calendar-change-month-forward:active { + background-color: rgba(239, 241, 245, 0.25); +} + +.calendar-change-month-back { + background-image: url("assets/calendar-arrow-left.svg"); +} + +.calendar-change-month-back:rtl { + background-image: url("assets/calendar-arrow-right.svg"); +} + +.calendar-change-month-forward { + background-image: url("assets/calendar-arrow-right.svg"); +} + +.calendar-change-month-forward:rtl { + background-image: url("assets/calendar-arrow-left.svg"); +} + +.datemenu-date-label { + padding: 0.4em 1.75em; + font-weight: normal; + text-align: center; + font-size: 14px; + color: #eff1f5; + border-radius: 12px; +} + +.calendar-day-base { + text-align: center; + width: 2.4em; + height: 2.4em; + padding: 0; + margin: 2px; + border-radius: 9999px; +} + +.calendar-day-base:hover { + background-color: rgba(239, 241, 245, 0.04); +} + +.calendar-day-base:active { + background-color: rgba(239, 241, 245, 0.12); +} + +.calendar-day-heading { + color: rgba(239, 241, 245, 0.7); + margin-top: 1em; +} + +.calendar-day { + border-width: 0; + color: rgba(239, 241, 245, 0.7); +} + +.calendar-day-top { + border-top-width: 0; +} + +.calendar-day-left { + border-left-width: 0; +} + +.calendar-nonwork-day { + color: #eff1f5; + background-color: transparent; + font-weight: bold; +} + +.calendar-today, +.calendar-today:active, +.calendar-today:focus, +.calendar-today:hover { + font-weight: bold; + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; + border-width: 0; +} + +.calendar-other-month-day { + color: rgba(239, 241, 245, 0.7); + opacity: 1; +} + +.calendar-week-number { + width: 2.4em; + height: 2.4em; + margin: 0; + color: rgba(239, 241, 245, 0.3); + font-weight: bold; + background-color: transparent; + border-radius: 9999px; +} + +.calendar-week-number StLabel { + padding: 0; + margin-top: 3px; +} + +.calendar-events-main-box { + height: 300px; + margin: 8px 0.8em 0 0; + padding: 8px; + min-width: 350px; + border: none; + border-radius: 12px; + background-gradient-direction: vertical; + background-gradient-start: rgba(239, 241, 245, 0.04); + background-gradient-end: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.7); +} + +.calendar-events-no-events-button { + margin: 6px 0; + padding: 6px; + border-radius: 12px; +} + +.calendar-events-no-events-button:hover { + background-gradient-direction: vertical; + background-gradient-start: rgba(239, 241, 245, 0.04); + background-gradient-end: rgba(239, 241, 245, 0.04); + box-shadow: none; +} + +.calendar-events-no-events-icon { + color: rgba(239, 241, 245, 0.5); +} + +.calendar-events-no-events-label { + font-size: 1.1em; + color: rgba(239, 241, 245, 0.5); + font-weight: bold; + text-align: center; + margin-top: 9px; +} + +.calendar-events-date-label { + padding: 3px 0 12px 3px; + font-size: 1.1em; + color: rgba(239, 241, 245, 0.7); + font-weight: bold; + text-align: center; +} + +.calendar-events-event-container { + padding: 2px; +} + +.calendar-events-main-box .separator { + -margin-horizontal: 1em; + -gradient-height: 1px; + -gradient-start: rgba(239, 241, 245, 0.12); + -gradient-end: rgba(239, 241, 245, 0.12); +} + +.calendar-event-button { + margin: 6px 0 6px 0; + border-radius: 12px; +} + +.calendar-event-button:hover { + background-gradient-direction: vertical; + background-gradient-start: rgba(239, 241, 245, 0.04); + background-gradient-end: rgba(239, 241, 245, 0.04); + box-shadow: none; +} + +.calendar-event-color-strip { + width: 4px; + border-radius: 4px 0 0 4px; +} + +.calendar-event-row-content { + margin: 6px; +} + +.calendar-event-time-past { + color: rgba(239, 241, 245, 0.32); + font-weight: bold; + text-align: left; + margin-bottom: 0.6em; +} + +.calendar-event-time-present { + font-weight: bold; + text-align: left; + margin-bottom: 0.6em; +} + +.calendar-event-time-present:all-day { + color: rgba(64, 160, 43, 0.6); +} + +.calendar-event-time-future { + text-align: left; + margin-bottom: 0.6em; +} + +.calendar-event-countdown { + color: rgba(239, 241, 245, 0.5); + font-weight: bold; + text-align: right; + margin-bottom: 0.6em; +} + +.calendar-event-countdown:soon { + color: #eff1f5; +} + +.calendar-event-countdown:imminent { + color: rgba(223, 142, 29, 0.6); +} + +.calendar-event-countdown:current { + color: rgba(64, 160, 43, 0.6); +} + +.calendar-event-summary { + color: rgba(239, 241, 245, 0.5); + text-align: left; + width: 200px; +} + +#notification { + border-radius: 12px; + padding: 12px; + spacing-rows: 9px; + spacing-columns: 9px; + margin-from-right-edge-of-screen: 18px; + width: 28em; + color: #eff1f5; + background-color: rgba(49, 50, 68, 0.8); + box-shadow: 0 5px 12px rgba(0, 0, 0, 0.35); + margin: 7px 12px 17px 12px; +} + +#notification .notification-button, +#notification .notification-icon-button { + padding: 6px; +} + +.menu #notification, .popup-menu #notification { + border: none; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.05); + box-shadow: none; + margin: 0; +} + +.menu #notification:hover, .popup-menu #notification:hover { + background-color: rgba(239, 241, 245, 0.1); + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15); +} + +.menu #notification, .menu #notification.multi-line-notification, .popup-menu #notification, .popup-menu #notification.multi-line-notification { + color: #eff1f5; +} + +.menu #notification .notification-button, +.menu #notification .notification-icon-button, .popup-menu #notification .notification-button, +.popup-menu #notification .notification-icon-button { + padding: 6px; +} + +#notification.multi-line-notification { + padding-bottom: 12px; + color: #eff1f5; +} + +#notification-scrollview { + max-height: 10em; +} + +#notification-scrollview > .top-shadow, +#notification-scrollview > .bottom-shadow { + height: 1em; +} + +#notification-scrollview:ltr > StScrollBar { + padding-left: 6px; +} + +#notification-scrollview:rtl > StScrollBar { + padding-right: 6px; +} + +#notification-body { + spacing: 6px; +} + +#notification-actions { + spacing: 9px; +} + +.notification-with-image { + min-height: 159px; + color: #eff1f5; +} + +.notification-button, .notification-icon-button { + padding: 6px; +} + +.notification-icon-button > StIcon { + icon-size: 36px; +} + +#altTabPopup { + padding: 8px; + spacing: 16px; +} + +.switcher-list { + color: #eff1f5; + background-color: #292c3c; + border: none; + border-radius: 12px; + padding: 20px; +} + +.switcher-list > StBoxLayout { + padding: 4px; +} + +.switcher-list-item-container { + spacing: 8px; +} + +.switcher-list .item-box { + padding: 8px; + border-radius: 12px; +} + +.switcher-list .item-box:outlined { + padding: 8px; + border: 1px solid #89b4fa; +} + +.switcher-list .item-box:selected { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; + border: 0px solid #89b4fa; +} + +.switcher-list .thumbnail { + width: 256px; +} + +.switcher-list .thumbnail-box { + padding: 2px; + spacing: 4px; +} + +.switcher-list .separator { + width: 1px; + background: rgba(255, 255, 255, 0.2); +} + +.switcher-arrow { + border-color: rgba(0, 0, 0, 0); + color: #eff1f5; +} + +.switcher-arrow:highlighted { + border-color: rgba(0, 0, 0, 0); + color: rgba(239, 241, 245, 0.7); +} + +.thumbnail-scroll-gradient-left { + background-color: rgba(0, 0, 0, 0); + border-radius: 24px; + border-radius-topright: 0px; + border-radius-bottomright: 0px; + width: 60px; +} + +.thumbnail-scroll-gradient-right { + background-color: rgba(0, 0, 0, 0); + border-radius: 24px; + border-radius-topleft: 0px; + border-radius-bottomleft: 0px; + width: 60px; +} + +.ripple-box { + width: 104px; + height: 104px; + background-image: url("assets/corner-ripple.svg"); + background-size: contain; +} + +.lightbox { + background-color: rgba(0, 0, 0, 0.4); +} + +.flashspot { + background-color: #eff1f5; +} + +.dialog, +.modal-dialog { + color: #eff1f5; + background-color: rgba(30, 30, 46, 0.95); + padding: 6px; + border-radius: 12px; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.75), 0 5px 18px rgba(0, 0, 0, 0.55); + /* border: 1px solid $divider; */ + border: 2px solid #89b4fa; +} + +.dialog > StBoxLayout:first-child, +.modal-dialog > StBoxLayout:first-child { + padding: 20px 10px 10px 10px; +} + +.dialog-button-box, +.modal-dialog-button-box { + spacing: 0; + margin: 0; + padding: 14px 10px; + background-color: transparent; + border: none; +} + +.dialog-button-box .modal-dialog-button, +.modal-dialog-button-box .modal-dialog-button { + padding-top: 0; + padding-bottom: 0; + height: 30px; +} + +.dialog .dialog-content-box, +.modal-dialog .dialog-content-box { + margin-top: 6px; + margin-bottom: 6px; + spacing: 6px; + max-width: 18em; +} + +.dialog .dialog-button:default:hover, +.modal-dialog .dialog-button:default:hover { + background-color: #ef1b49 !important; + color: #eff1f5 !important; +} + +.dialog .dialog-button:destructive-action, +.modal-dialog .dialog-button:destructive-action { + background-color: #d20f39; + color: #eff1f5; +} + +.dialog .confirm-dialog-title, +.modal-dialog .confirm-dialog-title { + text-align: center; +} + +.dialog .end-session-dialog, +.modal-dialog .end-session-dialog { + min-width: 40em; +} + +.dialog .end-session-dialog .dialog-content-box, +.modal-dialog .end-session-dialog .dialog-content-box { + spacing: 0; +} + +.dialog .end-session-dialog .dialog-list, +.modal-dialog .end-session-dialog .dialog-list { + spacing: 0; +} + +.dialog .end-session-dialog .dialog-list .dialog-list-title, +.modal-dialog .end-session-dialog .dialog-list .dialog-list-title { + color: #df8e1d; + background-color: tranparentize(#df8e1d, 0.9); + padding: 9px; + border-radius: 12px; + margin: 6px 0; +} + +.run-dialog { + padding: 6px 12px; + background-color: rgba(24, 24, 37, 0.9); + border-radius: 12px; + color: #eff1f5; +} + +.run-dialog > * { + padding: 0; +} + +.run-dialog-label { + font-size: 0; + font-weight: bold; + color: #eff1f5; + padding-bottom: 0; +} + +.run-dialog-error-label { + color: #d20f39; +} + +.run-dialog-error-box { + padding-top: 15px; + spacing: 5px; +} + +.run-dialog-completion-box { + padding-left: 15px; + font-size: 10px; +} + +.run-dialog-entry { + width: 21em; + padding: 3px 12px; + border-radius: 12px; + caret-color: #eff1f5; + selected-color: rgba(30, 30, 46, 0.87); + selection-background-color: #89b4fa; + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + border: 2px solid transparent; +} + +.run-dialog-entry:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + border: 2px solid #89b4fa; +} + +.run-dialog .modal-dialog-button-box { + border: none; + box-shadow: none; + background: none; + background-gradient-direction: none; +} + +.prompt-dialog { + width: 26em; +} + +.prompt-dialog .dialog-content-box { + spacing: 24px; + margin-bottom: 18px; +} + +.prompt-dialog-password-entry { + width: 20em; +} + +.prompt-dialog-password-layout { + spacing: 12px; +} + +.prompt-dialog-error-label, .prompt-dialog-info-label, .prompt-dialog-null-label { + text-align: center; +} + +.prompt-dialog-error-label { + color: #d20f39; +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 2px; +} + +.polkit-dialog-user-combo { + border-radius: 9px; + padding: 6px 36px; +} + +.polkit-dialog-user-combo:insensitive { + color: #eff1f5; +} + +/* CinnamonMountOperation Dialogs */ +.cinnamon-mount-operation-icon { + icon-size: 48px; +} + +.mount-password-reask { + color: #df8e1d; +} + +.show-processes-dialog, +.mount-question-dialog { + spacing: 24px; +} + +.show-processes-dialog-subject, +.mount-question-dialog-subject { + padding-top: 10px; + padding-left: 17px; + padding-bottom: 6px; +} + +.show-processes-dialog-subject:rtl, +.mount-question-dialog-subject:rtl { + padding-left: 0px; + padding-right: 17px; +} + +.show-processes-dialog-description, +.mount-question-dialog-description { + padding-left: 17px; + width: 28em; +} + +.show-processes-dialog-description:rtl, +.mount-question-dialog-description:rtl { + padding-right: 17px; +} + +.show-processes-dialog-app-list { + max-height: 200px; + padding-top: 24px; + padding-left: 49px; + padding-right: 32px; +} + +.show-processes-dialog-app-list:rtl { + padding-right: 49px; + padding-left: 32px; +} + +.show-processes-dialog-app-list-item { + color: #ccc; +} + +.show-processes-dialog-app-list-item:hover { + color: #eff1f5; +} + +.show-processes-dialog-app-list-item:ltr { + padding-right: 1em; +} + +.show-processes-dialog-app-list-item:rtl { + padding-left: 1em; +} + +.show-processes-dialog-app-list-item-icon:ltr { + padding-right: 17px; +} + +.show-processes-dialog-app-list-item-icon:rtl { + padding-left: 17px; +} + +.show-processes-dialog-app-list-item-name { + font-size: 1.1em; +} + +.magnifier-zoom-region { + border: 2px solid maroon; +} + +.magnifier-zoom-region .full-screen { + border-width: 0px; +} + +#keyboard { + background-color: rgba(24, 24, 37, 0.9); + border-width: 0; + border-top-width: 1px; + border-color: rgba(0, 0, 0, 0.4); +} + +.keyboard-layout { + spacing: 10px; + padding: 10px; +} + +.keyboard-row { + spacing: 15px; +} + +.keyboard-key { + min-height: 2em; + min-width: 2em; + font-size: 14pt; + font-weight: bold; + border-radius: 12px; + box-shadow: none; + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.04); +} + +.keyboard-key:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.keyboard-key:active, .keyboard-key:checked { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.3); +} + +.keyboard-key:grayed { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +.keyboard-subkeys { + color: #eff1f5; + padding: 5px; + -arrow-border-radius: 12px; + -arrow-background-color: rgba(24, 24, 37, 0.9); + -arrow-border-width: 1px; + -arrow-border-color: rgba(0, 0, 0, 0.4); + -arrow-base: 20px; + -arrow-rise: 10px; + -boxpointer-gap: 5px; +} + +.menu-favorites-box { + margin: auto; + margin-bottom: 6px; + padding: 6px; + transition-duration: 300; + background-color: rgba(239, 241, 245, 0.05); + border: none; + border-radius: 12px; +} + +.menu-favorites-button { + padding: 9px; + border: none; + border-radius: 6px; +} + +.menu-favorites-button:hover { + background-color: rgba(239, 241, 245, 0.1); +} + +.menu-places-box { + margin: auto; + padding: 9px; + border: 1px solid rgba(0, 0, 0, 0); +} + +.menu-places-button { + padding: 9px; +} + +.menu-categories-box { + padding: 9px 30px; +} + +.menu-applications-inner-box, .menu-applications-outer-box { + padding: 9px 9px 0 9px; +} + +.menu-application-button { + padding: 6px; + border-radius: 12px; + border: none; +} + +.menu-application-button:highlighted { + font-weight: bold; +} + +.menu-application-button-selected { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + padding: 6px; + border-radius: 12px; + border: none; +} + +.menu-application-button-selected:highlighted { + font-weight: bold; +} + +.menu-application-button-label:ltr { + padding-left: 6px; +} + +.menu-application-button-label:rtl { + padding-right: 6px; +} + +.menu StScrollView.menu-application-button { + padding: 3px 0; + border-radius: 12px; + background-color: #3d404f; + color: #eff1f5; +} + +.menu StScrollView.menu-application-button .popup-menu-item { + padding: 0; + spacing: 0; + margin: 0 3px; + border-radius: 12px; + color: #eff1f5; +} + +.menu StScrollView.menu-application-button .popup-menu-item:ltr { + padding-left: 6px; +} + +.menu StScrollView.menu-application-button .popup-menu-item:rtl { + padding-right: 6px; +} + +.menu StScrollView.menu-application-button .popup-menu-item:active { + border-image: none; + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.menu StScrollView.menu-application-button .popup-menu-item StIcon { + min-width: 22px; +} + +.menu StScrollView.menu-application-button .popup-menu-item StLabel:ltr { + padding: 6px 0 6px 6px; +} + +.menu StScrollView.menu-application-button .popup-menu-item StLabel:rtl { + padding: 6px 6px 6px 0; +} + +.menu-category-button { + padding: 6px; + border-radius: 12px; +} + +.menu-category-button-selected { + padding: 6px; +} + +.menu-category-button-hover, .menu-category-button-selected { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.menu-category-button-greyed { + padding: 6px; + color: rgba(239, 241, 245, 0.5); +} + +.menu-category-button-label:ltr { + padding-left: 6px; +} + +.menu-category-button-label:rtl { + padding-right: 6px; +} + +.menu-selected-app-box { + padding-right: 30px; + padding-left: 28px; + text-align: right; + height: 30px; +} + +.menu-selected-app-box:rtl { + padding-top: 10px; + height: 30px; +} + +.menu-selected-app-title { + font-weight: bold; +} + +.menu-selected-app-description { + max-width: 150px; + margin-bottom: 6px; +} + +.menu-search-box:ltr { + padding-left: 30px; +} + +.menu-search-box-rtl { + padding-right: 30px; +} + +#menu-search-entry { + width: 250px; + height: 15px; + font-weight: normal; + caret-color: #eff1f5; + border-radius: 12px; +} + +.menu-search-entry-icon { + icon-size: 1em; + color: #eff1f5; +} + +.media-keys-osd { + color: #eff1f5; + background-color: rgba(30, 30, 46, 0.99); + border: 1px solid rgba(239, 241, 245, 0.11); + border-radius: 12px; + text-align: center; + padding: 24px; +} + +.media-keys-osd { + margin-bottom: 1em; + border-radius: 9999px; + font-weight: bold; + spacing: 12px; + padding: 12px 24px; +} + +.media-keys-osd > * { + spacing: 12px; +} + +.media-keys-osd StIcon { + icon-size: 32px; +} + +.media-keys-osd StLabel:ltr { + margin-right: 6px; +} + +.media-keys-osd StLabel:rtl { + margin-left: 6px; +} + +.media-keys-osd .level { + min-width: 160px; + -barlevel-height: 6px; + -barlevel-background-color: #313244; + -barlevel-active-background-color: #eff1f5; + -barlevel-amplify-color: #df8e1d; + -barlevel-amplify-separator-width: 3px; +} + +.media-keys-osd .level:ltr { + margin-right: 6px; +} + +.media-keys-osd .level:rtl { + margin-left: 6px; +} + +.media-keys-osd .level-bar { + border-radius: 12px; + background-color: #eff1f5; +} + +.info-osd { + text-align: center; + font-weight: bold; + spacing: 1em; + padding: 16px; + color: rgba(239, 241, 245, 0.7); + background-color: rgba(30, 30, 46, 0.75); +} + +.osd-window { + text-align: center; + font-weight: bold; + spacing: 1em; + padding: 20px; + min-width: 64px; + min-height: 64px; + color: rgba(239, 241, 245, 0.7); + border-radius: 0; + background-color: rgba(30, 30, 46, 0.75); + border: none; +} + +.osd-window .osd-monitor-label { + font-size: 3em; +} + +.osd-window .level { + padding: 0; + height: 4px; + background-color: rgba(0, 0, 0, 0.35); + border-radius: 12px; + color: #89b4fa; +} + +.osd-window .level-bar { + border-radius: 12px; + background-color: #89b4fa; +} + +.workspace-switch-osd { + color: #89b4fa; + background-color: rgba(30, 30, 46, 0.99); + /* border: 1px solid transparentize($divider, 0.01); */ + border: 2px solid #89b4fa; + border-radius: 9px; + text-align: center; + padding: 24px; + min-width: 140px; + margin-bottom: 1em; + border-radius: 9999px; + font-weight: bold; + padding: 12px 36px 0 36px; +} + +.workspace-switch-osd-indicator-box { + spacing: 12px; +} + +.workspace-switch-osd-indicator { + background-color: rgba(239, 241, 245, 0.5); + padding: 2.6666666667px; + margin: 13.3333333333px; + border-radius: 32px; +} + +.workspace-switch-osd-indicator:active { + background-color: #89b4fa; + padding: 5.3333333333px; + margin: 10.6666666667px; +} + +.window-list-box { + spacing: 2px; +} + +.panel-bottom .window-list-box:ltr, .panel-top .window-list-box:ltr { + padding: 0 0 0 8px; +} + +.panel-bottom .window-list-box:rtl, .panel-top .window-list-box:rtl { + padding: 0 8px 0 0; +} + +.window-list-box.vertical { + padding: 6px 0 0 0; +} + +.window-list-box.vertical #appMenuIcon { + padding-top: 2px; +} + +.window-list-box:highlight { + background-color: rgba(210, 15, 57, 0.5); +} + +.window-list-item-label { + font-weight: normal; + width: 15em; + min-width: 5px; +} + +.window-list-item-box { + font-weight: normal; + background-image: none; + transition-duration: 100ms; + color: rgba(239, 241, 245, 0.9); + border-radius: 0; +} + +.panel-bottom .window-list-item-box StLabel { + padding-left: 6px; +} + +.panel-top .window-list-item-box StLabel { + padding-left: 6px; +} + +.panel-left .window-list-item-box StLabel { + padding-top: 6px; +} + +.panel-right .window-list-item-box StLabel { + padding-top: 6px; +} + +.panel-top .window-list-item-box { + border-top: 2px solid transparent; +} + +.panel-top .window-list-item-box StIcon, +.panel-top .window-list-item-box StBin, +.panel-top .window-list-item-box #appMenuIcon { + padding: 2px; + padding-top: 0; +} + +.panel-bottom .window-list-item-box { + border-bottom: 2px solid transparent; +} + +.panel-bottom .window-list-item-box StIcon, +.panel-bottom .window-list-item-box StBin, +.panel-bottom .window-list-item-box #appMenuIcon { + padding: 2px; + padding-bottom: 0; +} + +.panel-left .window-list-item-box { + border-left: 2px solid transparent; +} + +.panel-left .window-list-item-box StIcon, +.panel-left .window-list-item-box StBin, +.panel-left .window-list-item-box #appMenuIcon { + padding: 2px; + padding-left: 0; +} + +.panel-right .window-list-item-box { + border-right: 2px solid transparent; +} + +.panel-right .window-list-item-box StIcon, +.panel-right .window-list-item-box StBin, +.panel-right .window-list-item-box #appMenuIcon { + padding: 2px; + padding-right: 0; +} + +.window-list-item-box:hover { + color: rgba(239, 241, 245, 0.7); + background-gradient-direction: none; + background-color: rgba(239, 241, 245, 0.15); +} + +.window-list-item-box:active, .window-list-item-box:checked, .window-list-item-box:running { + color: rgba(239, 241, 245, 0.7); + background-gradient-direction: none; + background-color: rgba(239, 241, 245, 0.25); + border-color: rgba(239, 241, 245, 0.3); +} + +.window-list-item-box:active:hover, .window-list-item-box:checked:hover, .window-list-item-box:running:hover { + background-color: rgba(239, 241, 245, 0.3); +} + +.window-list-item-box:focus { + color: rgba(239, 241, 245, 0.7); + background-gradient-direction: none; + background-image: radial-gradient(5px 5px 45deg, circle cover, rgba(239, 241, 245, 0.7) 0%, rgba(239, 241, 245, 0.7) 100%); + border-color: #89b4fa; + background-color: rgba(239, 241, 245, 0.2); +} + +.window-list-item-box:focus:hover { + background-color: rgba(239, 241, 245, 0.3); +} + +.panel-top .window-list-item-box:focus { + background-position: top center; +} + +.panel-bottom .window-list-item-box:focus { + background-position: bottom center; +} + +.panel-left .window-list-item-box:focus { + background-position: left center; +} + +.panel-right .window-list-item-box:focus { + background-position: right center; +} + +.window-list-item-box.right, .window-list-item-box.left { + padding-left: 0px; + padding-right: 0px; +} + +.window-list-item-box .progress { + background-gradient-direction: vertical; + background-gradient-start: #40a02b; + background-gradient-end: #40a02b; + border-radius: 12px; + box-shadow: none; +} + +.window-list-item-demands-attention { + background-gradient-start: #df8e1d; + background-gradient-end: #df8e1d; +} + +.window-list-preview { + padding: 6px; + spacing: 6px; + border: none; + background-color: #313244; + border-radius: 12px; + color: #eff1f5; + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.35), 0 3px 12px rgba(0, 0, 0, 0.16); +} + +.grouped-window-list-thumbnail-label { + padding-left: 4px; +} + +.grouped-window-list-thumbnail-alert { + background-color: rgba(210, 15, 57, 0.5); +} + +.grouped-window-list-thumbnail-menu { + padding: 6px; + margin: 6px; + background-color: #292c3c; + border-radius: 12px; + background-clip: border-box; + box-shadow: 0 5px 12px rgba(0, 0, 0, 0.35); + border: 2px solid #89b4fa; +} + +.grouped-window-list-thumbnail-menu .item-box { + padding: 6px; + border-radius: 12px; + spacing: 6px; + margin: 1px; +} + +.grouped-window-list-thumbnail-menu .item-box:outlined { + background-color: rgba(239, 241, 245, 0.1); +} + +.grouped-window-list-thumbnail-menu .item-box:hover { + background-color: rgba(239, 241, 245, 0.15); +} + +.grouped-window-list-thumbnail-menu .thumbnail { + width: 256px; +} + +.grouped-window-list-thumbnail-menu .separator { + width: 1px; + background-color: rgba(239, 241, 245, 0.12); +} + +.grouped-window-list-number-label { + z-index: 120; + text-shadow: none; + color: rgba(30, 30, 46, 0.87); + padding: 0; +} + +.grouped-window-list-button-label { + padding-left: 2px; +} + +.grouped-window-list-badge { + border-radius: 256px; + background-color: #89b4fa; +} + +.grouped-window-list-item-box { + font-weight: normal; + transition-duration: 100ms; + border: none; + margin: 0; + color: rgba(239, 241, 245, 0.6); + border-radius: 0; + spacing: 6px; + border-bottom: 2px solid transparent; +} + +.grouped-window-list-item-box.top, .grouped-window-list-item-box.bottom { + padding: 0 2px; +} + +.grouped-window-list-item-box:hover { + color: rgba(239, 241, 245, 0.7); + background-gradient-direction: none; + background-color: rgba(239, 241, 245, 0.15); +} + +.grouped-window-list-item-box:active { + color: rgba(239, 241, 245, 0.7); + background-gradient-direction: none; + background-color: transparent; + border-color: rgba(239, 241, 245, 0.3); +} + +.grouped-window-list-item-box:active:hover { + background-color: rgba(239, 241, 245, 0.15); +} + +.grouped-window-list-item-box:focus { + color: rgba(239, 241, 245, 0.7); + background-gradient-direction: none; + background-color: rgba(239, 241, 245, 0.2); + border-color: #89b4fa; +} + +.grouped-window-list-item-box:focus:hover { + background-color: rgba(239, 241, 245, 0.3); +} + +.grouped-window-list-item-box .progress { + background-gradient-direction: vertical; + background-gradient-start: #40a02b; + background-gradient-end: #40a02b; + border-radius: 12px; + box-shadow: none; +} + +.grouped-window-list-item-demands-attention { + background-gradient-start: #df8e1d; + background-gradient-end: #df8e1d; +} + +.sound-button { + width: 22px; + height: 13px; + padding: 8px; +} + +.sound-button-container { + padding-right: 3px; + padding-left: 3px; +} + +.sound-button StIcon { + icon-size: 1.4em; +} + +.sound-track-infos { + padding: 5px; +} + +.sound-track-info { + padding-top: 2px; + padding-bottom: 2px; +} + +.sound-track-info StIcon { + icon-size: 16px; +} + +.sound-track-info StLabel { + padding-left: 5px; + padding-right: 5px; +} + +.sound-track-box { + padding-left: 15px; + padding-right: 15px; + max-width: 220px; +} + +.sound-seek-box { + padding-left: 15px; +} + +.sound-seek-box StLabel { + padding-top: 2px; +} + +.sound-seek-box StIcon { + icon-size: 16px; +} + +.sound-seek-slider { + width: 140px; +} + +.sound-volume-menu-item { + padding: 0.4em 1.75em; +} + +.sound-volume-menu-item StIcon { + icon-size: 1.14em; + padding-left: 8px; + padding-right: 8px; +} + +.sound-playback-control { + padding: 5px 10px 10px 10px; +} + +.sound-player { + padding: 0 0; + margin-top: 6px; + border-radius: 12px; + background-color: #3d404f; + color: #eff1f5; +} + +.sound-player > StBoxLayout:first-child { + padding: 5px 10px 10px 10px; + spacing: 0.5em; +} + +.sound-player > StBoxLayout:first-child StButton:small { + width: 24px; + height: 24px; + border-radius: 9999px; +} + +.sound-player > StBoxLayout:first-child StButton:small:hover { + background-color: rgba(239, 241, 245, 0.12); +} + +.sound-player > StBoxLayout:first-child StButton:small:active { + background-color: rgba(239, 241, 245, 0.3); +} + +.sound-player > StBoxLayout:first-child StButton:small StIcon { + icon-size: 16px; +} + +.sound-player-generic-coverart { + background: rgba(0, 0, 0, 0.2); +} + +.sound-player-overlay { + width: 290px; + height: 80px; + padding: 12px 18px; + spacing: 6px; + background-color: rgba(0, 0, 0, 0.45); + border: none; + border-radius: 0 0 12px 12px; + color: #eff1f5; + text-shadow: none; +} + +.sound-player-overlay StButton { + width: 16px; + height: 16px; + padding: 8px; + margin: 0 6px 6px; + color: #eff1f5; + border-radius: 9999px; + border: none; + text-shadow: none; +} + +.sound-player-overlay StButton StIcon { + icon-size: 16px; +} + +.sound-player-overlay StButton:hover { + background-color: rgba(239, 241, 245, 0.12); +} + +.sound-player-overlay StButton:active { + background-color: rgba(239, 241, 245, 0.3); +} + +.sound-player-overlay StButton:insensitive { + opacty: 0.35; + color: rgba(239, 241, 245, 0.5); +} + +.sound-player-overlay StLabel { + padding: 0 6px; +} + +.sound-player-overlay StBoxLayout { + padding-top: 2px; +} + +.sound-player .slider { + height: 0.5em; + padding: 0; + border: 0px solid rgba(8, 8, 12, 0.9); + border-bottom: 1px; + -slider-height: 0.5em; + -slider-background-color: #14141f; + -slider-border-color: rgba(0, 0, 0, 0); + -slider-active-background-color: #89b4fa; + -slider-active-border-color: rgba(0, 0, 0, 0); + -slider-border-width: 0px; + -slider-handle-radius: 0px; +} + +#workspaceSwitcher { + spacing: 0px; + padding: 3px; +} + +/* Controls the styling when using the "Simple buttons" option */ +.workspace-switcher { + padding-left: 3px; + padding-right: 3px; +} + +.workspace-button { + width: 20px; + height: 10px; + color: rgba(239, 241, 245, 0.7); + padding: 3px; + padding-top: 4px; + transition-duration: 300; +} + +.workspace-button:outlined, .workspace-button:outlined:hover { + color: #89b4fa; +} + +.workspace-button:hover { + color: #bad3fc; +} + +/* Controls the style when using the "Visual representation" option */ +.workspace-graph { + padding: 3px; + spacing: 3px; +} + +.workspace-graph .workspace { + border: 1px solid rgba(0, 0, 0, 0.4); + background-gradient-direction: none; + background-color: rgba(0, 0, 0, 0.2); +} + +.workspace-graph .workspace:active { + border: 1px solid #89b4fa; + background-gradient-direction: none; +} + +.workspace-graph .workspace .windows { + -active-window-background: rgba(60, 60, 92, 0.75); + -active-window-border: rgba(0, 0, 0, 0.8); + -inactive-window-background: rgba(60, 60, 92, 0.75); + -inactive-window-border: rgba(0, 0, 0, 0.8); +} + +.workspace-graph .workspace:active .windows { + -active-window-background: rgba(70, 70, 108, 0.75); + -active-window-border: rgba(0, 0, 0, 0.8); + -inactive-window-background: rgba(40, 40, 61, 0.75); + -inactive-window-border: rgba(0, 0, 0, 0.8); +} + +#panel-launchers-box { + padding: 0 6px; +} + +#panel-launchers-box.vertical { + padding: 3px 0; +} + +.panel-launcher { + padding: 2px; + transition-duration: 200ms; + border-radius: 0; +} + +.panel-launcher:hover { + background-gradient-direction: none; + background-color: rgba(239, 241, 245, 0.1); +} + +.panel-launcher:active { + background-color: rgba(239, 241, 245, 0.2); +} + +.launcher { + padding: 2px; + spacing: 2px; + transition-duration: 0.2s; + border-radius: 0; +} + +.launcher:hover { + background-gradient-direction: none; + background-color: rgba(239, 241, 245, 0.1); +} + +.launcher:active { + background-color: rgba(239, 241, 245, 0.2); +} + +.launcher .icon-box { + padding: 2px; +} + +.applet-separator { + padding: 1px 3px; +} + +.applet-separator-line { + width: 1px; + background: rgba(239, 241, 245, 0.12); +} + +.applet-box { + padding: 0 6px; + color: rgba(239, 241, 245, 0.7); + text-shadow: none; + transition-duration: 100ms; + border-radius: 0; +} + +.applet-box.vertical { + padding: 6px 0; +} + +.applet-box:hover { + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.04); +} + +.applet-box:checked, .applet-box:checked:hover { + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.12); +} + +.applet-box:highlight { + background-image: none; + border-image: none; + background-color: rgba(210, 15, 57, 0.5); +} + +.applet-label { + font-weight: bold; + color: rgba(239, 241, 245, 0.7); +} + +.applet-box:checked .applet-label { + color: rgba(239, 241, 245, 0.7); + text-shadow: none; +} + +.applet-icon { + color: rgba(239, 241, 245, 0.7); + icon-size: 16px; +} + +.applet-box:checked .applet-icon { + color: rgba(239, 241, 245, 0.7); + text-shadow: none; +} + +.user-icon { + width: 32px; + height: 32px; + background-color: transparent; + border: none; + border-radius: 0; +} + +.user-label { + color: #eff1f5; + font-size: 1em; + font-weight: bold; + margin: 0px; +} + +.desklet { + color: #eff1f5; +} + +.desklet:highlight { + background-color: rgba(210, 15, 57, 0.5); +} + +.desklet-with-borders { + color: #eff1f5; + background-color: rgba(24, 24, 37, 0.9); + padding: 12px; + padding-bottom: 16px; +} + +.desklet-with-borders:highlight { + background-color: rgba(210, 15, 57, 0.5); +} + +.desklet-with-borders-and-header { + color: #eff1f5; + background-color: rgba(24, 24, 37, 0.9); + border-radius: 6px; + border-radius-topleft: 0; + border-radius-topright: 0; + padding: 12px; + padding-bottom: 17px; +} + +.desklet-with-borders-and-header:highlight { + background-color: rgba(210, 15, 57, 0.5); +} + +.desklet-header { + color: #eff1f5; + background-color: rgba(24, 24, 37, 0.9); + border-radius: 0; + border-radius-topleft: 6px; + border-radius-topright: 6px; + font-size: 1em; + padding: 12px; + padding-bottom: 6px; +} + +.desklet-drag-placeholder { + border: 2px solid #89b4fa; + background-color: rgba(137, 180, 250, 0.3); +} + +.photoframe-box { + color: #eff1f5; + background-color: rgba(24, 24, 37, 0.9); + padding: 12px; + padding-bottom: 16px; +} + +.workspace-osd { + text-shadow: black 5px 5px 5px; + font-weight: bold; + font-size: 48pt; +} + +.notification-applet-padding { + padding: 0.5em 1em; +} + +.notification-applet-container { + max-height: 9999px; +} + +.tile-preview, +.tile-preview.snap, +.tile-hud, +.tile-hud.snap { + background-color: rgba(137, 180, 250, 0.3); + border: 1px solid #89b4fa; +} + +.xkcd-box { + padding: 6px; + border: 0px; + background-color: rgba(0, 0, 0, 0); + border-radius: 0px; +} diff --git a/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/thumbnail.png b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/thumbnail.png new file mode 100755 index 0000000..27bae67 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/cinnamon/thumbnail.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-left.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-left.svg new file mode 100755 index 0000000..ec8b478 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-right.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-right.svg new file mode 100755 index 0000000..6fc5556 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-today.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-today.svg new file mode 100755 index 0000000..fc3fdf7 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/calendar-today.svg @@ -0,0 +1,55 @@ + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-dark.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-dark.svg new file mode 100755 index 0000000..3d4e052 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-dark.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-active.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-active.svg new file mode 100755 index 0000000..9cfdefd --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-active.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-hover.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-hover.svg new file mode 100755 index 0000000..ef5123a --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off-hover.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off.svg new file mode 100755 index 0000000..b00efa6 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox-off.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox.svg new file mode 100755 index 0000000..126455b --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/checkbox.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/dash-placeholder.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/dash-placeholder.svg new file mode 100755 index 0000000..172156a --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/dash-placeholder.svg @@ -0,0 +1,4 @@ + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-events.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-events.svg new file mode 100755 index 0000000..239177d --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-events.svg @@ -0,0 +1,82 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-notifications.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-notifications.svg new file mode 100755 index 0000000..ae09f92 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/no-notifications.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/noise-texture.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/noise-texture.svg new file mode 100755 index 0000000..484f6c8 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/noise-texture.svg @@ -0,0 +1,78 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/process-working.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/process-working.svg new file mode 100755 index 0000000..0f311b0 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/process-working.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-off.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-off.svg new file mode 100755 index 0000000..6cd17d8 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-off.svg @@ -0,0 +1,59 @@ + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on-dark.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on-dark.svg new file mode 100755 index 0000000..0dd48e8 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on-dark.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on.svg new file mode 100755 index 0000000..e5ee9fd --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/assets/toggle-on.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/gnome-shell.css b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/gnome-shell.css new file mode 100755 index 0000000..677ca77 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/gnome-shell.css @@ -0,0 +1,6084 @@ +/* This stylesheet is generated, DO NOT EDIT */ +/* Copyright 2009, 2015 Red Hat, Inc. + * + * Portions adapted from Mx's data/style/default.css + * Copyright 2009 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* General Typography */ +.search-statustext, .app-folder-dialog .folder-name-container .folder-name-label, +.app-folder-dialog .folder-name-container .folder-name-entry { + font-weight: 800; + font-size: 20pt; +} + +.message-notification-group .message-group-header .message-group-title, .message-list .message-list-placeholder, .message-dialog-content .message-dialog-title, .lg-debug-flags-header { + font-weight: 800; + font-size: 15pt; +} + +.quick-toggle-menu .header .title { + font-weight: 700; + font-size: 15pt; +} + +.bt-menu-placeholder.popup-menu-item, .restart-message, .polkit-dialog-user-layout .polkit-dialog-user-label, +.polkit-dialog-user-layout .polkit-dialog-user-root-label, .message-dialog-content .message-dialog-title.lightweight { + font-weight: 700; + font-size: 13pt; +} + +.background-app-item .title, .message-list-controls, .dialog-list .dialog-list-title, .world-clocks-button .world-clocks-header, .calendar .calendar-month-label, .lg-extension-name { + font-weight: 700; + font-size: 11pt; +} + +.quick-toggle-menu .header .subtitle, .app-menu .popup-inactive-menu-item:first-child > StLabel { + font-weight: 700; + font-size: 9pt; +} + +.icon-label-button-container, .background-app-item .subtitle, .message .message-header .message-header-content .event-time, .prompt-dialog .prompt-dialog-error-label, +.prompt-dialog .prompt-dialog-info-label, +.prompt-dialog .prompt-dialog-null-label, .run-dialog .run-dialog-description, .dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + font-weight: 400; + font-size: 9pt; +} + +.calendar .calendar-week-number, .calendar .calendar-day-heading { + font-weight: 400; + font-size: 8pt; +} + +.calendar .calendar-day-heading { + font-feature-settings: 'tnum'; +} + +.ripple-pointer-location { + width: 48px; + height: 48px; + border-radius: 24px; + background-color: rgba(255, 255, 255, 0.3); + box-shadow: 0 0 2px 2px #ebf2fe; +} + +.pie-timer { + width: 60px; + height: 60px; + -pie-border-width: 3px; + -pie-border-color: #89b4fa; + -pie-background-color: rgba(255, 255, 255, 0.3); +} + +.magnifier-zoom-region { + border: 2px solid #89b4fa; +} + +.magnifier-zoom-region.full-screen { + border-width: 0; +} + +.shell-link { + border-radius: 12px; + color: #8fcbe8; +} + +.shell-link:hover { + color: #8fcbe8; + background-color: rgba(143, 203, 232, 0.15); +} + +.shell-link:active { + color: #8fcbe8; + background-color: rgba(143, 203, 232, 0.25); +} + +.lowres-icon { + icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); +} + +.icon-dropshadow { + icon-shadow: 0 3px 6px rgba(0, 0, 0, 0.2); +} + +/* Buttons */ +.quick-settings-system-item .icon-button, .quick-settings-system-item .background-app-item .close-button, .background-app-item .quick-settings-system-item .close-button, .quick-settings-system-item .message .message-header .message-expand-button, .message .message-header .quick-settings-system-item .message-expand-button, +.quick-settings-system-item .message .message-header .message-close-button, +.message .message-header .quick-settings-system-item .message-close-button, .quick-settings-system-item .message-notification-group .message-collapse-button, .message-notification-group .quick-settings-system-item .message-collapse-button, .hotplug-notification-item, .button { + color: #eff1f5; + background-color: #313244; + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:focus, .quick-settings-system-item .background-app-item .close-button:focus, .background-app-item .quick-settings-system-item .close-button:focus, .quick-settings-system-item .message .message-header .message-expand-button:focus, .message .message-header .quick-settings-system-item .message-expand-button:focus, +.quick-settings-system-item .message .message-header .message-close-button:focus, +.message .message-header .quick-settings-system-item .message-close-button:focus, .quick-settings-system-item .message-notification-group .message-collapse-button:focus, .message-notification-group .quick-settings-system-item .message-collapse-button:focus, .hotplug-notification-item:focus, .button:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:hover, .quick-settings-system-item .background-app-item .close-button:hover, .background-app-item .quick-settings-system-item .close-button:hover, .quick-settings-system-item .message .message-header .message-expand-button:hover, .message .message-header .quick-settings-system-item .message-expand-button:hover, +.quick-settings-system-item .message .message-header .message-close-button:hover, +.message .message-header .quick-settings-system-item .message-close-button:hover, .quick-settings-system-item .message-notification-group .message-collapse-button:hover, .message-notification-group .quick-settings-system-item .message-collapse-button:hover, .hotplug-notification-item:hover, .button:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:active, .quick-settings-system-item .background-app-item .close-button:active, .background-app-item .quick-settings-system-item .close-button:active, .quick-settings-system-item .message .message-header .message-expand-button:active, .message .message-header .quick-settings-system-item .message-expand-button:active, +.quick-settings-system-item .message .message-header .message-close-button:active, +.message .message-header .quick-settings-system-item .message-close-button:active, .quick-settings-system-item .message-notification-group .message-collapse-button:active, .message-notification-group .quick-settings-system-item .message-collapse-button:active, .hotplug-notification-item:active, .button:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:insensitive, .quick-settings-system-item .background-app-item .close-button:insensitive, .background-app-item .quick-settings-system-item .close-button:insensitive, .quick-settings-system-item .message .message-header .message-expand-button:insensitive, .message .message-header .quick-settings-system-item .message-expand-button:insensitive, +.quick-settings-system-item .message .message-header .message-close-button:insensitive, +.message .message-header .quick-settings-system-item .message-close-button:insensitive, .quick-settings-system-item .message-notification-group .message-collapse-button:insensitive, .message-notification-group .quick-settings-system-item .message-collapse-button:insensitive, .hotplug-notification-item:insensitive, .button:insensitive { + color: rgba(239, 241, 245, 0.35); + background-color: #313244; + box-shadow: none !important; +} + +.modal-dialog-button, .lg-obj-inspector-button, .candidate-page-button, .modal-dialog-linked-button, .icon-button.flat, .background-app-item .flat.close-button, .message-notification-group .flat.message-collapse-button, .message .message-header .flat.message-expand-button, +.message .message-header .flat.message-close-button, .button.flat, .popup-menu .button { + color: #eff1f5; + background-color: transparent; + box-shadow: none !important; +} + +.modal-dialog-button:focus, .lg-obj-inspector-button:focus, .candidate-page-button:focus, .modal-dialog-linked-button:focus, .icon-button.flat:focus, .background-app-item .flat.close-button:focus, .message-notification-group .flat.message-collapse-button:focus, .message .message-header .flat.message-expand-button:focus, +.message .message-header .flat.message-close-button:focus, .button.flat:focus, .popup-menu .button:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.modal-dialog-button:hover, .lg-obj-inspector-button:hover, .candidate-page-button:hover, .modal-dialog-linked-button:hover, .icon-button.flat:hover, .background-app-item .flat.close-button:hover, .message-notification-group .flat.message-collapse-button:hover, .message .message-header .flat.message-expand-button:hover, +.message .message-header .flat.message-close-button:hover, .button.flat:hover, .popup-menu .button:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.modal-dialog-button:active, .lg-obj-inspector-button:active, .candidate-page-button:active, .modal-dialog-linked-button:active, .icon-button.flat:active, .background-app-item .flat.close-button:active, .message-notification-group .flat.message-collapse-button:active, .message .message-header .flat.message-expand-button:active, +.message .message-header .flat.message-close-button:active, .button.flat:active, .popup-menu .button:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.modal-dialog-button:insensitive, .lg-obj-inspector-button:insensitive, .candidate-page-button:insensitive, .modal-dialog-linked-button:insensitive, .icon-button.flat:insensitive, .background-app-item .flat.close-button:insensitive, .message-notification-group .flat.message-collapse-button:insensitive, .message .message-header .flat.message-expand-button:insensitive, +.message .message-header .flat.message-close-button:insensitive, .button.flat:insensitive, .popup-menu .button:insensitive { + background-color: transparent; + color: rgba(239, 241, 245, 0.35); + box-shadow: none !important; +} + +.icon-button.default, .background-app-item .default.close-button, .message-notification-group .default.message-collapse-button, .message .message-header .default.message-expand-button, +.message .message-header .default.message-close-button, .button.default { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; + box-shadow: none !important; +} + +.icon-button.default:focus, .background-app-item .default.close-button:focus, .message-notification-group .default.message-collapse-button:focus, .message .message-header .default.message-expand-button:focus, +.message .message-header .default.message-close-button:focus, .button.default:focus { + color: rgba(30, 30, 46, 0.87); + background-color: rgba(30, 30, 46, 0.08); + box-shadow: none !important; +} + +.icon-button.default:hover, .background-app-item .default.close-button:hover, .message-notification-group .default.message-collapse-button:hover, .message .message-header .default.message-expand-button:hover, +.message .message-header .default.message-close-button:hover, .button.default:hover { + color: rgba(30, 30, 46, 0.87); + background-color: rgba(30, 30, 46, 0.12); + box-shadow: none !important; +} + +.icon-button.default:insensitive, .background-app-item .default.close-button:insensitive, .message-notification-group .default.message-collapse-button:insensitive, .message .message-header .default.message-expand-button:insensitive, +.message .message-header .default.message-close-button:insensitive, .button.default:insensitive { + color: rgba(30, 30, 46, 0.35); + background-color: #89b4fa; + box-shadow: none !important; +} + +.icon-button.default:active, .background-app-item .default.close-button:active, .message-notification-group .default.message-collapse-button:active, .message .message-header .default.message-expand-button:active, +.message .message-header .default.message-close-button:active, .button.default:active { + color: rgba(30, 30, 46, 0.87); + background-color: rgba(30, 30, 46, 0.2); + box-shadow: none !important; +} + +.button { + min-height: 20px; + padding: 6px 12px; + border-radius: 12px; + border: none; +} + +.icon-button, .background-app-item .close-button, .message-notification-group .message-collapse-button, .message .message-header .message-expand-button, +.message .message-header .message-close-button { + border-radius: 9999px; + padding: 6px; + min-height: 1.091em; +} + +.icon-button StIcon, .background-app-item .close-button StIcon, .message-notification-group .message-collapse-button StIcon, .message .message-header .message-expand-button StIcon, +.message .message-header .message-close-button StIcon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.screenshot-ui-show-pointer-button, .screenshot-ui-type-button { + color: #eff1f5; + background-color: transparent; + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:insensitive, .screenshot-ui-type-button:insensitive { + color: rgba(239, 241, 245, 0.35); + background-color: #1e1e2e; + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:focus, .screenshot-ui-type-button:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:hover, .screenshot-ui-type-button:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:active, .screenshot-ui-type-button:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:outlined, .screenshot-ui-type-button:outlined, .screenshot-ui-show-pointer-button:checked, .screenshot-ui-type-button:checked { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; + box-shadow: none !important; +} + +/* Check Boxes */ +.check-box StBoxLayout { + spacing: 0.8em; +} + +.check-box StBin { + width: 24px; + height: 24px; + padding: 3px; +} + +.check-box StBin, .check-box:focus StBin { + background-image: url("assets/checkbox-off.svg"); +} + +.check-box:hover StBin { + background-image: url("assets/checkbox-off-hover.svg"); +} + +.check-box:active StBin { + background-image: url("assets/checkbox-off-active.svg"); +} + +.check-box:checked StBin, .check-box:focus:checked StBin { + background-image: url("assets/checkbox-dark.svg"); +} + +/* Activities Ripple */ +.ripple-box { + background-color: rgba(137, 180, 250, 0.35); + box-shadow: 0 0 2px 2px #ebf2fe; + width: 52px; + height: 52px; + border-radius: 0 0 52px 0; +} + +.ripple-box:rtl { + border-radius: 0 0 0 52px; +} + +/* Modal Dialogs */ +.candidate-popup-content, .modal-dialog { + background-color: #292c3c; + border-radius: 21px; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.35); + border: 2px solid #e6e9ef; +} + +.modal-dialog-button:last-child, .modal-dialog-linked-button:last-child { + color: #1e1e2e; + background-color: #89b4fa; +} + +.modal-dialog-button:hover:last-child, .modal-dialog-linked-button:hover:last-child { + color: #1e1e2e; + background-color: #b5d0fc; +} + +.modal-dialog-button:active:last-child, .modal-dialog-linked-button:active:last-child { + color: #1e1e2e; + background-color: #71a4f9; +} + +.modal-dialog-button:insensitive:last-child, .modal-dialog-linked-button:insensitive:last-child { + color: #1e1e2e; + background-color: rgba(137, 180, 250, 0.05); +} + +.headline { + font-size: 12ptpt; +} + +.modal-dialog { + color: rgba(239, 241, 245, 0.7); + padding: 0 6px 6px 6px; +} + +.modal-dialog-linked-button { + min-height: 32px !important; + padding: 6px !important; + margin: 3px !important; + border: none !important; + border-radius: 12px; +} + +.modal-dialog-linked-button:first-child { + background-color: rgba(239, 241, 245, 0.04); +} + +.modal-dialog-linked-button:first-child:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.modal-dialog-linked-button:first-child:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.modal-dialog-linked-button:first-child:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.modal-dialog .modal-dialog-content-box { + margin: 30px 42px; + spacing: 30px; + max-width: 28em; +} + +.end-session-dialog { + width: 30em; +} + +.end-session-dialog .end-session-dialog-battery-warning, +.end-session-dialog .dialog-list-title { + color: #df8e1d; +} + +.message-dialog-content { + spacing: 18px; +} + +.message-dialog-content .message-dialog-title { + text-align: center; + font-size: 18pt; + font-weight: 800; +} + +.message-dialog-content .message-dialog-title.lightweight { + font-size: 13pt; + font-weight: 800; +} + +.message-dialog-content .message-dialog-description { + text-align: center; +} + +.dialog-list { + spacing: 18px; +} + +.dialog-list .dialog-list-title { + text-align: center; + font-weight: bold; +} + +.dialog-list .dialog-list-scrollview { + max-height: 200px; +} + +.dialog-list .dialog-list-box { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-title { + font-weight: bold; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + color: rgba(239, 241, 245, 0.7); + font-size: 10ptpt; +} + +.run-dialog .modal-dialog-content-box { + margin-top: 24px; + margin-bottom: 12px; +} + +.run-dialog .run-dialog-entry { + width: 20em; +} + +.run-dialog .run-dialog-description { + text-align: center; + color: rgba(239, 241, 245, 0.7); + font-size: 10ptpt; +} + +.prompt-dialog { + width: 28em; +} + +.prompt-dialog .modal-dialog-content-box { + margin-bottom: 24px; +} + +.prompt-dialog-password-grid { + spacing-rows: 8px; + spacing-columns: 4px; +} + +.prompt-dialog-password-grid .prompt-dialog-password-entry { + width: auto; +} + +.prompt-dialog-password-grid .prompt-dialog-password-entry:ltr { + margin-left: 20px; +} + +.prompt-dialog-password-grid .prompt-dialog-password-entry:rtl { + margin-right: 20px; +} + +.prompt-dialog-password-layout { + spacing: 8px; +} + +.prompt-dialog-password-entry { + width: 20em; +} + +.prompt-dialog-error-label, +.prompt-dialog-info-label, +.prompt-dialog-null-label { + text-align: center; + font-size: 10ptpt; + margin: 6px; +} + +.prompt-dialog-error-label { + color: #d20f39; +} + +.prompt-dialog-info-label, +.prompt-dialog-null-label { + color: rgba(239, 241, 245, 0.5); +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 8px; + margin-bottom: 6px; +} + +.polkit-dialog-user-layout .polkit-dialog-user-root-label { + color: #df8e1d; +} + +.audio-device-selection-dialog .modal-dialog-content-box { + margin-bottom: 28px; +} + +.audio-device-selection-dialog .audio-selection-box { + spacing: 20px; +} + +.audio-selection-device { + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.audio-selection-device:hover, .audio-selection-device:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.audio-selection-device:active { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.audio-selection-device-box { + padding: 18px; + spacing: 18px; +} + +.audio-selection-device-icon { + icon-size: 64px; +} + +.welcome-dialog-image { + background-image: url("resource:///org/gnome/shell/theme/gnome-shell-start.svg"); + background-size: contain; + height: 300px; + width: 300px; +} + +/* Entries */ +StEntry, +.popup-menu .search-entry { + min-height: 20px; + padding: 6px 12px; + margin: 2px; + border-radius: 12px; + color: #eff1f5; + caret-color: #eff1f5; + selection-background-color: #89b4fa; + selected-color: rgba(30, 30, 46, 0.87); + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + border: 2px solid transparent !important; + box-shadow: none !important; +} + +StEntry:hover, +.popup-menu .search-entry:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + border: 2px solid rgba(239, 241, 245, 0.3) !important; + box-shadow: none !important; +} + +StEntry:focus, +.popup-menu .search-entry:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + border: 2px solid #89b4fa !important; + box-shadow: none !important; +} + +StEntry:insensitive, +.popup-menu .search-entry:insensitive { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.35); + box-shadow: none !important; +} + +StEntry StIcon.capslock-warning, +.popup-menu .search-entry StIcon.capslock-warning { + icon-size: 16px; + warning-color: #df8e1d; + padding: 0; +} + +StEntry StIcon.peek-password, +.popup-menu .search-entry StIcon.peek-password { + icon-size: 16px; + padding: 0 4px; +} + +StEntry StLabel.hint-text, +.popup-menu .search-entry StLabel.hint-text { + margin-left: 2px; + color: rgba(239, 241, 245, 0.5); +} + +.hotplug-notification-item { + padding: 12px; + border-style: solid; + border-width: 0; + border-left-width: 0; + border-bottom-width: 0; +} + +.hotplug-notification-item:first-child { + border-radius: 0 0 0 12px; +} + +.hotplug-notification-item:last-child { + border-right-width: 0; + border-radius: 0 0 12px 0; +} + +.hotplug-notification-item:first-child:last-child { + border-radius: 0 0 12px 12px; +} + +.hotplug-notification-item-icon { + icon-size: 24px; + padding: 0 4px; +} + +.candidate-popup-boxpointer { + -arrow-border-radius: 2px; + -arrow-background-color: transparent; + -arrow-border-width: 0; + -arrow-border-color: transparent; + -arrow-base: 64px; + -arrow-rise: 12px; +} + +.candidate-popup-content { + color: rgba(239, 241, 245, 0.7); + box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.15); + border: none; + margin: 3px 8px; + padding: 6px; + spacing: 6px; + border-radius: 12px; +} + +.candidate-index { + padding: 0 0.5em 0 0; + color: rgba(239, 241, 245, 0.7); +} + +.candidate-box:selected .candidate-index { + color: rgba(30, 30, 46, 0.6); +} + +.candidate-box { + padding: 0.3em 0.5em 0.3em 0.5em; + margin-right: 2px; + border-radius: 6px; + color: rgba(239, 241, 245, 0.7); +} + +.candidate-box:hover { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.candidate-box:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +.candidate-box:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.candidate-box:last-child { + margin-right: 0; +} + +.candidate-page-button-box { + height: 2em; +} + +.vertical .candidate-page-button-box { + padding-top: 0.5em; +} + +.horizontal .candidate-page-button-box { + padding-left: 0.5em; +} + +.candidate-page-button { + padding: 4px 8px; + border-radius: 6px; +} + +.candidate-page-button-previous, +.candidate-page-button-next { + border-radius: 6px; +} + +.candidate-page-button-icon { + icon-size: 1em; +} + +/* On-screen Keyboard */ +#keyboard { + background-color: #1d1d1d; + box-shadow: none; +} + +#keyboard .page-indicator { + padding: 6px; +} + +#keyboard .page-indicator .page-indicator-icon { + width: 8px; + height: 8px; +} + +.key-container, +.keyboard-layout { + padding: 4px; + spacing: 4px; +} + +.keyboard-key { + font-size: 16ptpt; + font-weight: bold; + min-height: 1.2em; + min-width: 1.2em; + padding: 0 !important; + border-radius: 15px; + border: none; + color: rgba(239, 241, 245, 0.7); + background-color: #707070; + box-shadow: inset 0 -1px rgba(0, 0, 0, 0.85); +} + +.keyboard-key:focus, .keyboard-key:hover { + color: #eff1f5; + background-color: #656565; +} + +.keyboard-key:checked, .keyboard-key:active { + color: #eff1f5; + background-color: #717171; +} + +.keyboard-key:grayed { + background-color: #4b4b4b; + color: rgba(239, 241, 245, 0.7); +} + +.keyboard-key.default-key { + background-color: #4b4b4b; + box-shadow: inset 0 -1px rgba(0, 0, 0, 0.85); +} + +.keyboard-key.default-key:focus, .keyboard-key.default-key:hover { + color: #eff1f5; + background-color: #585858; +} + +.keyboard-key.default-key:checked, .keyboard-key.default-key:active { + color: #eff1f5; + background-color: #6a6a6a; +} + +.keyboard-key.enter-key { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +.keyboard-key.enter-key:focus, .keyboard-key.enter-key:hover { + color: rgba(30, 30, 46, 0.87); + background-color: #a1c4fb; +} + +.keyboard-key.enter-key:checked, .keyboard-key.enter-key:active { + color: rgba(30, 30, 46, 0.87); + background-color: #5895f8; +} + +.keyboard-key.shift-key-uppercase, .keyboard-key.shift-key-uppercase:focus, .keyboard-key.shift-key-uppercase:hover, .keyboard-key.shift-key-uppercase:checked, .keyboard-key.shift-key-uppercase:active { + color: #89b4fa; +} + +.keyboard-key StIcon { + icon-size: 1.125em; +} + +.keyboard-subkeys { + color: inherit; + -arrow-border-radius: 18px; + -arrow-background-color: #323233; + -arrow-border-width: 0; + -arrow-border-color: transparent; + -arrow-base: 20px; + -arrow-rise: 10px; + -boxpointer-gap: 6px; + box-shadow: inset 0 -1px rgba(0, 0, 0, 0.85); +} + +.emoji-page .keyboard-key { + background-color: transparent; + border: none; + color: initial; +} + +.emoji-panel .keyboard-key:latched { + border: none; + background-color: #89b4fa; +} + +.word-suggestions { + font-size: 14pt; + spacing: 12px; + min-height: 20pt; +} + +/* Login Dialog */ +#lockDialogGroup { + background-color: #1e1e2e; +} + +.login-dialog-banner-view { + padding-top: 24px; + max-width: 23em; +} + +.login-dialog, +.unlock-dialog { + border: none; + background-color: transparent; +} + +.login-dialog StEntry, +.unlock-dialog StEntry { + selection-background-color: #89b4fa; + selected-color: rgba(30, 30, 46, 0.87); + padding: 4px 8px; + min-height: 26px; + border-radius: 9999px; + caret-color: rgba(30, 30, 46, 0.87); + background-color: rgba(239, 241, 245, 0.04); + border-radius: 0; + border: none !important; + box-shadow: inset 0 -1px rgba(30, 30, 46, 0.15) !important; + color: rgba(30, 30, 46, 0.87); +} + +.login-dialog StEntry:focus, +.unlock-dialog StEntry:focus { + border: none !important; + background-color: rgba(239, 241, 245, 0.04); + box-shadow: inset 0 -2px #89b4fa !important; + color: rgba(30, 30, 46, 0.87); +} + +.login-dialog StEntry:insensitive, +.unlock-dialog StEntry:insensitive { + border: none !important; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(30, 30, 46, 0.35); +} + +.login-dialog StEntry StLabel.hint-text, +.unlock-dialog StEntry StLabel.hint-text { + color: rgba(30, 30, 46, 0.38); +} + +.login-dialog .modal-dialog-button-box, +.unlock-dialog .modal-dialog-button-box { + spacing: 3px; +} + +.login-dialog .modal-dialog-button, +.unlock-dialog .modal-dialog-button { + padding: 0 16px; + border: none; + color: rgba(30, 30, 46, 0.87); + background-color: transparent; + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:hover, .login-dialog .modal-dialog-button:focus, +.unlock-dialog .modal-dialog-button:hover, +.unlock-dialog .modal-dialog-button:focus { + color: rgba(30, 30, 46, 0.87); + background-color: rgba(239, 241, 245, 0.12); +} + +.login-dialog .modal-dialog-button:active, +.unlock-dialog .modal-dialog-button:active { + color: rgba(30, 30, 46, 0.87); + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:insensitive, +.unlock-dialog .modal-dialog-button:insensitive { + background-color: transparent; + color: rgba(30, 30, 46, 0.35); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default, +.unlock-dialog .modal-dialog-button:default { + color: rgba(30, 30, 46, 0.87); + background-color: #313244; + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default:hover, .login-dialog .modal-dialog-button:default:focus, +.unlock-dialog .modal-dialog-button:default:hover, +.unlock-dialog .modal-dialog-button:default:focus { + color: rgba(30, 30, 46, 0.87); + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default:active, +.unlock-dialog .modal-dialog-button:default:active { + color: rgba(30, 30, 46, 0.87); + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default:insensitive, +.unlock-dialog .modal-dialog-button:default:insensitive { + color: rgba(30, 30, 46, 0.35); + background-color: #313244; + box-shadow: none !important; +} + +.login-dialog .cancel-button, +.login-dialog .switch-user-button, +.login-dialog .login-dialog-session-list-button, +.unlock-dialog .cancel-button, +.unlock-dialog .switch-user-button, +.unlock-dialog .login-dialog-session-list-button { + padding: 0; + border-radius: 100px; + width: 32px; + height: 32px; + border: none; + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.login-dialog .cancel-button StIcon, +.login-dialog .switch-user-button StIcon, +.login-dialog .login-dialog-session-list-button StIcon, +.unlock-dialog .cancel-button StIcon, +.unlock-dialog .switch-user-button StIcon, +.unlock-dialog .login-dialog-session-list-button StIcon { + icon-size: 16px; +} + +.login-dialog .login-dialog-message-warning, +.unlock-dialog .login-dialog-message-warning { + color: rgba(239, 241, 245, 0.7); +} + +.login-dialog-logo-bin { + padding: 24px 0px; +} + +.login-dialog-banner { + color: rgba(239, 241, 245, 0.7); +} + +.login-dialog-button-box { + spacing: 5px; +} + +.login-dialog-message { + text-align: center; +} + +.login-dialog-message-warning { + color: #df8e1d; +} + +.login-dialog-message-hint { + padding-top: 0; + padding-bottom: 20px; +} + +.login-dialog-user-selection-box { + padding: 100px 0px; +} + +.login-dialog-not-listed-label { + padding-left: 2px; +} + +.login-dialog-not-listed-button:focus .login-dialog-not-listed-label, .login-dialog-not-listed-button:hover .login-dialog-not-listed-label { + color: #eff1f5; +} + +.login-dialog-not-listed-label { + font-size: 1em; + font-weight: bold; + color: rgba(239, 241, 245, 0.7); + padding-top: 1em; +} + +.login-dialog-not-listed-label:hover { + color: rgba(239, 241, 245, 0.7); +} + +.login-dialog-not-listed-label:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.login-dialog-user-list-view { + -st-vfade-offset: 1em; +} + +.login-dialog-user-list { + spacing: 12px; + padding: 0.2em; + width: 23em; +} + +.login-dialog-user-list:expanded .login-dialog-user-list-item:selected, .login-dialog-user-list:expanded .login-dialog-user-list-item:hover, .login-dialog-user-list:expanded .login-dialog-user-list-item:active { + background-color: rgba(239, 241, 245, 0.3); + color: rgba(239, 241, 245, 0.7); +} + +.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in { + border-right: 2px solid #89b4fa; +} + +.login-dialog-user-list-item { + border-radius: 18px; + padding: 6px; + color: rgba(239, 241, 245, 0.7); +} + +.login-dialog-user-list-item:ltr .user-widget { + padding-right: 1em; +} + +.login-dialog-user-list-item:rtl .user-widget { + padding-left: 1em; +} + +.login-dialog-user-list-item:focus { + background-color: rgba(239, 241, 245, 0.04) !important; +} + +.login-dialog-user-list-item:hover, .login-dialog-user-list-item:focus:hover { + background-color: rgba(239, 241, 245, 0.12) !important; + color: rgba(239, 241, 245, 0.7); +} + +.login-dialog-user-list-item:active, .login-dialog-user-list-item:focus:active { + background-color: rgba(239, 241, 245, 0.3) !important; + color: rgba(239, 241, 245, 0.7); +} + +.login-dialog-user-list-item .login-dialog-timed-login-indicator { + height: 2px; + margin: 6px 0 0 0; + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.user-widget-label { + color: rgba(239, 241, 245, 0.7); +} + +.user-widget.horizontal .user-widget-label { + font-size: 13ptpt; + font-weight: bold; + padding-left: 15px; +} + +.user-widget.horizontal .user-widget-label:ltr { + padding-left: 14px; + text-align: left; +} + +.user-widget.horizontal .user-widget-label:rtl { + padding-right: 14px; + text-align: right; +} + +.user-widget.vertical .user-widget-label { + font-size: 16ptpt; + text-align: center; + font-weight: normal; + padding-top: 16px; +} + +.login-dialog-prompt-layout { + padding-top: 24px; + padding-bottom: 12px; + spacing: 12px; + width: 23em; +} + +.login-dialog-prompt-entry { + height: 1.5em; +} + +.login-dialog-prompt-label { + color: rgba(239, 241, 245, 0.7); + font-size: 12ptpt; + padding-top: 1em; +} + +/* Looking Glass */ +#LookingGlassDialog { + background-color: #313244; + padding: 0; + spacing: 6px; + margin: 6px; + border-radius: 20px; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.25); + color: #eff1f5; + border: 2px solid #e6e9ef; +} + +#LookingGlassDialog > #Toolbar { + padding: 0 6px; + border: none; + border-radius: 20px 20px 0 0; + background-color: rgba(239, 241, 245, 0.04); + box-shadow: inset 0 -1px 0 rgba(239, 241, 245, 0.12); + spacing: 6px; +} + +#LookingGlassDialog .labels { + spacing: 6px; +} + +#LookingGlassDialog .notebook-tab { + -natural-hpadding: 12px; + -minimum-hpadding: 12px; + font-weight: bold; + color: rgba(239, 241, 245, 0.5); + padding-left: 16px; + padding-right: 16px; + min-height: 32px; + padding: 3px 30px; + transition-duration: 100ms; + border: none; + background-color: transparent; + border-radius: 0; +} + +#LookingGlassDialog .notebook-tab:hover { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; + text-shadow: none; +} + +#LookingGlassDialog .notebook-tab:selected { + border-color: transparent; + background-color: rgba(239, 241, 245, 0.12); + box-shadow: inset 0 -2px 0px #e6e9ef; + color: #eff1f5; + text-shadow: none; +} + +#LookingGlassDialog StBoxLayout#EvalBox { + padding: 4px; + spacing: 6px; + padding: 6px; +} + +#LookingGlassDialog StBoxLayout#ResultsArea { + spacing: 6px; + padding: 6px; +} + +.lg-dialog StEntry { + min-height: 22px; + selection-background-color: #89b4fa; + selected-color: rgba(30, 30, 46, 0.87); +} + +.lg-dialog .shell-link { + color: #8fcbe8; +} + +.lg-dialog .shell-link:hover { + color: #b9dff1; +} + +.lg-dialog .shell-link:active { + color: #65b7df; +} + +.lg-dialog .actor-link { + color: rgba(239, 241, 245, 0.5); +} + +.lg-dialog .actor-link:hover { + color: #eff1f5; +} + +.lg-dialog .actor-link:active { + color: rgba(239, 241, 245, 0.7); +} + +.lg-dialog .actor-link StIcon { + icon-size: 12px; +} + +.lg-completions-text { + font-size: 0.9em; + font-style: italic; + color: rgba(239, 241, 245, 0.7); +} + +.lg-obj-inspector-title { + spacing: 6px; + color: rgba(239, 241, 245, 0.7); +} + +.lg-obj-inspector-button { + padding: 0 16px; + border: none; + border-radius: 12px; +} + +.lg-obj-inspector-button:hover { + border: none; +} + +#lookingGlassExtensions { + padding: 6px; + color: rgba(239, 241, 245, 0.7); +} + +.lg-extensions-list { + padding: 6px; + spacing: 6px; + color: rgba(239, 241, 245, 0.7); +} + +.lg-extension { + border: none; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.7); + padding: 12px; +} + +.lg-extension:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.lg-extension:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.3); +} + +.lg-extension-meta { + spacing: 6px; + color: rgba(239, 241, 245, 0.7); +} + +#LookingGlassPropertyInspector { + color: rgba(239, 241, 245, 0.7); + background: #313244; + border: none; + border-radius: 12px; + padding: 6px; + margin: 5px 8px 11px; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.25); +} + +.lg-debug-flag-button { + color: rgba(239, 241, 245, 0.7); +} + +.lg-debug-flag-button StLabel { + padding: 6px, 12px; +} + +.lg-debug-flag-button:hover { + color: #eff1f5; +} + +.lg-debug-flag-button:active { + color: #eff1f5; +} + +.lg-debug-flags-header { + padding-top: 12px; + padding: 6px; +} + +.select-area-rubberband { + background-color: rgba(137, 180, 250, 0.3); + border: 1px solid #89b4fa; + border-radius: 12px; +} + +.user-icon { + background-size: contain; + color: rgba(239, 241, 245, 0.7); + border-radius: 9999px; + border: none; + box-shadow: none; + icon-size: 64px; +} + +.modal-dialog .user-icon { + box-shadow: none; +} + +.user-icon:hover { + color: #eff1f5; +} + +.user-icon StIcon { + background-color: #eff1f5; + border-radius: 9999px; + padding: 12px; + width: 40px; + height: 40px; +} + +.user-icon.user-avatar { + border: 2px solid #89b4fa; +} + +.user-widget.vertical .user-icon { + icon-size: 96px; +} + +.user-widget.vertical .user-icon StIcon { + padding: 20px; + padding-top: 18px; + padding-bottom: 22px; + width: 88px; + height: 88px; +} + +.lightbox { + background-color: black; +} + +.flashspot { + background-color: white; +} + +.hidden { + color: rgba(0, 0, 0, 0); +} + +.caps-lock-warning-label { + text-align: center; + padding-bottom: 8px; + font-size: 10ptpt; + color: #df8e1d; +} + +/* Network Dialogs */ +.nm-dialog { + max-height: 34em; + min-height: 31em; + min-width: 32em; +} + +.nm-dialog-content { + spacing: 20px; + padding: 24px; +} + +.nm-dialog-header-hbox { + spacing: 10px; +} + +.nm-dialog-airplane-box { + spacing: 12px; +} + +.nm-dialog-airplane-headline { + font-weight: bold; + text-align: center; +} + +.nm-dialog-airplane-text { + color: #eff1f5; +} + +.nm-dialog-header { + font-weight: bold; +} + +.nm-dialog-header-icon { + icon-size: 32px; +} + +.nm-dialog-header-hbox { + spacing: 10px; +} + +.nm-dialog-scroll-view { + border: none; + padding: 0; + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; +} + +.nm-dialog-item { + font-size: 11ptpt; + border-bottom: none; + padding: 12px; + spacing: 0px; +} + +.nm-dialog-item:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.nm-dialog-item:hover, .nm-dialog-item:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.nm-dialog-item:active { + background-color: rgba(239, 241, 245, 0.3); +} + +.nm-dialog-icon { + icon-size: 16px; +} + +.nm-dialog-icons { + spacing: 12px; +} + +.no-networks-label { + color: rgba(239, 241, 245, 0.5); +} + +.no-networks-box { + spacing: 6px; +} + +/* OSD */ +.screenshot-ui-panel, .workspace-switcher-container, .switcher-list, .resize-popup, .osd-window { + color: rgba(239, 241, 245, 0.7); + background-color: #1e1e2e; + border: none; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.25); + margin: 5px 8px 11px; + border-radius: 18px; + padding: 12px; +} + +.osd-window { + text-align: center; + font-weight: bold; +} + +.osd-window .osd-monitor-label { + font-size: 3em; +} + +.osd-window .level { + height: 2px; + border-radius: 2px; + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; + -barlevel-height: 2px; + -barlevel-background-color: rgba(239, 241, 245, 0.12); + -barlevel-active-background-color: #89b4fa; + -barlevel-overdrive-color: #d20f39; + -barlevel-overdrive-separator-width: 2px; + -barlevel-border-width: 0; + -barlevel-border-color: rgba(239, 241, 245, 0.12); +} + +.osd-window .level-bar { + background-color: white; + border-radius: 2px; +} + +.pad-osd-window { + padding: 32px; + background-color: #1e1e2e; +} + +.pad-osd-window .pad-osd-title-box { + spacing: 12px; +} + +.pad-osd-window .pad-osd-title-menu-box { + spacing: 6px; +} + +.combo-box-label { + width: 15em; +} + +#overview StScrollBar StBin#trough { + background-color: rgba(239, 241, 245, 0.12); +} + +#overview StScrollBar StButton#vhandle, +#overview StScrollBar StButton#hhandle { + background-color: rgba(239, 241, 245, 0.5); +} + +#overview StScrollBar StButton#vhandle:hover, +#overview StScrollBar StButton#hhandle:hover { + background-color: rgba(239, 241, 245, 0.7); +} + +#overview StScrollBar StButton#vhandle:active, +#overview StScrollBar StButton#hhandle:active { + background-color: #eff1f5; +} + +#overview { + spacing: 24px; +} + +.overview-controls { + padding-bottom: 30px; +} + +/* Top Bar */ +#panel { + color: rgba(239, 241, 245, 0.7); + font-weight: bold; + font-feature-settings: 'tnum'; + font-size: 11ptpt; + transition-duration: 250ms; + box-shadow: none; + border: none; + height: 35px; + background-color: rgba(30, 30, 46, 0.85); + margin: 5px 10px 1px; + border: 2px solid #89b4fa; + border-radius: 9999px; +} + +#panel .panel-corner { + -panel-corner-radius: 0; + -panel-corner-background-color: rgba(30, 30, 46, 0.6); + -panel-corner-border-width: 2px; + -panel-corner-border-color: transparent; + -panel-corner-opacity: 1; + transition-duration: 250ms; +} + +#panel .panel-button { + -natural-hpadding: 12px; + -minimum-hpadding: 12px; + font-weight: bold; + color: rgba(239, 241, 245, 0.7); + transition-duration: 150ms; + border-radius: 12px; + text-shadow: none; + box-shadow: none; + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button.clock-display { + box-shadow: none; +} + +#panel .panel-button.clock-display .clock { + transition-duration: 150ms; + border-radius: 12px; + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button:hover { + color: #89b4fa; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(57, 57, 72, 0.624); + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button:hover.clock-display { + box-shadow: none; + color: rgba(239, 241, 245, 0.7); +} + +#panel .panel-button:hover.clock-display .clock { + color: #89b4fa; + box-shadow: inset 0 0 0 1000px rgba(57, 57, 72, 0.624); + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button:active, #panel .panel-button:active:hover, #panel .panel-button:overview, #panel .panel-button:overview:hover, #panel .panel-button:focus, #panel .panel-button:focus:hover, #panel .panel-button:checked, #panel .panel-button:checked:hover { + color: #89b4fa; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(80, 81, 94, 0.648); +} + +#panel .panel-button:active.clock-display, #panel .panel-button:overview.clock-display, #panel .panel-button:focus.clock-display, #panel .panel-button:checked.clock-display { + box-shadow: none; + color: rgba(239, 241, 245, 0.7); +} + +#panel .panel-button:active.clock-display .clock, #panel .panel-button:overview.clock-display .clock, #panel .panel-button:focus.clock-display .clock, #panel .panel-button:checked.clock-display .clock { + color: #89b4fa; + box-shadow: inset 0 0 0 1000px rgba(80, 81, 94, 0.648); +} + +.unlock-screen #panel .panel-button, .login-screen #panel .panel-button, .lock-screen #panel .panel-button { + color: #eff1f5; +} + +.unlock-screen #panel .panel-button:focus, .unlock-screen #panel .panel-button:hover, .unlock-screen #panel .panel-button:active, .login-screen #panel .panel-button:focus, .login-screen #panel .panel-button:hover, .login-screen #panel .panel-button:active, .lock-screen #panel .panel-button:focus, .lock-screen #panel .panel-button:hover, .lock-screen #panel .panel-button:active { + color: #eff1f5; +} + +#panel .panel-button .system-status-icon { + icon-size: 16px; + padding: 6px; + margin: 0; + -st-icon-style: symbolic; +} + +#panel .panel-button .appindicator-trayicons-box { + margin: 0 6px; +} + +#panel .panel-button .app-menu-icon { + -st-icon-style: symbolic; +} + +#panel .panel-button#panelActivities { + -natural-hpadding: 18px; +} + +#panel .panel-button#panelActivities StBoxLayout { + padding: 0 3px; + spacing: 6px; +} + +#panel .panel-button#panelActivities .workspace-dot { + border-radius: 9999px; + min-width: 8px; + min-height: 8px; + background-color: #eff1f5; +} + +#panel:overview, #panel.unlock-screen, #panel.login-screen, #panel.lock-screen { + background-color: transparent; + box-shadow: none; + border: 2px solid transparent; +} + +#panel:overview StLabel, +#panel:overview StIcon, #panel.unlock-screen StLabel, +#panel.unlock-screen StIcon, #panel.login-screen StLabel, +#panel.login-screen StIcon, #panel.lock-screen StLabel, +#panel.lock-screen StIcon { + color: rgba(239, 241, 245, 0.7); +} + +#panel:overview .panel-button:hover, #panel.unlock-screen .panel-button:hover, #panel.login-screen .panel-button:hover, #panel.lock-screen .panel-button:hover { + color: #eff1f5; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(239, 241, 245, 0.12); +} + +#panel:overview .panel-button:hover.clock-display, #panel.unlock-screen .panel-button:hover.clock-display, #panel.login-screen .panel-button:hover.clock-display, #panel.lock-screen .panel-button:hover.clock-display { + box-shadow: none; + color: #eff1f5; +} + +#panel:overview .panel-button:hover.clock-display .clock, #panel.unlock-screen .panel-button:hover.clock-display .clock, #panel.login-screen .panel-button:hover.clock-display .clock, #panel.lock-screen .panel-button:hover.clock-display .clock { + color: #eff1f5; + box-shadow: inset 0 0 0 1000px rgba(239, 241, 245, 0.12); +} + +#panel:overview .panel-button:active, #panel:overview .panel-button:overview, #panel:overview .panel-button:focus, #panel:overview .panel-button:checked, #panel.unlock-screen .panel-button:active, #panel.unlock-screen .panel-button:overview, #panel.unlock-screen .panel-button:focus, #panel.unlock-screen .panel-button:checked, #panel.login-screen .panel-button:active, #panel.login-screen .panel-button:overview, #panel.login-screen .panel-button:focus, #panel.login-screen .panel-button:checked, #panel.lock-screen .panel-button:active, #panel.lock-screen .panel-button:overview, #panel.lock-screen .panel-button:focus, #panel.lock-screen .panel-button:checked { + color: #eff1f5; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(239, 241, 245, 0.2); +} + +#panel:overview .panel-button:active.clock-display, #panel:overview .panel-button:overview.clock-display, #panel:overview .panel-button:focus.clock-display, #panel:overview .panel-button:checked.clock-display, #panel.unlock-screen .panel-button:active.clock-display, #panel.unlock-screen .panel-button:overview.clock-display, #panel.unlock-screen .panel-button:focus.clock-display, #panel.unlock-screen .panel-button:checked.clock-display, #panel.login-screen .panel-button:active.clock-display, #panel.login-screen .panel-button:overview.clock-display, #panel.login-screen .panel-button:focus.clock-display, #panel.login-screen .panel-button:checked.clock-display, #panel.lock-screen .panel-button:active.clock-display, #panel.lock-screen .panel-button:overview.clock-display, #panel.lock-screen .panel-button:focus.clock-display, #panel.lock-screen .panel-button:checked.clock-display { + box-shadow: none; + color: #eff1f5; +} + +#panel:overview .panel-button:active.clock-display .clock, #panel:overview .panel-button:overview.clock-display .clock, #panel:overview .panel-button:focus.clock-display .clock, #panel:overview .panel-button:checked.clock-display .clock, #panel.unlock-screen .panel-button:active.clock-display .clock, #panel.unlock-screen .panel-button:overview.clock-display .clock, #panel.unlock-screen .panel-button:focus.clock-display .clock, #panel.unlock-screen .panel-button:checked.clock-display .clock, #panel.login-screen .panel-button:active.clock-display .clock, #panel.login-screen .panel-button:overview.clock-display .clock, #panel.login-screen .panel-button:focus.clock-display .clock, #panel.login-screen .panel-button:checked.clock-display .clock, #panel.lock-screen .panel-button:active.clock-display .clock, #panel.lock-screen .panel-button:overview.clock-display .clock, #panel.lock-screen .panel-button:focus.clock-display .clock, #panel.lock-screen .panel-button:checked.clock-display .clock { + box-shadow: inset 0 0 0 1000px rgba(239, 241, 245, 0.2); + color: #eff1f5; +} + +#panel:overview .panel-button#panelActivities .workspace-dot, #panel.unlock-screen .panel-button#panelActivities .workspace-dot, #panel.login-screen .panel-button#panelActivities .workspace-dot, #panel.lock-screen .panel-button#panelActivities .workspace-dot { + background-color: #eff1f5; +} + +#panel:overview .panel-corner, #panel.unlock-screen .panel-corner, #panel.login-screen .panel-corner, #panel.lock-screen .panel-corner { + -panel-corner-radius: 0; + -panel-corner-background-color: transparent; + -panel-corner-border-color: transparent; +} + +#panel Gjs_status_keyboard_InputSourceIndicator.panel-button, +#panel Gjs_appindicatorsupport_rgcjonas_gmail_com_indicatorStatusIcon_IndicatorStatusIcon.panel-button, +#panel Gjs_appindicatorsupport_rgcjonas_gmail_com_indicatorStatusIcon_AppIndicatorsIndicatorStatusIcon.panel-button { + -natural-hpadding: 18px !important; + -minimum-hpadding: 18px !important; +} + +#panel .screencast-indicator, +#panel .remote-access-indicator { + color: #df8e1d; +} + +/* Popovers/Menus */ +.popup-menu-boxpointer { + -arrow-border-radius: 18px; + -arrow-background-color: transparent; + -arrow-border-width: 0; + -arrow-border-color: transparent; + -arrow-base: 12px; + -arrow-rise: 0; + -arrow-box-shadow: none; + background: transparent; +} + +.popup-menu { + min-width: 12em; + color: rgba(239, 241, 245, 0.7) !important; + padding: 0; + border-radius: 30px; + box-shadow: 0 3px 5px -2px rgba(0, 0, 0, 0.18); + margin: 6px 6px 8px; +} + +.popup-menu .popup-menu-content { + padding: 6px; + background-color: #1e1e2e; + border-radius: 12px; + margin: 0; + border: 2px solid #89b4fa; +} + +.popup-menu .popup-menu-item { + spacing: 6px; + color: rgba(239, 241, 245, 0.7) !important; + text-shadow: none; + border-radius: 12px; + margin: 0; + transition-duration: 100ms; + background-color: transparent; +} + +.popup-menu .popup-menu-item:checked { + border: none; + box-shadow: none; + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.12) !important; + border-radius: 12px 12px 0 0 !important; +} + +.popup-menu .popup-menu-item:checked:focus, .popup-menu .popup-menu-item:checked:hover, .popup-menu .popup-menu-item:checked.selected { + color: #eff1f5 !important; + background-color: alpha(currentColor, 0.08) !important; +} + +.popup-menu .popup-menu-item:checked:active { + color: #eff1f5 !important; + background-color: alpha(currentColor, 0.12) !important; +} + +.popup-menu .popup-menu-item:checked:insensitive { + color: rgba(239, 241, 245, 0.32) !important; +} + +.popup-menu .popup-menu-item:focus, .popup-menu .popup-menu-item:hover, .popup-menu .popup-menu-item.selected { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.12) !important; + transition-duration: 0; +} + +.popup-menu .popup-menu-item:active, .popup-menu .popup-menu-item.selected:active { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.3) !important; +} + +.popup-menu .popup-menu-item:insensitive { + color: rgba(239, 241, 245, 0.32) !important; +} + +.popup-menu .popup-sub-menu { + background-color: rgba(239, 241, 245, 0.12) !important; + color: rgba(239, 241, 245, 0.7) !important; + border: none; + box-shadow: none; + margin: 0; + border-radius: 0 0 12px 12px !important; +} + +.popup-menu .popup-sub-menu .popup-menu-item { + margin: 0; +} + +.popup-menu .popup-sub-menu .popup-menu-item:focus, .popup-menu .popup-sub-menu .popup-menu-item:hover, .popup-menu .popup-sub-menu .popup-menu-item.selected { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.popup-menu .popup-sub-menu .popup-menu-item:active, .popup-menu .popup-sub-menu .popup-menu-item.selected:active { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.3) !important; +} + +.popup-menu .popup-sub-menu .popup-menu-item:insensitive { + color: rgba(239, 241, 245, 0.32) !important; +} + +.popup-menu .popup-inactive-menu-item { + color: rgba(239, 241, 245, 0.7) !important; +} + +.popup-menu .popup-inactive-menu-item:insensitive { + color: rgba(239, 241, 245, 0.32) !important; +} + +.popup-menu.panel-menu { + -boxpointer-gap: 4px; + margin-bottom: 1.75em; +} + +.popup-menu-arrow, +.popup-menu-icon { + icon-size: 16px; +} + +.popup-menu-ornament { + width: 1.2em; +} + +.popup-menu-ornament:ltr { + text-align: right; +} + +.popup-menu-ornament:rtl { + text-align: left; +} + +.background-menu { + -boxpointer-gap: 4px; + -arrow-rise: 0px; +} + +.aggregate-menu { + min-width: 20em; +} + +.aggregate-menu .popup-menu-icon { + padding: 0; + margin: 0 3px; + -st-icon-style: symbolic; +} + +.app-menu { + max-width: 27.25em; +} + +.app-menu .popup-menu-ornament { + width: 0 !important; +} + +.app-menu .popup-inactive-menu-item:first-child > StLabel:ltr { + margin-right: 8px; +} + +.app-menu .popup-inactive-menu-item:first-child > StLabel:rtl { + margin-left: 8px; +} + +/* Screen Shield */ +.unlock-dialog-clock { + color: white; + font-weight: 300; + text-align: center; + spacing: 24px; + padding-bottom: 2.5em; +} + +.unlock-dialog-clock-time { + font-size: 64pt; + padding-top: 42px; + font-feature-settings: 'tnum'; +} + +.unlock-dialog-clock-date { + font-size: 16pt; + font-weight: normal; +} + +.unlock-dialog-clock-hint { + font-weight: normal; + padding-top: 48px; +} + +.unlock-dialog-notifications-container { + margin: 12px 0; + spacing: 6px; + width: 23em; + background-color: transparent; +} + +.unlock-dialog-notifications-container .summary-notification-stack-scrollview { + padding-top: 0; + padding-bottom: 0; +} + +.unlock-dialog-notifications-container .notification, +.unlock-dialog-notifications-container .unlock-dialog-notification-source { + padding: 12px 6px; + border: none; + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 18px; +} + +.unlock-dialog-notifications-container .notification.critical, +.unlock-dialog-notifications-container .unlock-dialog-notification-source.critical { + background-color: #2e2e47; +} + +.unlock-dialog-notification-label { + padding: 0px 0px 0px 12px; +} + +.unlock-dialog-notification-count-text { + weight: bold; + padding: 0 6px; + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; + border-radius: 9999px; + margin-right: 12px; +} + +.screen-shield-background { + background: black; + box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.15); +} + +#unlockDialogNotifications StButton#vhandle, +#unlockDialogNotifications StButton#hhandle { + background-color: rgba(30, 30, 46, 0.3); +} + +#unlockDialogNotifications StButton#vhandle:hover, #unlockDialogNotifications StButton#vhandle:focus, +#unlockDialogNotifications StButton#hhandle:hover, +#unlockDialogNotifications StButton#hhandle:focus { + background-color: rgba(30, 30, 46, 0.5); +} + +#unlockDialogNotifications StButton#vhandle:active, +#unlockDialogNotifications StButton#hhandle:active { + background-color: rgba(137, 180, 250, 0.5); +} + +/* Scrollbars */ +StScrollView.vfade { + -st-vfade-offset: 32px; +} + +StScrollView.hfade { + -st-hfade-offset: 32px; +} + +StScrollBar { + padding: 0; +} + +StScrollView StScrollBar { + min-width: 12px; + min-height: 12px; +} + +StScrollBar StBin#trough { + border-radius: 9999px; + background-color: rgba(239, 241, 245, 0.12); + margin: 3px; +} + +StScrollBar StButton#vhandle, +StScrollBar StButton#hhandle { + border-radius: 9999px; + background-color: rgba(239, 241, 245, 0.5); + border: 3px solid transparent; + margin: 3px; +} + +StScrollBar StButton#vhandle:hover, +StScrollBar StButton#hhandle:hover { + background-color: rgba(239, 241, 245, 0.7); +} + +StScrollBar StButton#vhandle:active, +StScrollBar StButton#hhandle:active { + background-color: #eff1f5; +} + + +.search-entry { + width: 320px; + min-height: 32px; + padding: 0 12px; + color: rgba(239, 241, 245, 0.7); + transition-duration: 150ms; + border-radius: 12px; + caret-color: #eff1f5; + selection-background-color: rgba(239, 241, 245, 0.12); + selected-color: rgba(30, 30, 46, 0.87) !important; + color: #eff1f5; + background-color: #313244; + border: 2px solid transparent !important; + box-shadow: none !important; +} + + +.search-entry:hover { + color: #eff1f5; + background-color: #313244; + border: 2px solid rgba(239, 241, 245, 0.3) !important; + box-shadow: none !important; +} + + +.search-entry:focus { + color: #eff1f5; + background-color: #313244; + border: 2px solid #89b4fa !important; + box-shadow: none !important; +} + + +.search-entry .search-entry-icon { + icon-size: 16px; + padding: 0; + color: rgba(239, 241, 245, 0.32); +} + + +.search-entry:hover .search-entry-icon, +.search-entry:focus .search-entry-icon { + color: rgba(239, 241, 245, 0.7); +} + + +.search-entry:insensitive { + border: none; + color: rgba(239, 241, 245, 0.32); +} + + +.search-entry StLabel.hint-text { + color: rgba(239, 241, 245, 0.5); +} + +/* Slider */ +.slider { + height: 20px; + color: #313244; + -slider-height: 2px; + -slider-background-color: rgba(239, 241, 245, 0.3); + -slider-border-color: #89b4fa; + -slider-active-background-color: #89b4fa; + -slider-active-border-color: #89b4fa; + -slider-border-width: 2px; + -slider-handle-radius: 7px; + -slider-handle-border-width: 2px; + -slider-handle-border-color: #89b4fa; + -barlevel-height: 15px; + -barlevel-background-color: rgba(239, 241, 245, 0.3); + -barlevel-border-color: transparent; + -barlevel-active-background-color: #89b4fa; + -barlevel-active-border-color: transparent; + -barlevel-overdrive-color: #d20f39; + -barlevel-overdrive-border-color: transparent; + -barlevel-overdrive-separator-width: 2px; + -barlevel-border-width: 0; +} + +/* App Switcher */ +.switcher-popup { + padding: 8px; + spacing: 24px; +} + +.switcher-list .item-box { + padding: 8px; + border-radius: 12px; + border: 1px solid transparent; + background-color: transparent; +} + +.switcher-list .item-box:outlined { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.switcher-list .item-box:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.switcher-list .thumbnail-box { + padding: 2px; + spacing: 6px; +} + +.switcher-list .thumbnail { + width: 256px; +} + +.switcher-list .separator { + width: 1px; + background: rgba(239, 241, 245, 0.12); +} + +.switcher-list .switcher-list-item-container { + spacing: 12px; +} + +.switcher-arrow { + border-color: rgba(0, 0, 0, 0); + color: rgba(239, 241, 245, 0.5); +} + +.switcher-arrow:highlighted { + color: #eff1f5; +} + +.input-source-switcher-symbol { + font-size: 34pt; + width: 96px; + height: 96px; +} + +.cycler-highlight { + border: 5px solid #89b4fa; +} + +/* Switches */ +.toggle-switch { + width: 46px; + height: 24px; + background-size: contain; +} + +.toggle-switch, .popup-sub-menu .toggle-switch { + background-image: url("assets/toggle-off.svg"); +} + +.toggle-switch:checked, .popup-sub-menu .toggle-switch:checked { + background-image: url("assets/toggle-on-dark.svg"); +} + +/* Tiled window previews */ +.tile-preview { + background-color: rgba(137, 180, 250, 0.3); + border: 1px solid #89b4fa; +} + +.tile-preview-left.on-primary { + border-radius: 13px 0 0 0; +} + +.tile-preview-right.on-primary { + border-radius: 0 13px 0 0; +} + +.tile-preview-left.tile-preview-right.on-primary { + border-radius: 13px 13px 0 0; +} + +/* Workspace Switcher */ +.workspace-switcher-group { + padding: 12px; +} + +.workspace-switcher { + background: transparent; + border: none; + border-radius: 0; + padding: 0; + spacing: 12px; +} + +.ws-switcher-box { + background: transparent; + height: 50px; + background-size: 32px; + background: rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.ws-switcher-active-up, +.ws-switcher-active-down, +.ws-switcher-active-left, +.ws-switcher-active-right { + height: 52px; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + border-radius: 15px; + border: none; +} + +/* App Icons */ +.icon-grid { + row-spacing: 12px; + column-spacing: 12px; + max-row-spacing: 36px; + max-column-spacing: 36px; + page-padding-top: 24px; + page-padding-bottom: 24px; + page-padding-left: 18px; + page-padding-right: 18px; +} + +.overview-tile, .grid-search-result { + color: rgba(239, 241, 245, 0.7); + border-radius: 30px; + padding: 6px; + border: none; + transition-duration: 100ms; + text-align: center; + background-color: transparent; +} + +.overview-tile:hover, .grid-search-result:hover, .overview-tile:focus, .grid-search-result:focus, .overview-tile:selected, .grid-search-result:selected { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + border-image: none; + background-image: none; +} + +.overview-tile:active, .grid-search-result:active, .overview-tile:checked, .grid-search-result:checked { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.3); + box-shadow: none; +} + +.app-folder { + background-color: rgba(239, 241, 245, 0.12); + border-radius: 30px; + color: rgba(239, 241, 245, 0.7); +} + +.app-folder .overview-icon { + background-color: transparent; + border-radius: 30px; +} + +.app-folder:hover { + background-color: rgba(239, 241, 245, 0.2); + color: #eff1f5; +} + +.app-folder:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +.app-grid-running-dot { + width: 6px; + height: 3px; + border-radius: 2px; + background-color: rgba(239, 241, 245, 0.3); + margin-bottom: 0; +} + +StWidget.focused .app-grid-running-dot { + width: 24px; + background-color: #eff1f5 !important; +} + +.app-folder-dialog-container { + padding-top: 32px; +} + +.app-folder-dialog { + width: 720px; + height: 720px; + border-radius: 54px; + padding: 12px; + background-color: #1e1e2e; + border: 1px solid black; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.1); +} + +.app-folder-dialog .folder-name-container { + padding: 24px 36px; + padding-bottom: 0; +} + +.app-folder-dialog .folder-name-container .folder-name-entry { + width: 12em; + border: none; + caret-color: #eff1f5; +} + +.app-folder-dialog .folder-name-container .folder-name-entry:focus { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.app-folder-dialog .icon-button, .app-folder-dialog .background-app-item .close-button, .background-app-item .app-folder-dialog .close-button, .app-folder-dialog .message-notification-group .message-collapse-button, .message-notification-group .app-folder-dialog .message-collapse-button, .app-folder-dialog .message .message-header .message-expand-button, .message .message-header .app-folder-dialog .message-expand-button, +.app-folder-dialog .message .message-header .message-close-button, +.message .message-header .app-folder-dialog .message-close-button { + background-color: rgba(239, 241, 245, 0.06); + color: rgba(239, 241, 245, 0.7); + border: none; + padding: 0; + width: 36px; + height: 36px; + border-radius: 9999px; +} + +.app-folder-dialog .icon-button > StIcon, .app-folder-dialog .background-app-item .close-button > StIcon, .background-app-item .app-folder-dialog .close-button > StIcon, .app-folder-dialog .message-notification-group .message-collapse-button > StIcon, .message-notification-group .app-folder-dialog .message-collapse-button > StIcon, .app-folder-dialog .message .message-header .message-expand-button > StIcon, .message .message-header .app-folder-dialog .message-expand-button > StIcon, +.app-folder-dialog .message .message-header .message-close-button > StIcon, +.message .message-header .app-folder-dialog .message-close-button > StIcon { + icon-size: 16px; +} + +.app-folder-dialog .icon-button:hover, .app-folder-dialog .background-app-item .close-button:hover, .background-app-item .app-folder-dialog .close-button:hover, .app-folder-dialog .message-notification-group .message-collapse-button:hover, .message-notification-group .app-folder-dialog .message-collapse-button:hover, .app-folder-dialog .message .message-header .message-expand-button:hover, .message .message-header .app-folder-dialog .message-expand-button:hover, +.app-folder-dialog .message .message-header .message-close-button:hover, +.message .message-header .app-folder-dialog .message-close-button:hover { + background-color: rgba(239, 241, 245, 0.12); +} + +.app-folder-dialog .icon-button:checked, .app-folder-dialog .background-app-item .close-button:checked, .background-app-item .app-folder-dialog .close-button:checked, .app-folder-dialog .message-notification-group .message-collapse-button:checked, .message-notification-group .app-folder-dialog .message-collapse-button:checked, .app-folder-dialog .message .message-header .message-expand-button:checked, .message .message-header .app-folder-dialog .message-expand-button:checked, +.app-folder-dialog .message .message-header .message-close-button:checked, +.message .message-header .app-folder-dialog .message-close-button:checked, .app-folder-dialog .icon-button:active, .app-folder-dialog .background-app-item .close-button:active, .background-app-item .app-folder-dialog .close-button:active, .app-folder-dialog .message-notification-group .message-collapse-button:active, .message-notification-group .app-folder-dialog .message-collapse-button:active, .app-folder-dialog .message .message-header .message-expand-button:active, .message .message-header .app-folder-dialog .message-expand-button:active, +.app-folder-dialog .message .message-header .message-close-button:active, +.message .message-header .app-folder-dialog .message-close-button:active { + background-color: #eff1f5; + color: rgba(30, 30, 46, 0.87); +} + +.app-folder-dialog .page-indicators { + margin-bottom: 18px; +} + +.rename-folder-popup .rename-folder-popup-item { + spacing: 6px; +} + +.rename-folder-popup .rename-folder-popup-item:ltr, .rename-folder-popup .rename-folder-popup-item:rtl { + padding: 0 12px; +} + +.system-action-icon { + box-shadow: 0 4px 4px rgba(0, 0, 0, 0.2); + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 9999px; + icon-size: 48px; +} + +.page-navigation-hint.dnd { + background: rgba(255, 255, 255, 0.1); +} + +.page-navigation-hint.next:ltr, .page-navigation-hint.previous:rtl { + background-gradient-start: rgba(255, 255, 255, 0.05); + background-gradient-end: transparent; + background-gradient-direction: horizontal; + border-radius: 27px 0px 0px 27px; +} + +.page-navigation-hint.previous:ltr, .page-navigation-hint.next:rtl { + background-gradient-start: transparent; + background-gradient-end: rgba(255, 255, 255, 0.05); + background-gradient-direction: horizontal; + border-radius: 0px 27px 27px 0px; +} + +.page-navigation-arrow { + margin: 6px; + padding: 18px; + width: 24px; + height: 24px; + border-radius: 9999px; + transition-duration: 100ms; + color: rgba(239, 241, 245, 0.7); + background-color: transparent; +} + +.page-navigation-arrow > StIcon { + color: #eff1f5; +} + +.page-navigation-arrow:insensitive { + background-color: transparent; + color: rgba(239, 241, 245, 0.5); +} + +.page-navigation-arrow:hover { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.page-navigation-arrow:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +/* Date/Time Menu */ +.popup-menu .message, .world-clocks-button, +.weather-button, +.events-button { + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + border: none; + box-shadow: none; + text-shadow: none; +} + +.popup-menu .message:hover, .world-clocks-button:hover, +.weather-button:hover, +.events-button:hover, .popup-menu .message:focus, .world-clocks-button:focus, +.weather-button:focus, +.events-button:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none; +} + +.popup-menu .message:active, .world-clocks-button:active, +.weather-button:active, +.events-button:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none; +} + +#calendarArea { + padding: 0; +} + +.datemenu-calendar-column { + spacing: 6px; + border: none; + padding: 0 !important; + margin: 0 !important; +} + +.datemenu-calendar-column:ltr { + margin-right: 0; + border-left-width: 0; +} + +.datemenu-calendar-column:rtl { + margin-left: 0; + border-right-width: 0; +} + +.datemenu-calendar-column .datemenu-displays-section { + padding-bottom: 0; +} + +.datemenu-calendar-column .datemenu-displays-box { + spacing: 6px; +} + +.world-clocks-header, +.weather-header, +.events-section-title { + color: rgba(239, 241, 245, 0.7); + font-weight: bold; +} + +.datemenu-today-button, +.datemenu-displays-box { + margin: 4px 6px; +} + +/* today button (the date) */ +.datemenu-today-button { + border: none; + box-shadow: none; + background: none; + padding: 6px 12px; + margin: 0; + text-shadow: none; + color: rgba(239, 241, 245, 0.7); + border-radius: 12px; + margin: 4px; +} + +.datemenu-today-button:ltr { + margin-left: 4px; +} + +.datemenu-today-button:rtl { + margin-right: 4px; +} + +.datemenu-today-button:hover, .datemenu-today-button:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.datemenu-today-button:active { + background-color: rgba(239, 241, 245, 0.2); +} + +.datemenu-today-button .day-label { + font-size: 12ptpt; + font-weight: bold; +} + +.datemenu-today-button .date-label { + font-size: 18ptpt; + font-weight: normal; +} + +/* Calendar */ +.calendar { + border: none; + box-shadow: none; + background-color: transparent; + padding: 6px !important; + margin: 4px !important; + text-shadow: none; + border-radius: 18px; + color: rgba(239, 241, 245, 0.7); +} + +.calendar .calendar-month-label { + padding: 6px 0; + color: rgba(239, 241, 245, 0.7) !important; + font-weight: bold; + text-align: center; + text-shadow: none; + background-color: transparent; +} + +.calendar .calendar-change-month-back, +.calendar .calendar-change-month-forward { + padding: 0 !important; + margin: 3px 0 !important; +} + +.calendar .calendar-change-month-back StIcon, +.calendar .calendar-change-month-forward StIcon { + icon-size: 16px; +} + +.calendar .pager-button { + width: 32px !important; + height: 32px !important; + margin: 2px !important; + border-radius: 9999px; + background-color: transparent; + color: #eff1f5; + box-shadow: none !important; +} + +.calendar .pager-button:hover, .calendar .pager-button:focus { + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none !important; +} + +.calendar .pager-button:active { + background-color: rgba(239, 241, 245, 0.3); + box-shadow: none !important; +} + +.calendar .calendar-day { + font-size: 10ptpt; + text-align: center; + width: 34px !important; + height: 34px !important; + padding: 0 !important; + margin: 2px !important; + border-radius: 9999px; + color: rgba(239, 241, 245, 0.7) !important; + border: none; + font-feature-settings: 'tnum'; + background-color: transparent; +} + +.calendar .calendar-day:hover, .calendar .calendar-day:focus { + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none !important; + outline: none !important; +} + +.calendar .calendar-day:active, .calendar .calendar-day:selected { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.3); + border-color: transparent !important; + box-shadow: none !important; + outline: none !important; +} + +.calendar .calendar-day.calendar-weekend { + color: rgba(239, 241, 245, 0.5) !important; +} + +.calendar .calendar-day { + border-width: 0; +} + +.calendar .calendar-day-top { + border-top-width: 0; +} + +.calendar .calendar-day-left { + border-left-width: 0; +} + +.calendar .calendar-nonwork-day { + color: #eff1f5; +} + +.calendar .calendar-today { + font-weight: bold; + color: rgba(239, 241, 245, 0.7) !important; + background-color: rgba(239, 241, 245, 0.06); + border: none; +} + +.calendar .calendar-today:hover, .calendar .calendar-today:focus { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5 !important; +} + +.calendar .calendar-today:active { + background-color: #71a4f9; + color: rgba(30, 30, 46, 0.87) !important; +} + +.calendar .calendar-today:selected { + background-color: #89b4fa; + color: #1e1e2e !important; +} + +.calendar .calendar-today:selected:hover, .calendar .calendar-today:selected:focus { + background-color: #b0cdfc; + color: #1e1e2e !important; +} + +.calendar .calendar-day-with-events { + color: rgba(239, 241, 245, 0.7); + background-image: url("assets/calendar-today.svg"); +} + +.calendar .calendar-day-with-events.calendar-work-day { + color: rgba(239, 241, 245, 0.7); + font-weight: bold; +} + +.calendar .calendar-other-month { + color: rgba(239, 241, 245, 0.32) !important; + font-weight: normal; +} + +.calendar .calendar-other-month.calendar-weekend { + color: rgba(239, 241, 245, 0.32) !important; +} + +.calendar .calendar-day-heading { + font-weight: bold; + text-align: center; + margin: 4px; + padding: 3px 6px; + border-radius: 12px; + background-color: transparent; + color: #eff1f5; +} + +.calendar .calendar-week-number { + width: 26px; + height: 20px; + margin: 6px 2px !important; + padding: 0; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + font-weight: bold; + font-feature-settings: 'tnum'; + text-align: center; +} + +.world-clocks-button, +.weather-button, +.events-button { + padding: 12px !important; + margin: 4px 0 0 !important; +} + +.events-button .events-box { + spacing: 6px; +} + +.events-button .events-list { + spacing: 12px; + text-shadow: none; + color: rgba(239, 241, 245, 0.7); +} + +.events-button .events-title { + font-weight: bold; + text-shadow: none; + color: rgba(239, 241, 245, 0.5); +} + +.events-button .event-time { + font-feature-settings: 'tnum'; + font-size: 10ptpt; + color: rgba(239, 241, 245, 0.5); +} + +.world-clocks-button .world-clocks-grid { + spacing-rows: 6px; + spacing-columns: 12px; +} + +.world-clocks-button .world-clocks-header { + color: rgba(239, 241, 245, 0.5); +} + +.world-clocks-button .world-clocks-city { + font-weight: bold; + font-size: 11ptpt; + color: rgba(239, 241, 245, 0.7); +} + +.world-clocks-button .world-clocks-time { + font-feature-settings: 'tnum'; + font-size: 11ptpt; + color: #eff1f5; +} + +.world-clocks-button .world-clocks-time:ltr { + text-align: right; +} + +.world-clocks-button .world-clocks-time:rtl { + text-align: left; +} + +.world-clocks-button .world-clocks-timezone { + font-feature-settings: 'tnum'; + font-size: 10ptpt; + color: rgba(239, 241, 245, 0.5); +} + +.world-clocks-grid, +.weather-grid { + spacing-rows: 0.4em; + spacing-columns: 0.8em; +} + +.weather-button .weather-box { + spacing: 10px; +} + +.weather-button .weather-header-box { + spacing: 6px; +} + +.weather-button .weather-header { + font-weight: bold; + color: rgba(239, 241, 245, 0.7); +} + +.weather-button .weather-header.location { + font-weight: normal; + font-size: 10ptpt; + color: rgba(239, 241, 245, 0.5); +} + +.weather-button .weather-grid { + spacing-rows: 6px; + spacing-columns: 12px; +} + +.weather-button .weather-forecast-time { + font-feature-settings: 'tnum'; + font-size: 9ptpt; + font-weight: normal; + padding-top: 0.2em; + padding-bottom: 0.4em; + color: rgba(239, 241, 245, 0.7); +} + +.weather-button .weather-forecast-icon { + icon-size: 32px; +} + +.weather-button .weather-forecast-temp { + font-weight: bold; +} + +/* Check Boxes */ +.check-box StBoxLayout { + spacing: 0.8em; +} + +.check-box StBin { + width: 24px; + height: 24px; + padding: 3px; + border-radius: 9999px; +} + +.check-box StIcon { + icon-size: 0; + padding: 0; + color: transparent !important; + border: none !important; + background-color: transparent !important; +} + +.check-box StBin, .check-box:focus StBin { + background-image: url("assets/checkbox-off.svg"); + background-color: tranparent; + box-shadow: none; +} + +.check-box:hover StBin { + background-image: url("assets/checkbox-off-hover.svg"); + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.04); +} + +.check-box:active StBin { + background-image: url("assets/checkbox-off-active.svg"); +} + +.check-box:checked StBin, .check-box:focus:checked StBin { + background-image: url("assets/checkbox.svg"); +} + +/* Dash */ +#dash { + margin-top: 16px; +} + +#dash .dash-background { + background-color: rgba(49, 50, 68, 0.65); + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.12); + border: none; + /* remove black border on ubuntu */ + padding: 4px 3px; + border-radius: 23px; +} + +#dash .dash-item-container .placeholder { + background-image: none; + background-size: contain; + height: 32px; +} + +#dash .dash-item-container .empty-dash-drop-target { + width: 32px; + height: 32px; +} + +#dash .dash-item-container .show-apps, +#dash .dash-item-container .overview-tile, +#dash .dash-item-container .grid-search-result { + background: none; + box-shadow: none; + border: none; + border-radius: 0; + padding: 0; + margin: 0 2px; + padding-bottom: 16px; +} + +#dash .dash-item-container .show-apps .overview-icon, +#dash .dash-item-container .overview-tile .overview-icon, +#dash .dash-item-container .grid-search-result .overview-icon { + border-radius: 16px; + padding: 4px; + spacing: 4px; + text-align: center; + transition-duration: 100ms; + background-color: transparent; + color: #eff1f5; +} + +#dash .dash-item-container .show-apps:focus .overview-icon, +#dash .dash-item-container .overview-tile:focus .overview-icon, +#dash .dash-item-container .grid-search-result:focus .overview-icon { + background-color: rgba(239, 241, 245, 0.12); +} + +#dash .dash-item-container .show-apps:hover .overview-icon, +#dash .dash-item-container .overview-tile:hover .overview-icon, +#dash .dash-item-container .grid-search-result:hover .overview-icon { + background-color: rgba(239, 241, 245, 0.15); + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.15); +} + +#dash .dash-item-container .show-apps:active .overview-icon, +#dash .dash-item-container .overview-tile:active .overview-icon, +#dash .dash-item-container .grid-search-result:active .overview-icon { + background-color: rgba(239, 241, 245, 0.3); +} + +#dash .dash-item-container .show-apps:checked .overview-icon, +#dash .dash-item-container .overview-tile:checked .overview-icon, +#dash .dash-item-container .grid-search-result:checked .overview-icon { + background-color: rgba(239, 241, 245, 0.12); +} + +#dash .dash-item-container .app-well-app-running-dot, +#dash .dash-item-container .app-grid-running-dot { + margin-bottom: 12px; + offset-y: 8px; + width: 6px; + height: 6px; + border-radius: 9999px; + background-color: #eff1f5; +} + +#dash .dash-separator { + width: 1px; + margin-left: 4px; + margin-right: 4px; + background-color: rgba(239, 241, 245, 0.25); +} + +#dash .dash-separator, +#dash .dash-background { + margin-bottom: 16px; +} + +.dash-label { + background-color: #181825; + color: #9399b2; + border-radius: 12px; + padding: 6px 12px; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.12); + border: none; + text-align: center; + -y-offset: 12px; + -x-offset: 8px; +} + +/* Modal Dialogs */ +.modal-dialog, .candidate-popup-content { + background-color: #292c3c; + border-radius: 18px; + border: none; + box-shadow: inset 0 0.5px rgba(239, 241, 245, 0.1); + border: 2px solid #89b4fa; +} + +.modal-dialog-button:last-child, .modal-dialog-linked-button:last-child { + background-color: #89b4fa; + color: #1e1e2e; +} + +.modal-dialog-button:hover:last-child, .modal-dialog-linked-button:hover:last-child { + background-color: #b5d0fc; + color: #1e1e2e; +} + +.modal-dialog-button:active:last-child, .modal-dialog-linked-button:active:last-child { + background-color: #71a4f9; + color: #1e1e2e; +} + +.modal-dialog-button:insensitive:last-child, .modal-dialog-linked-button:insensitive:last-child { + background-color: rgba(137, 180, 250, 0.05); + color: rgba(137, 180, 250, 0.35); +} + +.headline { + font-size: 12ptpt; +} + +.modal-dialog { + color: rgba(239, 241, 245, 0.7); + padding: 12px; + margin: 0; +} + +.modal-dialog-button, .modal-dialog-linked-button { + min-height: 32px !important; + padding: 6px !important; + margin: 0 !important; + border: none !important; + border-radius: 12px; +} + +.modal-dialog-button:first-child, .modal-dialog-linked-button:first-child { + background-color: rgba(239, 241, 245, 0.04); +} + +.modal-dialog-button:first-child:focus, .modal-dialog-linked-button:first-child:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.modal-dialog-button:first-child:hover, .modal-dialog-linked-button:first-child:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.modal-dialog-button:first-child:active, .modal-dialog-linked-button:first-child:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.modal-dialog .modal-dialog-button-box { + padding-top: 6px; +} + +.modal-dialog .modal-dialog-content-box { + margin: 6px; + spacing: 6px; + max-width: 28em; +} + +.end-session-dialog { + width: 26em; +} + +.end-session-dialog .end-session-dialog-battery-warning, +.end-session-dialog .dialog-list-title { + color: #df8e1d; + background-color: rgba(223, 142, 29, 0.1); + padding: 9px; + border-radius: 12px; + margin: 4px 0; +} + +.message-dialog-content { + spacing: 18px; +} + +.message-dialog-content .message-dialog-title { + text-align: center; +} + +.message-dialog-content .message-dialog-description { + text-align: center; +} + +.dialog-list { + spacing: 18px; +} + +.dialog-list .dialog-list-title { + text-align: center; +} + +.dialog-list .dialog-list-scrollview { + max-height: 200px; +} + +.dialog-list .dialog-list-box { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-title { + font-weight: bold; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + color: rgba(239, 241, 245, 0.7); +} + +.run-dialog { + width: 26em; + padding-bottom: 6px; +} + +.run-dialog .run-dialog-entry { + padding: 12px 9px; +} + +.run-dialog .run-dialog-description { + text-align: center; + color: rgba(239, 241, 245, 0.7); +} + +.prompt-dialog { + width: 28em; +} + +.prompt-dialog .prompt-dialog-password-grid { + spacing-rows: 8px; + spacing-columns: 4px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry { + width: auto; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:ltr { + margin-left: 20px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:rtl { + margin-right: 20px; +} + +.prompt-dialog .prompt-dialog-password-layout { + spacing: 8px; +} + +.prompt-dialog .prompt-dialog-password-entry { + width: 20em; + padding: 12px 9px; +} + +.prompt-dialog .prompt-dialog-error-label, +.prompt-dialog .prompt-dialog-info-label, +.prompt-dialog .prompt-dialog-null-label { + text-align: center; +} + +.prompt-dialog .prompt-dialog-error-label { + color: #df8e1d; +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 8px; + margin-bottom: 6px; +} + +.polkit-dialog-user-layout .polkit-dialog-user-root-label { + color: #df8e1d; +} + +.audio-device-selection-dialog { + min-width: 24em; +} + +.audio-device-selection-dialog .audio-selection-box { + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device { + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:hover, .audio-device-selection-dialog .audio-selection-box .audio-selection-device:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:active { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-box { + padding: 12px; + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-icon { + icon-size: 64px; +} + +.welcome-dialog-image { + background-image: url("resource:///org/gnome/shell/theme/gnome-shell-start.svg"); + background-size: contain; + height: 300px; + width: 300px; +} + +/* Access portal dialog */ +.access-dialog { + text-align: center; +} + +/* Modal Dialogs */ +.modal-dialog, .candidate-popup-content { + background-color: #292c3c; + border-radius: 18px; + border: none; + box-shadow: inset 0 0.5px rgba(239, 241, 245, 0.1); + border: 2px solid #89b4fa; +} + +.modal-dialog-linked-button:last-child, .modal-dialog-button:last-child { + background-color: #89b4fa; + color: #1e1e2e; +} + +.modal-dialog-linked-button:hover:last-child, .modal-dialog-button:hover:last-child { + background-color: #b5d0fc; + color: #1e1e2e; +} + +.modal-dialog-linked-button:active:last-child, .modal-dialog-button:active:last-child { + background-color: #71a4f9; + color: #1e1e2e; +} + +.modal-dialog-linked-button:insensitive:last-child, .modal-dialog-button:insensitive:last-child { + background-color: rgba(137, 180, 250, 0.05); + color: rgba(137, 180, 250, 0.35); +} + +.headline { + font-size: 12ptpt; +} + +.modal-dialog { + color: rgba(239, 241, 245, 0.7); + padding: 12px; + margin: 0; +} + +.modal-dialog-button, .modal-dialog-linked-button { + min-height: 32px !important; + padding: 6px !important; + margin: 0 !important; + border: none !important; + border-radius: 12px; +} + +.modal-dialog-button:first-child, .modal-dialog-linked-button:first-child { + background-color: rgba(239, 241, 245, 0.04); +} + +.modal-dialog-button:first-child:focus, .modal-dialog-linked-button:first-child:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.modal-dialog-button:first-child:hover, .modal-dialog-linked-button:first-child:hover { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.modal-dialog-button:first-child:active, .modal-dialog-linked-button:first-child:active { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + box-shadow: none !important; +} + +.modal-dialog .modal-dialog-button-box { + padding-top: 6px; +} + +.modal-dialog .modal-dialog-content-box { + margin: 6px; + spacing: 6px; + max-width: 28em; +} + +.end-session-dialog { + width: 26em; +} + +.end-session-dialog .end-session-dialog-battery-warning, +.end-session-dialog .dialog-list-title { + color: #df8e1d; + background-color: rgba(223, 142, 29, 0.1); + padding: 9px; + border-radius: 12px; + margin: 4px 0; +} + +.message-dialog-content { + spacing: 18px; +} + +.message-dialog-content .message-dialog-title { + text-align: center; +} + +.message-dialog-content .message-dialog-description { + text-align: center; +} + +.dialog-list { + spacing: 18px; +} + +.dialog-list .dialog-list-title { + text-align: center; +} + +.dialog-list .dialog-list-scrollview { + max-height: 200px; +} + +.dialog-list .dialog-list-box { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-title { + font-weight: bold; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + color: rgba(239, 241, 245, 0.7); +} + +.run-dialog { + width: 26em; + padding-bottom: 6px; +} + +.run-dialog .run-dialog-entry { + padding: 12px 9px; +} + +.run-dialog .run-dialog-description { + text-align: center; + color: rgba(239, 241, 245, 0.7); +} + +.prompt-dialog { + width: 28em; +} + +.prompt-dialog .prompt-dialog-password-grid { + spacing-rows: 8px; + spacing-columns: 4px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry { + width: auto; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:ltr { + margin-left: 20px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:rtl { + margin-right: 20px; +} + +.prompt-dialog .prompt-dialog-password-layout { + spacing: 8px; +} + +.prompt-dialog .prompt-dialog-password-entry { + width: 20em; + padding: 12px 9px; +} + +.prompt-dialog .prompt-dialog-error-label, +.prompt-dialog .prompt-dialog-info-label, +.prompt-dialog .prompt-dialog-null-label { + text-align: center; +} + +.prompt-dialog .prompt-dialog-error-label { + color: #df8e1d; +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 8px; + margin-bottom: 6px; +} + +.polkit-dialog-user-layout .polkit-dialog-user-root-label { + color: #df8e1d; +} + +.audio-device-selection-dialog { + min-width: 24em; +} + +.audio-device-selection-dialog .audio-selection-box { + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device { + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:hover, .audio-device-selection-dialog .audio-selection-box .audio-selection-device:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:active { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-box { + padding: 12px; + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-icon { + icon-size: 64px; +} + +.welcome-dialog-image { + background-image: url("resource:///org/gnome/shell/theme/gnome-shell-start.svg"); + background-size: contain; + height: 300px; + width: 300px; +} + +/* Access portal dialog */ +.access-dialog { + text-align: center; +} + +/* Message List */ +.message-list { + width: 29em; + text-shadow: none; + border: solid rgba(239, 241, 245, 0.12); + padding: 0; +} + +.message-list:ltr { + margin-left: 0; + margin-right: 8px; + padding-right: 10px; + border-right-width: 0; +} + +.message-list:rtl { + margin-right: 0; + margin-left: 8px; + padding-left: 10px; + border-left-width: 0; +} + +.message-list .message-list-placeholder { + spacing: 12px; + color: rgba(239, 241, 245, 0.32); +} + +.message-list .message-list-placeholder > StIcon { + icon-size: 96px; + margin-bottom: 12px; + -st-icon-style: symbolic; +} + +.message-list-sections { + margin: 0; + padding-bottom: 6px; +} + +.message-list-sections:ltr { + margin-right: 0; +} + +.message-list-sections:rtl { + margin-left: 0; +} + +.message-list-section, +.message-list-sections, +.message-list-section-list { + spacing: 6px; +} + +.message-list-controls { + margin: 8px 16px 0; + padding: 6px; + spacing: 6px; +} + +.message-list-controls .dnd-button { + border-width: 2px; + border-color: transparent; + border-radius: 32px; + border-style: solid; +} + +.message-list-controls .dnd-button:focus { + border-color: rgba(137, 180, 250, 0.6); +} + +.message { + padding: 0; + margin: 3px; + border-radius: 20px; +} + +.popup-menu .message { + border-radius: 12px; +} + +.popup-menu .message .notification-button:first-child:ltr { + border-radius: 0 0 0 12px; +} + +.popup-menu .message .notification-button:last-child:ltr { + border-radius: 0 0 12px; +} + +.popup-menu .message .notification-button:first-child:rtl { + border-radius: 0 0 12px; +} + +.popup-menu .message .notification-button:last-child:rtl { + border-radius: 0 0 0 12px; +} + +.popup-menu .message .notification-button:first-child:last-child { + border-radius: 0 0 12px 12px; +} + +.message .message-header { + padding: 0 0.409em; + margin: 6px; + margin-bottom: 0; + spacing: 6px; + color: rgba(239, 241, 245, 0.5); +} + +.message .message-header .message-source-icon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.message .message-header .message-header-content { + spacing: 6px; + min-height: 1.637em; + padding-bottom: 6px; +} + +.message .message-header .message-header-content .message-source-title { + font-weight: bold; +} + +.message .message-header .message-header-content .event-time { + padding-bottom: 0.068em; + color: rgba(239, 241, 245, 0.5); +} + +.message .message-header .message-header-content .event-time:ltr { + text-align: right; +} + +.message .message-header .message-header-content .event-time:rtl { + text-align: left; +} + +.message .message-header .message-expand-button, +.message .message-header .message-close-button { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button, .message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:active, +.message .message-header .message-close-button, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:active { + color: #eff1f5; +} + +.message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:focus, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.message .message-header .message-expand-button:active, .message .message-header .message-expand-button:active:hover, +.message .message-header .message-close-button:active, +.message .message-header .message-close-button:active:hover { + background-color: rgba(239, 241, 245, 0.3); +} + +.message .message-header .message-expand-button:insensitive, +.message .message-header .message-close-button:insensitive { + background-color: rgba(239, 241, 245, 0.04); +} + +.message .message-header .message-expand-button { + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button:ltr { + margin-right: 6px; +} + +.message .message-header .message-expand-button:rtl { + margin-left: 6px; +} + +.message .message-box { + padding: 6px; + margin: 6px; + margin-top: 0; + spacing: 6px; +} + +.message .message-box .message-icon { + icon-size: 48px; + -st-icon-style: symbolic; +} + +.message .message-box .message-icon:ltr { + margin-right: 6px; +} + +.message .message-box .message-icon:rtl { + margin-left: 6px; +} + +.message .message-box .message-icon.message-themed-icon { + border-radius: 9999px; + icon-size: 16px; + min-width: 48px; + min-height: 48px; + color: rgba(239, 241, 245, 0.5); + background-color: rgba(239, 241, 245, 0.12); +} + +.message .message-box:first-child { + margin-top: 12px; +} + +.message .message-box .message-content { + spacing: 4px; +} + +.message .message-box .message-content .message-title { + font-weight: bold; +} + +.url-highlighter { + link-color: #8fcbe8; +} + +.message-media-control { + margin: 4px 6px; + padding: 12px; + border-radius: 9999px; + border: none; + color: rgba(239, 241, 245, 0.7); +} + +.message-media-control:hover, .message-media-control:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.message-media-control:active { + background-color: rgba(239, 241, 245, 0.3); +} + +.message-media-control:hover, .message-media-control:focus, .message-media-control:active { + color: #eff1f5; +} + +.message-media-control:insensitive { + color: rgba(239, 241, 245, 0.5); +} + +.message-media-control StIcon { + icon-size: 16px; +} + +.media-message .message-icon { + border-radius: 6px !important; +} + +.media-message .message-icon.message-themed-icon { + icon-size: 32px !important; +} + +/* Message List */ +.message-list { + width: 29em; + text-shadow: none; + border: solid rgba(239, 241, 245, 0.12); + padding: 0; +} + +.message-list:ltr { + margin-left: 2px; + margin-right: 8px; + padding-right: 10px; + border-right-width: 0; +} + +.message-list:rtl { + margin-right: 0; + margin-left: 8px; + padding-left: 10px; + border-left-width: 0; +} + +.message-list .message-list-placeholder { + spacing: 12px; + color: rgba(239, 241, 245, 0.32); +} + +.message-list .message-list-placeholder > StIcon { + icon-size: 96px; + margin-bottom: 12px; + -st-icon-style: symbolic; +} + +.message-view { + -st-vfade-offset: 24px; +} + +.message-view:ltr { + margin-right: 12px; +} + +.message-view:rtl { + margin-left: 12px; +} + +.message-view .message { + margin-bottom: 12px !important; +} + +.message-list-controls { + margin: 8px 16px 0; + padding: 6px; + spacing: 6px; +} + +.message-list-controls .dnd-button { + border-width: 2px; + border-color: transparent; + border-radius: 32px; + border-style: solid; +} + +.message-list-controls .dnd-button:focus { + border-color: rgba(137, 180, 250, 0.6); +} + +.message-notification-group { + spacing: 12px; +} + +.message-notification-group .message-group-header { + padding: 6px; +} + +.message-notification-group .message-group-header .message-group-title { + margin: 0 4px; +} + +.message-notification-group .message-collapse-button { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + padding: 4px !important; + border: 4px transparent solid; +} + +.message-notification-group .message-collapse-button:hover { + background-color: rgba(239, 241, 245, 0.3); +} + +.message-notification-group .message-collapse-button:active { + background-color: rgba(239, 241, 245, 0.2); +} + +.message { + padding: 0; + margin: 3px; + border-radius: 20px; +} + +.popup-menu .message { + border-radius: 12px; + color: rgba(239, 241, 245, 0.5); + background-color: #26263a; + border: 1px solid rgba(30, 30, 46, 0.75); + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.1); + /* &:insensitive { + color: $text-disabled; + background-color: lighten($background, 4%); + box-shadow: none !important; + } */ +} + +.popup-menu .message:hover, .popup-menu .message:focus { + color: rgba(137, 180, 250, 0.5); + background-color: #28283d; +} + +.popup-menu .message:active { + color: #eff1f5; + background-color: #26263a; + box-shadow: none !important; +} + +.message:second-in-stack { + background-color: #2a2a41; +} + +.message:lower-in-stack { + background-color: #2e2e47; + border: 1px solid rgba(239, 241, 245, 0); +} + +.message .message-header { + padding: 0 0.409em; + margin: 6px; + margin-bottom: 0; + spacing: 6px; + color: rgba(239, 241, 245, 0.5); + /* .message-close-button { + margin-left: $base_padding * 0.5; + padding: 4px; + } */ +} + +.message .message-header:ltr { + padding-right: 0; +} + +.message .message-header:rtl { + padding-left: 0; +} + +.message .message-header .message-source-icon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.message .message-header .message-header-content { + spacing: 6px; + min-height: 1.637em; + padding-bottom: 6px; +} + +.message .message-header .message-header-content .message-source-title { + font-weight: bold; +} + +.message .message-header .message-header-content .event-time { + padding-bottom: 0.068em; + color: rgba(239, 241, 245, 0.5); +} + +.message .message-header .message-header-content .event-time:ltr { + text-align: right; +} + +.message .message-header .message-header-content .event-time:rtl { + text-align: left; +} + +.message .message-header .message-expand-button, +.message .message-header .message-close-button { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button, .message .message-header .message-expand-button:hover, +.message .message-header .message-close-button, +.message .message-header .message-close-button:hover { + color: #eff1f5; +} + +.message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:focus, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.message .message-header .message-expand-button:active, .message .message-header .message-expand-button:active:hover, +.message .message-header .message-close-button:active, +.message .message-header .message-close-button:active:hover { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.message .message-header .message-expand-button:insensitive, +.message .message-header .message-close-button:insensitive { + background-color: rgba(239, 241, 245, 0.04); +} + +.message .message-header .message-expand-button { + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button:ltr { + margin-right: 6px; +} + +.message .message-header .message-expand-button:rtl { + margin-left: 6px; +} + +.message .message-box { + padding: 6px; + margin: 6px; + margin-top: 0; + spacing: 6px; +} + +.message .message-box .message-icon { + icon-size: 48px; + -st-icon-style: symbolic; +} + +.message .message-box .message-icon:ltr { + margin-right: 6px; +} + +.message .message-box .message-icon:rtl { + margin-left: 6px; +} + +.message .message-box .message-icon.message-themed-icon { + border-radius: 9999px; + icon-size: 16px; + min-width: 48px; + min-height: 48px; + color: rgba(239, 241, 245, 0.5); + background-color: rgba(239, 241, 245, 0.12); +} + +.message .message-box:first-child { + margin-top: 12px; +} + +.message .message-box .message-content { + spacing: 4px; +} + +.message .message-box .message-content .message-title { + font-weight: bold; +} + +.url-highlighter { + link-color: #8fcbe8; +} + +.message-media-control { + margin: 4px 6px; + padding: 12px; + border-radius: 9999px; + border: none; + color: rgba(239, 241, 245, 0.7); +} + +.message-media-control:hover, .message-media-control:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.message-media-control:active { + background-color: rgba(239, 241, 245, 0.3); +} + +.message-media-control:hover, .message-media-control:focus, .message-media-control:active { + color: #eff1f5; +} + +.message-media-control:insensitive { + color: rgba(239, 241, 245, 0.5); +} + +.message-media-control StIcon { + icon-size: 16px; +} + +.media-message .message-icon { + border-radius: 6px !important; +} + +.media-message .message-icon.message-themed-icon { + icon-size: 32px !important; +} + +/* Message List */ +.message-list { + width: 29em; + text-shadow: none; + border: solid rgba(239, 241, 245, 0.12); + padding: 0; +} + +.message-list:ltr { + margin-left: 2px; + margin-right: 8px; + padding-right: 10px; + border-right-width: 0; +} + +.message-list:rtl { + margin-right: 0; + margin-left: 8px; + padding-left: 10px; + border-left-width: 0; +} + +.message-list .message-list-placeholder { + spacing: 12px; + color: rgba(239, 241, 245, 0.32); +} + +.message-list .message-list-placeholder > StIcon { + icon-size: 96px; + margin-bottom: 12px; + -st-icon-style: symbolic; +} + +.message-view { + -st-vfade-offset: 24px; +} + +.message-view:ltr { + margin-right: 12px; +} + +.message-view:rtl { + margin-left: 12px; +} + +.message-view .message { + margin-bottom: 12px !important; +} + +.message-list-controls { + margin: 8px 16px 0; + padding: 6px; + spacing: 6px; +} + +.message-list-controls .dnd-button { + border-width: 2px; + border-color: transparent; + border-radius: 32px; + border-style: solid; +} + +.message-list-controls .dnd-button:focus { + border-color: rgba(137, 180, 250, 0.6); +} + +.message-notification-group { + spacing: 12px; +} + +.message-notification-group .message-group-header { + padding: 6px; +} + +.message-notification-group .message-group-header .message-group-title { + margin: 0 4px; +} + +.message-notification-group .message-collapse-button { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.2); + padding: 4px !important; + border: 4px transparent solid; +} + +.message-notification-group .message-collapse-button:hover { + background-color: rgba(239, 241, 245, 0.3); +} + +.message-notification-group .message-collapse-button:active { + background-color: rgba(239, 241, 245, 0.2); +} + +.message { + padding: 0; + margin: 3px; + border-radius: 20px; +} + +.popup-menu .message { + border-radius: 12px; + color: rgba(239, 241, 245, 0.5); + background-color: #26263a; + border: 1px solid rgba(30, 30, 46, 0.75); + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.1); + /* &:insensitive { + color: $text-disabled; + background-color: lighten($background, 4%); + box-shadow: none !important; + } */ +} + +.popup-menu .message:hover, .popup-menu .message:focus { + color: rgba(137, 180, 250, 0.5); + background-color: #28283d; +} + +.popup-menu .message:active { + color: #eff1f5; + background-color: #26263a; + box-shadow: none !important; +} + +.message:second-in-stack { + background-color: #2a2a41; +} + +.message:lower-in-stack { + background-color: #2e2e47; + border: 1px solid rgba(239, 241, 245, 0); +} + +.message .message-header { + padding: 0 0.409em; + margin: 6px; + margin-bottom: 0; + spacing: 6px; + color: rgba(239, 241, 245, 0.5); + /* .message-close-button { + margin-left: $base_padding * 0.5; + padding: 4px; + } */ +} + +.message .message-header:ltr { + padding-right: 0; +} + +.message .message-header:rtl { + padding-left: 0; +} + +.message .message-header .message-source-icon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.message .message-header .message-header-content { + spacing: 6px; + min-height: 1.637em; + padding-bottom: 6px; +} + +.message .message-header .message-header-content .message-source-title { + font-weight: bold; +} + +.message .message-header .message-header-content .event-time { + padding-bottom: 0.068em; + color: rgba(239, 241, 245, 0.5); +} + +.message .message-header .message-header-content .event-time:ltr { + text-align: right; +} + +.message .message-header .message-header-content .event-time:rtl { + text-align: left; +} + +.message .message-header .message-expand-button, +.message .message-header .message-close-button { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button, .message .message-header .message-expand-button:hover, +.message .message-header .message-close-button, +.message .message-header .message-close-button:hover { + color: #eff1f5; +} + +.message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:focus, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.message .message-header .message-expand-button:active, .message .message-header .message-expand-button:active:hover, +.message .message-header .message-close-button:active, +.message .message-header .message-close-button:active:hover { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.message .message-header .message-expand-button:insensitive, +.message .message-header .message-close-button:insensitive { + background-color: rgba(239, 241, 245, 0.04); +} + +.message .message-header .message-expand-button { + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button:ltr { + margin-right: 6px; +} + +.message .message-header .message-expand-button:rtl { + margin-left: 6px; +} + +.message .message-box { + padding: 6px; + margin: 6px; + margin-top: 0; + spacing: 6px; +} + +.message .message-box .message-icon { + icon-size: 48px; + -st-icon-style: symbolic; +} + +.message .message-box .message-icon:ltr { + margin-right: 6px; +} + +.message .message-box .message-icon:rtl { + margin-left: 6px; +} + +.message .message-box .message-icon.message-themed-icon { + border-radius: 9999px; + icon-size: 16px; + min-width: 48px; + min-height: 48px; + color: rgba(239, 241, 245, 0.5); + background-color: rgba(239, 241, 245, 0.12); +} + +.message .message-box:first-child { + margin-top: 12px; +} + +.message .message-box .message-content { + spacing: 4px; +} + +.message .message-box .message-content .message-title { + font-weight: bold; +} + +.url-highlighter { + link-color: #8fcbe8; +} + +.message-media-control { + margin: 4px 6px; + padding: 12px; + border-radius: 9999px; + border: none; + color: rgba(239, 241, 245, 0.7); +} + +.message-media-control:hover, .message-media-control:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.message-media-control:active { + background-color: rgba(239, 241, 245, 0.3); +} + +.message-media-control:hover, .message-media-control:focus, .message-media-control:active { + color: #eff1f5; +} + +.message-media-control:insensitive { + color: rgba(239, 241, 245, 0.5); +} + +.message-media-control StIcon { + icon-size: 16px; +} + +.media-message .message-icon { + border-radius: 6px !important; +} + +.media-message .message-icon.message-themed-icon { + icon-size: 32px !important; +} + +.workspace-animation { + background-color: #1e1e2e; +} + +.calendar .calendar-change-month-back, +.calendar .calendar-change-month-forward { + padding: 0 2px; +} + +/* Notifications & Message Tray */ +.notification-banner { + min-height: 64px; + width: 34em; + margin: 20px; + border-radius: 12px; + color: rgba(239, 241, 245, 0.7); + background-color: #292c3c; + border: none; + text-shadow: none; + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.25); + border-radius: 18px; + border: 2px solid #89b4fa; +} + +.notification-banner:hover, .notification-banner:active { + color: #eff1f5; + background-color: #292c3c; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.25); + margin: 20px; +} + +.notification-banner:focus { + color: #eff1f5; + background-color: #292c3c; +} + +.notification-buttons-bin { + background-color: transparent; + padding-top: 0; + border: none; + border-top: 1px solid rgba(239, 241, 245, 0.12); + spacing: 0; +} + +.notification-button { + min-height: 44px; + padding: 0 18px; + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + font-weight: 500; + border: none; +} + +.notification-button:focus { + background-color: transparent; + color: #eff1f5; + box-shadow: inset 0 0 0 2px rgba(239, 241, 245, 0.12); +} + +.notification-button:hover, .notification-button:focus:hover { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; + box-shadow: none; +} + +.notification-button:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +.notification-button:first-child:ltr { + border-radius: 0 0 0 18px; +} + +.notification-button:last-child:ltr { + border-radius: 0 0 18px; + margin-right: 0 !important; +} + +.notification-button:first-child:rtl { + border-radius: 0 0 18px; +} + +.notification-button:last-child:rtl { + border-radius: 0 0 0 18px; + margin-left: 0 !important; +} + +.notification-button:first-child:last-child { + border-radius: 0 0 18px 18px; + margin-left: 0 !important; + margin-right: 0 !important; +} + +/* Notifications & Message Tray */ +.notification-banner { + min-height: 64px; + width: 34em; + padding: 0; + margin: 12px 8px 8px; + color: rgba(239, 241, 245, 0.7); + background-color: #232634; + text-shadow: none; + border-radius: 18px; + border: none; + border: 2px solid #89b4fa; +} + +.notification-banner:hover, .notification-banner:active, .notification-banner:focus { + color: #89b4fa; + background-color: #2d3143; + border: 1px solid rgba(30, 30, 46, 0.75); + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.1); +} + +.notification-buttons-bin { + spacing: 0; +} + +.notification-button { + min-height: 6px; + padding: 12px 0; + margin: 0; + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + font-weight: 500; + border: none; + border-radius: 12px; +} + +.notification-button:focus { + background-color: transparent; + color: #eff1f5; + box-shadow: inset 0 0 0 2px rgba(239, 241, 245, 0.12); +} + +.notification-button:hover, .notification-button:focus:hover { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; + box-shadow: none; +} + +.notification-button:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +/* Notifications & Message Tray */ +.notification-banner { + min-height: 64px; + width: 34em; + padding: 0; + margin: 12px 8px 8px; + color: rgba(239, 241, 245, 0.7); + background-color: #232634; + text-shadow: none; + border-radius: 18px; + border: none; + border: 2px solid #89b4fa; +} + +.notification-banner:hover, .notification-banner:active, .notification-banner:focus { + color: #89b4fa; + background-color: #2d3143; + border: 1px solid rgba(30, 30, 46, 0.75); + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.1); +} + +.notification-buttons-bin { + spacing: 0; +} + +.notification-button { + min-height: 6px; + padding: 12px 0; + margin: 0; + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + font-weight: 500; + border: none; + border-radius: 12px; +} + +.notification-button:focus { + background-color: transparent; + color: #eff1f5; + box-shadow: inset 0 0 0 2px rgba(239, 241, 245, 0.12); +} + +.notification-button:hover, .notification-button:focus:hover { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; + box-shadow: none; +} + +.notification-button:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +.controls-manager, +.secondary-monitor-workspaces { + spacing: 12px; +} + +#overviewGroup { + background-color: #11111b; +} + +.osd-window { + spacing: 12px; + padding: 12px 18px; + margin-bottom: 4em; +} + +.osd-window > * { + spacing: 8px; +} + +.osd-window StIcon { + icon-size: 32px; +} + +.osd-window StLabel:ltr { + margin-right: 6px; +} + +.osd-window StLabel:rtl { + margin-left: 6px; +} + +#appMenu { + spacing: 6px; +} + +#appMenu .label-shadow { + color: transparent; +} + +#appMenu .panel-status-menu-box { + padding: 0 6px; + spacing: 6px; +} + +.popup-menu .popup-menu-item { + padding: 9px 12px; +} + +.popup-separator-menu-item { + padding: 3px 0 !important; +} + +.popup-separator-menu-item .popup-menu-ornament { + width: 0 !important; +} + +.popup-separator-menu-item .popup-separator-menu-item-separator { + height: 1px; + background-color: rgba(239, 241, 245, 0.12); + margin: 6px 32px; + padding: 0 !important; +} + +.popup-sub-menu .popup-separator-menu-item .popup-separator-menu-item-separator { + padding: 0 !important; + margin: 0 32px 0 0; + height: 1px; +} + +.popup-menu-ornament { + icon-size: 16px !important; + width: 16px; +} + +/* Quick Settings */ +.quick-settings { + padding: 18px !important; + border-radius: 24px !important; + margin-top: 6px !important; +} + +.quick-settings .icon-button, .quick-settings .background-app-item .close-button, .background-app-item .quick-settings .close-button, .quick-settings .message .message-header .message-expand-button, .message .message-header .quick-settings .message-expand-button, +.quick-settings .message .message-header .message-close-button, +.message .message-header .quick-settings .message-close-button, .quick-settings .message-notification-group .message-collapse-button, .message-notification-group .quick-settings .message-collapse-button, +.quick-settings .button { + padding: 10.5px; +} + +.quick-settings .icon-button > StIcon, .quick-settings .background-app-item .close-button > StIcon, .background-app-item .quick-settings .close-button > StIcon, .quick-settings .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings .message-expand-button > StIcon, +.quick-settings .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings .message-close-button > StIcon, .quick-settings .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings .message-collapse-button > StIcon, +.quick-settings .button > StIcon { + icon-size: 16px; +} + +.quick-settings-grid { + spacing-rows: 12px; + spacing-columns: 12px; +} + +.quick-toggle, +.quick-menu-toggle { + border-radius: 12px; + min-width: 12em; + max-width: 12em; + min-height: 44px; + border: none; + margin: 1px; +} + +.quick-toggle { + background-color: rgba(239, 241, 245, 0.08) !important; + /* Move padding into the box; this is to allow menu arrows + to extend to the border */ +} + +.quick-toggle:hover { + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.quick-toggle:active { + background-color: rgba(239, 241, 245, 0.15) !important; +} + +.quick-toggle:checked { + background-color: rgba(137, 180, 250, 0.95) !important; + color: #1e1e2e; +} + +.quick-toggle:checked:hover { + background-color: #b2ccf8 !important; + color: #1e1e2e; +} + +.quick-toggle:checked:active { + background-color: #9dc0f9 !important; + color: #1e1e2e; +} + +.quick-toggle > StBoxLayout { + spacing: 6px; +} + +.quick-toggle.button { + padding: 0; +} + +.quick-toggle > StBoxLayout { + padding: 0 12px; +} + +.quick-toggle:ltr > StBoxLayout { + padding-left: 15px; +} + +.quick-toggle:rtl > StBoxLayout { + padding-right: 15px; +} + +.quick-toggle .quick-toggle-title { + font-weight: bold; +} + +.quick-toggle StBoxLayout > .quick-toggle-subtitle { + font-weight: normal; + font-size: 12px; +} + +.quick-toggle .quick-toggle-icon { + icon-size: 16px; +} + +.quick-menu-toggle .quick-toggle { + min-width: auto; + max-width: auto; +} + +.quick-menu-toggle .quick-toggle:ltr { + border-radius: 12px 0 0 12px; +} + +.quick-menu-toggle .quick-toggle:ltr > StBoxLayout { + padding-right: 9px; +} + +.quick-menu-toggle .quick-toggle:rtl { + border-radius: 0 12px 12px 0; +} + +.quick-menu-toggle .quick-toggle:rtr > StBoxLayout { + padding-left: 9px; +} + +.quick-menu-toggle .quick-toggle:ltr:last-child { + border-radius: 12px; +} + +.quick-menu-toggle .quick-toggle:rtl:last-child { + border-radius: 12px; +} + +.quick-menu-toggle .quick-toggle-arrow { + background-color: rgba(239, 241, 245, 0.08) !important; + padding: 6px 10.5px; + border: none !important; + color: #eff1f5; + margin: 1px; +} + +.quick-menu-toggle .quick-toggle-arrow:hover { + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.quick-menu-toggle .quick-toggle-arrow:active { + background-color: rgba(239, 241, 245, 0.15) !important; +} + +.quick-menu-toggle .quick-toggle-arrow:checked { + background-color: rgba(137, 180, 250, 0.75) !important; + color: #1e1e2e; +} + +.quick-menu-toggle .quick-toggle-arrow:checked:hover { + background-color: #b2ccf8 !important; + color: #1e1e2e; +} + +.quick-menu-toggle .quick-toggle-arrow:checked:active { + background-color: #9dc0f9 !important; + color: #1e1e2e; +} + +.quick-menu-toggle .quick-toggle-arrow:ltr { + border-radius: 0 12px 12px 0; +} + +.quick-menu-toggle .quick-toggle-arrow:rtl { + border-radius: 12px 0 0 12px; +} + +.quick-slider > StBoxLayout { + spacing: 6px; +} + +.quick-slider .slider-bin { + min-height: 16px; + padding: 6px; + border-radius: 9999px; +} + +.quick-slider .slider-bin:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.quick-slider .quick-toggle-icon { + icon-size: 16px; +} + +.quick-slider .icon-button, .quick-slider .background-app-item .close-button, .background-app-item .quick-slider .close-button, .quick-slider .message .message-header .message-expand-button, .message .message-header .quick-slider .message-expand-button, +.quick-slider .message .message-header .message-close-button, +.message .message-header .quick-slider .message-close-button, .quick-slider .message-notification-group .message-collapse-button, .message-notification-group .quick-slider .message-collapse-button { + background-color: rgba(239, 241, 245, 0.08) !important; + color: #89b4fa !important; + border-radius: 12px; + padding: 9px; +} + +.quick-slider .icon-button:hover, .quick-slider .background-app-item .close-button:hover, .background-app-item .quick-slider .close-button:hover, .quick-slider .message .message-header .message-expand-button:hover, .message .message-header .quick-slider .message-expand-button:hover, +.quick-slider .message .message-header .message-close-button:hover, +.message .message-header .quick-slider .message-close-button:hover, .quick-slider .message-notification-group .message-collapse-button:hover, .message-notification-group .quick-slider .message-collapse-button:hover { + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.quick-slider .icon-button:active, .quick-slider .background-app-item .close-button:active, .background-app-item .quick-slider .close-button:active, .quick-slider .message .message-header .message-expand-button:active, .message .message-header .quick-slider .message-expand-button:active, +.quick-slider .message .message-header .message-close-button:active, +.message .message-header .quick-slider .message-close-button:active, .quick-slider .message-notification-group .message-collapse-button:active, .message-notification-group .quick-slider .message-collapse-button:active { + background-color: rgba(239, 241, 245, 0.04); +} + +.quick-toggle-menu { + background-color: #292c3c !important; + color: #eff1f5 !important; + border-radius: 24px !important; + padding: 12px; + margin: 12px 18px 0; +} + +.quick-toggle-menu .popup-menu-item { + border-radius: 12px !important; +} + +.quick-toggle-menu .popup-menu-item:focus, .quick-toggle-menu .popup-menu-item:hover, .quick-toggle-menu .popup-menu-item.selected { + color: #89b4fa !important; + background-color: rgba(239, 241, 245, 0.1) !important; +} + +.quick-toggle-menu .popup-menu-item:active { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.2) !important; +} + +.quick-toggle-menu .popup-menu-item > StIcon { + -st-icon-style: symbolic; +} + +.quick-toggle-menu .header { + spacing-rows: 3px; + spacing-columns: 12px; + padding-bottom: 12px; +} + +.quick-toggle-menu .header .icon { + icon-size: 24px; + border-radius: 12px; + padding: 9px; + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.quick-toggle-menu .header .icon.active { + background-color: #89b4fa !important; + color: rgba(30, 30, 46, 0.87); +} + +.quick-settings-system-item > StBoxLayout { + spacing: 12px; +} + +.quick-settings-system-item .icon-button, .quick-settings-system-item .background-app-item .close-button, .background-app-item .quick-settings-system-item .close-button, .quick-settings-system-item .message .message-header .message-expand-button, .message .message-header .quick-settings-system-item .message-expand-button, +.quick-settings-system-item .message .message-header .message-close-button, +.message .message-header .quick-settings-system-item .message-close-button, .quick-settings-system-item .message-notification-group .message-collapse-button, .message-notification-group .quick-settings-system-item .message-collapse-button { + background-color: rgba(239, 241, 245, 0.08); + color: #89b4fa !important; + border-radius: 12px; +} + +.quick-settings-system-item .icon-button > StIcon, .quick-settings-system-item .background-app-item .close-button > StIcon, .background-app-item .quick-settings-system-item .close-button > StIcon, .quick-settings-system-item .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings-system-item .message-expand-button > StIcon, +.quick-settings-system-item .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings-system-item .message-close-button > StIcon, .quick-settings-system-item .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings-system-item .message-collapse-button > StIcon { + -st-icon-style: symbolic; + icon-size: 16px; +} + +.quick-settings-system-item .power-item { + color: #89b4fa !important; + min-height: 0; + min-width: 0; +} + +.quick-settings-system-item .power-item:insensitive { + color: #eff1f5; + background-color: #313244; + box-shadow: none !important; + background-color: transparent; +} + +.nm-network-item .wireless-secure-icon { + icon-size: 8px; +} + +.bt-device-item .popup-menu-icon { + -st-icon-style: symbolic; +} + +.bt-menu-placeholder.popup-menu-item { + text-align: center; + padding: 2em 4em; +} + +.device-subtitle { + color: rgba(239, 241, 245, 0.5); +} + +.background-apps-quick-toggle { + min-height: 40px; + background-color: transparent; +} + +.background-apps-quick-toggle StIcon { + icon-size: 16px !important; +} + +.background-app-item .popup-menu-icon { + icon-size: 32px !important; + -st-icon-style: regular !important; +} + +.background-app-item .close-button { + padding: 6px; +} + +.background-app-item.popup-inactive-menu-item { + color: #eff1f5; +} + +/* Quick Settings */ +.quick-settings { + padding: 18px !important; + border-radius: 24px !important; + margin-top: 6px !important; +} + +.quick-settings .icon-button, .quick-settings .message .message-header .message-expand-button, .message .message-header .quick-settings .message-expand-button, +.quick-settings .message .message-header .message-close-button, +.message .message-header .quick-settings .message-close-button, .quick-settings .message-notification-group .message-collapse-button, .message-notification-group .quick-settings .message-collapse-button, .quick-settings .background-app-item .close-button, .background-app-item .quick-settings .close-button, +.quick-settings .button { + padding: 10.5px; +} + +.quick-settings .icon-button > StIcon, .quick-settings .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings .message-expand-button > StIcon, +.quick-settings .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings .message-close-button > StIcon, .quick-settings .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings .message-collapse-button > StIcon, .quick-settings .background-app-item .close-button > StIcon, .background-app-item .quick-settings .close-button > StIcon, +.quick-settings .button > StIcon { + icon-size: 16px; +} + +.quick-settings-grid { + spacing-rows: 12px; + spacing-columns: 12px; +} + +.quick-toggle, +.quick-toggle-has-menu { + border-radius: 12px; + min-width: 12em; + max-width: 12em; + min-height: 44px; + border: none; + margin: 1px; +} + +.quick-toggle { + background-color: rgba(239, 241, 245, 0.12) !important; + color: #1e1e2e; + /* Move padding into the box; this is to allow menu arrows + to extend to the border */ +} + +.quick-toggle:hover { + background-color: rgba(137, 180, 250, 0.25) !important; + color: #1e1e2e; +} + +.quick-toggle:active { + background-color: rgba(137, 180, 250, 0.5) !important; +} + +.quick-toggle:checked { + background-color: rgba(137, 180, 250, 0.95) !important; + color: #1e1e2e; +} + +.quick-toggle:checked:hover { + background-color: #b2ccf8 !important; + color: #1e1e2e; +} + +.quick-toggle:checked:active { + background-color: #9dc0f9 !important; + color: #1e1e2e; +} + +.quick-toggle > StBoxLayout { + spacing: 6px; +} + +.quick-toggle.button { + padding: 0; +} + +.quick-toggle > StBoxLayout { + padding: 0 12px; +} + +.quick-toggle:ltr > StBoxLayout { + padding-left: 15px; +} + +.quick-toggle:rtl > StBoxLayout { + padding-right: 15px; +} + +.quick-toggle .quick-toggle-title { + font-weight: bold; +} + +.quick-toggle .quick-toggle-subtitle { + font-weight: normal; + font-size: 12px; +} + +.quick-toggle .quick-toggle-icon { + icon-size: 16px; +} + +.quick-toggle-has-menu .quick-toggle { + min-width: auto; + max-width: auto; +} + +.quick-toggle-has-menu .quick-toggle:ltr { + border-radius: 12px 0 0 12px; +} + +.quick-toggle-has-menu .quick-toggle:ltr { + padding-right: 9px; +} + +.quick-toggle-has-menu .quick-toggle:rtl { + border-radius: 0 12px 12px 0; +} + +.quick-toggle-has-menu .quick-toggle:rtr { + padding-left: 9px; +} + +.quick-toggle-has-menu .quick-toggle:ltr:last-child { + border-radius: 12px; +} + +.quick-toggle-has-menu .quick-toggle:rtl:last-child { + border-radius: 12px; +} + +.quick-toggle-has-menu .quick-toggle-menu-button { + padding: 6px 10.5px; + border: none !important; + margin: 1px; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:ltr { + border-radius: 0 12px 12px 0; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:rtl { + border-radius: 12px 0 0 12px; +} + +.quick-toggle-has-menu .quick-toggle-separator { + width: 0; +} + +.quick-toggle-has-menu .quick-toggle-menu-button { + background-color: rgba(239, 241, 245, 0.12) !important; + color: #eff1f5; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:hover { + background-color: rgba(137, 180, 250, 0.25) !important; + color: #eff1f5; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:active { + background-color: rgba(239, 241, 245, 0.15) !important; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:checked { + background-color: rgba(137, 180, 250, 0.75) !important; + color: #1e1e2e; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:checked:hover { + background-color: #b2ccf8 !important; + color: #1e1e2e; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:checked:active { + background-color: #9dc0f9 !important; + color: #1e1e2e; +} + +.quick-slider > StBoxLayout { + spacing: 6px; +} + +.quick-slider .slider-bin { + min-height: 16px; + padding: 6px; + border-radius: 9999px; +} + +.quick-slider .slider-bin:focus { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.08); + box-shadow: none !important; +} + +.quick-slider .quick-toggle-icon { + icon-size: 16px; +} + +.quick-slider .icon-button, .quick-slider .message .message-header .message-expand-button, .message .message-header .quick-slider .message-expand-button, +.quick-slider .message .message-header .message-close-button, +.message .message-header .quick-slider .message-close-button, .quick-slider .message-notification-group .message-collapse-button, .message-notification-group .quick-slider .message-collapse-button, .quick-slider .background-app-item .close-button, .background-app-item .quick-slider .close-button { + background-color: rgba(239, 241, 245, 0.08) !important; + color: #89b4fa !important; + border-radius: 12px; + padding: 9px; +} + +.quick-slider .icon-button:hover, .quick-slider .message .message-header .message-expand-button:hover, .message .message-header .quick-slider .message-expand-button:hover, +.quick-slider .message .message-header .message-close-button:hover, +.message .message-header .quick-slider .message-close-button:hover, .quick-slider .message-notification-group .message-collapse-button:hover, .message-notification-group .quick-slider .message-collapse-button:hover, .quick-slider .background-app-item .close-button:hover, .background-app-item .quick-slider .close-button:hover { + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.quick-slider .icon-button:active, .quick-slider .message .message-header .message-expand-button:active, .message .message-header .quick-slider .message-expand-button:active, +.quick-slider .message .message-header .message-close-button:active, +.message .message-header .quick-slider .message-close-button:active, .quick-slider .message-notification-group .message-collapse-button:active, .message-notification-group .quick-slider .message-collapse-button:active, .quick-slider .background-app-item .close-button:active, .background-app-item .quick-slider .close-button:active { + background-color: rgba(239, 241, 245, 0.04); +} + +.quick-toggle-menu { + background-color: #292c3c !important; + color: #eff1f5 !important; + border-radius: 24px !important; + padding: 12px; + margin: 12px 18px 0; +} + +.quick-toggle-menu .popup-menu-item { + border-radius: 12px !important; +} + +.quick-toggle-menu .popup-menu-item:focus, .quick-toggle-menu .popup-menu-item:hover, .quick-toggle-menu .popup-menu-item.selected { + color: #89b4fa !important; + background-color: rgba(239, 241, 245, 0.1) !important; +} + +.quick-toggle-menu .popup-menu-item:active { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.2) !important; +} + +.quick-toggle-menu .popup-menu-item > StIcon { + -st-icon-style: symbolic; +} + +.quick-toggle-menu .header { + spacing-rows: 3px; + spacing-columns: 12px; + padding-bottom: 12px; +} + +.quick-toggle-menu .header .icon { + icon-size: 24px; + border-radius: 12px; + padding: 9px; + background-color: rgba(239, 241, 245, 0.12) !important; +} + +.quick-toggle-menu .header .icon.active { + background-color: #89b4fa !important; + color: rgba(30, 30, 46, 0.87); +} + +.quick-settings-system-item > StBoxLayout { + spacing: 12px; +} + +.quick-settings-system-item .icon-button, .quick-settings-system-item .message .message-header .message-expand-button, .message .message-header .quick-settings-system-item .message-expand-button, +.quick-settings-system-item .message .message-header .message-close-button, +.message .message-header .quick-settings-system-item .message-close-button, .quick-settings-system-item .message-notification-group .message-collapse-button, .message-notification-group .quick-settings-system-item .message-collapse-button, .quick-settings-system-item .background-app-item .close-button, .background-app-item .quick-settings-system-item .close-button { + background-color: rgba(239, 241, 245, 0.08); + color: #89b4fa !important; + border-radius: 12px; +} + +.quick-settings-system-item .icon-button > StIcon, .quick-settings-system-item .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings-system-item .message-expand-button > StIcon, +.quick-settings-system-item .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings-system-item .message-close-button > StIcon, .quick-settings-system-item .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings-system-item .message-collapse-button > StIcon, .quick-settings-system-item .background-app-item .close-button > StIcon, .background-app-item .quick-settings-system-item .close-button > StIcon { + -st-icon-style: symbolic; + icon-size: 16px; +} + +.quick-settings-system-item .power-item { + color: #89b4fa !important; + min-height: 0; + min-width: 0; +} + +.quick-settings-system-item .power-item:insensitive { + color: #eff1f5; + background-color: #313244; + box-shadow: none !important; + background-color: transparent; +} + +.nm-network-item .wireless-secure-icon { + icon-size: 8px; +} + +.bt-device-item .popup-menu-icon { + -st-icon-style: symbolic; +} + +.bt-menu-placeholder.popup-menu-item { + text-align: center; + padding: 2em 4em; +} + +.device-subtitle { + color: rgba(239, 241, 245, 0.5); +} + +.background-apps-quick-toggle { + min-height: 40px; + background-color: transparent; +} + +.background-apps-quick-toggle StIcon { + icon-size: 16px !important; +} + +.background-app-item .popup-menu-icon { + icon-size: 32px !important; + -st-icon-style: regular !important; +} + +.background-app-item .close-button { + padding: 6px; +} + +.background-app-item.popup-inactive-menu-item { + color: #eff1f5; +} + +.search-entry { + margin-top: 24px; + margin-bottom: 6px; +} + +/* Search */ +.list-search-result, .search-provider-icon { + border-radius: 12px; + padding: 6px; + transition-duration: 100ms; + text-align: center; + background-color: transparent; +} + +.list-search-result:focus, .search-provider-icon:focus, .list-search-result:hover, .search-provider-icon:hover, .list-search-result:selected, .search-provider-icon:selected { + background-color: rgba(239, 241, 245, 0.12); + transition-duration: 0; +} + +.list-search-result:active, .search-provider-icon:active, .list-search-result:checked, .search-provider-icon:checked { + background-color: rgba(239, 241, 245, 0.2); +} + +#searchResults { + margin: 0 4px; +} + +#searchResultsContent { + max-width: 1044px; +} + +.search-section { + spacing: 18px; +} + +.search-section .search-section-separator { + height: 8px; + background-color: transparent; +} + +.search-section-content { + border-radius: 27px; + padding: 12px; + margin: 0 12px; + border: none; + box-shadow: none; + background: none; + text-shadow: none; + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.12); +} + +.search-statustext { + color: rgba(239, 241, 245, 0.5); +} + +.grid-search-results { + spacing: 30px; + margin: 0 12px; +} + +.search-provider-icon:ltr { + margin-right: 4px; +} + +.search-provider-icon:rtl { + margin-left: 4px; +} + +.search-provider-icon .list-search-provider-content { + spacing: 12px; +} + +.search-provider-icon .list-search-provider-content .list-search-provider-details { + width: 120px; + color: rgba(239, 241, 245, 0.7); +} + +.list-search-results { + spacing: 6px; +} + +.list-search-result .list-search-result-content { + spacing: 6px; +} + +.list-search-result .list-search-result-title { + spacing: 12px; +} + +.list-search-result .list-search-result-description { + color: rgba(239, 241, 245, 0.7); +} + +.icon-label-button-container { + spacing: 6px; +} + +.icon-label-button-container StIcon { + icon-size: 32px; +} + +.screenshot-ui-panel { + border-radius: 39px; + padding: 18px; + padding-bottom: 12px; + margin-bottom: 4em; + spacing: 12px; +} + +.screenshot-ui-close-button { + padding: 6px !important; + margin-top: 12px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.15); +} + +.screenshot-ui-close-button.left { + margin-left: 12px; +} + +.screenshot-ui-close-button.right { + margin-right: 12px; +} + +.screenshot-ui-type-button { + min-width: 48px; + padding: 12px 18px !important; + border-radius: 21px; +} + +.screenshot-ui-capture-button { + width: 36px; + height: 36px; + border-radius: 9999px; + border: 4px #eff1f5; + padding: 4px; +} + +.screenshot-ui-capture-button .screenshot-ui-capture-button-circle { + background-color: #eff1f5; + transition-duration: 200ms; + border-radius: 9999px; +} + +.screenshot-ui-capture-button .screenshot-ui-capture-button-circle:hover, .screenshot-ui-capture-button .screenshot-ui-capture-button-circle:focus { + background-color: rgba(239, 241, 245, 0.12); +} + +.screenshot-ui-capture-button:hover .screenshot-ui-capture-button-circle, .screenshot-ui-capture-button:focus .screenshot-ui-capture-button-circle { + background-color: #c0c8d8; +} + +.screenshot-ui-capture-button:active .screenshot-ui-capture-button-circle { + background-color: #586a8d; +} + +.screenshot-ui-capture-button:cast .screenshot-ui-capture-button-circle { + background-color: #d20f39; +} + +.screenshot-ui-capture-button:cast:hover .screenshot-ui-capture-button-circle, .screenshot-ui-capture-button:cast:focus .screenshot-ui-capture-button-circle { + background-color: #ea113f; +} + +.screenshot-ui-capture-button:cast:active .screenshot-ui-capture-button-circle { + background-color: #b10d30; +} + +.screenshot-ui-shot-cast-container { + background-color: #28283d; + border-radius: 18px; + padding: 3px; + spacing: 3px; +} + +.screenshot-ui-shot-cast-container:ltr { + margin-left: 3px; +} + +.screenshot-ui-shot-cast-container:rtl { + margin-right: 3px; +} + +.screenshot-ui-shot-cast-button { + padding: 6px 12px; + background-color: transparent; + border-radius: 15px; +} + +.screenshot-ui-shot-cast-button:hover, .screenshot-ui-shot-cast-button:focus { + background-color: #32324d; +} + +.screenshot-ui-shot-cast-button:active { + background-color: rgba(239, 241, 245, 0.3); +} + +.screenshot-ui-shot-cast-button:checked { + background-color: #eff1f5; + color: #1e1e2e; +} + +.screenshot-ui-shot-cast-button:insensitive { + color: rgba(239, 241, 245, 0.5); +} + +.screenshot-ui-shot-cast-button StIcon { + icon-size: 16px; +} + +.screenshot-ui-show-pointer-button { + border-radius: 9999px; + padding: 12px !important; +} + +.screenshot-ui-show-pointer-button StIcon { + icon-size: 16px; +} + +.screenshot-ui-area-indicator-shade { + background-color: rgba(0, 0, 0, 0.3); +} + +.screenshot-ui-area-selector .screenshot-ui-area-indicator-shade { + background-color: rgba(0, 0, 0, 0.5); +} + +.screenshot-ui-area-selector .screenshot-ui-area-indicator-selection { + border: 2px solid #eff1f5; +} + +.screenshot-ui-area-selector-handle { + border-radius: 9999px; + background-color: #89b4fa; + box-shadow: 0 1px 3px 2px rgba(0, 0, 0, 0.2); + width: 24px; + height: 24px; +} + +.screenshot-ui-window-selector { + background-color: #292c3c; +} + +.screenshot-ui-window-selector .screenshot-ui-window-selector-window-container { + margin: 100px; +} + +.screenshot-ui-window-selector:primary-monitor .screenshot-ui-window-selector-window-container { + margin-bottom: 200px; +} + +.screenshot-ui-window-selector-window-border { + transition-duration: 200ms; + border-radius: 18px; + border: 6px transparent; +} + +.screenshot-ui-window-selector-check { + transition-duration: 200ms; + color: transparent; + border-radius: 9999px; + border-width: 12px; + icon-size: 24px; +} + +.screenshot-ui-window-selector-window:hover .screenshot-ui-window-selector-window-border { + border-color: #4085f7; +} + +.screenshot-ui-window-selector-window:checked .screenshot-ui-window-selector-window-border { + border-color: #89b4fa; + background-color: rgba(137, 180, 250, 0.2); +} + +.screenshot-ui-window-selector-window:checked .screenshot-ui-window-selector-check { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +.screenshot-ui-screen-selector { + transition-duration: 200ms; + background-color: rgba(0, 0, 0, 0.5); +} + +.screenshot-ui-screen-selector:hover { + background-color: rgba(0, 0, 0, 0.3); +} + +.screenshot-ui-screen-selector:active { + background-color: rgba(0, 0, 0, 0.7); +} + +.screenshot-ui-screen-selector:checked { + background-color: transparent; + border: 2px solid #eff1f5; +} + +.screenshot-ui-tooltip { + color: #eff1f5; + background-color: #1e1e2e; + border-radius: 9999px; + padding: 6px 12px; + text-align: center; + -y-offset: 24px; +} + +/* Switches */ +.toggle-switch { + width: 46px; + height: 24px; + background-size: contain; + background-image: url("assets/toggle-off.svg"); + transition-duration: 100ms; + color: transparent; +} + +.toggle-switch:checked { + background-image: url("assets/toggle-on.svg"); + color: transparent; +} + +.toggle-switch:checked .handle { + background: none; +} + +.toggle-switch StIcon { + icon-size: 0; +} + +.toggle-switch .handle { + margin: 0; + width: 0; + height: 0; + background: none; + box-shadow: none; + transition-duration: 0; +} + +.window-picker { + spacing: 6px; +} + +.window-caption { + color: #eff1f5; + background-color: #1e1e2e; + border-radius: 9999px; + padding: 6px 12px; +} + +.window-close, .screenshot-ui-close-button { + background-color: #292c3c; + color: #eff1f5; + border-radius: 9999px; + padding: 3px; + height: 30px; + width: 30px; + box-shadow: -1px 1px 5px 0px rgba(0, 0, 0, 0.5); + transition-duration: 300ms; +} + +.window-close:hover, .screenshot-ui-close-button:hover { + color: #eff1f5; + background-color: #35394e; +} + +.window-close:active, .screenshot-ui-close-button:active { + color: #eff1f5; + background-color: #1d1f2a; +} + +.workspace-background { + border-radius: 30px; + background-color: #1e1e2e; + box-shadow: 0 4px 16px 4px rgba(0, 0, 0, 0.3); +} + +/* Workspace pager */ +.workspace-thumbnails { + visible-width: 32px; + spacing: 6px; + padding: 6px; +} + +.workspace-thumbnails .workspace-thumbnail { + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.12); + border: none; + border-radius: 12px; +} + +.workspace-thumbnails .placeholder { + background-image: url("assets/dash-placeholder.svg"); + background-size: contain; + width: 18px; + height: 24px; +} + +.workspace-thumbnail-indicator { + border: 3px solid #89b4fa; + border-radius: 3px; + padding: 0px; +} + +.bottom #dashtodockDashScrollview, +.top #dashtodockDashScrollview { + -st-hfade-offset: 24px; +} + +.left #dashtodockDashScrollview, +.right #dashtodockDashScrollview { + -st-vfade-offset: 24px; +} + +#dashtodockContainer { + background-color: transparent; +} + +#dashtodockContainer .number-overlay { + color: #eff1f5; + background-color: rgba(0, 0, 0, 0.75); + text-align: center; +} + +#dashtodockContainer .notification-badge { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; + box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.25); + border-radius: 9999px; + margin: 2px; + padding: 0.25em 0.6em; + font-weight: bold; + text-align: center; +} + +#dashtodockContainer.straight-corner #dash, #dashtodockContainer.shrink.straight-corner #dash { + border-radius: 0; + margin: 0; +} + +#dashtodockContainer.straight-corner #dash .dash-background, #dashtodockContainer.shrink.straight-corner #dash .dash-background { + border-radius: 0; +} + +#dashtodockContainer.extended.top #dash, #dashtodockContainer.extended.bottom #dash, #dashtodockContainer.extended.right #dash, #dashtodockContainer.extended.left #dash { + margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0; + padding: 0 0; +} + +#dashtodockContainer.extended.top #dash .dash-background, #dashtodockContainer.extended.bottom #dash .dash-background, #dashtodockContainer.extended.right #dash .dash-background, #dashtodockContainer.extended.left #dash .dash-background { + border-radius: 0; + margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0; +} + +#dashtodockContainer.left #dash, #dashtodockContainer.right #dash { + margin-top: 0; + padding: 12px 0; +} + +#dashtodockContainer.left #dash .dash-background, #dashtodockContainer.right #dash .dash-background { + margin-bottom: 0; +} + +#dashtodockContainer.left .dash-item-container .app-well-app, +#dashtodockContainer.left .show-apps, #dashtodockContainer.right .dash-item-container .app-well-app, +#dashtodockContainer.right .show-apps { + padding: 6px; +} + +#dashtodockContainer.left #dash { + margin-left: 6px; +} + +#dashtodockContainer.right #dash { + margin-right: 6px; +} + +#dashtodockContainer.dashtodock #dash .dash-background { + background-color: rgba(30, 30, 46, 0.6); +} + +#dashtodockContainer #dash .dash-background { + background-color: rgba(30, 30, 46, 0.85); + border: 2px solid #89b4fa; +} + +#dashtodockContainer .app-well-app-running-dot { + background-color: rgba(239, 241, 245, 0.3) !important; +} + +#dashtodockContainer StWidget.focused .app-well-app-running-dot { + background-color: #e6e9ef !important; +} + +#dashtodockContainer:overview #dash .app-well-app-running-dot { + background-color: rgba(239, 241, 245, 0.3) !important; +} + +#dashtodockContainer:overview #dash StWidget.focused .app-well-app-running-dot { + background-color: #eff1f5 !important; +} + +#dashtodockContainer .show-apps .overview-icon, +#dashtodockContainer .app-well-app .overview-icon { + color: rgba(239, 241, 245, 0.7); +} + +#dashtodockContainer .show-apps:hover .overview-icon, #dashtodockContainer .show-apps:focus .overview-icon, #dashtodockContainer .show-apps:selected .overview-icon, +#dashtodockContainer .app-well-app:hover .overview-icon, +#dashtodockContainer .app-well-app:focus .overview-icon, +#dashtodockContainer .app-well-app:selected .overview-icon { + background-color: rgba(239, 241, 245, 0.12); +} + +#dashtodockContainer .show-apps:active .overview-icon, #dashtodockContainer .show-apps:checked .overview-icon, +#dashtodockContainer .app-well-app:active .overview-icon, +#dashtodockContainer .app-well-app:checked .overview-icon { + background-color: rgba(239, 241, 245, 0.3); +} + +#dashtodockContainer:overview #dash .show-apps .overview-icon, #dashtodockContainer:overview #dash .app-well-app .overview-icon { + color: rgba(239, 241, 245, 0.7); +} + +#dashtodockContainer:overview #dash .show-apps:hover .overview-icon, #dashtodockContainer:overview #dash .show-apps:focus .overview-icon, #dashtodockContainer:overview #dash .show-apps:selected .overview-icon, #dashtodockContainer:overview #dash .app-well-app:hover .overview-icon, #dashtodockContainer:overview #dash .app-well-app:focus .overview-icon, #dashtodockContainer:overview #dash .app-well-app:selected .overview-icon { + background-color: rgba(239, 241, 245, 0.12); +} + +#dashtodockContainer:overview #dash .show-apps:active .overview-icon, #dashtodockContainer:overview #dash .show-apps:checked .overview-icon, #dashtodockContainer:overview #dash .app-well-app:active .overview-icon, #dashtodockContainer:overview #dash .app-well-app:checked .overview-icon { + background-color: rgba(239, 241, 245, 0.3); +} + +#dashtodockContainer .app-well-app-running-dot { + background-color: rgba(239, 241, 245, 0.3); +} + +#dashtodockContainer StWidget.focused .app-well-app-running-dot { + background-color: #e6e9ef; +} + +#dashtodockContainer.opaque #dash .dash-background { + background-color: rgba(30, 30, 46, 0.6); +} + +#dashtodockContainer.transparent #dash .dash-background { + background-color: rgba(30, 30, 46, 0.35); +} + +#dashtodockContainer:overview #dash .dash-background { + background-color: rgba(239, 241, 245, 0.12); + border: 2px solid transparent; +} + +#dashtodockContainer.opaque:overview #dash .dash-background, #dashtodockContainer.transparent:overview #dash .dash-background { + background-color: transparent !important; + box-shadow: none !important; +} + +#dashtodockContainer.extended:overview #dash .dash-background, #dashtodockContainer.opaque.extended:overview #dash .dash-background, #dashtodockContainer.transparent.extended:overview #dash .dash-background { + background-color: rgba(30, 30, 46, 0.6); +} + +#dashtodockContainer.running-dots .dash-item-container > StButton, #dashtodockContainer.dashtodock .dash-item-container > StButton { + transition-duration: 250ms; + background-size: contain; +} + +#dashtodockContainer.extended .app-well-app .overview-icon, +#dashtodockContainer.extended .show-apps .overview-icon, #dashtodockContainer.extended:overview .app-well-app .overview-icon, +#dashtodockContainer.extended:overview .show-apps .overview-icon { + border-radius: 12px; +} + +#dashtodockContainer .metro .overview-icon { + border-radius: 0; +} + +.dashtodock-app-well-preview-menu-item { + padding: 1em 1em 0.5em 1em; +} + +#dashtodockPreviewSeparator.popup-separator-menu-item-horizontal { + background-color: rgba(239, 241, 245, 0.25); + width: 1px; + height: auto; + border-right-width: 1px; + margin: 32px 0; +} + +.openweather-button, .openweather-button-action, .openweather-menu-button-container, .openweather-button-box { + border: 1px solid transparent; +} + +.openweather-provider { + padding: 0 16px; + font-weight: 500; + border: 1px solid transparent; +} + +.openweather-current-icon, .openweather-current-summary, .openweather-current-summarybox { + background: none; + color: #eff1f5; +} + +.openweather-current-databox-values { + background: none; + color: rgba(239, 241, 245, 0.5); +} + +.openweather-current-databox-captions { + background: none; + color: rgba(239, 241, 245, 0.5); +} + +.openweather-forecast-icon, .openweather-forecast-summary { + background: none; + color: rgba(239, 241, 245, 0.7); +} + +.openweather-forecast-day, .openweather-forecast-temperature { + background: none; + color: rgba(239, 241, 245, 0.5); +} + +.openweather-sunrise-icon, .openweather-sunset-icon, .openweather-build-icon { + color: rgba(239, 241, 245, 0.7); +} + +.cosmic-dock #dock { + border-radius: 16px !important; + border: none !important; + margin: 6px !important; + background-color: rgba(49, 50, 68, 0.65) !important; + box-shadow: inset 0 1px rgba(255, 255, 255, 0.08) !important; +} + +.cosmic-dock #dock .dash-background { + background-color: transparent !important; + margin-bottom: 0 !important; + padding: 0; + box-shadow: none !important; +} + +.cosmic-application-dialog { + border-radius: 18px; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.08); + background-color: #292c3c; + color: #eff1f5; +} + +.cosmic-application-dialog .overview-icon { + color: #eff1f5; +} + +.cosmic-applications-separator { + background: rgba(239, 241, 245, 0.12); +} + +.cosmic-folder-edit-button { + box-shadow: none; + border-radius: 12px; + border-width: 0; + color: #eff1f5; + background: rgba(239, 241, 245, 0.04); +} + +.cosmic-folder-edit-button .cosmic-folder-edit-button:hover { + background: rgba(239, 241, 245, 0.12); +} + +.cosmic-applications-icon { + color: rgba(239, 241, 245, 0.7); +} + +.cosmic-applications-folder-title { + color: rgba(239, 241, 245, 0.7); +} + +.cosmic-applications-available { + color: #eff1f5; +} + +.pop-shell-active-hint { + border-style: solid; + border-color: #df8e1d; + border-radius: 12px; + box-shadow: none; +} + +.pop-shell-overlay { + background-color: rgba(137, 180, 250, 0.3); +} + +.pop-shell-search-element:select { + background: rgba(239, 241, 245, 0.12); + border-radius: 12px; + color: #eff1f5; +} + +.pop-shell-tab { + border: 1px solid rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.pop-shell-tab-active { + background: #df8e1d; +} + +.pop-shell-tab-inactive { + background: rgba(223, 142, 29, 0.35); +} + +.pop-shell-tab-urgent { + background: #d20f39; +} + +#panel.light-panel .panel-button, +#panel.dark-panel .panel-button, +#panel.transparent-panel .panel-button { + color: rgba(239, 241, 245, 0.7) !important; +} + +#panel.light-panel .panel-button.clock-display .clock, +#panel.dark-panel .panel-button.clock-display .clock, +#panel.transparent-panel .panel-button.clock-display .clock { + color: rgba(239, 241, 245, 0.7) !important; +} + +#panel.light-panel .panel-button:hover, +#panel.dark-panel .panel-button:hover, +#panel.transparent-panel .panel-button:hover { + color: rgba(239, 241, 245, 0.7) !important; + background-color: rgba(239, 241, 245, 0.12) !important; +} + +#panel.light-panel .panel-button:hover.clock-display .clock, +#panel.dark-panel .panel-button:hover.clock-display .clock, +#panel.transparent-panel .panel-button:hover.clock-display .clock { + background-color: rgba(239, 241, 245, 0.12) !important; +} + +#panel.light-panel .panel-button:active, #panel.light-panel .panel-button:checked, #panel.light-panel .panel-button:focus, +#panel.dark-panel .panel-button:active, +#panel.dark-panel .panel-button:checked, +#panel.dark-panel .panel-button:focus, +#panel.transparent-panel .panel-button:active, +#panel.transparent-panel .panel-button:checked, +#panel.transparent-panel .panel-button:focus { + color: #eff1f5 !important; + background-color: rgba(239, 241, 245, 0.3) !important; +} + +#panel.light-panel .panel-button:active.clock-display .clock, #panel.light-panel .panel-button:checked.clock-display .clock, #panel.light-panel .panel-button:focus.clock-display .clock, +#panel.dark-panel .panel-button:active.clock-display .clock, +#panel.dark-panel .panel-button:checked.clock-display .clock, +#panel.dark-panel .panel-button:focus.clock-display .clock, +#panel.transparent-panel .panel-button:active.clock-display .clock, +#panel.transparent-panel .panel-button:checked.clock-display .clock, +#panel.transparent-panel .panel-button:focus.clock-display .clock { + background-color: rgba(239, 241, 245, 0.3) !important; +} + +#panel.light-panel .panel-button:hover.clock-display, #panel.light-panel .panel-button:active.clock-display, #panel.light-panel .panel-button:overview.clock-display, #panel.light-panel .panel-button:focus.clock-display, #panel.light-panel .panel-button:checked.clock-display, +#panel.dark-panel .panel-button:hover.clock-display, +#panel.dark-panel .panel-button:active.clock-display, +#panel.dark-panel .panel-button:overview.clock-display, +#panel.dark-panel .panel-button:focus.clock-display, +#panel.dark-panel .panel-button:checked.clock-display, +#panel.transparent-panel .panel-button:hover.clock-display, +#panel.transparent-panel .panel-button:active.clock-display, +#panel.transparent-panel .panel-button:overview.clock-display, +#panel.transparent-panel .panel-button:focus.clock-display, +#panel.transparent-panel .panel-button:checked.clock-display { + background-color: transparent !important; +} + +#panel.light-panel .panel-button:hover.clock-display .clock, #panel.light-panel .panel-button:active.clock-display .clock, #panel.light-panel .panel-button:overview.clock-display .clock, #panel.light-panel .panel-button:focus.clock-display .clock, #panel.light-panel .panel-button:checked.clock-display .clock, +#panel.dark-panel .panel-button:hover.clock-display .clock, +#panel.dark-panel .panel-button:active.clock-display .clock, +#panel.dark-panel .panel-button:overview.clock-display .clock, +#panel.dark-panel .panel-button:focus.clock-display .clock, +#panel.dark-panel .panel-button:checked.clock-display .clock, +#panel.transparent-panel .panel-button:hover.clock-display .clock, +#panel.transparent-panel .panel-button:active.clock-display .clock, +#panel.transparent-panel .panel-button:overview.clock-display .clock, +#panel.transparent-panel .panel-button:focus.clock-display .clock, +#panel.transparent-panel .panel-button:checked.clock-display .clock { + color: #eff1f5 !important; +} + +.overview-components-transparent .search-entry, +.overview-components-light .search-entry, +.overview-components-dark .search-entry { + caret-color: #eff1f5 !important; +} + +.overview-components-transparent .search-entry .search-entry-icon, +.overview-components-light .search-entry .search-entry-icon, +.overview-components-dark .search-entry .search-entry-icon { + color: rgba(239, 241, 245, 0.7) !important; +} + +.overview-components-transparent .search-entry StLabel.hint-text, +.overview-components-light .search-entry StLabel.hint-text, +.overview-components-dark .search-entry StLabel.hint-text { + color: rgba(239, 241, 245, 0.3) !important; +} + +.overview-components-transparent .search-section-content, +.overview-components-light .search-section-content, +.overview-components-dark .search-section-content { + border-radius: 16px; +} + +.overview-components-transparent .search-section-separator, +.overview-components-light .search-section-separator, +.overview-components-dark .search-section-separator { + height: 0 !important; + background-color: transparent !important; +} diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-events.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-events.svg new file mode 120000 index 0000000..d2fcad0 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-events.svg @@ -0,0 +1 @@ +assets/no-events.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-notifications.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-notifications.svg new file mode 120000 index 0000000..175731c --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/no-notifications.svg @@ -0,0 +1 @@ +assets/no-notifications.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/pad-osd.css b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/pad-osd.css new file mode 100755 index 0000000..8db7cf0 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/pad-osd.css @@ -0,0 +1,31 @@ +.Leader { + stroke-width: 0.5 !important; + stroke: #535353; + fill: none !important; +} + +.Button { + stroke-width: 0.25; + stroke: #ededed; + fill: #ededed; +} + +.Ring { + stroke-width: 0.5 !important; + stroke: #535353 !important; + fill: none !important; +} + +.Label { + stroke: none !important; + stroke-width: 0.1 !important; + font-size: 0.1 !important; + fill: transparent !important; +} + +.TouchStrip, +.TouchRing { + stroke-width: 0.1 !important; + stroke: #ededed !important; + fill: #535353 !important; +} diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/process-working.svg b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/process-working.svg new file mode 120000 index 0000000..a6586c3 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gnome-shell/process-working.svg @@ -0,0 +1 @@ +assets/process-working.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/apps.rc b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/apps.rc new file mode 100755 index 0000000..530e72f --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/apps.rc @@ -0,0 +1,92 @@ +# vim:set ft=gtkrc ts=2 sw=2 sts=2 ai et: +# +# This file, unlike hacks.rc, contains legitimate cases we need to handle, e.g. +# custom widgets, programs giving us a chance to alter their UI to fit more with +# the theme or stuff that is supposed to look different, like panels. + +# TODO: This could really look nicer +style "gimp_spin_scale" { + # Spin background + bg[NORMAL] = @base_color + + engine "pixmap" { + image { + function = BOX + state = NORMAL + detail = "spinbutton_up" + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_up" + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_up" + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_up" + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = NORMAL + detail = "spinbutton_down" + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_down" + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_down" + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_down" + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + } + } +} + +style "chrome_gtk_frame" { + ChromeGtkFrame::frame-color = @titlebar_bg_color + ChromeGtkFrame::inactive-frame-color = @titlebar_bg_color + ChromeGtkFrame::incognito-frame-color = @titlebar_bg_color + ChromeGtkFrame::incognito-inactive-frame-color = @titlebar_bg_color + + ChromeGtkFrame::frame-gradient-size = 0 +} + +# Disable spin button assets for GimpSpinScale +class "GimpSpinScale" style "gimp_spin_scale" + +# Chromium lets us define some colours and settings for better integration +class "ChromeGtkFrame" style "chrome_gtk_frame" diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/border.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/border.png new file mode 100755 index 0000000..20d503b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/border.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-active.png new file mode 100755 index 0000000..d941286 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-disabled.png new file mode 100755 index 0000000..72e96fa Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-hover.png new file mode 100755 index 0000000..a60405b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button.png new file mode 100755 index 0000000..453c9f0 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/button.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-active.png new file mode 100755 index 0000000..275d7e2 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-disabled.png new file mode 100755 index 0000000..2a9097a Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-hover.png new file mode 100755 index 0000000..c539166 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked.png new file mode 100755 index 0000000..6280ed9 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-checked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-active.png new file mode 100755 index 0000000..fa24191 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-disabled.png new file mode 100755 index 0000000..08ec632 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-hover.png new file mode 100755 index 0000000..f890a8e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed.png new file mode 100755 index 0000000..2fbb7ed Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-mixed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-active.png new file mode 100755 index 0000000..a03bff5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-disabled.png new file mode 100755 index 0000000..810d142 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-hover.png new file mode 100755 index 0000000..21b60e2 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked.png new file mode 100755 index 0000000..121b009 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/checkbox-unchecked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-active.png new file mode 100755 index 0000000..4209874 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-disabled.png new file mode 100755 index 0000000..b89db89 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-hover.png new file mode 100755 index 0000000..c289e30 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry.png new file mode 100755 index 0000000..90ea958 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-left-entry.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-active.png new file mode 100755 index 0000000..ed4b9ac Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-disabled.png new file mode 100755 index 0000000..03a91a3 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-hover.png new file mode 100755 index 0000000..a874724 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry.png new file mode 100755 index 0000000..6503c06 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/combo-right-entry.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-active.png new file mode 100755 index 0000000..13f2d70 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background-disabled.png new file mode 100755 index 0000000..ce14ba8 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background.png new file mode 100755 index 0000000..fdf26ab Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-background.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-disabled.png new file mode 100755 index 0000000..72e96fa Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-hover.png new file mode 100755 index 0000000..c56ef47 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry.png new file mode 100755 index 0000000..453c9f0 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/entry.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-active.png new file mode 100755 index 0000000..d941286 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-disabled.png new file mode 100755 index 0000000..49e9508 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-hover.png new file mode 100755 index 0000000..a60405b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button.png new file mode 100755 index 0000000..49e9508 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/flat-button.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/focus.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/focus.png new file mode 100755 index 0000000..189c575 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/focus.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-inline.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-inline.png new file mode 100755 index 0000000..d2f09d8 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-inline.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-notebook.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-notebook.png new file mode 100755 index 0000000..f617e4f Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame-notebook.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame.png new file mode 100755 index 0000000..f617e4f Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/frame.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-active.png new file mode 100755 index 0000000..dc092fa Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-hover.png new file mode 100755 index 0000000..16c85bb Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz.png new file mode 100755 index 0000000..92142fd Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-horz.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-active.png new file mode 100755 index 0000000..d7d2c6e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-hover.png new file mode 100755 index 0000000..69d104b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert.png new file mode 100755 index 0000000..8beda09 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/handle-vert.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked-disabled.png new file mode 100755 index 0000000..0d607e1 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked.png new file mode 100755 index 0000000..b29ba2e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-checked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed-disabled.png new file mode 100755 index 0000000..ba05833 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed.png new file mode 100755 index 0000000..4fbda14 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-mixed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png new file mode 100755 index 0000000..2f8d2d0 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked.png new file mode 100755 index 0000000..c493574 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-checkbox-unchecked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked-disabled.png new file mode 100755 index 0000000..48c1a26 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked.png new file mode 100755 index 0000000..aad36a4 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-checked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed-disabled.png new file mode 100755 index 0000000..ba05833 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed.png new file mode 100755 index 0000000..4fbda14 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-mixed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked-disabled.png new file mode 100755 index 0000000..2f8d2d0 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked.png new file mode 100755 index 0000000..c493574 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/menu-radio-unchecked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt-disabled.png new file mode 100755 index 0000000..8761247 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt.png new file mode 100755 index 0000000..6fcbf3c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-alt.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-disabled.png new file mode 100755 index 0000000..ed84ff0 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down.png new file mode 100755 index 0000000..5378d6d Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-down.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt-disabled.png new file mode 100755 index 0000000..4aa5495 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt.png new file mode 100755 index 0000000..540ee6c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-alt.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-disabled.png new file mode 100755 index 0000000..988b263 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-semi.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-semi.png new file mode 100755 index 0000000..51c5b22 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left-semi.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left.png new file mode 100755 index 0000000..79c4b9c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-left.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt-disabled.png new file mode 100755 index 0000000..58041f9 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt.png new file mode 100755 index 0000000..11ead9e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-alt.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-disabled.png new file mode 100755 index 0000000..633d232 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-semi.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-semi.png new file mode 100755 index 0000000..9b77f10 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right-semi.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right.png new file mode 100755 index 0000000..d6c41a8 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-right.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt-disabled.png new file mode 100755 index 0000000..1303814 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt.png new file mode 100755 index 0000000..d91dc92 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-alt.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-disabled.png new file mode 100755 index 0000000..85ca589 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up.png new file mode 100755 index 0000000..324d867 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/pan-up.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-progress.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-progress.png new file mode 100755 index 0000000..47b4188 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-progress.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-trough.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-trough.png new file mode 100755 index 0000000..0ab5001 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/progressbar-trough.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-active.png new file mode 100755 index 0000000..beb1c5e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-disabled.png new file mode 100755 index 0000000..b60b0b1 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-hover.png new file mode 100755 index 0000000..c503278 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked.png new file mode 100755 index 0000000..1d7635c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-checked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-active.png new file mode 100755 index 0000000..fa24191 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-disabled.png new file mode 100755 index 0000000..08ec632 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-hover.png new file mode 100755 index 0000000..f890a8e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed.png new file mode 100755 index 0000000..2fbb7ed Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-mixed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-active.png new file mode 100755 index 0000000..a03bff5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-disabled.png new file mode 100755 index 0000000..810d142 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-hover.png new file mode 100755 index 0000000..21b60e2 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked.png new file mode 100755 index 0000000..121b009 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/radio-unchecked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-active.png new file mode 100755 index 0000000..41dfeaf Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-disabled.png new file mode 100755 index 0000000..ba71de2 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough.png new file mode 100755 index 0000000..8fa6c3b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-horz-trough.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-active.png new file mode 100755 index 0000000..ae9dbd7 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-disabled.png new file mode 100755 index 0000000..7880b39 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-hover.png new file mode 100755 index 0000000..c45185c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider.png new file mode 100755 index 0000000..6bba655 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-active.png new file mode 100755 index 0000000..6fa5b42 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-disabled.png new file mode 100755 index 0000000..142e937 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough.png new file mode 100755 index 0000000..00f75cd Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scale-vert-trough.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-active.png new file mode 100755 index 0000000..7336715 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-disabled.png new file mode 100755 index 0000000..c624d53 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-hover.png new file mode 100755 index 0000000..20708af Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider.png new file mode 100755 index 0000000..0c300a6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-trough.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-trough.png new file mode 100755 index 0000000..77a7314 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-horz-trough.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png new file mode 100755 index 0000000..8d12ce3 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png new file mode 100755 index 0000000..3935e89 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png new file mode 100755 index 0000000..cfdfff5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider.png new file mode 100755 index 0000000..c39715e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-trough.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-trough.png new file mode 100755 index 0000000..bcb2864 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-ltr-trough.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png new file mode 100755 index 0000000..13f396e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png new file mode 100755 index 0000000..1ea4e64 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png new file mode 100755 index 0000000..db2ecbd Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider.png new file mode 100755 index 0000000..e2dbcff Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-trough.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-trough.png new file mode 100755 index 0000000..48c8066 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/scrollbar-vert-rtl-trough.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-active.png new file mode 100755 index 0000000..f09c8aa Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-disabled.png new file mode 100755 index 0000000..eab59c9 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-hover.png new file mode 100755 index 0000000..12b4cc4 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down.png new file mode 100755 index 0000000..a6f8cdd Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-down.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-active.png new file mode 100755 index 0000000..6dc88ef Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-disabled.png new file mode 100755 index 0000000..c4d63e6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-hover.png new file mode 100755 index 0000000..09cc0bc Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up.png new file mode 100755 index 0000000..297a745 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-ltr-up.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-active.png new file mode 100755 index 0000000..4779bcb Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-disabled.png new file mode 100755 index 0000000..5aca284 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-hover.png new file mode 100755 index 0000000..011a1a9 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down.png new file mode 100755 index 0000000..ff9dc75 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-down.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-active.png new file mode 100755 index 0000000..d9c1685 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-disabled.png new file mode 100755 index 0000000..2e7e347 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-hover.png new file mode 100755 index 0000000..b729b68 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up.png new file mode 100755 index 0000000..5159624 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/spin-rtl-up.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/tab.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/tab.png new file mode 100755 index 0000000..d01630b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/tab.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-active.png new file mode 100755 index 0000000..45da44f Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-hover.png new file mode 100755 index 0000000..a240cb6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button.png new file mode 100755 index 0000000..269e20e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-ltr-button.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-active.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-active.png new file mode 100755 index 0000000..a5a46b9 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-hover.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-hover.png new file mode 100755 index 0000000..810a277 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button-hover.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button.png new file mode 100755 index 0000000..269e20e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/assets/treeview-rtl-button.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/gtkrc b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/gtkrc new file mode 100755 index 0000000..07ffb00 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/gtkrc @@ -0,0 +1,36 @@ +# Based on Bridge by ScionicSpectre and Adwaita by GNOME +# vim:set ts=2 sw=2 sts=2 ai et: +# +# This is the GTK 2 version of Materia. It's whole purpose is to look as the +# GTK 3 version as much as possible until GTK 2 dies completely. +# +# Note: comments for explaining styles are on the bottom of each file beside the +# widget matches. + +# Declare the colours used throughout the theme. +# There shouldn't be any fiddling with them in the theme files themselves in +# order to not mess up the dark theme. + +# Text/base +gtk-color-scheme = "text_color:#E9E9ED\nbase_color:#1A1B26" +# Foreground/background +gtk-color-scheme = "fg_color:#E9E9ED\nbg_color:#1A1B26" +# Selected foreground/background +gtk-color-scheme = "selected_fg_color:#E9E9ED\nselected_bg_color:#7AA2F7" +# Titlebar foreground/background +gtk-color-scheme = "titlebar_fg_color:#E9E9ED\ntitlebar_bg_color:#292E42" +# Menus +gtk-color-scheme = "menu_color:#323449" +# Tooltips foreground/background +gtk-color-scheme = "tooltip_fg_color:#E9E9ED\ntooltip_bg_color:#414868" +# Links +gtk-color-scheme = "link_color:#7DCFFF\nvisited_link_color:#BB9AF7" + +# Set GTK settings +gtk-auto-mnemonics = 1 +gtk-primary-button-warps-slider = 1 + +# And hand over the control to the theme files +include "main.rc" +include "apps.rc" +include "hacks.rc" diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/hacks.rc b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/hacks.rc new file mode 100755 index 0000000..c288da3 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/hacks.rc @@ -0,0 +1,36 @@ +# vim:set ft=gtkrc ts=2 sw=2 sts=2 ai et: +# +# This file contains horrible hacks to make this theme work with some programs +# This is mostly due to the limitations of GTK 2 but sometimes its the fault of +# the programs themselves. Not going to point fingers. +# +# Either way, it's a WONTFIX for both, hence this horrible file. + +style "toplevel_hack" { + engine "adwaita" {} +} + +style "chrome_entry" { + base[NORMAL] = @base_color + base[INSENSITIVE] = @base_color +} + +style "vim_notebook" { + bg[NORMAL] = @base_color + bg[ACTIVE] = @bg_color +} + +# Vim puts an eventbox between the tab and the label and colours it, +# we need to handle that +widget "vim-main-window*GtkNotebook.GtkEventBox" style "vim_notebook" + +# (he)xchat input box +class "SexySpellEntry" style:highest "normal_entry" + +# Chromium uses base as the fill colour of its own entries +# This would be fine but GTK uses it to fill the surrounding space, so its set to bg +# That results in Chromium using it for the fill, so we need to handle that +widget_class "*Chrom*" style "chrome_entry" + +# Hack to be able to match widgets in LibreOffice +class "GtkWindow" style "toplevel_hack" diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/main.rc b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/main.rc new file mode 100755 index 0000000..8349b0e --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-2.0/main.rc @@ -0,0 +1,2708 @@ +# vim:set ft=gtkrc ts=2 sw=2 sts=2 ai et: +# +# This is the main theme file, handling all the default widgets and theme +# properties. Since GTK 2 is old, we need to overcome some of its limitations, +# which is also mostly done in this file. Sadly not all of them can be overcome +# so there will always be a visible difference between the GTK 2 and 3 theme. + +style "default" { + xthickness = 1 + ythickness = 1 + + #################### + # Style Properties # + #################### + + GtkWidget::focus-padding = 0 + GtkWidget::focus-line-width = 2 + GtkWidget::focus-line-pattern = "\2\1" + + GtkToolbar::space-size = 5 # 1 + 2*2 (separator + margins) + GtkToolbar::internal-padding = 2 + GtkToolButton::icon-spacing = 4 + + GtkWidget::tooltip-radius = 4 + GtkWidget::tooltip-alpha = 230 + GtkWidget::new-tooltip-style = 1 #for compatibility + + GtkWidget::link-color = @link_color + GtkWidget::visited-link-color = @visited_link_color + GnomeHRef::link_color = @link_color + GtkHTML::link-color = @link_color + GtkHTML::vlink-color = @visited_link_color + GtkIMHtml::hyperlink-color = @link_color + GtkIMHtml::hyperlink-visited-color = @visited_link_color + + GtkSeparatorMenuItem::horizontal-padding = 0 + GtkSeparatorMenuItem::wide-separators = 1 + GtkSeparatorMenuItem::separator-height = 3 + + GtkButton::child-displacement-y = 0 + + GtkButton::default-border = {0, 0, 0, 0} + GtkButton::default-outside-border = {0, 0, 0, 0} + GtkButton::inner-border = {0, 0, 0, 0} + + GtkEntry::state-hint = 1 + GtkEntry::inner-border = {0, 0, 0, 0} + + GtkPaned::handle-size = 8 + GtkHPaned::handle-size = 8 + GtkVPaned::handle-size = 8 + + GtkScrollbar::trough-border = 0 + GtkRange::trough-border = 0 + GtkRange::slider-width = 17 + GtkRange::stepper-size = 0 + GtkRange::activate-slider = 1 + + GtkScrollbar::activate-slider = 1 + GtkScrollbar::stepper-size = 0 + GtkScrollbar::has-backward-stepper = 0 + GtkScrollbar::has-forward-stepper = 0 + GtkScrollbar::min-slider-length = 32 # 24 + 2*4 (margins) + GtkScrolledWindow::scrollbar-spacing = 0 + GtkScrolledWindow::scrollbars-within-bevel = 1 + + GtkScale::slider_length = 24 + GtkScale::slider_width = 24 + GtkScale::trough-side-details = 1 + + GtkProgressBar::min-horizontal-bar-height = 4 + GtkProgressBar::min-vertical-bar-width = 4 + GtkProgressBar::xspacing = 4 + GtkProgressBar::yspacing = 4 + + GtkStatusbar::shadow_type = GTK_SHADOW_NONE + GtkSpinButton::shadow_type = GTK_SHADOW_NONE + GtkMenuBar::shadow-type = GTK_SHADOW_NONE + GtkToolbar::shadow-type = GTK_SHADOW_NONE + # TODO: find out what this comment means: + # ( every window is misaligned for the sake of menus ): + GtkMenuBar::internal-padding = 0 + GtkMenu::horizontal-padding = 0 + GtkMenu::vertical-padding = 4 + GtkMenu::double-arrows = 0 + GtkMenuItem::arrow-scaling = 1 + GtkMenuItem::toggle-spacing = 12 + + GtkCheckButton::indicator-size = 24 + GtkCheckButton::indicator_spacing = 2 + GtkOptionMenu::indicator_spacing = {8, 8, 4, 4} + + GtkTreeView::expander-size = 16 + GtkTreeView::vertical-separator = 0 + GtkTreeView::horizontal-separator = 4 + GtkTreeView::allow-rules = 0 + # Set this because some apps read it + GtkTreeView::odd-row-color = @base_color + GtkTreeView::even-row-color = @base_color + + GtkExpander::expander-size = 16 + + GtkNotebook::tab-overlap = 0 + + ########## + # Colors # + ########## + + bg[NORMAL] = @bg_color + bg[PRELIGHT] = @bg_color + bg[SELECTED] = mix (0.24, @selected_bg_color, @bg_color) + bg[INSENSITIVE] = @bg_color + bg[ACTIVE] = @bg_color + + fg[NORMAL] = @fg_color + fg[PRELIGHT] = @fg_color + fg[SELECTED] = @fg_color + fg[INSENSITIVE] = mix (0.5, @fg_color, @bg_color) + fg[ACTIVE] = @fg_color + + text[NORMAL] = @text_color + text[PRELIGHT] = @text_color + text[SELECTED] = @text_color + text[INSENSITIVE] = mix (0.5, @text_color, @base_color) + text[ACTIVE] = @text_color + + base[NORMAL] = @base_color + base[PRELIGHT] = mix (0.08, @text_color, @base_color) + base[SELECTED] = mix (0.24, @selected_bg_color, @base_color) + base[INSENSITIVE] = mix (0.5, @base_color, @bg_color) + base[ACTIVE] = mix (0.24, @selected_bg_color, @base_color) + + # For succinctness, all reasonable pixmap options remain here + + # Draw frame around menu in a non-compositied environment + # This needs to go before pixmap because we need to override some stuff + engine "adwaita" {} + + engine "pixmap" { + + ################# + # Check Buttons # + ################# + + image { + function = CHECK + state = NORMAL + shadow = OUT + overlay_file = "assets/checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = OUT + overlay_file = "assets/checkbox-unchecked-hover.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = OUT + overlay_file = "assets/checkbox-unchecked-active.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = SELECTED + shadow = OUT + overlay_file = "assets/checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/checkbox-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = IN + overlay_file = "assets/checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = IN + overlay_file = "assets/checkbox-checked-hover.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = IN + overlay_file = "assets/checkbox-checked-active.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = SELECTED + shadow = IN + overlay_file = "assets/checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = IN + overlay_file = "assets/checkbox-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed-hover.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed-active.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = SELECTED + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed-disabled.png" + overlay_stretch = FALSE + } + + ################# + # Radio Buttons # + ################# + + image { + function = OPTION + state = NORMAL + shadow = OUT + overlay_file = "assets/radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = OUT + overlay_file = "assets/radio-unchecked-hover.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = OUT + overlay_file = "assets/radio-unchecked-active.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = SELECTED + shadow = OUT + overlay_file = "assets/radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/radio-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = IN + overlay_file = "assets/radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = IN + overlay_file = "assets/radio-checked-hover.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = IN + overlay_file = "assets/radio-checked-active.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = SELECTED + shadow = IN + overlay_file = "assets/radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = IN + overlay_file = "assets/radio-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed-hover.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed-active.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = SELECTED + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed-disabled.png" + overlay_stretch = FALSE + } + + ########## + # Arrows # + ########## + + # Overrides + + # Disable arrows in spinbuttons + image { + function = ARROW + detail = "spinbutton" + } + + # Disable arrows for qt in scrollbars + + image { + function = ARROW + detail = "vscrollbar" + } + + image { + function = ARROW + detail = "hscrollbar" + } + + # Menu arrows + + image { + function = ARROW + state = NORMAL + detail = "menuitem" + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = PRELIGHT + detail = "menuitem" + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menuitem" + overlay_file = "assets/pan-left-disabled.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = NORMAL + detail = "menuitem" + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = PRELIGHT + detail = "menuitem" + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menuitem" + overlay_file = "assets/pan-right-disabled.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menu_scroll_arrow_up" + overlay_file = "assets/pan-up-disabled.png" + overlay_stretch = FALSE + } + + image { + function = ARROW + detail = "menu_scroll_arrow_up" + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menu_scroll_arrow_down" + overlay_file = "assets/pan-down-disabled.png" + overlay_stretch = FALSE + } + + image { + function = ARROW + detail = "menu_scroll_arrow_down" + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + # Regular arrows + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-left-alt.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-left-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-right-alt.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-right-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + ###################### + # Option Menu Arrows # + ###################### + + image { + function = TAB + state = NORMAL + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + } + + image { + function = TAB + state = PRELIGHT + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = TAB + state = ACTIVE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = TAB + state = INSENSITIVE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + } + + ######### + # Lines # + ######### + + image { + function = VLINE + file = "assets/border.png" + border = {1, 0, 0, 0} + } + + image { + function = HLINE + file = "assets/border.png" + border = {0, 0, 1, 0} + } + + ######### + # Focus # + ######### + + image { + function = FOCUS + file = "assets/focus.png" + border = {5, 5, 5, 5} # Super strange, {4, 4, 4, 4} does not work properly... + stretch = TRUE + } + + ########### + # Handles # + ########### + + image { + function = HANDLE + detail = "handlebox" + overlay_file = "assets/handle-vert.png" + overlay_stretch = FALSE + } + + image { + function = HANDLE + state = NORMAL + overlay_file = "assets/handle-horz.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + + image { + function = HANDLE + state = PRELIGHT + overlay_file = "assets/handle-horz-hover.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + + image { + function = HANDLE + state = ACTIVE + overlay_file = "assets/handle-horz-active.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + + image { + function = HANDLE + state = NORMAL + overlay_file = "assets/handle-vert.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + + image { + function = HANDLE + state = PRELIGHT + overlay_file = "assets/handle-vert-hover.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + + image { + function = HANDLE + state = ACTIVE + overlay_file = "assets/handle-vert-active.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + + image { + function = RESIZE_GRIP + } + + ############# + # Expanders # + ############# + + image { + function = EXPANDER + expander_style = EXPANDED + state = NORMAL + file = "assets/pan-down-alt.png" + } + + image { + function = EXPANDER + expander_style = EXPANDED + state = PRELIGHT + file = "assets/pan-down.png" + } + + image { + function = EXPANDER + expander_style = EXPANDED + state = ACTIVE + file = "assets/pan-down.png" + } + + image { + function = EXPANDER + expander_style = EXPANDED + state = INSENSITIVE + file = "assets/pan-down-alt-disabled.png" + } + + # LTR + + image { + function = EXPANDER + expander_style = COLLAPSED + state = NORMAL + file = "assets/pan-right-alt.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = PRELIGHT + file = "assets/pan-right.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = ACTIVE + file = "assets/pan-right.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = INSENSITIVE + file = "assets/pan-right-alt-disabled.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = SEMI_COLLAPSED + file = "assets/pan-right-semi.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = SEMI_EXPANDED + file = "assets/pan-right-semi.png" + direction = LTR + } + + # RTL + + image { + function = EXPANDER + expander_style = COLLAPSED + state = NORMAL + file = "assets/pan-left-alt.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = PRELIGHT + file = "assets/pan-left.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = ACTIVE + file = "assets/pan-left.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = INSENSITIVE + file = "assets/pan-left-alt-disabled.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = SEMI_COLLAPSED + file = "assets/pan-left-semi.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = SEMI_EXPANDED + file = "assets/pan-left-semi.png" + direction = RTL + } + + ############# + # Notebooks # + ############# + + # Left + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {0, 1, 0, 0} + stretch = TRUE + gap_side = RIGHT + } + + image { + function = EXTENSION + gap_side = RIGHT + } + + # Right + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {1, 0, 0, 0} + stretch = TRUE + gap_side = LEFT + } + + image { + function = EXTENSION + gap_side = LEFT + } + + # Up + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {0, 0, 0, 1} + stretch = TRUE + gap_side = BOTTOM + } + + image { + function = EXTENSION + gap_side = BOTTOM + } + + # Down + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {0, 0, 1, 0} + stretch = TRUE + gap_side = TOP + } + + image { + function = EXTENSION + gap_side = TOP + } + + # Inner frame + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {1, 0, 0, 0} + gap_side = LEFT + } + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {0, 1, 0, 0} + gap_side = RIGHT + } + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {0, 0, 1, 0} + gap_side = TOP + } + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {0, 0, 0, 1} + gap_side = BOTTOM + } + + # Standalone frame + image { + function = BOX + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + } + + ############## + # Scrollbars # + ############## + + image { + function = BOX + detail = "trough" + file = "assets/scrollbar-horz-trough.png" + border = {0, 0, 1, 0} + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough" + file = "assets/scrollbar-vert-ltr-trough.png" + border = {1, 0, 0, 0} + orientation = VERTICAL + direction = LTR + } + + image { + function = BOX + detail = "trough" + file = "assets/scrollbar-vert-rtl-trough.png" + border = {0, 1, 0, 0} + orientation = VERTICAL + direction = RTL + } + + # Horizontal sliders + + image { + function = SLIDER + state = NORMAL + detail = "slider" + file = "assets/scrollbar-horz-slider.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = SLIDER + state = PRELIGHT + detail = "slider" + file = "assets/scrollbar-horz-slider-hover.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = SLIDER + state = ACTIVE + detail = "slider" + file = "assets/scrollbar-horz-slider-active.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "slider" + file = "assets/scrollbar-horz-slider-disabled.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + # Vertical sliders + + image { + function = SLIDER + state = NORMAL + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + image { + function = SLIDER + state = PRELIGHT + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider-hover.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + image { + function = SLIDER + state = ACTIVE + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider-active.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider-disabled.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + # RTL + + image { + function = SLIDER + state = NORMAL + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + image { + function = SLIDER + state = PRELIGHT + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider-hover.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + image { + function = SLIDER + state = ACTIVE + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider-active.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider-disabled.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + ########## + # Scales # + ########## + + # Troughs, overrided later on. We set them here too because some widgets + # don't specify their orientation. + + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-horz-trough.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-upper" + file = "assets/scale-horz-trough-disabled.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-horz-trough-active.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-lower" + file = "assets/scale-horz-trough-disabled.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-vert-trough.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-upper" + file = "assets/scale-vert-trough-disabled.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-vert-trough-active.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-lower" + file = "assets/scale-vert-trough-disabled.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + # Sliders + + image { + function = SLIDER + state = NORMAL + detail = "hscale" + file = "assets/scale-slider.png" + } + + image { + function = SLIDER + state = PRELIGHT + detail = "hscale" + file = "assets/scale-slider-hover.png" + } + + image { + function = SLIDER + state = ACTIVE + detail = "hscale" + file = "assets/scale-slider-active.png" + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "hscale" + file = "assets/scale-slider-disabled.png" + } + + image { + function = SLIDER + state = NORMAL + detail = "vscale" + file = "assets/scale-slider.png" + } + + image { + function = SLIDER + state = PRELIGHT + detail = "vscale" + file = "assets/scale-slider-hover.png" + } + + image { + function = SLIDER + state = ACTIVE + detail = "vscale" + file = "assets/scale-slider-active.png" + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "vscale" + file = "assets/scale-slider-disabled.png" + } + + ########### + # Menubar # + ########### + + image { + function = BOX + detail = "menubar" + file = "assets/border.png" + border = {0, 0, 0, 1} + } + + ######### + # Menus # + ######### + + image { + function = BOX + state = PRELIGHT + detail = "menu_scroll_arrow_up" + file = "assets/border.png" + } + + image { + function = BOX + detail = "menu_scroll_arrow_up" + file = "assets/border.png" + border = {0, 0, 0, 1} + } + + image { + function = BOX + state = PRELIGHT + detail = "menu_scroll_arrow_down" + file = "assets/border.png" + } + + image { + function = BOX + detail = "menu_scroll_arrow_down" + file = "assets/border.png" + border = {0, 0, 1, 0} + } + + ########### + # Entries # + ########### + + image { + function = SHADOW + state = ACTIVE + detail = "entry" + file = "assets/entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = SHADOW + state = INSENSITIVE + detail = "entry" + file = "assets/entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = SHADOW + detail = "entry" + file = "assets/entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = FLAT_BOX + state = ACTIVE + detail = "entry_bg" + file = "assets/entry-background.png" + } + + image { + function = FLAT_BOX + state = INSENSITIVE + detail = "entry_bg" + file = "assets/entry-background-disabled.png" + } + + image { + function = FLAT_BOX + detail = "entry_bg" + file = "assets/entry-background.png" + } + + ######### + # Spins # + ######### + + # Spin-Up LTR + + image { + function = BOX + state = NORMAL + detail = "spinbutton_up" + file = "assets/spin-ltr-up.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_up" + file = "assets/spin-ltr-up-hover.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_up" + file = "assets/spin-ltr-up-active.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_up" + file = "assets/spin-ltr-up-disabled.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + direction = LTR + } + + # Spin-Up RTL + + image { + function = BOX + state = NORMAL + detail = "spinbutton_up" + file = "assets/spin-rtl-up.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_up" + file = "assets/spin-rtl-up-hover.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_up" + file = "assets/spin-rtl-up-hover.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_up" + file = "assets/spin-rtl-up-disabled.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + direction = RTL + } + + # Spin-Down LTR + + image { + function = BOX + state = NORMAL + detail = "spinbutton_down" + file = "assets/spin-ltr-down.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_down" + file = "assets/spin-ltr-down-hover.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_down" + file = "assets/spin-ltr-down-active.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_down" + file = "assets/spin-ltr-down-disabled.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + direction = LTR + } + + # Spin-Down RTL + + image { + function = BOX + state = NORMAL + detail = "spinbutton_down" + file = "assets/spin-rtl-down.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_down" + file = "assets/spin-rtl-down-hover.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_down" + file = "assets/spin-rtl-down-active.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_down" + file = "assets/spin-rtl-down-disabled.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + direction = RTL + } + + ############## + # Scrollbars # + ############## + + image { + function = BOX + detail = "bar" + file = "assets/progressbar-progress.png" + stretch = TRUE + border = {0, 0, 0, 0} + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "bar" + file = "assets/progressbar-progress.png" + stretch = TRUE + border = {0, 0, 0, 0} + orientation = VERTICAL + } + + ############# + # Treeviews # + ############# + + # Disable active the column highlight + # We need to match specific cells or we break stuff + # Looking at you deadbeef + + image { + function = FLAT_BOX + detail = "cell_even_sorted" + state = NORMAL + } + + image { + function = FLAT_BOX + detail = "cell_odd_sorted" + state = NORMAL + } + + # Disable all the other shadows + # This prevents the Raleigh effect + image { + function = SHADOW + } + } +} + +style "menubar" { + bg[NORMAL] = @titlebar_bg_color + fg[NORMAL] = mix(0.7, @titlebar_fg_color, @titlebar_bg_color) + fg[PRELIGHT] = @titlebar_fg_color + fg[INSENSITIVE] = mix(0.3, @titlebar_fg_color, @titlebar_bg_color) + bg[INSENSITIVE] = @bg_color + # Needed to fix Firefox's menubar text + bg[SELECTED] = mix(0.12, @titlebar_fg_color, @titlebar_bg_color) + fg[SELECTED] = @titlebar_fg_color +} + +style "menubar_item" { + xthickness = 3 + ythickness = 4 + + fg[NORMAL] = mix(0.7, @titlebar_fg_color, @titlebar_bg_color) + bg[PRELIGHT] = mix(0.12, @titlebar_fg_color, @titlebar_bg_color) + fg[PRELIGHT] = @titlebar_fg_color + fg[INSENSITIVE] = mix(0.3, @titlebar_fg_color, @titlebar_bg_color) +} + +style "menu" { + xthickness = 0 + ythickness = 0 + + bg[NORMAL] = @menu_color + bg[INSENSITIVE] = @menu_color + bg[PRELIGHT] = @menu_color + bg[SELECTED] = mix(0.08, @fg_color, @menu_color) +} + +style "menu_item" { + xthickness = 4 + ythickness = 4 + + bg[PRELIGHT] = mix(0.08, @fg_color, @menu_color) + fg[PRELIGHT] = @fg_color + # Chromium uses this setting + bg[SELECTED] = mix(0.08, @fg_color, @menu_color) + text[SELECTED] = @fg_color + # Some widgets use text, we need to handle that + text[NORMAL] = @fg_color + text[PRELIGHT] = @fg_color + + # Unfortunately we can't tell regular and menu checks/radios apart + # Without the heirarchy + engine "pixmap" { + + ################# + # Check Buttons # + ################# + + image { + function = CHECK + state = NORMAL + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = IN + overlay_file = "assets/menu-checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = IN + overlay_file = "assets/menu-checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = IN + overlay_file = "assets/menu-checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = IN + overlay_file = "assets/menu-checkbox-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed-disabled.png" + overlay_stretch = FALSE + } + + ################# + # Radio Buttons # + ################# + + image { + function = OPTION + state = NORMAL + shadow = OUT + overlay_file = "assets/menu-radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = OUT + overlay_file = "assets/menu-radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = OUT + overlay_file = "assets/menu-radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/menu-radio-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = IN + overlay_file = "assets/menu-radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = IN + overlay_file = "assets/menu-radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = IN + overlay_file = "assets/menu-radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = IN + overlay_file = "assets/menu-radio-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed-disabled.png" + overlay_stretch = FALSE + } + } +} + +style "separator_menu_item" { + xthickness = 0 + ythickness = 2 + + engine "pixmap" { + image { + function = BOX + file = "assets/border.png" + border = {0, 0, 0, 1} + } + } +} + +style "button_label" { + # fg[NORMAL] = mix(0.7, @fg_color, @bg_color) + # fg[INSENSITIVE] = mix(0.3, @fg_color, @bg_color) + + font_name = "Medium" +} + +style "normal_button_label" { + # fg[NORMAL] = @fg_color + # fg[INSENSITIVE] = mix(0.5, @fg_color, @bg_color) + + font_name = "Regular" +} + +style "button" { + xthickness = 6 + ythickness = 6 + + # For the sake of sanity style buttons this way + engine "pixmap" { + + ########### + # Buttons # + ########### + + image { + function = BOX + state = NORMAL + file = "assets/button.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = PRELIGHT + shadow = OUT + file = "assets/button-hover.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + # Don't add hover effect on pressed buttons + image { + function = BOX + state = PRELIGHT + shadow = IN + file = "assets/button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = ACTIVE + file = "assets/button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + file = "assets/button-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + } +} + +style "link_button" { + # Disable the button effect, leave just the link + engine "pixmap" { + image { + function = BOX + } + } +} + +style "entry" { + base[NORMAL] = @bg_color + base[SELECTED] = mix (0.24, @selected_bg_color, @bg_color) + base[INSENSITIVE] = @bg_color + base[ACTIVE] = mix (0.24, @selected_bg_color, @bg_color) + + # We set this same as the border of the border of the entry + # This way there's no overlap + xthickness = 6 + ythickness = 6 +} + +style "combobox" { + xthickness = 6 + ythickness = 6 + + # This affects only the button beside an entry + GtkButton::inner-border = {0, 0, 0, 0} + + # For the sake of sanity style buttons this way + engine "pixmap" { + + ########### + # Buttons # + ########### + + image { + function = BOX + state = NORMAL + file = "assets/entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = PRELIGHT + file = "assets/entry-hover.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = ACTIVE + file = "assets/entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + file = "assets/entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + } +} + +style "combobox_cellview" { + # text[NORMAL] = mix(0.7, @fg_color, @bg_color) + # text[INSENSITIVE] = mix(0.3, @fg_color, @bg_color) +} + +style "combobox_entry" { + # Since one side of the button is missing, we need to shift the arrow a little to the right + GtkButton::inner-border = {0, 2, 0, 0} + + base[NORMAL] = @base_color + base[ACTIVE] = @base_color + + engine "pixmap" { + + ############# + # LTR entry # + ############# + + image { + function = SHADOW + state = NORMAL + detail = "entry" + file = "assets/combo-left-entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = SHADOW + state = ACTIVE + detail = "entry" + file = "assets/combo-left-entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = SHADOW + state = INSENSITIVE + detail = "entry" + file = "assets/combo-left-entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + ############# + # RTL entry # + ############# + + image { + function = SHADOW + state = NORMAL + detail = "entry" + file = "assets/combo-right-entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = SHADOW + state = ACTIVE + detail = "entry" + file = "assets/combo-right-entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = SHADOW + state = INSENSITIVE + detail = "entry" + file = "assets/combo-right-entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = RTL + } + + ############## + # LTR button # + ############## + + image { + function = BOX + state = NORMAL + detail = "button" + file = "assets/combo-right-entry.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + detail = "button" + file = "assets/combo-right-entry-hover.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + detail = "button" + file = "assets/combo-right-entry-active.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = INSENSITIVE + detail = "button" + file = "assets/combo-right-entry-disabled.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + ############## + # RTL button # + ############## + + image { + function = BOX + state = NORMAL + detail = "button" + file = "assets/combo-left-entry.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + detail = "button" + file = "assets/combo-left-entry-hover.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + detail = "button" + file = "assets/combo-left-entry-active.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = INSENSITIVE + detail = "button" + file = "assets/combo-left-entry-disabled.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + } +} + +style "combo_button_padding" { + # Since one side of the button is missing, we need to shift the arrow a + # little to the right. + # This is the same thing we've done above but the combo, unlike the combobox, + # uses padding the same way as a button. + GtkButton::inner-border = {3, 6, 3, 3} +} + +style "notebook" { + xthickness = 3 + ythickness = 3 + bg[NORMAL] = @base_color +} + +style "notebook_tab_label" { + fg[ACTIVE] = mix(0.7, @fg_color, @bg_color) + + font_name = "Medium" +} + +style "notebook_viewport" { + bg[NORMAL] = @base_color +} + +style "notebook_bg" { + bg[NORMAL] = @base_color + bg[PRELIGHT] = @base_color + bg[INSENSITIVE] = @base_color +} + +style "notebook_entry" { + base[NORMAL] = @base_color + base[SELECTED] = mix (0.24, @selected_bg_color, @base_color) + base[INSENSITIVE] = @base_color + base[ACTIVE] = mix (0.24, @selected_bg_color, @base_color) +} + +style "normal_bg" { + bg[NORMAL] = @bg_color + bg[PRELIGHT] = @bg_color + bg[INSENSITIVE] = @bg_color +} + +style "normal_entry" { + base[NORMAL] = @bg_color + base[SELECTED] = mix (0.24, @selected_bg_color, @bg_color) + base[INSENSITIVE] = @bg_color + base[ACTIVE] = mix (0.24, @selected_bg_color, @bg_color) +} + +style "textview" { + bg[NORMAL] = @base_color +} + +style "scale_horz" { + engine "pixmap" { + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-horz-trough.png" + border = {6, 6, 0, 0} + stretch = TRUE + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-horz-trough-active.png" + border = {6, 6, 0, 0} + stretch = TRUE + } + } +} + +style "scale_vert" { + engine "pixmap" { + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-vert-trough.png" + border = {0, 0, 6, 6} + stretch = TRUE + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-vert-trough-active.png" + border = {0, 0, 6, 6} + stretch = TRUE + } + } +} + +style "progressbar" { + xthickness = 0 + ythickness = 0 + + fg[PRELIGHT] = @selected_fg_color + + engine "pixmap" { + image { + function = BOX + detail = "trough" + file = "assets/progressbar-trough.png" + border = {0, 0, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough" + file = "assets/progressbar-trough.png" + border = {0, 0, 0, 0} + stretch = TRUE + orientation = VERTICAL + } + } +} + +style "treeview_header" { + xthickness = 2 + ythickness = 2 + + fg[NORMAL] = mix(0.7, @fg_color, @base_color) + fg[PRELIGHT] = @fg_color + + font_name = "Medium" + + GtkButton::inner-border = {4, 4, 0, 2} + + engine "pixmap" { + image { + function = BOX + state = NORMAL + file = "assets/treeview-ltr-button.png" + border = {0, 1, 0, 1} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + file = "assets/treeview-ltr-button-hover.png" + border = {0, 1, 0, 1} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + file = "assets/treeview-ltr-button-active.png" + border = {0, 1, 0, 1} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = NORMAL + file = "assets/treeview-rtl-button.png" + border = {1, 0, 0, 1} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + file = "assets/treeview-rtl-button-hover.png" + border = {1, 0, 0, 1} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + file = "assets/treeview-rtl-button-active.png" + border = {1, 0, 0, 1} + stretch = TRUE + direction = RTL + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + } +} + +style "scrolled_window" { + engine "pixmap" { + image { + function = SHADOW + file = "assets/frame.png" + border = {1, 1, 1, 1} + stretch = TRUE + } + } +} + +style "frame" { + engine "pixmap" { + image { + function = SHADOW + shadow = NONE + } + + image { + function = SHADOW + file = "assets/frame.png" + border = {1, 1, 1, 1} + stretch = TRUE + } + + image { + function = SHADOW_GAP + file = "assets/frame.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_start_file = "assets/border.png" + gap_end_file = "assets/border.png" + } + } +} + +style "tool_button" { + GtkButton::inner-border = {2, 2, 2, 2} + + # For the sake of sanity style buttons this way + engine "pixmap" { + image { + function = BOX + state = NORMAL + file = "assets/flat-button.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = PRELIGHT + shadow = OUT + file = "assets/flat-button-hover.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + # Don't add hover effect on pressed buttons + image { + function = BOX + state = PRELIGHT + shadow = IN + file = "assets/flat-button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = ACTIVE + file = "assets/flat-button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + shadow = OUT + file = "assets/flat-button-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + shadow = IN + file = "assets/button-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + } +} + +style "toolbar_separator" { + GtkWidget::wide-separators = 1 + GtkWidget::separator-width = 1 + GtkWidget::separator-height = 1 + + engine "pixmap" { + image { + function = BOX + file = "assets/border.png" + } + } +} + +style "inline_toolbar" { + # GtkToolbar::button-relief = GTK_RELIEF_NORMAL + bg[NORMAL] = @base_color + + engine "pixmap" { + image { + function = BOX + file = "assets/frame-inline.png" + border = {1, 1, 0, 1} + stretch = TRUE + } + } +} + +style "tooltip" { + xthickness = 8 + ythickness = 8 + + bg[NORMAL] = @tooltip_bg_color + fg[NORMAL] = @tooltip_fg_color + bg[SELECTED] = @tooltip_bg_color +} + +style "disable_text_shadow" { + engine "murrine" { + textstyle = 0 + } +} + +style "disable_separator" { + xthickness = 0 + ythickness = 0 + + GtkWidget::wide-separators = 1 +} + +# Default style, containing theme properties and trying to match every widget as +# much as possible, which is not only faster than trying to match every widget +# by its own but also less bug-prune and more consistent. However there is some +# widget specific stuff that needs to be taken care of, which is the point of +# every other style below. +class "GtkWidget" style "default" + +###################################### +# Override padding, style and colour # +###################################### + +class "GtkButton" style "button" +class "GtkLinkButton" style "link_button" +class "GtkEntry" style "entry" +class "GtkOldEditable" style "entry" +class "GtkNotebook" style "notebook" +class "GtkHScale" style "scale_horz" +class "GtkVScale" style "scale_vert" +class "GtkProgressBar" style "progressbar" +class "GtkScrolledWindow" style "scrolled_window" +class "GtkFrame" style "frame" +class "GtkSeparatorToolItem" style "toolbar_separator" +class "GtkMenuBar" style "menubar" +class "GtkMenu" style "menu" +class "GtkTextView" style "textview" + +# Menu and menubar items +widget_class "**" style "menu_item" +widget_class "*.*" style "menubar_item" +widget_class "**" style "separator_menu_item" + +# Treeview buttons +widget_class "***" style "treeview_header" + +# Give the file chooser toolbar a border +widget_class "**" style "inline_toolbar" + +# Fix padding on regular comboboxes +widget_class "*." style "combobox" +widget_class "*" style "combobox" + +# And disable separators on them +widget_class "*.*" style "disable_separator" +widget_class "**" style "disable_separator" +widget_class "**" style "disable_separator" + +# Join together the ComboBoxEntry entry and button +widget_class "**" style "combobox_entry" + +# Join the Combo entry and button +widget_class "**" style "combobox_entry" + +# Tweak the padding on the button a little bit because it +# uses it a bit differently +widget_class "*." style "combo_button_padding" + +# Alas we cannot do the same for ComboBoxText because there +# isn't a way to apply the style to only the comboboxes that +# have an entry inside + +# Tool buttons have different styles +widget_class "**" style "tool_button" +widget_class "**.*" style "tool_button" + +# Notebooks +widget_class "*." style "notebook_tab_label" +widget_class "*.." style "notebook_tab_label" + +# Notebooks are white, act accordingly +widget_class "**" style "notebook_entry" +widget_class "**" style "notebook_bg" +widget_class "**" style "notebook_bg" +widget_class "***" style "notebook_bg" +widget_class "**" style "notebook_bg" +widget_class "*.*" style "notebook_bg" + +# However, stuff inside eventboxes inside notebooks is grey +# again, react +widget_class "***" style "normal_entry" +widget_class "***" style "normal_bg" +widget_class "***" style "normal_bg" + +# Button labels +widget_class "*." style "button_label" + +# Normalize button labels +widget_class "*." style "normal_button_label" +widget_class "*." style "normal_button_label" + +# ComboBoxes tend to draw the button label with text[] +# instead of fg[], we need to fix that +widget_class "**" style "combobox_cellview" + +# Disable white text shadows +widget_class "*" style "disable_text_shadow" +widget_class "*" style "disable_text_shadow" + +# GTK tooltips +widget "gtk-tooltip*" style "tooltip" diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg new file mode 100755 index 0000000..c3eedb0 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..96be359 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..f016658 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..1bc6987 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg @@ -0,0 +1,50 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/close.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/close.svg new file mode 100755 index 0000000..06201c3 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/close.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg new file mode 100755 index 0000000..e2a252b --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/maximize.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/maximize.svg new file mode 100755 index 0000000..39316eb --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/maximize.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/minimize.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/minimize.svg new file mode 100755 index 0000000..f3683b9 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/minimize.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic.svg new file mode 100755 index 0000000..d13b029 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg new file mode 100755 index 0000000..ed8d87a --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg new file mode 120000 index 0000000..79b7355 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..b68859d --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..de0d789 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..7f0235f --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg @@ -0,0 +1,47 @@ + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg new file mode 100755 index 0000000..993f308 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg new file mode 100755 index 0000000..740bc8b --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic.svg new file mode 100755 index 0000000..73a1dbe --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic.svg @@ -0,0 +1,40 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg new file mode 100755 index 0000000..bec2ee4 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..37d9c04 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..1bc5cb6 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg new file mode 100755 index 0000000..caed76f --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..58aa5ff --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg @@ -0,0 +1,46 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..0e477a9 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..d0980e2 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg new file mode 100755 index 0000000..0fdb530 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg new file mode 100755 index 0000000..251e2f5 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg new file mode 120000 index 0000000..86dfcec --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..bafb558 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/unmaximize.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/unmaximize.svg new file mode 100755 index 0000000..492d47a --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scalable/unmaximize.svg @@ -0,0 +1,46 @@ + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png new file mode 100755 index 0000000..890208f Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png new file mode 100755 index 0000000..e8ea798 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png new file mode 100755 index 0000000..ee2c1af Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png new file mode 100755 index 0000000..87e30c3 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png new file mode 100755 index 0000000..e95eb5b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png new file mode 100755 index 0000000..0a0a8ed Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider.png new file mode 100755 index 0000000..15f51ef Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider@2.png new file mode 100755 index 0000000..b8d71b6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-after-slider@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png new file mode 100755 index 0000000..d661dbd Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png new file mode 100755 index 0000000..b1b439f Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png new file mode 100755 index 0000000..5f45aa0 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png new file mode 100755 index 0000000..586083b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png new file mode 100755 index 0000000..52c2550 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png new file mode 100755 index 0000000..b8e8088 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider.png new file mode 100755 index 0000000..f38270e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider@2.png new file mode 100755 index 0000000..fe7e7e1 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-horz-marks-before-slider@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png new file mode 100755 index 0000000..4f242a2 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png new file mode 100755 index 0000000..f558cf6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png new file mode 100755 index 0000000..c5311b5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png new file mode 100755 index 0000000..4a597ca Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png new file mode 100755 index 0000000..8b83821 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png new file mode 100755 index 0000000..910f982 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider.png new file mode 100755 index 0000000..26f31e9 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider@2.png new file mode 100755 index 0000000..600c1d5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-after-slider@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png new file mode 100755 index 0000000..49b673d Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png new file mode 100755 index 0000000..edd9faf Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png new file mode 100755 index 0000000..3e6f1b1 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png new file mode 100755 index 0000000..b8aea05 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png new file mode 100755 index 0000000..6477531 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png new file mode 100755 index 0000000..f322929 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider.png new file mode 100755 index 0000000..6867860 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider@2.png new file mode 100755 index 0000000..9171590 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/scale-vert-marks-before-slider@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png new file mode 100755 index 0000000..f7c2bca Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png new file mode 100755 index 0000000..a18b567 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked.png new file mode 100755 index 0000000..9ba5afd Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked@2.png new file mode 100755 index 0000000..35f212f Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-checked@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png new file mode 100755 index 0000000..aca41ba Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png new file mode 100755 index 0000000..a151740 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked.png new file mode 100755 index 0000000..5726153 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png new file mode 100755 index 0000000..d54e840 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk-dark.css b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk-dark.css new file mode 100755 index 0000000..11d2255 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk-dark.css @@ -0,0 +1,8598 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #89b4fa 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #89b4fa 100%, transparent 0%); + } +} + +* { + background-clip: padding-box; + -gtktoolbutton-icon-spacing: 4; + -gtktextview-error-underline-color: #d20f39; + -gtkscrolledwindow-scrollbar-spacing: 0; + -gtktoolitemgroup-expander-size: 11; + -gtkwidget-text-handle-width: 20; + -gtkwidget-text-handle-height: 20; + -gtkdialog-button-spacing: 6; + -gtkdialog-action-area-border: 4; + -gtkdialog-content-area-border: 4; + outline-style: solid; + outline-width: 0; + outline-color: alpha(currentColor, 0.15); + outline-offset: -4px; + -gtk-outline-radius: 12px; + -gtk-secondary-caret-color: #89b4fa; +} + +.thunar .standard-view.frame widget.view:selected, XfdesktopIconView.view:active, calendar.raven-calendar:selected, box.vertical > widget > widget:selected, calendar:selected, modelbutton.flat:selected, +.menuitem.button.flat:selected, .background.csd .view:selected { + color: #eff1f5; + background-color: alpha(currentColor, 0.1); +} + +.nautilus-window notebook .view:not(treeview) selection, .nautilus-window notebook .view:not(treeview):selected, .nautilus-window flowboxchild:selected .icon-item-background, label selection, flowbox flowboxchild:selected { + color: #89b4fa; + background-color: rgba(137, 180, 250, 0.2); +} + +.nemo-window .nemo-window-pane widget.entry:selected, window.background.csd evview.view.content-view:selected, window.background.csd evview.view.content-view:selected:backdrop, .nautilus-window.background.csd notebook widget.view:selected, spinbutton.vertical selection, spinbutton:not(.vertical) selection, +entry selection, textview text selection:focus, textview text selection, widget.view:selected, .view:selected { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +treeview.view:selected { + color: rgba(30, 30, 46, 0.87); + background-color: #e6e9ef; +} + +.linked:not(.vertical) > button, .linked:not(.vertical) > spinbutton.vertical, .linked:not(.vertical) > spinbutton:not(.vertical), .linked:not(.vertical) > entry { + border-radius: 0; +} + +.linked:not(.vertical) > button:first-child, .linked:not(.vertical) > spinbutton.vertical:first-child, .linked:not(.vertical) > spinbutton:first-child:not(.vertical), .linked:not(.vertical) > entry:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > button:last-child, .linked:not(.vertical) > spinbutton.vertical:last-child, .linked:not(.vertical) > spinbutton:last-child:not(.vertical), .linked:not(.vertical) > entry:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > button:only-child, .linked:not(.vertical) > spinbutton.vertical:only-child, .linked:not(.vertical) > spinbutton:only-child:not(.vertical), .linked:not(.vertical) > entry:only-child { + border-radius: 12px; +} + +.linked.vertical > button, .linked.vertical > spinbutton.vertical, .linked.vertical > spinbutton:not(.vertical), .linked.vertical > entry { + border-radius: 0; +} + +.linked.vertical > button:first-child, .linked.vertical > spinbutton.vertical:first-child, .linked.vertical > spinbutton:first-child:not(.vertical), .linked.vertical > entry:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > button:last-child, .linked.vertical > spinbutton.vertical:last-child, .linked.vertical > spinbutton:last-child:not(.vertical), .linked.vertical > entry:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > button:only-child, .linked.vertical > spinbutton.vertical:only-child, .linked.vertical > spinbutton:only-child:not(.vertical), .linked.vertical > entry:only-child { + border-radius: 12px; +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #1e1e2e; + color: #eff1f5; +} + +.background.csd { + border-radius: 0 0 12px 12px; +} + +.background.maximized, .background.solid-csd { + border-radius: 0; +} + +*:disabled { + -gtk-icon-effect: dim; +} + +.gtkstyle-fallback { + background-color: #1e1e2e; + color: #eff1f5; +} + +.gtkstyle-fallback:hover { + background-color: #14141f; + color: #eff1f5; +} + +.gtkstyle-fallback:active { + background-color: #0a0a0f; + color: #eff1f5; +} + +.gtkstyle-fallback:disabled { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.5); +} + +.gtkstyle-fallback:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.view { + background-color: #313244; + color: #eff1f5; +} + +.view:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.view:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.view:selected:hover { + box-shadow: none; +} + +window.background.csd > stack.view { + border-radius: 0 0 12px 12px; +} + +textview text { + background-color: #313244; +} + +textview border { + background-color: #313244; + color: rgba(239, 241, 245, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 12px; +} + +flowbox rubberband, +.rubberband, +rubberband, +XfdesktopIconView.view .rubberband, +.content-view rubberband, +.content-view .rubberband, +treeview.view rubberband { + border: 1px solid #89b4fa; + background-color: rgba(137, 180, 250, 0.3); +} + +flowbox flowboxchild { + padding: 3px; + border-radius: 12px; + color: #eff1f5; +} + +flowbox flowboxchild button.osd.remove-button { + min-height: 28px; + min-width: 28px; + padding: 0; + margin: 6px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +label { + caret-color: currentColor; +} + +label.separator { + color: rgba(239, 241, 245, 0.7); +} + +label:disabled { + color: rgba(239, 241, 245, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; +} + +label.osd { + border-radius: 12px; + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; +} + +.dim-label { + color: rgba(239, 241, 245, 0.7); +} + +assistant .sidebar { + padding: 4px 0; +} + +assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(239, 241, 245, 0.5); + font-weight: 500; +} + +assistant .sidebar label.highlight { + color: #eff1f5; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + -gtk-icon-transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry { + background-color: rgba(30, 30, 46, 0.04); + color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus { + color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active) { + color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled { + background-color: rgba(30, 30, 46, 0.04); + color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image { + color: rgba(30, 30, 46, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled { + color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image { + color: rgba(30, 30, 46, 0.87); +} + +spinbutton.vertical, spinbutton:not(.vertical), +entry { + min-height: 34px; + padding: 0 8px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton.vertical:focus, spinbutton:focus:not(.vertical), +entry:focus { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #89b4fa; +} + +spinbutton.vertical:drop(active), spinbutton:drop(active):not(.vertical), +entry:drop(active) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + +spinbutton.vertical:disabled, spinbutton:disabled:not(.vertical), +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.flat.vertical, spinbutton.flat:not(.vertical), +entry.flat { + min-height: 0; + padding: 2px; + border-radius: 0; + background-color: transparent; +} + +spinbutton.vertical image, spinbutton:not(.vertical) image, +entry image { + color: rgba(239, 241, 245, 0.7); +} + +spinbutton.vertical image:hover, spinbutton:not(.vertical) image:hover, spinbutton.vertical image:active, spinbutton:not(.vertical) image:active, +entry image:hover, +entry image:active { + color: #eff1f5; +} + +spinbutton.vertical image:disabled, spinbutton:not(.vertical) image:disabled, +entry image:disabled { + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.vertical image.left, spinbutton:not(.vertical) image.left, +entry image.left { + margin-left: 1px; + margin-right: 6px; +} + +spinbutton.vertical image.right, spinbutton:not(.vertical) image.right, +entry image.right { + margin-left: 6px; + margin-right: 1px; +} + +spinbutton.vertical undershoot.left, spinbutton:not(.vertical) undershoot.left, +entry undershoot.left { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(239, 241, 245, 0.3) 50%); + padding-left: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: left top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.vertical undershoot.right, spinbutton:not(.vertical) undershoot.right, +entry undershoot.right { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(239, 241, 245, 0.3) 50%); + padding-right: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: right top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.error.vertical, spinbutton.error:not(.vertical), +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton.error.vertical:focus, spinbutton.error:focus:not(.vertical), +entry.error:focus { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #d20f39; +} + +spinbutton.error.vertical:disabled, spinbutton.error:disabled:not(.vertical), +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.warning.vertical, spinbutton.warning:not(.vertical), +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton.warning.vertical:focus, spinbutton.warning:focus:not(.vertical), +entry.warning:focus { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #df8e1d; +} + +spinbutton.warning.vertical:disabled, spinbutton.warning:disabled:not(.vertical), +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.vertical progress, spinbutton:not(.vertical) progress, +entry progress { + margin: 2px -8px; + border-bottom: 2px solid #89b4fa; + background-color: transparent; +} + +treeview entry.flat, treeview entry { + background-color: #313244; +} + +treeview entry.flat, treeview entry.flat:focus, treeview entry, treeview entry:focus { + border-image: none; + box-shadow: none; +} + +.entry-tag, .photos-entry-tag, .documents-entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.entry-tag:hover, .photos-entry-tag:hover, .documents-entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag, :dir(ltr) .photos-entry-tag, :dir(ltr) .documents-entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag, :dir(rtl) .photos-entry-tag, :dir(rtl) .documents-entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button, .button.photos-entry-tag, .button.documents-entry-tag { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active), .button.photos-entry-tag:not(:hover):not(:active), .button.documents-entry-tag:not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.001, to(#89b4fa), to(transparent)); + } + to { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(#89b4fa), to(transparent)); + } +} + +.xfce4-panel.background button, .raven-mpris button.image-button, .mate-panel-menu-bar button, infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button { + color: rgba(239, 241, 245, 0.7); +} + +.xfce4-panel.background button:focus, .raven-mpris button.image-button:focus, .mate-panel-menu-bar button:focus, infobar.warning > revealer > box button:focus, .xfce4-panel.background button:hover, .raven-mpris button.image-button:hover, .mate-panel-menu-bar button:hover, infobar.warning > revealer > box button:hover, .xfce4-panel.background button:active, .raven-mpris button.image-button:active, .mate-panel-menu-bar button:active, infobar.warning > revealer > box button:active, .xfce4-panel.background button:checked, .raven-mpris button.image-button:checked, .mate-panel-menu-bar button:checked, infobar.warning > revealer > box button:checked { + color: #eff1f5; +} + +.xfce4-panel.background button:disabled, .raven-mpris button.image-button:disabled, .mate-panel-menu-bar button:disabled, infobar.warning > revealer > box button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.xfce4-panel.background button:checked:disabled, .raven-mpris button.image-button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, infobar.warning > revealer > box button:checked:disabled { + color: rgba(239, 241, 245, 0.5); +} + +actionbar > revealer > box button:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: #313244; + color: #eff1f5; +} + +actionbar > revealer > box button:checked:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: rgba(30, 30, 46, 0.87); + color: #e6e9ef; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat, terminal-window notebook > header > box button.flat { + color: rgba(30, 30, 46, 0.6); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:hover, terminal-window notebook > header > box button.flat:hover, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:active, terminal-window notebook > header > box button.flat:active, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:focus, terminal-window notebook > header > box button.flat:focus { + color: rgba(30, 30, 46, 0.87); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:checked, terminal-window notebook > header > box button.flat:checked { + background-color: rgba(30, 30, 46, 0.87); + color: #e6e9ef; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:disabled, terminal-window notebook > header > box button.flat:disabled { + color: rgba(30, 30, 46, 0.3); +} + +button { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(239, 241, 245, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #eff1f5; +} + +button:focus { + box-shadow: 0 0 0 2px rgba(137, 180, 250, 0.35); +} + +button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +button:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +button:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +button:checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +button:checked:hover { + box-shadow: inset 0 0 0 9999px transparent; +} + +button:checked:disabled { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.1); + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +.raven .expander-button, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, .nautilus-window headerbar revealer > button, button.titlebutton:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, button.close, button.circular, .inline-toolbar button:not(.text-button) { + border-radius: 9999px; +} + +.raven .expander-button label, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle label, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat) label, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, .nautilus-window headerbar revealer > button label, button.titlebutton:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, button.close label, button.circular label, .inline-toolbar button:not(.text-button) label { + padding: 0; +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat, .gedit-document-panel row button.flat, .nautilus-window .floating-bar button, placessidebar.sidebar row button.sidebar-button, notebook > header tab button.flat, +notebook > header tab button.close-button, spinbutton.vertical button, spinbutton:not(.vertical) button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button, .drop-shadow button, .budgie-panel button, .budgie-popover row button, .budgie-settings-window buttonbox.inline-toolbar button, #mate-menu button, #MatePanelPopupWindow button, popover.messagepopover .popover-action-area button, tabbox > tab button, placessidebar.sidebar row button.sidebar-button, calendar.button, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular, treeview.view header button button.circular, row.activatable button.circular, notebook > header > tabs > arrow, modelbutton.flat, +.menuitem.button.flat, spinbutton.vertical button, spinbutton:not(.vertical) button, .nemo-window .toolbar button, #buttonbox_frame button, .xfce4-panel.background button, .raven stackswitcher.linked > button, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button, .lock-dialog button, .mate-panel-menu-bar button, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, layouttabbar button, filechooser #pathbarbox > stack > box > button, messagedialog .dialog-action-box button, +messagedialog .dialog-action-box .linked:not(.vertical) > button, .app-notification button, popover.background.menu button, +popover.background button.model, .nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action), button.flat { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: rgba(239, 241, 245, 0.7); +} + +.budgie-session-dialog .linked.horizontal > button:focus, +.budgie-polkit-dialog .linked.horizontal > button:focus, +.budgie-run-dialog .linked.horizontal > button:focus, .drop-shadow button:focus, .budgie-panel button:focus, .budgie-popover row button:focus, .budgie-settings-window buttonbox.inline-toolbar button:focus, #mate-menu button:focus, #MatePanelPopupWindow button:focus, popover.messagepopover .popover-action-area button:focus, tabbox > tab button:focus, placessidebar.sidebar row button.sidebar-button:focus, calendar.button:focus, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:focus, treeview.view header button button.circular:focus, row.activatable button.circular:focus, notebook > header > tabs > arrow:focus, modelbutton.flat:focus, +.menuitem.button.flat:focus, spinbutton.vertical button:focus, spinbutton:not(.vertical) button:focus, .nemo-window .toolbar button:focus, #buttonbox_frame button:focus, .xfce4-panel.background button:focus, .raven stackswitcher.linked > button:focus, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:focus, .lock-dialog button:focus, .mate-panel-menu-bar button:focus, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, layouttabbar button:focus, filechooser #pathbarbox > stack > box > button:focus, messagedialog .dialog-action-box button:focus, +messagedialog .dialog-action-box .linked:not(.vertical) > button:focus, .app-notification button:focus, popover.background.menu button:focus, +popover.background button.model:focus, .nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), button.flat:focus { + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + color: #eff1f5; +} + +.budgie-session-dialog .linked.horizontal > button:hover, +.budgie-polkit-dialog .linked.horizontal > button:hover, +.budgie-run-dialog .linked.horizontal > button:hover, .drop-shadow button:hover, .budgie-panel button:hover, .budgie-popover row button:hover, .budgie-settings-window buttonbox.inline-toolbar button:hover, #mate-menu button:hover, #MatePanelPopupWindow button:hover, popover.messagepopover .popover-action-area button:hover, tabbox > tab button:hover, placessidebar.sidebar row button.sidebar-button:hover, calendar.button:hover, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:hover, treeview.view header button button.circular:hover, row.activatable button.circular:hover, notebook > header > tabs > arrow:hover, modelbutton.flat:hover, +.menuitem.button.flat:hover, spinbutton.vertical button:hover, spinbutton:not(.vertical) button:hover, .nemo-window .toolbar button:hover, #buttonbox_frame button:hover, .xfce4-panel.background button:hover, .raven stackswitcher.linked > button:hover, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:hover, .lock-dialog button:hover, .mate-panel-menu-bar button:hover, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, layouttabbar button:hover, filechooser #pathbarbox > stack > box > button:hover, messagedialog .dialog-action-box button:hover, +messagedialog .dialog-action-box .linked:not(.vertical) > button:hover, .app-notification button:hover, popover.background.menu button:hover, +popover.background button.model:hover, .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), button.flat:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #eff1f5; +} + +.budgie-session-dialog .linked.horizontal > button:active, +.budgie-polkit-dialog .linked.horizontal > button:active, +.budgie-run-dialog .linked.horizontal > button:active, .drop-shadow button:active, .budgie-panel button:active, .budgie-popover row button:active, .budgie-settings-window buttonbox.inline-toolbar button:active, #mate-menu button:active, #MatePanelPopupWindow button:active, popover.messagepopover .popover-action-area button:active, tabbox > tab button:active, placessidebar.sidebar row button.sidebar-button:active, calendar.button:active, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:active, treeview.view header button button.circular:active, row.activatable button.circular:active, notebook > header > tabs > arrow:active, modelbutton.flat:active, +.menuitem.button.flat:active, spinbutton.vertical button:active, spinbutton:not(.vertical) button:active, .nemo-window .toolbar button:active, #buttonbox_frame button:active, .xfce4-panel.background button:active, .raven stackswitcher.linked > button:active, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:active, .lock-dialog button:active, .mate-panel-menu-bar button:active, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, layouttabbar button:active, filechooser #pathbarbox > stack > box > button:active, messagedialog .dialog-action-box button:active, +messagedialog .dialog-action-box .linked:not(.vertical) > button:active, .app-notification button:active, popover.background.menu button:active, +popover.background button.model:active, .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), button.flat:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #eff1f5; +} + +.budgie-session-dialog .linked.horizontal > button:disabled, +.budgie-polkit-dialog .linked.horizontal > button:disabled, +.budgie-run-dialog .linked.horizontal > button:disabled, .drop-shadow button:disabled, .budgie-panel button:disabled, .budgie-popover row button:disabled, .budgie-settings-window buttonbox.inline-toolbar button:disabled, #mate-menu button:disabled, #MatePanelPopupWindow button:disabled, popover.messagepopover .popover-action-area button:disabled, tabbox > tab button:disabled, placessidebar.sidebar row button.sidebar-button:disabled, calendar.button:disabled, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:disabled, treeview.view header button button.circular:disabled, row.activatable button.circular:disabled, notebook > header > tabs > arrow:disabled, modelbutton.flat:disabled, +.menuitem.button.flat:disabled, spinbutton.vertical button:disabled, spinbutton:not(.vertical) button:disabled, .nemo-window .toolbar button:disabled, #buttonbox_frame button:disabled, .xfce4-panel.background button:disabled, .raven stackswitcher.linked > button:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:disabled, .lock-dialog button:disabled, .mate-panel-menu-bar button:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, layouttabbar button:disabled, filechooser #pathbarbox > stack > box > button:disabled, messagedialog .dialog-action-box button:disabled, +messagedialog .dialog-action-box .linked:not(.vertical) > button:disabled, .app-notification button:disabled, popover.background.menu button:disabled, +popover.background button.model:disabled, .nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action), button.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .toolbar button:checked, #buttonbox_frame button:checked, .xfce4-panel.background button:checked, .raven stackswitcher.linked > button:checked, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked, .lock-dialog button:checked, .mate-panel-menu-bar button:checked, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, layouttabbar button:checked, filechooser #pathbarbox > stack > box > button:checked, messagedialog .dialog-action-box button:checked, +messagedialog .dialog-action-box .linked:not(.vertical) > button:checked, .app-notification button:checked, popover.background.menu button:checked, +popover.background button.model:checked, .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action), button.flat:checked, button.flat:checked:hover { + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +.nemo-window .toolbar button:checked:disabled, #buttonbox_frame button:checked:disabled, .xfce4-panel.background button:checked:disabled, .raven stackswitcher.linked > button:checked:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked:disabled, .lock-dialog button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, layouttabbar button:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, messagedialog .dialog-action-box button:checked:disabled, .app-notification button:checked:disabled, popover.background.menu button:checked:disabled, +popover.background button.model:checked:disabled, .nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(239, 241, 245, 0.5); +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child) { + margin: 0 4px; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + border-radius: 12px; +} + +button.osd { + min-width: 24px; + min-width: 24px; + padding: 5px; + background-color: #1e1e2e; + color: #eff1f5; +} + +button.osd:focus { + box-shadow: none; +} + +button.osd:hover { + background-color: #3d3e4c; + color: #eff1f5; +} + +button.osd:active { + background-color: #525360; + color: #eff1f5; +} + +button.osd:disabled { + opacity: 0; +} + +button.osd.image-button, button.osd.circular { + padding: 11px; +} + +button.osd.image-button > image, button.osd.circular > image { + padding: 0; +} + +button.suggested-action { + background-color: #1e66f5; + color: #eff1f5; + box-shadow: none; +} + +button.suggested-action:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(30, 102, 245, 0.2), 0 4px 3px 0 rgba(30, 102, 245, 0.14), 0 1px 6px 0 rgba(30, 102, 245, 0.12); +} + +button.suggested-action:checked { + background-color: #5d90f5; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(30, 102, 245, 0.3), 0 2px 3px -1px rgba(30, 102, 245, 0.24), 0 2px 5px 0 rgba(30, 102, 245, 0.12); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(30, 102, 245, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #1e66f5; +} + +button.suggested-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +button.suggested-action.flat:checked { + background-color: rgba(30, 102, 245, 0.3); +} + +button.destructive-action { + background-color: #d20f39; + color: #eff1f5; + box-shadow: none; +} + +button.destructive-action:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(210, 15, 57, 0.2), 0 4px 3px 0 rgba(210, 15, 57, 0.14), 0 1px 6px 0 rgba(210, 15, 57, 0.12); +} + +button.destructive-action:checked { + background-color: #db5371; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(210, 15, 57, 0.3), 0 2px 3px -1px rgba(210, 15, 57, 0.24), 0 2px 5px 0 rgba(210, 15, 57, 0.12); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(210, 15, 57, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #d20f39; +} + +button.destructive-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +button.destructive-action.flat:checked { + background-color: rgba(210, 15, 57, 0.3); +} + +.stack-switcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +.stack-switcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +.stack-switcher > button.needs-attention:checked > label, +.stack-switcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +.primary-toolbar button { + -gtk-icon-shadow: none; +} + +button.close, button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +stacksidebar.sidebar row.needs-attention > label, .stack-switcher > button.needs-attention > label, +.stack-switcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar.sidebar row.needs-attention > label:dir(rtl), .stack-switcher > button.needs-attention > label:dir(rtl), +.stack-switcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + +/********* + * Links * + *********/ +*:link, +link { + color: #8fcbe8; +} + +*:visited { + color: #8839ef; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #8fcbe8; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #8839ef; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton:not(.vertical) { + padding: 0; +} + +spinbutton:not(.vertical) entry { + min-width: 30px; + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +spinbutton:not(.vertical) button { + border: solid 6px transparent; +} + +spinbutton:not(.vertical) button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(239, 241, 245, 0.7); +} + +spinbutton:not(.vertical) button.up:dir(ltr), spinbutton:not(.vertical) button.down:dir(rtl) { + margin-left: -3px; +} + +spinbutton:not(.vertical) button.up:dir(rtl), spinbutton:not(.vertical) button.down:dir(ltr) { + margin-right: -3px; +} + +spinbutton.vertical { + padding: 0; +} + +spinbutton.vertical:disabled { + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.vertical entry { + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical button { + padding: 0; + border: solid 6px transparent; +} + +spinbutton.vertical button:focus:not(:hover):not(:active) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(239, 241, 245, 0.7); +} + +spinbutton.vertical button.up { + margin: 0 3px; +} + +spinbutton.vertical button.down { + margin: 0 3px; +} + +treeview spinbutton:not(.vertical) { + min-height: 0; + border-style: none; + border-radius: 0; +} + +treeview spinbutton:not(.vertical) entry { + min-height: 0; + padding: 1px 2px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-radius: 0 9px 9px 0; + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #fab387; + box-shadow: inset 0 0 0 2px #fab387; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #eff1f5; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top), combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) { + background-color: transparent; + background-image: linear-gradient(to left, transparent 50%, rgba(239, 241, 245, 0.3) 50%); + padding-top: 1px; + background-size: 12px 1px; + background-repeat: repeat-x; + background-origin: content-box; + background-position: left top; + margin: 0 4px; +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +toolbar { + -gtkwidget-window-dragging: true; + padding: 2px 3px; + background-color: #1e1e2e; +} + +.osd toolbar { + background-color: transparent; +} + +frame.documents-dropdown, .app-notification, toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +frame.documents-dropdown:backdrop, .app-notification:backdrop, toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +frame.left.documents-dropdown, .left.app-notification, frame.right.documents-dropdown, .right.app-notification, frame.top.documents-dropdown, .top.app-notification, frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.left, toolbar.osd.right, toolbar.osd.top, toolbar.osd.bottom { + border-radius: 0; +} + +frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +toolbar.horizontal > separator { + margin: 2px; +} + +toolbar.vertical > separator { + margin: 2px; +} + +toolbar:not(.inline-toolbar):not(.osd) scale, +toolbar:not(.inline-toolbar):not(.osd) entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton, +toolbar:not(.inline-toolbar):not(.osd) button { + margin: 2px 1px; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:first-child) { + margin-left: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:last-child) { + margin-right: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) spinbutton entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton button { + margin: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) switch { + margin: 8px 2px; +} + +.toolbar { + background-color: #313244; +} + +frame .toolbar { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.inline-toolbar { + padding: 6px; + border-style: solid; + border-width: 0 1px 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +.frame .inline-toolbar { + border-width: 1px 0 0; + background-color: transparent; +} + +searchbar > revealer > box, +.location-bar { + padding: 6px; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; + background-clip: border-box; +} + +searchbar > revealer > box { + margin: -6px; +} + +/*************** + * Header bars * + ***************/ +.nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar .linked:not(.vertical) > button:not(.text-button), headerbar .linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + border-radius: 12px; +} + +.nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +.nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:not(.text-button), headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:focus:not(.text-button), headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:hover:not(.text-button), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:active:not(.text-button), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:disabled:not(.text-button), headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar button:backdrop:checked:not(.text-button), headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:checked:disabled:not(.text-button), headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar entry, .titlebar entry { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +.nemo-window .primary-toolbar entry:disabled, .titlebar entry:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar entry image, .titlebar entry image { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar entry image:hover, .titlebar entry image:hover, .nemo-window .primary-toolbar entry image:active, .titlebar entry image:active { + color: #eff1f5; +} + +.nemo-window .primary-toolbar entry image:disabled, .titlebar entry image:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.titlebar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 12px 12px 0 0; + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* @if $outline == 'false' { */ + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* } */ +} + +.titlebar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.titlebar:backdrop { + color: rgba(239, 241, 245, 0.7); +} + +.titlebar:backdrop:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.csd .titlebar:backdrop { + background-color: #1e1e2e; +} + +.titlebar .title { + padding: 0 12px; + font-weight: bold; +} + +.titlebar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +.titlebar .subtitle, +.titlebar .dim-label { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(239, 241, 245, 0.7); +} + +.titlebar .subtitle:backdrop, +.titlebar .dim-label:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +.titlebar .titlebar { + background-color: transparent; + box-shadow: none; +} + +.titlebar + separator, +.titlebar + separator.sidebar { + background-color: #1e1e2e; + background-image: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +.titlebar + separator:backdrop, +.titlebar + separator.sidebar:backdrop { + background-color: #1e1e2e; +} + +.titlebar.selection-mode + separator, .titlebar.selection-mode + separator.sidebar, .selection-mode .titlebar + separator, .selection-mode .titlebar + separator.sidebar { + background-color: #89b4fa; +} + +.titlebar.selection-mode + separator:backdrop, .titlebar.selection-mode + separator.sidebar:backdrop, .selection-mode .titlebar + separator:backdrop, .selection-mode .titlebar + separator.sidebar:backdrop { + background-color: #89b4fa; +} + +.background.csd.unified .titlebar + separator, .background.csd.unified .titlebar + separator.sidebar { + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.titlebar .linked:not(.vertical) > entry { + border-radius: 12px; + margin-left: 3px; + margin-right: 3px; +} + +.titlebar button.suggested-action:disabled, +.titlebar button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +.titlebar .path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; + padding-left: 5px; + padding-right: 5px; +} + +.titlebar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + animation: ripple-on-headerbar 225ms cubic-bezier(0, 0, 0.2, 1); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode:backdrop { + color: rgba(30, 30, 46, 0.6); + background-color: #a6c7fb; +} + +.titlebar.selection-mode .subtitle:link { + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):disabled { + color: rgba(30, 30, 46, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked { + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked:disabled { + color: rgba(30, 30, 46, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:not(.titlebutton) { + color: rgba(30, 30, 46, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:disabled { + color: rgba(30, 30, 46, 0.3); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked { + color: rgba(30, 30, 46, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked:disabled { + color: rgba(30, 30, 46, 0.3); +} + +.titlebar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +.titlebar.selection-mode .selection-menu arrow { + -gtkarrow-arrow-scaling: 1; +} + +.titlebar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +.tiled .titlebar, .tiled-top .titlebar, .tiled-right .titlebar, .tiled-bottom .titlebar, .tiled-left .titlebar, .maximized .titlebar, .fullscreen .titlebar { + border-radius: 0; +} + +.titlebar.default-decoration { + min-height: 24px; + padding: 6px 12px; + border-radius: 12px 12px 0 0; + border: none; + background-color: #1e1e2e; + background-image: none; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +.titlebar.default-decoration:backdrop { + background-color: #1e1e2e; +} + +.tiled .titlebar.default-decoration, .maximized .titlebar.default-decoration, .fullscreen .titlebar.default-decoration { + box-shadow: none; + border-radius: 0; +} + +.titlebar.default-decoration button.titlebutton { + min-height: 24px; + min-width: 24px; + margin: 0; + padding: 0; +} + +.background.csd .titlebar.default-decoration { + padding: 6px; + box-shadow: none; +} + +.background:not(.csd) .titlebar.default-decoration button.titlebutton:active { + background-size: 1000% 1000%; +} + +.solid-csd .titlebar:dir(rtl), .solid-csd .titlebar:dir(ltr) { + border-radius: 0; + box-shadow: none; +} + +headerbar { + min-height: 46px; + padding: 0 6px; +} + +box.vertical headerbar { + background-color: #1e1e2e; +} + +headerbar entry, +headerbar spinbutton, +headerbar button, +headerbar stackswitcher { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar button, +headerbar button.image-button { + border-radius: 12px; +} + +headerbar > box.left, +headerbar > box.right { + padding: 0 4px; +} + +headerbar separator.titlebutton, +headerbar separator.sidebar { + margin-top: 11.5px; + margin-bottom: 11.5px; + background-color: transparent; +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar spinbutton button { + margin-top: 0; + margin-bottom: 0; +} + +headerbar .entry-tag, headerbar .photos-entry-tag, headerbar .documents-entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar.windowhandle viewswitcher { + border-radius: 0 0 12px 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) { + border-radius: 9px; + margin: 6px 3px; + min-width: 120px; + padding: 0; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) > stack > box { + padding: 0 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +):focus { + box-shadow: none; +} + +headerbar.windowhandle > button.popup label, +headerbar.windowhandle > button.popup image { + min-height: 0; +} + +headerbar.windowhandle viewswitchertitle > squeezer { + margin-top: 0; + margin-bottom: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher { + margin: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher > box.horizontal > button.radio { + margin: 0; + padding: 0; + border-radius: 0; +} + +/************ + * Pathbars * + ************/ +.caja-pathbar button, +.path-bar.linked:not(.vertical) > button { + padding-left: 5px; + padding-right: 5px; + border-radius: 6px; + margin-left: 1px; + margin-right: 1px; + background-color: alpha(currentColor, 0.08); +} + +.caja-pathbar button:disabled, +.path-bar.linked:not(.vertical) > button:disabled { + background-color: alpha(currentColor, 0.05); +} + +.caja-pathbar button:first-child, +.path-bar.linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.caja-pathbar button:last-child, +.path-bar.linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.caja-pathbar button:checked, +.path-bar.linked:not(.vertical) > button:checked { + background-color: alpha(currentColor, 0.16); + color: #eff1f5; +} + +.caja-pathbar button label, +.caja-pathbar button image, +.path-bar.linked:not(.vertical) > button label, +.path-bar.linked:not(.vertical) > button image { + margin-left: 3px; + margin-right: 3px; +} + +.caja-pathbar button.slider-button, +.path-bar.linked:not(.vertical) > button.slider-button { + padding-left: 4px; + padding-right: 4px; +} + +/************** + * Tree Views * + **************/ +treeview.view { + border-left-color: rgba(239, 241, 245, 0.12); + border-top-color: rgba(239, 241, 245, 0.12); +} + +* { + -gtktreeview-horizontal-separator: 4; + -gtktreeview-grid-line-width: 1; + -gtktreeview-grid-line-pattern: ''; + -gtktreeview-tree-line-width: 1; + -gtktreeview-tree-line-pattern: ''; + -gtktreeview-expander-size: 16; +} + +.csd +treeview.view:not(:selected):not(:hover):not(.progressbar):not(.expander):not( +.trough +):not(.separator) { + background-color: transparent; +} + +treeview.view.separator { + min-height: 6px; + color: rgba(239, 241, 245, 0.12); +} + +treeview.view:drop(active) { + border-style: solid none; + border-width: 9999px; + border-color: alpha(currentColor, 0.08); +} + +treeview.view:drop(active).after { + border-top-style: none; +} + +treeview.view:drop(active).before { + border-bottom-style: none; +} + +treeview.view.expander { + color: rgba(239, 241, 245, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); +} + +treeview.view.expander:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view.expander:checked { + -gtk-icon-transform: unset; +} + +treeview.view.expander:hover, treeview.view.expander:active { + color: #eff1f5; +} + +treeview.view.expander:disabled { + color: rgba(239, 241, 245, 0.32); +} + +treeview.view.expander:selected { + color: rgba(30, 30, 46, 0.6); +} + +treeview.view.expander:selected:hover, treeview.view.expander:selected:active { + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.expander:selected:disabled { + color: rgba(30, 30, 46, 0.3); +} + +treeview.view.progressbar { + border: none; + box-shadow: none; + background-color: #89b4fa; + background-image: none; + border-radius: 9999px; + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.progressbar:selected, treeview.view.progressbar:selected:hover, treeview.view.progressbar:selected:focus { + box-shadow: none; + background-color: #98bdf9; + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.progressbar:selected:backdrop, treeview.view.progressbar:selected:hover:backdrop, treeview.view.progressbar:selected:focus:backdrop { + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.progressbar:backdrop, treeview.view.progressbar:selected:backdrop { + background-color: rgba(239, 241, 245, 0.3); +} + +treeview.view.trough { + border: none; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); + background-image: none; + border-radius: 9999px; + padding: 0; + margin: 0; +} + +treeview.view.trough:selected, treeview.view.trough:selected:hover, treeview.view.trough:selected:focus { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); +} + +treeview.view.trough:backdrop, treeview.view.trough:selected:backdrop { + background-color: rgba(239, 241, 245, 0.12); +} + +treeview.view header button { + padding: 2px 6px; + border: none; + border-right: 1px solid transparent; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; + background-clip: border-box; + border-image: linear-gradient(to bottom, transparent 20%, rgba(239, 241, 245, 0.12) 20%, rgba(239, 241, 245, 0.12) 80%, transparent 80%) 0 1 0 0/0 1px 0 0 stretch; +} + +treeview.view header button:not(:focus):not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +treeview.view header button, treeview.view header button:disabled { + background-color: #313244; +} + +treeview.view header button:last-child { + border-right: none; + border-image: none; +} + +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #313244; + background-clip: border-box; + color: #89b4fa; +} + +treeview.view acceleditor > label { + background-color: #89b4fa; +} + +/********* + * Menus * + *********/ +menubar, +.menubar { + -gtkwidget-window-dragging: true; + padding: 0; + background-color: #1e1e2e; + color: #eff1f5; + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +menubar:backdrop, +.menubar:backdrop { + color: rgba(239, 241, 245, 0.7); + background-color: #1e1e2e; +} + +.csd menubar, .csd .menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > menuitem, +.menubar > menuitem { + transition: none; + min-height: 20px; + padding: 4px 8px; + color: rgba(239, 241, 245, 0.7); + border-radius: 12px; +} + +menubar > menuitem:hover, +.menubar > menuitem:hover { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +menubar > menuitem:backdrop, +.menubar > menuitem:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +menubar > menuitem:disabled, +.menubar > menuitem:disabled { + color: rgba(239, 241, 245, 0.32); +} + +menubar > menuitem label:disabled, +.menubar > menuitem label:disabled { + color: inherit; +} + +menubar > menuitem > window.popup.background > menu menuitem, +.menubar > menuitem > window.popup.background > menu menuitem { + transition: none; +} + +.background.popup { + background-color: transparent; +} + +menu { + margin: 6px; + padding: 6px; + background-color: #232634; + background-clip: border-box; + border-radius: 12px; + border: 2px solid #89b4fa; +} + +.csd menu { + border: none; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.1); +} + +menu menuitem { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + min-width: 40px; + padding: 4px 8px; + color: #eff1f5; + font: initial; + text-shadow: none; + border-radius: 12px; +} + +menu menuitem:hover { + background-color: alpha(currentColor, 0.08); +} + +menu menuitem:active { + background-color: alpha(currentColor, 0.12); +} + +menu menuitem:disabled { + color: rgba(239, 241, 245, 0.5); +} + +menu menuitem accelerator { + color: rgba(239, 241, 245, 0.7); +} + +menu menuitem:disabled accelerator { + color: rgba(239, 241, 245, 0.32); +} + +menu menuitem arrow { + min-height: 16px; + min-width: 16px; +} + +menu menuitem arrow:dir(ltr) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + margin-left: 8px; +} + +menu menuitem arrow:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); + margin-right: 8px; +} + +menu menuitem label:dir(rtl), menu menuitem label:dir(ltr) { + color: inherit; +} + +menu .view:selected { + background-color: #3d404f; +} + +menu > arrow { + min-height: 16px; + min-width: 16px; + padding: 4px; + background-color: #292c3c; + color: rgba(239, 241, 245, 0.7); +} + +menu > arrow.top { + margin-top: 0; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menu > arrow.bottom { + margin-top: 8px; + margin-bottom: -12px; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menu > arrow:hover { + background-image: image(alpha(currentColor, 0.08)); + color: #eff1f5; +} + +menu > arrow:disabled { + border-color: transparent; + background-color: transparent; + color: transparent; +} + +menu separator { + margin: 4px 0; +} + +/************ + * Popovers * + ************/ +popover.background { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 0; + background-color: #232634; + border-radius: 12px; +} + +popover.background, .csd popover.background { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +popover.background > stack { + margin: 0; +} + +popover.background > toolbar { + margin: 0; +} + +popover.background > list, +popover.background > .view, +popover.background > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover.background > scrolledwindow > viewport.frame > list { + background-color: transparent; + padding: 6px; +} + +popover.background > scrolledwindow > viewport.frame > list > row { + border-radius: 12px; + padding: 6px; +} + +popover.background .view:not(:selected), +popover.background toolbar { + background-color: #232634; +} + +popover.background button, +popover.background entry, +popover.background combobox { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio) { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):first-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):last-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.background.menu button, +popover.background button.model { + min-height: 32px; + padding: 0 8px; + border-radius: 12px; +} + +popover.background separator { + margin: 3px 0; + background-color: transparent; +} + +popover.background list separator { + margin: 0; +} + +modelbutton.flat, +.menuitem.button.flat { + min-height: 28px; + padding: 0 8px; + border-radius: 12px; + color: #eff1f5; +} + +modelbutton.flat arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +modelbutton.flat arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +/************* + * Notebooks * + *************/ +tabbox > tab, notebook > header tab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + padding: 3px 12px; + border: none; + outline: none; + background-clip: padding-box; + color: rgba(239, 241, 245, 0.7); + font-weight: 500; + border-radius: 9px; +} + +tabbox > tab:hover, notebook > header tab:hover { + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +tabbox > tab:disabled, notebook > header tab:disabled { + color: rgba(239, 241, 245, 0.32); +} + +tabbox > tab:checked, notebook > header tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbox > tab:checked:disabled, notebook > header tab:checked:disabled { + color: rgba(239, 241, 245, 0.5); +} + +notebook { + background-color: rgba(239, 241, 245, 0.04); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: transparent; +} + +notebook.frame { + border-radius: 15px; +} + +notebook.frame scrolledwindow.frame { + border: none; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(239, 241, 245, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header tab > box:drop(active) { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +notebook > header tab button.flat:last-child, +notebook > header tab button.close-button:last-child { + margin-left: 6px; + margin-right: -6px; +} + +notebook > header tab button.flat:first-child, +notebook > header tab button.close-button:first-child { + margin-left: -6px; + margin-right: 6px; +} + +notebook > header.top tabs > tab + tab, notebook > header.bottom tabs > tab + tab { + margin-left: 3px; +} + +notebook > header.top tabs:not(:only-child):first-child, notebook > header.bottom tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top tabs:not(:only-child):last-child, notebook > header.bottom tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top tabs tab.reorderable-page, notebook > header.bottom tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left tabs > tab + tab, notebook > header.right tabs > tab + tab { + margin-top: 3px; +} + +notebook > header.left tabs:not(:only-child):first-child, notebook > header.right tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left tabs:not(:only-child):last-child, notebook > header.right tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left tabs tab.reorderable-page, notebook > header.right tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > button.image-button { + min-height: 24px; + min-width: 24px; + padding: 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); +} + +* { + -gtkscrollbar-has-backward-stepper: false; + -gtkscrollbar-has-forward-stepper: false; +} + +scrollbar, +scrollbar button { + border: none; + min-width: 0; + min-height: 0; + padding: 0; + border-radius: 0; + background-color: transparent; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 12px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(239, 241, 245, 0.5); +} + +scrollbar slider:hover { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar slider:active { + background-color: rgba(239, 241, 245, 0.7); +} + +scrollbar slider:disabled { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar.fine-tune slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.fine-tune.horizontal slider { + border-width: 5px 4px; +} + +scrollbar.fine-tune.vertical slider { + border-width: 4px 5px; +} + +scrollbar.overlay-indicator trough { + background-color: rgba(239, 241, 245, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal slider { + min-width: 40px; +} + +scrollbar.vertical slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border: none; + border-radius: 9999px; + background-color: rgba(239, 241, 245, 0.5); + background-clip: padding-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #89b4fa; +} + +switch:disabled { + opacity: 0.5; +} + +switch slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #eff1f5; + border: none; + color: transparent; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12); +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; +} + +checkbutton.text-button, +radiobutton.text-button { + padding: 2px; +} + +checkbutton.text-button label:not(:only-child), +radiobutton.text-button label:not(:only-child) { + margin: 0 4px; +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate), +actionbar > revealer > box radio:not(:checked):not(:indeterminate) { + background-color: rgba(30, 30, 46, 0.12); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):hover, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):hover { + box-shadow: 0 0 0 6px rgba(30, 30, 46, 0.04); + background-color: rgba(30, 30, 46, 0.15); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):active, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):active { + box-shadow: 0 0 0 6px rgba(30, 30, 46, 0.12); + background-color: rgba(30, 30, 46, 0.2); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):disabled, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):disabled { + background-color: rgba(30, 30, 46, 0.04); +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + color: transparent; + background-color: rgba(239, 241, 245, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.04); + background-color: rgba(239, 241, 245, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(239, 241, 245, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(30, 30, 46, 0.6); + background-color: #89b4fa; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.15); + background-color: #bad3fc; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.2); + background-color: #89b4fa; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(30, 30, 46, 0.3); + background-color: rgba(137, 180, 250, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem radio { + transition: none; + margin: 0; + padding: 0; +} + +menu menuitem check:dir(ltr), menu menuitem radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +menu menuitem check:dir(rtl), menu menuitem radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem check:hover, menu menuitem check:disabled, menu menuitem check:checked:hover, menu menuitem check:indeterminate:hover, menu menuitem radio, menu menuitem radio:hover, menu menuitem radio:disabled, menu menuitem radio:checked:hover, menu menuitem radio:indeterminate:hover { + box-shadow: none; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic@2.svg"))); +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check, +menu menuitem check { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > checkbutton > check:checked, +menu menuitem check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check:indeterminate, +menu menuitem check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio, +menu menuitem radio { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > radiobutton > radio:checked, +menu menuitem radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio:indeterminate, +menu menuitem radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +check:not(:checked):indeterminate:active, +radio:not(:checked):indeterminate:active { + -gtk-icon-transform: scaleX(-1); +} + +treeview.view radio, +treeview.view check { + padding: 0; + margin: 0; + background-color: rgba(239, 241, 245, 0.12); +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view radio:selected:not(:disabled):not(:checked):not(:indeterminate), +treeview.view check:selected:not(:disabled):not(:checked):not(:indeterminate) { + background-color: rgba(30, 30, 46, 0.12); +} + +treeview.view radio:checked, treeview.view radio:indeterminate, +treeview.view check:checked, +treeview.view check:indeterminate { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + background-image: none; +} + +.view.content-view.check:not(list), +.content-view .tile check:not(list) { + min-height: 40px; + min-width: 40px; + margin: 0; + padding: 0; + border-radius: 9999px; +} + +.view.content-view.check:not(list):not(:checked), +.content-view .tile check:not(list):not(:checked) { + background-image: image(rgba(239, 241, 245, 0.25)); +} + +.view.content-view.check:not(list):hover, .view.content-view.check:not(list):checked, +.content-view .tile check:not(list):hover, +.content-view .tile check:not(list):checked { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1); +} + +.view.content-view.check:not(list):checked, +.content-view .tile check:not(list):checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale slider { + min-height: 18px; + min-width: 18px; + margin: -8px; +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune slider { + margin: -7px; +} + +scale trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(239, 241, 245, 0.3); +} + +scale trough:disabled { + background-color: rgba(239, 241, 245, 0.12); +} + +scale highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#89b4fa); +} + +scale highlight:disabled { + background-color: #1e1e2e; + background-image: image(rgba(239, 241, 245, 0.32)); +} + +scale fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.3); +} + +scale fill:disabled { + background-color: transparent; +} + +scale slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #89b4fa; + background-color: #313244; + box-shadow: inset 0 0 0 2px #89b4fa; +} + +scale slider:hover { + box-shadow: inset 0 0 0 2px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale slider:active { + box-shadow: inset 0 0 0 4px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale slider:disabled { + box-shadow: inset 0 0 0 2px rgba(239, 241, 245, 0.32); +} + +scale marks, +scale value { + color: rgba(239, 241, 245, 0.7); +} + +scale indicator { + background-color: rgba(239, 241, 245, 0.3); + color: transparent; +} + +scale.horizontal marks.top { + margin-bottom: 7px; + margin-top: -15px; +} + +scale.horizontal.fine-tune marks.top { + margin-bottom: 6px; + margin-top: -14px; +} + +scale.horizontal marks.bottom { + margin-top: 7px; + margin-bottom: -15px; +} + +scale.horizontal.fine-tune marks.bottom { + margin-top: 6px; + margin-bottom: -14px; +} + +scale.vertical marks.top { + margin-right: 7px; + margin-left: -15px; +} + +scale.vertical.fine-tune marks.top { + margin-right: 6px; + margin-left: -14px; +} + +scale.vertical marks.bottom { + margin-left: 7px; + margin-right: -15px; +} + +scale.vertical.fine-tune marks.bottom { + margin-left: 6px; + margin-right: -14px; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.horizontal.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-before:not(.marks-after) slider, scale.horizontal.marks-before:not(.marks-after) slider:hover, scale.horizontal.marks-before:not(.marks-after) slider:active, scale.horizontal.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-disabled-dark.svg"), url("assets/scale-horz-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-after:not(.marks-before) slider, scale.horizontal.marks-after:not(.marks-before) slider:hover, scale.horizontal.marks-after:not(.marks-before) slider:active, scale.horizontal.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-disabled-dark.svg"), url("assets/scale-horz-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-before:not(.marks-after) slider, scale.vertical.marks-before:not(.marks-after) slider:hover, scale.vertical.marks-before:not(.marks-after) slider:active, scale.vertical.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-disabled-dark.svg"), url("assets/scale-vert-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-after:not(.marks-before) slider, scale.vertical.marks-after:not(.marks-before) slider:hover, scale.vertical.marks-after:not(.marks-before) slider:active, scale.vertical.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-disabled-dark.svg"), url("assets/scale-vert-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal slider:dir(ltr), scale.color.horizontal slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(239, 241, 245, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #89b4fa; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #89b4fa; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #df8e1d; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #89b4fa; +} + +levelbar block.full { + background-color: #40a02b; +} + +levelbar block.empty { + background-color: rgba(239, 241, 245, 0.12); +} + +/**************** + * Print dialog * +*****************/ +printdialog paper { + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; + color: #eff1f5; +} + +printdialog .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame > border, .frame { + margin: 0; + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0; + box-shadow: none; +} + +.frame.view { + border-radius: 12px; +} + +.frame.flat { + border-style: none; +} + +frame.flat > border, frame > border.flat, statusbar frame > border { + border: none; +} + +actionbar > revealer > box { + margin: 6px 0 0 0; + padding: 6px; + border: none; + color: #eff1f5; + background-color: #1e1e2e; + border-radius: 0 0 12px 12px; +} + +actionbar > revealer > box button { + border-radius: 6px; +} + +actionbar > revealer > box button.combo:only-child { + border-radius: 6px; + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); +} + +actionbar > revealer > box button.combo:only-child:hover, actionbar > revealer > box button.combo:only-child:active { + color: #89b4fa; +} + +actionbar > revealer > box button.combo:only-child:disabled { + color: #89b4fa; +} + +actionbar > revealer > box stackswitcher { + background-color: rgba(30, 30, 46, 0.04); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + color: rgba(30, 30, 46, 0.6); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover, actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: rgba(30, 30, 46, 0.87); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + background-color: #313244; + color: #eff1f5; +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked:hover { + background-color: #313244; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +overshoot.top { + background-image: -gtk-gradient(radial, center top, 0, center top, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, center top, 0, center top, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center top; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.bottom { + background-image: -gtk-gradient(radial, center bottom, 0, center bottom, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, center bottom, 0, center bottom, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.left { + background-image: -gtk-gradient(radial, left center, 0, left center, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, left center, 0, left center, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: left center; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.right { + background-image: -gtk-gradient(radial, right center, 0, right center, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, right center, 0, right center, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: right center; + background-color: transparent; + border: none; + box-shadow: none; +} + +junction { + border-style: solid none none solid; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +junction:dir(rtl) { + border-style: solid solid none none; +} + +separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +preferences stacksidebar.sidebar list separator, placessidebar.sidebar list > separator, stacksidebar.sidebar + separator.vertical, +stacksidebar.sidebar separator.horizontal, button.font separator, button.file separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +/********* + * Lists * + *********/ +window.background.csd stack stack stack frame > list, +window.background.csd > stack > stack > box > frame > list, +window.background.csd > stack > stack > box > box > frame > list, +window.background.csd > stack > box > stack > box > frame > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > list, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list, window.background.csd > stack > list, +window.background.csd > stack > scrolledwindow > viewport > box > list, +window.background.csd > box > stack > scrolledwindow > viewport > box > list, preferencesgroup list, +.geary-accounts-editor-pane list, window.background.csd.unified > deck > deck > deck list, hdyleaflet list.view, +hdyleaflet list.frame, +leaflet list.view, +leaflet list.frame, +box.horizontal > stack.background list.view, +box.horizontal > stack.background list.frame, hdyleaflet stack.background scrolledwindow > viewport list, +hdyleaflet overlay scrolledwindow > viewport list, +leaflet stack.background scrolledwindow > viewport list, +leaflet overlay scrolledwindow > viewport list, +box.horizontal > stack.background stack.background scrolledwindow > viewport list, +box.horizontal > stack.background overlay scrolledwindow > viewport list, hdyleaflet frame:not(.view) list:not(.contacts-contact-list), +leaflet frame:not(.view) list:not(.contacts-contact-list), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list), list.tweak-group list, list.content:not(.conversation-listbox) { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.csd stack stack stack frame > list > separator, +window.background.csd > stack > stack > box > frame > list > separator, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list > separator, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list > separator, window.background.csd > stack > list > separator, +window.background.csd > stack > scrolledwindow > viewport > box > list > separator, preferencesgroup list > separator, +.geary-accounts-editor-pane list > separator, window.background.csd.unified > deck > deck > deck list > separator, hdyleaflet list.view > separator, +hdyleaflet list.frame > separator, +leaflet list.view > separator, +leaflet list.frame > separator, +box.horizontal > stack.background list.view > separator, +box.horizontal > stack.background list.frame > separator, hdyleaflet stack.background scrolledwindow > viewport list > separator, +hdyleaflet overlay scrolledwindow > viewport list > separator, +leaflet stack.background scrolledwindow > viewport list > separator, +leaflet overlay scrolledwindow > viewport list > separator, +box.horizontal > stack.background stack.background scrolledwindow > viewport list > separator, +box.horizontal > stack.background overlay scrolledwindow > viewport list > separator, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +leaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) > separator, list.tweak-group list > separator, list.content:not(.conversation-listbox) > separator { + background: none; + min-height: 0; +} + +window.background.csd stack stack stack frame > list row, +window.background.csd > stack > stack > box > frame > list row, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list row, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list row, window.background.csd > stack > list row, +window.background.csd > stack > scrolledwindow > viewport > box > list row, preferencesgroup list row, +.geary-accounts-editor-pane list row, window.background.csd.unified > deck > deck > deck list row, hdyleaflet list.view row, +hdyleaflet list.frame row, +leaflet list.view row, +leaflet list.frame row, +box.horizontal > stack.background list.view row, +box.horizontal > stack.background list.frame row, hdyleaflet stack.background scrolledwindow > viewport list row, +hdyleaflet overlay scrolledwindow > viewport list row, +leaflet stack.background scrolledwindow > viewport list row, +leaflet overlay scrolledwindow > viewport list row, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row, +box.horizontal > stack.background overlay scrolledwindow > viewport list row, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row, +leaflet frame:not(.view) list:not(.contacts-contact-list) row, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row, list.tweak-group list > row, list.content:not(.conversation-listbox) > row { + border-radius: 0; +} + +window.background.csd stack stack stack frame > list row:not(:first-child), window.background.csd > stack > list row:not(:first-child), preferencesgroup list row:not(:first-child), +.geary-accounts-editor-pane list row:not(:first-child), window.background.csd.unified > deck > deck > deck list row:not(:first-child), hdyleaflet list.view row:not(:first-child), +hdyleaflet list.frame row:not(:first-child), +leaflet list.view row:not(:first-child), +leaflet list.frame row:not(:first-child), +box.horizontal > stack.background list.view row:not(:first-child), +box.horizontal > stack.background list.frame row:not(:first-child), hdyleaflet stack.background scrolledwindow > viewport list row:not(:first-child), +hdyleaflet overlay scrolledwindow > viewport list row:not(:first-child), +leaflet stack.background scrolledwindow > viewport list row:not(:first-child), +leaflet overlay scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background overlay scrolledwindow > viewport list row:not(:first-child), hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +leaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), list.tweak-group list > row:not(:first-child), list.content:not(.conversation-listbox) > row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +window.background.csd stack stack stack frame > list row:first-child, window.background.csd > stack > list row:first-child, preferencesgroup list row:first-child, +.geary-accounts-editor-pane list row:first-child, window.background.csd.unified > deck > deck > deck list row:first-child, hdyleaflet list.view row:first-child, +hdyleaflet list.frame row:first-child, +leaflet list.view row:first-child, +leaflet list.frame row:first-child, +box.horizontal > stack.background list.view row:first-child, +box.horizontal > stack.background list.frame row:first-child, hdyleaflet stack.background scrolledwindow > viewport list row:first-child, +hdyleaflet overlay scrolledwindow > viewport list row:first-child, +leaflet stack.background scrolledwindow > viewport list row:first-child, +leaflet overlay scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:first-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:first-child, list.tweak-group list > row:first-child, list.content:not(.conversation-listbox) > row:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:last-child, window.background.csd > stack > list row:last-child, preferencesgroup list row:last-child, +.geary-accounts-editor-pane list row:last-child, window.background.csd.unified > deck > deck > deck list row:last-child, hdyleaflet list.view row:last-child, +hdyleaflet list.frame row:last-child, +leaflet list.view row:last-child, +leaflet list.frame row:last-child, +box.horizontal > stack.background list.view row:last-child, +box.horizontal > stack.background list.frame row:last-child, hdyleaflet stack.background scrolledwindow > viewport list row:last-child, +hdyleaflet overlay scrolledwindow > viewport list row:last-child, +leaflet stack.background scrolledwindow > viewport list row:last-child, +leaflet overlay scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:last-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:last-child, list.tweak-group list > row:last-child, list.content:not(.conversation-listbox) > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:only-child, window.background.csd > stack > list row:only-child, preferencesgroup list row:only-child, +.geary-accounts-editor-pane list row:only-child, window.background.csd.unified > deck > deck > deck list row:only-child, hdyleaflet list.view row:only-child, +hdyleaflet list.frame row:only-child, +leaflet list.view row:only-child, +leaflet list.frame row:only-child, +box.horizontal > stack.background list.view row:only-child, +box.horizontal > stack.background list.frame row:only-child, hdyleaflet stack.background scrolledwindow > viewport list row:only-child, +hdyleaflet overlay scrolledwindow > viewport list row:only-child, +leaflet stack.background scrolledwindow > viewport list row:only-child, +leaflet overlay scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:only-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:only-child, list.tweak-group list > row:only-child, list.content:not(.conversation-listbox) > row:only-child { + border-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:focus, window.background.csd > stack > list row:focus, preferencesgroup list row:focus, +.geary-accounts-editor-pane list row:focus, window.background.csd.unified > deck > deck > deck list row:focus, hdyleaflet list.view row:focus, +hdyleaflet list.frame row:focus, +leaflet list.view row:focus, +leaflet list.frame row:focus, +box.horizontal > stack.background list.view row:focus, +box.horizontal > stack.background list.frame row:focus, hdyleaflet stack.background scrolledwindow > viewport list row:focus, +hdyleaflet overlay scrolledwindow > viewport list row:focus, +leaflet stack.background scrolledwindow > viewport list row:focus, +leaflet overlay scrolledwindow > viewport list row:focus, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:focus, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:focus, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:focus, list.tweak-group list > row:focus, list.content:not(.conversation-listbox) > row:focus { + box-shadow: inset 0 0 0 1000px alpha(currentColor, 0.05); +} + +list { + border-color: rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); +} + +list row { + padding: 6px; + background-clip: padding-box; +} + +list.navigation-sidebar { + padding: 3px; +} + +list.navigation-sidebar > row { + border-radius: 12px; +} + +paned scrolledwindow > viewport.frame > list { + background-color: transparent; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable, treeview.view header button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:focus, treeview.view header button:focus, row.activatable:focus { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:hover, treeview.view header button:hover, row.activatable:hover { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.has-open-popup.activatable, treeview.view header button.has-open-popup, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:active, treeview.view header button:active, row.activatable.has-open-popup, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; +} + +row:selected { + color: inherit; + background-color: alpha(currentColor, 0.06); +} + +row:selected image, +row:selected label { + color: #eff1f5; +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled image, +row:selected:disabled label { + color: rgba(239, 241, 245, 0.5); +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 8px; + padding: 6px 15px; +} + +.app-notification button.flat:last-child { + margin-right: -9px; +} + +.app-notification button.text-button:not(:disabled) { + color: #89b4fa; +} + +.app-notification.frame, +.app-notification border { + border-style: none; +} + +/************* + * Expanders * + *************/ +expander title > arrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); + color: rgba(239, 241, 245, 0.7); +} + +expander title > arrow:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +expander title > arrow:checked { + -gtk-icon-transform: unset; +} + +expander title > arrow:hover, expander title > arrow:active { + color: #eff1f5; +} + +expander title > arrow:disabled { + color: rgba(239, 241, 245, 0.32); +} + +/************ + * Calendar * + ************/ +calendar { + padding: 1px; + border: 1px solid rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +calendar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +calendar:selected { + border-radius: 13px; +} + +calendar.header { + border-style: none none solid; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; +} + +calendar.highlight { + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +calendar:indeterminate { + color: rgba(239, 241, 245, 0.32); +} + +/*********** + * Dialogs * + ***********/ +messagedialog.background { + background-color: #1e1e2e; +} + +messagedialog.background .titlebar { + min-height: 12px; +} + +messagedialog.background .titlebar, messagedialog.background .titlebar:backdrop { + background-color: #1e1e2e; +} + +messagedialog.background.csd { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +messagedialog .titlebar, messagedialog.background.csd .titlebar { + border: none; + /* box-shadow: inset 0 1px highlight($surface); */ +} + +messagedialog .dialog-action-box { + margin-top: -6px; +} + +messagedialog .dialog-action-box button, messagedialog .dialog-action-box button:first-child, messagedialog .dialog-action-box button:last-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button, +messagedialog .dialog-action-box .linked:not(.vertical) > button:first-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button:last-child { + border-radius: 12px; +} + +messagedialog .dialog-action-box button:not(:last-child), +messagedialog .dialog-action-box .linked:not(.vertical) > button:not(:last-child) { + margin-right: 6px; +} + +messagedialog .dialog-action-box button.suggested-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.suggested-action:not(:disabled) { + color: #1e66f5; +} + +messagedialog .dialog-action-box button.destructive-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.destructive-action:not(:disabled) { + color: #d20f39; +} + +.csd filechooser { + background-color: #1e1e2e; + border-radius: 0 0 12px 12px; +} + +filechooser .dialog-action-box { + border-top: 1px solid transparent; +} + +filechooser treeview.view header > button { + background-color: #181825; +} + +filechooser #pathbarbox { + background-color: #181825; + border-radius: 12px 12px 0 0; + margin: 0 4px; +} + +filechooser stack.view { + background-color: transparent; + padding: 0 4px; +} + +filechooser stack.view scrolledwindow { + background-color: #181825; + border-radius: 0 0 12px 12px; +} + +filechooser stack.view scrolledwindow list { + background-color: transparent; +} + +filechooser stack.view > placesview { + background-color: transparent; + padding: 4px; +} + +filechooser stack.view frame > border { + border: none; +} + +.csd filechooser placessidebar { + background: none; + border-bottom-left-radius: 12px; +} + +filechooser paned > separator { + background: none; +} + +filechooser paned box.vertical { + background-color: #181825; + border-radius: 12px; + margin: 0 6px 0 1px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; +} + +stacksidebar.sidebar:dir(ltr) list, stacksidebar.sidebar.left list, stacksidebar.sidebar.left:dir(rtl) list, .sidebar:not(separator):dir(ltr), .sidebar:not(separator).left { + border-right: 1px solid rgba(239, 241, 245, 0.12); + border-left-style: none; +} + +stacksidebar.sidebar:dir(rtl) list, stacksidebar.sidebar.right list, .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { + border-left: 1px solid rgba(239, 241, 245, 0.12); + border-right-style: none; +} + +.sidebar list { + background-color: transparent; +} + +paned .sidebar.left, paned .sidebar.right, paned .sidebar.left:dir(rtl), paned .sidebar:dir(rtl), paned .sidebar:dir(ltr), paned .sidebar { + border-style: none; +} + +stacksidebar.sidebar list { + padding: 3px; + background-color: #313244; +} + +stacksidebar.sidebar row { + min-height: 34px; + padding: 0 3px; + border-radius: 12px; +} + +stacksidebar.sidebar row + row { + margin-top: 3px; +} + +stacksidebar.sidebar row:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + font-weight: 500; +} + +stacksidebar.sidebar row:selected label, +stacksidebar.sidebar row:selected image { + color: rgba(30, 30, 46, 0.87); +} + +stacksidebar.sidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +/**************** + * File chooser * + ****************/ +placessidebar.sidebar { + margin: 0 0 0 4px; + padding: 0; +} + +placessidebar.sidebar > viewport.frame { + border-style: none; +} + +placessidebar.sidebar list { + background-color: transparent; + color: #eff1f5; +} + +placessidebar.sidebar row { + min-height: 32px; + margin: 0; + padding: 0; + color: #eff1f5; + border-radius: 6px; +} + +placessidebar.sidebar row:hover, placessidebar.sidebar row:active { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #89b4fa; +} + +placessidebar.sidebar row > revealer { + padding: 0 8px 0 16px; +} + +placessidebar.sidebar row:selected { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #89b4fa; + font-weight: 500; +} + +placessidebar.sidebar row:disabled { + color: rgba(30, 30, 46, 0.3); +} + +placessidebar.sidebar row image.sidebar-icon { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar.sidebar row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar.sidebar row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar.sidebar row label.sidebar-label { + color: inherit; +} + +placessidebar.sidebar row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar.sidebar row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar.sidebar row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar.sidebar row.sidebar-new-bookmark-row { + color: #89b4fa; +} + +placessidebar.sidebar row.sidebar-new-bookmark-row image.sidebar-icon { + color: #89b4fa; +} + +placessidebar.sidebar row:drop(active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + padding-left: 8px; + padding-right: 8px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(rgba(239, 241, 245, 0.12)); + background-size: 1px 1px; + background-clip: content-box; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #1e1e2e; + background-image: image(rgba(239, 241, 245, 0.12)), image(rgba(239, 241, 245, 0.12)); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************** + * GtkInfoBar * + **************/ +infobar { + border: none; + margin-bottom: 0; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #313244; +} + +infobar.info > revealer > box, +infobar.info > revealer > box link:link, +infobar.info > revealer > box flowboxchild, infobar.info:hover > revealer > box, +infobar.info:hover > revealer > box link:link, +infobar.info:hover > revealer > box flowboxchild, infobar.info:backdrop > revealer > box, +infobar.info:backdrop > revealer > box link:link, +infobar.info:backdrop > revealer > box flowboxchild { + color: #89b4fa; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #89b4fa; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #89b4fa; +} + +infobar.action > revealer > box, +infobar.action > revealer > box link:link, +infobar.action > revealer > box flowboxchild, infobar.action:backdrop > revealer > box, +infobar.action:backdrop > revealer > box link:link, +infobar.action:backdrop > revealer > box flowboxchild, infobar.question > revealer > box, +infobar.question > revealer > box link:link, +infobar.question > revealer > box flowboxchild, infobar.question:backdrop > revealer > box, +infobar.question:backdrop > revealer > box link:link, +infobar.question:backdrop > revealer > box flowboxchild { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #71a4f9; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #df8e1d; +} + +infobar.warning > revealer > box, +infobar.warning > revealer > box link:link, +infobar.warning > revealer > box flowboxchild, infobar.warning:backdrop > revealer > box, +infobar.warning:backdrop > revealer > box link:link, +infobar.warning:backdrop > revealer > box flowboxchild { + color: #eff1f5; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.warning:hover > revealer > box { + background-color: #c8801a; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #d20f39; + color: #eff1f5; +} + +infobar.error > revealer > box, +infobar.error > revealer > box link:link, +infobar.error > revealer > box flowboxchild, infobar.error:backdrop > revealer > box, +infobar.error:backdrop > revealer > box link:link, +infobar.error:backdrop > revealer > box flowboxchild { + color: #eff1f5; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.error:hover > revealer > box { + background-color: #ba0d33; +} + +/************ + * Tooltips * + ************/ +tooltip { + box-shadow: none; +} + +tooltip.background { + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; + border-radius: 12px; +} + +tooltip.background.csd { + border-radius: 12px; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +tooltip decoration { + background-color: transparent; +} + +tooltip > box { + margin: -6px; + min-height: 24px; + padding: 4px 8px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #eff1f5; +} + +colorswatch.light { + color: rgba(30, 30, 46, 0.87); +} + +colorswatch overlay { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +colorswatch overlay:hover { + box-shadow: 0 0 0 2px #89b4fa; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(239, 241, 245, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(239, 241, 245, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #1e1e2e; +} + +/********************** + * Window Decorations * + **********************/ +decoration { + transition: none; + /* border-radius: $window-radius; */ + border-radius: 12px 12px 0 0; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; + margin: 10px; +} + +decoration:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +.tiled decoration, .tiled-top decoration, .tiled-right decoration, .tiled-bottom decoration, .tiled-left decoration { + border-radius: 0; +} + +.maximized decoration, .fullscreen decoration { + border-radius: 0; + box-shadow: none; +} + +.popup decoration { + box-shadow: none; + border: none; +} + +.ssd decoration { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #89b4fa; +} + +.ssd decoration:backdrop { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #292c3c; +} + +.metacity decoration { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border: none; +} + +.csd.popup decoration { + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa; +} + +tooltip.csd decoration { + border-radius: 12px; + box-shadow: none; + border: none; +} + +messagedialog.background.csd decoration { + border-radius: 12px; + border: 1px solid rgba(239, 241, 245, 0.1); + background-color: #292c3c; + background-clip: border-box; +} + +.solid-csd decoration { + margin: 0; + padding: 2px; + border-radius: 0; + box-shadow: none; + background-color: #1e1e2e; + border: 1px solid #4a4b5a; +} + +.solid-csd decoration:backdrop { + background-color: #1e1e2e; +} + +button.titlebutton:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + /* min-height: 22px; */ + /* min-width: 22px; */ + padding: 0; + margin: 0 0px; +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:not(.suggested-action):not(.destructive-action), button.close.titlebutton:not(.suggested-action):not(.destructive-action) { + background-color: rgba(239, 241, 245, 0.12); + color: rgba(239, 241, 245, 0.7); +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.maximize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.close.titlebutton:not(.suggested-action):not(.destructive-action) image { + padding: 0; + background: none; + box-shadow: none; +} + +button.minimize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; + background-color: alpha(currentColor, 0.15); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), inset 0 1px rgba(239, 241, 245, 0.1); +} + +button.minimize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.close.titlebutton:active:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; + background-color: alpha(currentColor, 0.2); +} + +button.minimize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +button.minimize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; + background-color: alpha(currentColor, 0.15); +} + +.monospace { + font-family: monospace; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #89b4fa; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.top:dir(ltr), cursor-handle.bottom:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +cursor-handle.bottom:dir(ltr), cursor-handle.top:dir(rtl) { + -gtk-icon-transform: unset; +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; + -gtk-icon-transform: rotate(45deg); +} + +.context-menu { + font: initial; +} + +.keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(239, 241, 245, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(239, 241, 245, 0.12); + background-color: #292c3c; + color: #eff1f5; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #89b4fa; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) + button { + margin-left: 3px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker.background entry { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +popover.emoji-picker.background entry:focus { + border-bottom: 1px solid #89b4fa; + box-shadow: inset 0 -1px #89b4fa; + background-color: transparent; +} + +popover.emoji-picker scrolledwindow { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +button.emoji-section { + margin: 4px; +} + +button.emoji-section:checked { + color: #89b4fa; +} + +button.emoji-section:not(:last-child) { + margin-right: 0; +} + +popover.emoji-picker .emoji { + min-width: 3em; + min-height: 3em; + padding: 0 8px; +} + +popover.emoji-picker .emoji widget { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker .emoji widget:hover { + background-color: alpha(currentColor, 0.08); +} + +popover.emoji-completion { + padding: 8px 0; +} + +popover.emoji-completion arrow { + border: none; + background: none; +} + +popover.emoji-completion .emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +popover.emoji-completion .emoji:hover { + background-color: alpha(currentColor, 0.08); +} + +/************ + * Nautilus * + ************/ +.nautilus-window.background.csd { + border-radius: 0 0 12px 12px; + background-color: #313244; +} + +.nautilus-window.background.csd:backdrop { + background-color: #313244; +} + +.nautilus-window.background.csd > grid.horizontal > paned.horizontal > separator, +.nautilus-window.background.csd > deck > box.vertical > paned.horizontal > separator { + margin-left: 0; +} + +.nautilus-window.background.csd placessidebar > viewport.frame > list > separator { + background: none; +} + +.nautilus-window.background.csd.unified notebook { + border-radius: 0; +} + +.nautilus-window.background.csd:not(.unified) .nautilus-list-view { + background-color: transparent; + border-bottom-right-radius: 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook { + background-color: #313244; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook > stack { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook scrolledwindow +> .view:not(:selected):not(:hover):not(:checked) { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > stack > frame > scrolledwindow > viewport > list { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar { + background-color: transparent; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar > revealer > box { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) paned > separator.wide { + min-width: 12px; + box-shadow: 12px 0 #313244; + background-color: #313244; + background-image: image(#4a4b5a); +} + +.nautilus-window.maximized, +.nautilus-window.maximized placessidebar { + border-radius: 0; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border: none; + border-radius: 12px; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(30, 30, 46, 0.87); +} + +.nautilus-canvas-item.dim-label, +.nautilus-list-dim-label { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-desktop.nemo-canvas-item, .caja-desktop.caja-canvas-item, +.nautilus-desktop.nautilus-canvas-item { + color: #eff1f5; +} + +@keyframes nautilus-operations-button-needs-attention { + to { + background-color: alpha(currentColor, 0.08); + } +} + +.nautilus-operations-button-needs-attention { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 2 alternate; +} + +.nautilus-operations-button-needs-attention-multiple { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 6 alternate; +} + +.path-bar-box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border-radius: 12px; +} + +.path-bar-box button { + margin: 0; +} + +.path-bar-box.width-maximized { + background-color: rgba(239, 241, 245, 0.04); +} + +.path-bar-box.background.frame { + border-style: none; + background-color: rgba(239, 241, 245, 0.04); +} + +.path-bar-box .path-bar button label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .path-bar button label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) { + padding-left: 11px; + padding-right: 11px; + margin-left: 1px; + margin-right: 1px; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button.image-button image:not(:only-child) { + margin: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr), .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl) { + background-color: rgba(239, 241, 245, 0.08); +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr):disabled, .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl):disabled { + background-color: transparent; + color: rgba(239, 241, 245, 0.5); +} + +.windowhandle .linked.nautilus-path-bar { + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action) { + margin-top: 0; + margin-bottom: 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir { + color: #eff1f5; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:hover, .windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:active { + background: none; + box-shadow: none; +} + +.disk-space-display.unknown { + background-color: rgba(239, 241, 245, 0.3); + color: rgba(239, 241, 245, 0.3); +} + +.disk-space-display.used { + background-color: #89b4fa; + color: #89b4fa; +} + +.disk-space-display.free { + background-color: rgba(239, 241, 245, 0.12); + color: rgba(239, 241, 245, 0.12); +} + +.search-information { + padding: 2px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; + color: #eff1f5; +} + +.conflict-row:not(:selected) { + background-color: #654e38; +} + +.nautilus-window flowboxchild .icon-item-background { + padding: 4px; + border-radius: 6px; +} + +.nautilus-window flowboxchild:selected { + background-color: transparent; +} + +.nautilus-window notebook :not(treeview).view { + border-radius: 6px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > scrolledwindow.frame { + border-style: none; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child { + margin: -6px 0 0 -6px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > label { + margin: 0 8px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > box > button { + border-radius: 0; +} + +.nautilus-window > popover.menu:not(:last-child) { + padding: 3px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box { + margin-top: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box { + margin-bottom: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box.linked { + margin-top: 1px; +} + +.nautilus-window > popover.menu:not(:last-child) separator { + margin-bottom: -2px; +} + +.nautilus-menu-sort-heading { + margin: 1px 3px; + font-weight: 500; +} + +.nautilus-menu-sort-heading:disabled { + color: rgba(239, 241, 245, 0.7); +} + +.nautilus-window paned > separator { + background-color: #313244; +} + +/********* + * gedit * + *********/ +window.org-gnome-gedit > paned.titlebar > separator { + background-color: transparent; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > box.horizontal { + margin: 4px 0; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > scrolledwindow { + border-bottom-left-radius: 12px; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned stack scrolledwindow viewport.frame list.gedit-document-panel { + background: none; +} + +.open-document-selector-path-label { + color: rgba(239, 241, 245, 0.7); + font-size: smaller; +} + +.open-document-selector-match { + background-color: #df8e1d; + color: #eff1f5; +} + +.gedit-document-panel { + background-color: #313244; +} + +.gedit-document-panel row button.flat { + margin-top: 8px; + margin-bottom: 8px; +} + +.gedit-document-panel-group-row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.gedit-side-panel-paned statusbar { + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0 0 12px 12px; +} + +.gedit-search-slider { + margin: 0 6px 10px; + padding: 6px; + background-color: #292c3c; + border-radius: 0 0 12px 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05), 0 0 0 2px #e6e9ef; +} + +.gedit-search-slider .linked:not(.vertical) > entry .gedit-search-entry-occurrences-tag { + all: unset; + color: rgba(239, 241, 245, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) .gedit-search-entry-occurrences-tag { + margin-left: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) image.right { + margin-right: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) .gedit-search-entry-occurrences-tag { + margin-right: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) image.left { + margin-left: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:not(.error) { + background-color: #292c3c; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button { + color: rgba(239, 241, 245, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:hover, .gedit-search-slider .linked:not(.vertical) > entry.error ~ button:active { + color: #eff1f5; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +frame.gedit-map-frame > border:dir(ltr) { + border-style: none none none solid; +} + +frame.gedit-map-frame > border:dir(rtl) { + border-style: none solid none none; +} + +/********** + * Tweaks * + **********/ +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame { + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 12px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + background-color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:hover { + background-color: rgba(30, 30, 46, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:active { + background-color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:disabled { + background-color: rgba(30, 30, 46, 0.3); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(30, 30, 46, 0.3); +} + +leaflet.unfolded > box.vertical:last-child > scrolledwindow > viewport.frame, +leaflet.unfolded > box.vertical:last-child > stack > scrolledwindow > viewport.frame { + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + padding: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > separator { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row { + padding: 0; + margin: -1px; + color: #eff1f5; + border-radius: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:active, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:focus { + color: #eff1f5; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected { + font-weight: 500; + background-color: rgba(239, 241, 245, 0.04); + border-radius: 9px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected label, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected image { + color: #89b4fa; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:focus { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row + row { + margin-top: 3px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + border: none; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar trough { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + border: 4px solid transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + border: none; + margin: 1px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.tweak { + padding: 3px; +} + +.tweak.title:hover { + box-shadow: none; +} + +.tweak-group-startup { + border: 1px solid rgba(239, 241, 245, 0.12); +} + +.tweak-group-startup > row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +row#Focus, +row#ClickMethod, +row#PrimaryWorkspaceTweak, +row#workspaces-only-on-primary { + margin-top: 4px; +} + +leaflet.titlebar > .titlebar.tweak-titlebar-left, +leaflet.titlebar > .titlebar.tweak-titlebar-right, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-left, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-right { + background-color: inherit; + box-shadow: inherit; + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + background-color: transparent; + margin: 0; +} + +/************************ + * Gnome Control Center * + ************************/ +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:not(:only-child) { + border-top-left-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:not(:only-child) { + border-top-right-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:only-child, window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:only-child { + border-top-right-radius: 12px; + border-top-left-radius: 12px; +} + +window.background.csd > stack:not(.titlebar) > stack.background { + border-radius: 0 0 12px 12px; +} + +window.background.csd > leaflet > stack.background, +window.background.csd > hdyleaflet > stack.background, +window.background.csd > box.horizontal > stack.background { + background: none; +} + +window.background.csd > leaflet > stack.background frame > border, +window.background.csd > hdyleaflet > stack.background frame > border, +window.background.csd > box.horizontal > stack.background frame > border { + border: none; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame { + background-color: #313244; + border-bottom-right-radius: 12px; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view { + background: none; +} + +window.background.csd > leaflet frame.view, +window.background.csd > hdyleaflet frame.view, +window.background.csd > box.horizontal frame.view { + border-radius: 12px; + background: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + margin: 6px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list { + border-top-width: 0; + border-bottom-width: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list > row { + border-radius: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list { + border-top-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list > row { + border-radius: 12px 12px 0 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list { + border-bottom-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list > row { + border-radius: 0 0 12px 12px; +} + +window.background.csd hdycolumn stack frame.view > stack > stack list > separator { + background-color: rgba(239, 241, 245, 0.12); +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack > box.horizontal > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list { + background: none; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list > row:not(:hover):not(:active):not(:selected) { + background-color: transparent; +} + +/************************ + * Gnome system monitor * + ************************/ +window#gnome-system-monitor.background.csd > box.vertical > stack { + background-color: #313244; + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background.csd > box.vertical > stack > box.vertical > revealer > actionbar > revealer > box { + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background:not(.csd) > box.vertical > headerbar { + box-shadow: none; +} + +/************************ + * Gnome Sound Recorder * + ************************/ +stack > grid.vertical > scrolledwindow { + border: none; + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical > scrolledwindow > viewport.frame list { + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical scrolledwindow.frame.emptyGrid { + border: none; +} + +/****************** + * Gnome Contacts * + ******************/ +window.background.csd scrolledwindow.contacts-contact-form { + border-bottom-right-radius: 12px; +} + +/************************ + * Epiphany (Gnome Web) * + ************************/ +tabbox { + border: none; + background-color: rgba(239, 241, 245, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +tabbox > tab button { + min-height: 24px; + min-width: 24px; + border-radius: 9999px; + border: none; + padding: 0; + margin-right: -6px; +} + +/***************** + * Gnome Weather * + *****************/ +#weather-page, +#weekly-forecast-frame { + border-bottom-right-radius: 12px; +} + +#weather-page-content-view { + border-bottom-right-radius: 12px; + border-bottom-left-radius: 12px; +} + +/*************** + * Gnome Music * + ***************/ +window.background.csd box.vertical > overlay > stack.background { + border-radius: 0 0 12px 12px; +} + +/**************** + * Gnome Clocks * + ****************/ +/************* + * Rhythmbox * + *************/ +window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.background > box.vertical > toolbar.primary-toolbar > toolitem button.flat.scale, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + min-height: 24px; + min-width: 24px; + padding: 5px; + margin: 0; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.12); +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button { + border-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:first-child), .sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:last-child) { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):first-child { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):last-child { + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button > widget > box > image { + padding: 0; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal { + padding: 6px; + margin: -1px 0; + border-bottom: none; + border-top: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: transparent; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + margin: 6px 0; +} + +window.csd > box.vertical > box.vertical > frame, +window.solid-csd > box.vertical > box.vertical > frame { + margin: -1px 0; + padding: 0; +} + +window.csd > box.vertical > box.vertical > frame > border, +window.solid-csd > box.vertical > box.vertical > frame > border { + border: none; +} + +window.background > box.vertical > toolbar.primary-toolbar { + padding: 0 12px 0 6px; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(239, 241, 245, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #eff1f5; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised > widget > box > image { + padding: 0 3px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + padding: 6px; + margin: -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > box { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + padding: 0 6px 6px; + margin: 0 -6px -6px 0; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(239, 241, 245, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + padding: 3px; + margin: -1px -6px -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(239, 241, 245, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > paned > box:first-child > box { + padding: 0 6px 6px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +/********** + * Polari * + **********/ +.polari-room-list .sidebar { + background: none; +} + +.polari-room-list .sidebar > row.activatable:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +stack.view.polari-entry-area { + background-color: #1e1e2e; + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-bottom-right-radius: 12px; +} + +stack:disabled.view.polari-entry-area { + background-image: image(#1e1e2e); +} + +/*********** + * Builder * + ***********/ +layouttabbar { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; +} + +layouttabbar > box > button { + margin: 3px 0; +} + +layouttab { + margin: 0 8px; + border-style: none solid; + border-width: 1px; + border-color: rgba(30, 30, 46, 0.2); + box-shadow: inset 0 -2px #89b4fa; + background-color: #313244; +} + +layouttab separator.vertical { + margin: 8px 4px; +} + +layouttab button.text-button, layouttab button.image-button, layouttab button { + margin-top: 8px; + margin-bottom: 8px; + padding: 0 4px; +} + +layout { + border: 1px solid rgba(30, 30, 46, 0.2); + -pnldockbin-handle-size: 1; +} + +entry.search-missing { + background-color: #d20f39; + color: #eff1f5; +} + +window.workbench treeview.image { + color: rgba(239, 241, 245, 0.7); +} + +popover.popover-selector list { + padding: 6px; +} + +popover.popover-selector list row { + border-radius: 12px; +} + +popover.popover-selector list row image:dir(ltr) { + margin-right: 6px; +} + +popover.popover-selector list row image:dir(rtl) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(ltr) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(rtl) { + margin-right: 6px; +} + +omnibar.linked:not(.vertical) entry { + border-radius: 12px; +} + +omnibar:not(:hover):not(:active) entry { + color: rgba(239, 241, 245, 0.7); +} + +popover.omnibar list row:not(:last-child) { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +entry.preferences-search { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: #313244; +} + +preferences stacksidebar.sidebar list { + background-color: #313244; +} + +preferences stacksidebar.sidebar:dir(ltr) list, preferences stacksidebar.sidebar:dir(rtl) list { + border-style: none; +} + +preferences > box > box:dir(ltr) { + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +preferences > box > box:dir(rtl) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +popover.messagepopover.background { + padding: 0; +} + +popover.messagepopover .popover-action-area button { + padding: 8px 16px; + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0; +} + +popover.messagepopover .popover-action-area button:first-child { + border-bottom-left-radius: 12px; +} + +popover.messagepopover .popover-action-area button:last-child { + border-bottom-right-radius: 12px; +} + +popover.messagepopover .popover-content-area { + margin: 16px; +} + +popover.transfers list { + background-color: transparent; +} + +popover.transfers list row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +popover.transfers list row > box { + padding: 10px; +} + +dockbin { + border: 1px solid rgba(30, 30, 46, 0.2); + -pnldockbin-handle-size: 1; +} + +dockpaned { + border: 1px solid rgba(30, 30, 46, 0.2); +} + +eggsearchbar box.search-bar { + padding: 0 8px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; +} + +docktabstrip { + padding: 0 8px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; +} + +docktab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + margin-bottom: -1px; + padding: 6px 6px; + border-width: 1px; + border-color: transparent; + box-shadow: inset 0 -2px transparent; + background-image: radial-gradient(circle, #89b4fa 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 0% 0%; + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +docktab:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +docktab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 225ms cubic-bezier(0, 0, 0.2, 1), background-image 525ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 -2px #89b4fa; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-size: 1000% 1000%; + color: #eff1f5; +} + +dockoverlayedge { + background-color: #1e1e2e; +} + +dockoverlayedge docktabstrip { + padding: 0; + border: none; +} + +dockoverlayedge.left-edge docktab:checked { + box-shadow: inset -2px 0 #89b4fa; +} + +dockoverlayedge.right-edge docktab:checked { + box-shadow: inset 2px 0 #89b4fa; +} + +pillbox { + background-color: #1e1e2e; + border-radius: 12px; +} + +layoutpane entry.search { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: #313244; +} + +editortweak entry.search { + margin-bottom: -1px; + box-shadow: none; + background-color: transparent; +} + +.gb-search-entry-occurrences-tag { + box-shadow: none; + background-color: transparent; +} + +docktabstrip { + min-height: 39px; +} + +window.workbench preferences preferencesgroup list entry { + padding-top: 8px; + padding-bottom: 8px; +} + +button.run-arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.dzlmenubutton image { + min-width: 28px; +} + +button.dzlmenubutton image.arrow { + min-width: 25px; +} + +button.dzlmenubuttonitem { + color: #eff1f5; + font-weight: normal; +} + +button.dzlmenubuttonitem:disabled { + color: rgba(239, 241, 245, 0.5); +} + +idelayoutstackheader { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +idelayoutstackheader button:checked { + color: #eff1f5; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher { + padding: 8px 0; + background-color: #1e1e2e; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(ltr) { + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(rtl) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button { + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:active { + background-image: radial-gradient(circle, rgba(137, 180, 250, 0.7) 10%, transparent 0%); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:checked { + background-color: transparent; + color: #eff1f5; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr) { + margin-right: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr):checked { + box-shadow: inset -2px 0 #89b4fa; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl) { + margin-left: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl):checked { + box-shadow: inset 2px 0 #89b4fa; +} + +ideeditorsidebar notebook header { + background: transparent; +} + +popover.messagepopover list { + border: 1px solid rgba(239, 241, 245, 0.12); +} + +popover.messagepopover list row:not(:last-child) { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +/********** + * Photos * + **********/ +GdMainIconView.content-view { + -gdmainiconview-icon-size: 48; +} + +.documents-counter { + margin: 8px; + border-radius: 9999px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + font-weight: bold; +} + +.documents-scrolledwin.frame { + border-style: none; +} + +.documents-scrolledwin.frame frame.content-view > border { + border-style: none; +} + +.photos-fade-in { + opacity: 1; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.photos-fade-out { + opacity: 0; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +button.photos-filter-preview { + color: #eff1f5; + font-weight: normal; +} + +button.photos-filter-preview:checked { + background-color: alpha(currentColor, 0.06); + color: #eff1f5; +} + +button.photos-filter-preview:checked image { + color: #eff1f5; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(ltr) { + border-style: none none none solid; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(rtl) { + border-style: none solid none none; +} + +/********* + * Music * + *********/ +.side-panel:dir(ltr) { + border-style: solid; + border-color: rgba(239, 241, 245, 0.12); +} + +.side-panel:dir(rtl) { + border-style: solid; + border-color: rgba(239, 241, 245, 0.12); +} + +.side-panel .view { + background-image: image(#313244); +} + +.side-panel .view:hover { + background-image: image(#404152); +} + +.side-panel .view:selected { + background-image: image(#89b4fa); +} + +.side-panel .view:selected:hover { + background-image: image(rgba(130, 171, 237, 0.9896)); +} + +.songs-list:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +frame.documents-dropdown { + margin: 8px; +} + +frame.documents-dropdown > border { + border: none; +} + +box.vertical > revealer > toolbar.search-bar { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; +} + +box.vertical > revealer > toolbar.search-bar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +/************* + * Documents * + *************/ +.documents-scrolledwin { + background-color: transparent; +} + +.documents-scrolledwin .content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) border { + border: none; +} + +window.background.csd > stack > box > revealer > actionbar > revealer > box { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +/******************* + * Document Viewer * + *******************/ +window.background.csd evview.view.content-view { + border-radius: 0 0 12px 12px; +} + +/********************************* + * Archive Manager (File roller) * + *********************************/ +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #313244; +} + +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow > treeview.view:not(:hover):not(:selected):not(:selected):not( +:hover +):not(.progressbar):not(.expander):not(.trough):not( +.separator +) { + background-color: #313244; +} + +.background.csd > grid.horizontal > paned.horizontal > box.vertical > scrolledwindow { + border-radius: 0 0 0 12px; + background-color: #1e1e2e; +} + +/************ + * Terminal * + ************/ +terminal-window decoration { + border-radius: 12px 12px 0 0; +} + +terminal-window.background.csd, terminal-window.background.csd.maximized { + border-radius: 0; +} + +terminal-window notebook > header > box { + margin: -2px -2px -2px 1px; +} + +terminal-window notebook > header > box button.flat { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; +} + +window.background > box.vertical > box.horizontal > frame > border { + border: none; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list { + /* border-radius: $corner-radius; */ + margin: 0 6px 6px; + background-color: #1e1e2e; + color: #eff1f5; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row { + padding: 0 2px; + margin: 2px 0; + border-radius: 12px; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:selected, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:hover { + color: #89b4fa; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:active { + color: #eff1f5; +} + +window.background > box.vertical > box.horizontal > stack > widget > notebook.frame { + margin: 0 6px 6px 0; +} + +.terminal-window { + background-color: #1e1e2e; +} + +.terminal-window tabbar tabbox { + background-color: #313244; + margin: 0; + border-radius: 0; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; +} + +/********* + * To Do * + *********/ +task-list-view taskrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 0 -8px; +} + +task-list-view taskrow:hover { + transition: none; +} + +task-list-view taskrow label { + margin: 0 8px; +} + +task-list-view taskrow image.dim-label { + min-width: 16px; +} + +task-list-view > box > revealer > box > button { + margin: -5px; +} + +task-list-view > box > revealer > box > button .dim-label { + color: inherit; +} + +tasklistview taskrow { + outline: none; +} + +tasklistview taskrow entry, tasklistview taskrow entry:focus, tasklistview taskrow entry:disabled { + box-shadow: none; +} + +tasklistview taskrow image.dim-label { + min-width: 16px; +} + +tasklistview > box > revealer > box > button { + margin: -5px; +} + +tasklistview > box > revealer > box > button .dim-label { + color: inherit; +} + +/******* + * Eog * + *******/ +#eog-thumb-nav scrolledwindow { + border-top: none; +} + +/************* + * Evolution * + *************/ +frame.taskbar > border { + border-style: solid none none; +} + +box.vertical > paned.horizontal notebook widget .frame { + border-style: none; +} + +/*********** + * Fractal * + ***********/ +.background.csd.main-window .sidebar.rooms-sidebar { + border-bottom-left-radius: 12px; +} + +/******** + * Gitg * + ********/ +frame.commit-frame > border { + border-style: solid none none; +} + +/************** + * Characters * + **************/ +box.dialog-vbox scrolledwindow.related { + border: 1px solid rgba(30, 30, 46, 0.2); +} + +list.categories { + background-image: image(#313244); +} + +/********* + * Boxes * + *********/ +.transparent-bg + stack overlay > label { + min-height: 24px; + padding: 0 4px; + border-radius: 12px; + background-color: #292c3c; + color: #eff1f5; +} + +/************** + * Calculator * + **************/ +button.title label { + min-height: 34px; +} + +/********* + * Geary * + *********/ +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer, +window#GearyMainWindow.background.csd stack#conversation_viewer { + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox, +window#GearyMainWindow.background.csd stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox { + background: none; + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded { + animation: none; + background-image: none; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box { + border-radius: 0; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar { + color: #eff1f5; + background-color: #1e1e2e; + box-shadow: none; + border-bottom: 1px solid rgba(30, 30, 46, 0.2); +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-composer-box actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-composer-box actionbar > revealer > box { + border-bottom-left-radius: 0; +} + +.geary-accounts-editor-pane frame:not(.geary-signature) > border, +.geary-accounts-editor-pane scrolledwindow.frame { + border: none; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout { + background-color: #313244; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar { + background-color: #1e1e2e; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar:backdrop, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar:backdrop { + background-color: #1e1e2e; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > box.vertical + separator.sidebar { + min-width: 1px; + background-color: rgba(239, 241, 245, 0.12); +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow { + padding: 3px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view { + border: 1px solid transparent; + border-radius: 12px; + padding: 6px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:selected, .geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:active { + border-radius: 12px; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.geary-main-window.unified separator.geary-sidebar-pane-separator { + min-width: 1px; + background-color: rgba(239, 241, 245, 0.12); +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable { + border: 1px solid rgba(239, 241, 245, 0.12); + border-bottom-width: 0; + background-color: #313244; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane { + border-radius: 0 0 8px 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background { + background-color: transparent; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background > revealer > box { + border-radius: 0 0 6px 6px; +} + +/************** + * Extensions * + **************/ +window.background.csd stack stack stack frame > border, +window.background.csd > stack > stack > box > frame > border, +window.background.csd > stack > stack > box > box > frame > border, +window.background.csd > stack > box > stack > box > frame > border, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > border, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > border, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > border { + border: none; +} + +window.background.csd > stack > box > box > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport > list { + border-bottom-left-radius: 12px; +} + +window.background.csd > stack > box > .sidebar > scrolledwindow > viewport > list { + padding: 0 0; +} + +/*********** + * Dialogs * + ***********/ +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:first-child { + border-radius: 0 0 0 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:last-child { + border-radius: 0 0 12px 0; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow, +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #313244; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active), +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list row.activatable:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack toolbar.toolbar { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd stack scrolledwindow.frame { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view > text { + background: none; +} + +dialog.background.csd stack scrolledwindow viewport.frame.view { + border-radius: 12px; +} + +window.background.csd.unified { + background-color: #1e1e2e; +} + +window.background.csd.unified headerbar { + box-shadow: none; +} + +window.background.csd.unified > decoration-overlay { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +window.background.csd.unified, +window.background.csd.unified > decoration, +window.background.csd.unified > decoration-overlay { + border-radius: 12px; +} + +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen > decoration-overlay { + box-shadow: none; +} + +window.background.csd.unified.tiled, +window.background.csd.unified.tiled > decoration, +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top, +window.background.csd.unified.tiled-top > decoration, +window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right, +window.background.csd.unified.tiled-right > decoration, +window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom, +window.background.csd.unified.tiled-bottom > decoration, +window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left, +window.background.csd.unified.tiled-left > decoration, +window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized, +window.background.csd.unified.maximized > decoration, +window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen, +window.background.csd.unified.fullscreen > decoration, +window.background.csd.unified.fullscreen > decoration-overlay { + border-radius: 0; +} + +/********* + * Tilix * + *********/ +overlay > revealer.left > scrolledwindow.frame, overlay > revealer.right > scrolledwindow.frame { + border-style: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +overlay > revealer.left > scrolledwindow.frame { + margin-right: 32px; +} + +overlay > revealer.right > scrolledwindow.frame { + margin-left: 32px; +} + +.terminix-session-sidebar, +.tilix-session-sidebar { + background-image: image(#292c3c); +} + +.terminal-titlebar button { + border-radius: 0; +} + +button.image-button.session-new-button { + min-width: 30px; +} + +notebook.tilix-background tab > box > stack { + margin: -6px; +} + +button.flat.tilix-small-button { + min-height: 20px; + min-width: 16px; +} + +/************** + * Terminator * + **************/ +.terminator-terminal-window paned > separator { + background-color: #1e1e2e; +} + +.terminator-terminal-window notebook.frame { + border-style: none; +} + +/************* + * Ubitquity * + *************/ +#live_installer .menubar progressbar trough { + border-radius: 4px; + background-color: rgba(239, 241, 245, 0.12); +} + +/********* + * Meld * + ********/ +.meld-notebook, +.meld-notebook > stack { + background: none; + border-radius: 0 0 12px 12px; +} + +.meld-notebook-child { + background-color: #313244; + border-radius: 0 0 12px 12px; +} + +statusbar.meld-status-bar { + background: none; +} + +/*********** + * Eclipse * + ***********/ +window.background > box.vertical > scrolledwindow > widget toolbar { + padding: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar separator, +window.background > box.vertical > scrolledwindow > widget toolbar button { + margin: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar button { + border-radius: 12px; +} + +/************ + * Chromium * + ************/ +window.background.chromium { + background-color: #313244; + color: #eff1f5; +} + +window.background.chromium headerbar.titlebar { + padding: 0 12px; + /* border-radius: $corner-radius $corner-radius 0 0; */ +} + +window.background.chromium headerbar.titlebar button.toggle { + border: none; + background-color: transparent; + background-image: none; +} + +window.background.chromium headerbar.titlebar button.toggle:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #eff1f5; +} + +window.background.chromium headerbar.titlebar button.toggle:checked, window.background.chromium headerbar.titlebar button.toggle:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #eff1f5; +} + +window.background.chromium headerbar.titlebar button.titlebutton { + min-width: 16px; + min-height: 16px; + margin: 0; + padding: 0; + background-size: 16px 16px; + border: none; +} + +window.background.chromium button { + border-width: 1px; + border-style: solid; + border-color: #4a4b5a; + background-color: #1e1e2e; + color: #eff1f5; +} + +window.background.chromium entry.chromium { + background-color: rgba(239, 241, 245, 0.06); +} + +window.background.chromium entry.chromium, window.background.chromium entry.chromium:focus { + border-image: none; + color: #eff1f5; +} + +window.background.chromium > textview.view, +window.background.chromium textview { + background-color: rgba(239, 241, 245, 0.06); + color: #eff1f5; +} + +window.background.chromium > menubar { + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.chromium menu { + background-color: #232634; + /* border: 0px solid if($variant == 'light', $solid-border, $window-border); */ + border-radius: 0; +} + +window.background.chromium menu menuitem { + border-radius: 0; + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.chromium menu menuitem:hover { + background-color: #292c3c; + color: #89b4fa; +} + +/*********** + * Firefox * + ***********/ +#MozillaGtkWidget decoration { + border: none; +} + +#MozillaGtkWidget > widget text { + background-color: #1e1e2e; +} + +#MozillaGtkWidget > widget text:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +#MozillaGtkWidget > widget > separator { + color: #4a4b5a; +} + +#MozillaGtkWidget > widget > scrollbar { + background-clip: border-box; +} + +#MozillaGtkWidget > widget > frame > border { + border-color: #4a4b5a; +} + +#MozillaGtkWidget > widget > entry, +#MozillaGtkWidget > widget > button > button { + border: 1px solid #4a4b5a; + border-radius: 12px; + box-shadow: none; +} + +#MozillaGtkWidget > widget > entry:disabled, +#MozillaGtkWidget > widget > button > button:disabled { + border-color: rgba(239, 241, 245, 0.12); +} + +#MozillaGtkWidget > widget > entry { + min-height: 30px; + background-color: #313244; +} + +#MozillaGtkWidget > widget > entry:focus { + border-color: #89b4fa; + box-shadow: inset 0 0 0 1px #89b4fa; +} + +#MozillaGtkWidget > widget > entry:disabled { + background-color: #313244; +} + +#MozillaGtkWidget > widget > button > button { + padding: 4px 8px; + background-size: auto; +} + +#MozillaGtkWidget > widget > button > button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +#MozillaGtkWidget > widget > button > button:active { + background-image: image(alpha(currentColor, 0.12)); +} + +#MozillaGtkWidget > widget > checkbutton > check, +#MozillaGtkWidget > widget > radiobutton > radio { + margin: 0; + padding: 0; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate), +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate) { + color: #414559; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):hover, #MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):active, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):hover, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):active { + color: #6c7086; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):disabled, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):disabled { + color: rgba(65, 69, 89, 0.5); +} + +#MozillaGtkWidget menu { + border: none; +} + +#MozillaGtkWidget > widget > menubar { + color: rgba(239, 241, 245, 0.7); +} + +#MozillaGtkWidget > widget > menubar:hover { + color: #eff1f5; +} + +#MozillaGtkWidget > widget > menubar:disabled { + color: rgba(239, 241, 245, 0.32); +} + +#MozillaGtkWidget > widget > frame { + color: #4a4b5a; +} + +#MozillaGtkWidget menu > separator { + color: #4a4b5a; +} + +window.background:not(.csd) > window > menu menuitem { + transition: none; +} + +/************ + * Inkscape * + ************/ +#ToolboxCommon > #AuxToolbox #StyleSwatch { + font-size: smaller; +} + +#ToolboxCommon > #AuxToolbox #Kludge { + padding: 0; +} + +#ToolboxCommon > #AuxToolbox spinbutton, +#ToolboxCommon > #AuxToolbox entry { + min-height: 32px; +} + +#ToolboxCommon > #AuxToolbox button:not(.up):not(.down) { + min-height: 24px; + min-width: 16px; + padding: 4px 8px; +} + +#ToolboxCommon > #AuxToolbox spinbutton button { + border-width: 4px; +} + +#ToolboxCommon > toolbar.vertical { + margin-top: -4px; +} + +#ToolboxCommon > toolbar.vertical button { + min-height: 24px; + min-width: 24px; + padding: 4px; +} + +#CanvasTable button { + min-height: 16px; + min-width: 16px; + padding: 0; +} + +#CanvasTable #HorizontalScrollbar { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(ltr) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(rtl) { + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +#Canvas_and_Dock frame > border { + border: none; +} + +#Canvas_and_Dock widget > widget > button.flat { + min-height: 16px; + min-width: 16px; + padding: 4px; +} + +#Canvas_and_Dock widget > widget > box.horizontal image { + padding: 4px; +} + +#Canvas_and_Dock box.horizontal > box.vertical > button.flat { + min-height: 16px; + min-width: 24px; + padding: 8px 4px; +} + +scrolledwindow#DialogNotebook > viewport.frame > notebook.frame button.close-button image { + padding: 4px; +} + +#InKscapeCanvas { + background-color: #313244; + border-radius: 12px; +} + +/*********** + * Synapse * + ***********/ +/*************** + * Libreoffice * + ***************/ +window.background > grid +> widget +> widget +> scrolledwindow +> viewport +> grid +> box +> box +> frame +> box { + background-color: #1e1e2e; +} + +/********* + * Pamac * + *********/ +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list { + border: none; + border-radius: 0; +} + +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list > row.activatable { + border-radius: 12px; +} + +dialog-host > floating-sheet > sheet > widget.response-area { + padding: 6px; +} + +window.background:not(.csd):not(.solid-csd) > button:not(:hover):not(:active):not(:checked):not(:disabled):not(.flat) { + /* background-color: if($variant == 'light', $grey-100, $grey-900); */ + background-color: #1e1e2e; +} + +window.background:not(.csd) > box +> widget +> widget +> widget +> widget +> widget +> widget +> widget +> scrolledwindow entry:focus { + background-color: #292938; +} + +/********* + * Unity * + *********/ +UnityDecoration { + -unitydecoration-extents: 28px 0 0 0; + -unitydecoration-input-extents: 8px; + -unitydecoration-shadow-offset-x: 0; + -unitydecoration-shadow-offset-y: 3px; + -unitydecoration-active-shadow-color: rgba(0, 0, 0, 0.48); + -unitydecoration-active-shadow-radius: 18px; + -unitydecoration-inactive-shadow-color: rgba(0, 0, 0, 0.32); + -unitydecoration-inactive-shadow-radius: 6px; + -unitydecoration-glow-size: 8px; + -unitydecoration-glow-color: #89b4fa; + -unitydecoration-title-indent: 4px; + -unitydecoration-title-fade: 32px; + -unitydecoration-title-alignment: 0; +} + +UnityDecoration .top { + padding: 0 2px; + border-style: none; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #1e1e2e; + color: #eff1f5; +} + +UnityDecoration .top:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.7); +} + +UnityDecoration .menuitem { + color: rgba(239, 241, 245, 0.7); +} + +UnityDecoration .menuitem:hover { + box-shadow: inset 0 -2px #e6e9ef; + background-color: transparent; + color: #eff1f5; +} + +.background:not(.csd) headerbar:not(.titlebar) { + border-radius: 0; + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +.background:not(.csd) headerbar:not(.titlebar).inline-toolbar { + border-style: none; +} + +UnityPanelWidget, +.unity-panel { + background-color: #1e1e2e; + color: #eff1f5; +} + +UnityPanelWidget:backdrop, +.unity-panel:backdrop { + color: rgba(239, 241, 245, 0.7); +} + +.unity-panel.menuitem, +.unity-panel .menuitem { + color: rgba(239, 241, 245, 0.7); +} + +.unity-panel.menubar.menuitem:hover, +.unity-panel.menubar .menuitem *:hover { + box-shadow: inset 0 -2px #e6e9ef; + background-color: transparent; + color: #eff1f5; +} + +.menu IdoPlaybackMenuItem.menuitem:active { + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); + animation: spin 1s linear infinite; + color: #89b4fa; +} + +/************** + * Mate-Panel * + **************/ +.mate-panel-menu-bar menubar, +#PanelApplet-window-menu-applet-button { + background-color: transparent; +} + +.mate-panel-menu-bar { + background-color: rgba(30, 30, 46, 0.6); + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +.mate-panel-menu-bar button { + min-height: 16px; + min-width: 16px; + padding: 0; + border-radius: 0; +} + +PanelToplevel.horizontal > grid > button { + min-width: 24px; +} + +PanelToplevel.vertical > grid > button { + min-height: 24px; +} + +PanelSeparator { + color: rgba(239, 241, 245, 0.12); +} + +MatePanelAppletFrameDBus { + border-style: solid; + border-color: rgba(239, 241, 245, 0.12); +} + +.mate-panel-menu-bar.horizontal MatePanelAppletFrameDBus { + border-width: 0 1px; +} + +.mate-panel-menu-bar.vertical MatePanelAppletFrameDBus { + border-width: 1px 0; +} + +.mate-panel-menu-bar menubar > menuitem { + color: rgba(239, 241, 245, 0.7); +} + +.mate-panel-menu-bar menubar > menuitem:hover { + color: #eff1f5; +} + +.mate-panel-menu-bar menubar > menuitem:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.mate-panel-menu-bar.horizontal menubar > menuitem { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical menubar > menuitem { + padding: 8px 0; +} + +.mate-panel-menu-bar menubar menu > menuitem { + min-height: 28px; + padding: 0 6px; +} + +.mate-panel-menu-bar #PanelApplet button { + -gtkwidget-window-dragging: true; +} + +.mate-panel-menu-bar #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0/0 0 0px; +} + +.mate-panel-menu-bar #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2/0 0 2px; +} + +.mate-panel-menu-bar #tasklist-button image:dir(ltr), +.mate-panel-menu-bar #tasklist-button label:dir(rtl) { + padding-left: 4px; +} + +.mate-panel-menu-bar #tasklist-button label:dir(ltr), +.mate-panel-menu-bar #tasklist-button image:dir(rtl) { + padding-right: 4px; +} + +.mate-panel-menu-bar.vertical #tasklist-button { + min-height: 32px; +} + +.mate-panel-menu-bar.horizontal #showdesktop-button image { + min-width: 24px; + padding: 0 4px; +} + +.mate-panel-menu-bar.vertical #showdesktop-button image { + min-height: 24px; + padding: 4px 0; +} + +PanelApplet.wnck-applet .wnck-pager { + background-color: transparent; + color: #89b4fa; +} + +PanelApplet.wnck-applet .wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +PanelApplet.wnck-applet .wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +PanelApplet.wnck-applet .wnck-pager:selected { + background-color: #89b4fa; +} + +.mate-panel-menu-bar.horizontal #clock-applet-button label { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical #clock-applet-button label { + padding: 8px 0; +} + +#MatePanelPopupWindow { + border: 1px solid rgba(30, 30, 46, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +#MatePanelPopupWindow frame > border { + border-style: none; +} + +#MatePanelPopupWindow calendar { + border-style: none; +} + +#MatePanelPopupWindow calendar:not(:selected) { + background-color: transparent; +} + +#MatePanelPopupWindow calendar + box { + margin-top: -5px; + padding-top: 5px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +#MatePanelPopupWindow expander > title { + min-height: 32px; +} + +#MatePanelPopupWindow button { + padding: 4px 16px; +} + +#MatePanelPopupWindow > frame > box > box > box > widget { + color: rgba(239, 241, 245, 0.12); +} + +na-tray-applet { + -natrayapplet-icon-padding: 3px; + -natrayapplet-icon-size: 16; +} + +.mate-panel-menu-bar { + -panelmenubar-icon-visible: true; +} + +.mate-panel-applet-slider { + border: 1px solid rgba(30, 30, 46, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.mate-panel-applet-slider frame > border { + border-style: none; +} + +#PanelApplet:not(:selected) > box { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +#PanelApplet:selected > box { + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +#mate-menu { + border: 1px solid rgba(30, 30, 46, 0.2); + background-color: #292c3c; +} + +#mate-menu button { + min-height: 24px; + min-width: 24px; + padding: 4px 0; + color: #eff1f5; + font-weight: normal; +} + +#mate-menu button:not(.flat) { + background-color: alpha(currentColor, 0.1); +} + +#mate-menu button image, +#mate-menu button label + label { + color: rgba(239, 241, 245, 0.7); +} + +#mate-menu entry { + margin: 0 0 4px; +} + +#mate-menu entry image { + margin: 0; +} + +#mate-menu entry + button { + margin: 0 4px 4px; + padding: 5px; +} + +.brisk-menu { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.brisk-menu entry { + margin-bottom: -2px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.brisk-menu entry + box > box:dir(ltr) { + margin-right: -2px; + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +.brisk-menu entry + box > box:dir(rtl) { + margin-left: -2px; + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +.brisk-menu .categories-list { + padding-top: 4px; +} + +.brisk-menu .categories-list button { + margin: 0 4px; +} + +.brisk-menu .categories-list button:checked { + color: #89b4fa; +} + +.brisk-menu .session-button { + padding: 11px; +} + +.brisk-menu .frame { + border-style: none; +} + +.brisk-menu .apps-list { + padding: 4px 0; + background-color: transparent; +} + +.brisk-menu .apps-list row { + padding: 0; +} + +.brisk-menu .apps-list row:hover { + box-shadow: none; +} + +.brisk-menu .apps-list button { + border-radius: 0; + color: #eff1f5; + font-weight: normal; +} + +/********************* + * CAJA File manager * + *********************/ +.caja-navigation-window button.toggle.image-button { + border-radius: 12px; +} + +.caja-pathbar button { + margin: 0 -1px 0 -2px; +} + +.caja-pathbar button.slider-button { + min-width: 24px; +} + +.caja-pathbar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.caja-side-pane notebook viewport.frame, +.caja-side-pane notebook widget .vertical { + background-color: #313244; +} + +.caja-side-pane notebook, +.caja-notebook { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.caja-side-pane notebook .frame, +.caja-notebook .frame { + border-style: none; +} + +.caja-canvas-item { + border-radius: 12px; +} + +.caja-desktop.view .entry, +.caja-navigation-window .view .entry { + border: none; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + background-image: none; + color: #eff1f5; +} + +.caja-desktop.view .entry:selected, +.caja-navigation-window .view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-desktop.view .entry { + background-color: #313244; + color: #eff1f5; + caret-color: currentColor; +} + +.caja-desktop.view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-navigation-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.caja-notebook frame > border { + border-style: none; +} + +#caja-extra-view-widget { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +#caja-extra-view-widget > box > box > label { + font-weight: bold; +} + +/********* + * Pluma * + *********/ +.pluma-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.pluma-window statusbar frame > border { + border-style: none; +} + +.pluma-window statusbar frame button.flat { + padding: 0 4px; + border-radius: 0; +} + +.pluma-window statusbar frame button.flat widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.pluma-print-preview toolbar { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat { + margin: 1px; +} + +.pluma-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.pluma-window paned.horizontal box.vertical notebook.frame { + margin-top: -1px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.pluma-window paned.horizontal box.vertical notebook.frame box.vertical toolbar.horizontal { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +/********* + * Atril * + *********/ +.atril-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.atril-window paned.horizontal box.vertical notebook .frame { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +/* mate-screensaver lock dialog */ +.lock-dialog { + border: 1px solid rgba(30, 30, 46, 0.2); + border-radius: 13px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.lock-dialog frame > border { + border-style: none; +} + +.lock-dialog button:not(:disabled) { + color: #89b4fa; +} + +/* multimedia OSD */ +MsdOsdWindow.background.osd { + border-radius: 12px; + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; +} + +MsdOsdWindow.background.osd .trough { + border-radius: 0; + background-color: rgba(239, 241, 245, 0.12); +} + +MsdOsdWindow.background.osd .progressbar { + border-radius: 0; + background-color: #89b4fa; +} + +/****************** + * Budgie Desktop * + ******************/ +.budgie-container { + background-color: transparent; +} + +.budgie-settings-window list.sidebar { + background: none; + border-radius: 0 0 0 12px; +} + +.budgie-settings-window buttonbox.inline-toolbar { + border-style: none none solid; +} + +.budgie-settings-window buttonbox.inline-toolbar button { + border-radius: 12px; +} + +.budgie-popover { + border-color: #292c3c; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #e6e9ef; + background-clip: border-box; + background-color: #292c3c; + border-radius: 12px; +} + +.budgie-popover frame.container { + padding: 6px; + border: none; +} + +.budgie-popover frame.container .container { + padding: 0; +} + +.budgie-popover list, +.budgie-popover row { + padding: 0; +} + +.budgie-popover separator { + margin: 3px 0; +} + +.budgie-popover border { + border: none; +} + +.budgie-popover list { + background-color: transparent; +} + +.budgie-popover row:hover { + box-shadow: none; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) { + background-color: rgba(239, 241, 245, 0.04); + border-right: none; + border-bottom-left-radius: 12px; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable { + padding: 6px 8px; +} + +.budgie-popover treeview.view.sidebar { + border-right: none; + background: none; +} + +.budgie-popover treeview.view.sidebar:hover { + background-color: alpha(currentColor, 0.08); +} + +.budgie-popover treeview.view.sidebar:selected { + background-color: alpha(currentColor, 0.12); +} + +.budgie-popover.bottom scrolledwindow.sidebar:not(.categories) { + padding-top: 12px; + border-top-left-radius: 12px; + border-bottom-left-radius: 0; +} + +.budgie-popover > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.budgie-popover.bottom > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: none; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.budgie-popover.budgie-menu .container { + padding: 0; +} + +.budgie-popover.budgie-menu .sidebar, +.budgie-popover.budgie-menu scrollbar, +.budgie-popover.budgie-menu entry.search { + background-color: transparent; +} + +.budgie-popover.budgie-menu entry.search { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + font-size: 120%; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories { + background-color: rgba(239, 241, 245, 0.04); + padding-bottom: 12px; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button { + border-radius: 0; +} + +.budgie-popover.budgie-menu scrolledwindow > viewport.frame > list > row.activatable > button.flat { + border-radius: 0; +} + +.budgie-popover.budgie-menu list.left-overlay-menu { + border-radius: 12px; + background-color: #313244; + padding: 6px; + margin: 6px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #e6e9ef; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable { + border-radius: 12px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable:not(:last-child) { + margin-bottom: 3px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable button.menuitem { + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer { + border-top: 1px solid rgba(239, 241, 245, 0.12); + padding: 6px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat { + padding: 3px; + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat.image-button { + border-radius: 9999px; + padding: 6px; + min-height: 16px; + min-width: 16px; + margin-left: 6px; + background-clip: border-box; +} + +.budgie-popover.user-menu list, +.budgie-popover.user-menu row { + border: none; + background: none; + box-shadow: none; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child { + margin-bottom: 0; + outline-width: 0; + border-radius: 12px; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child button.indicator-item { + transition: none; + animation: none; +} + +.budgie-popover.night-light-indicator .view-header { + margin: 0 6px; +} + +.budgie-popover.places-menu .name-button image:dir(ltr) { + margin-right: 3px; +} + +.budgie-popover.places-menu .name-button image:dir(rtl) { + margin-left: 3px; +} + +.budgie-popover.places-menu .unmount-button { + margin: 2px; + padding: 0; +} + +.budgie-popover.places-menu .places-list:not(.always-expand) { + margin-top: 3px; + padding-top: 3px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.budgie-popover.places-menu .alternative-label { + padding: 3px; + font-size: 15px; +} + +.budgie-popover.workspace-popover flowboxchild { + padding: 0; +} + +.workspace-switcher .workspace-layout { + border: 0 solid rgba(239, 241, 245, 0.12); +} + +.top .workspace-switcher .workspace-layout:dir(ltr), .bottom .workspace-switcher .workspace-layout:dir(ltr) { + border-left-width: 1px; +} + +.top .workspace-switcher .workspace-layout:dir(rtl), .bottom .workspace-switcher .workspace-layout:dir(rtl) { + border-right-width: 1px; +} + +.left .workspace-switcher .workspace-layout, .right .workspace-switcher .workspace-layout { + border-top-width: 1px; +} + +.workspace-switcher .workspace-item, +.workspace-switcher .workspace-add-button { + border: 0 solid rgba(239, 241, 245, 0.12); +} + +.top .workspace-switcher .workspace-item:dir(ltr), .bottom .workspace-switcher .workspace-item:dir(ltr), .top .workspace-switcher .workspace-add-button:dir(ltr), .bottom .workspace-switcher .workspace-add-button:dir(ltr) { + border-right-width: 1px; +} + +.top .workspace-switcher .workspace-item:dir(rtl), .bottom .workspace-switcher .workspace-item:dir(rtl), .top .workspace-switcher .workspace-add-button:dir(rtl), .bottom .workspace-switcher .workspace-add-button:dir(rtl) { + border-left-width: 1px; +} + +.left .workspace-switcher .workspace-item, .right .workspace-switcher .workspace-item, .left .workspace-switcher .workspace-add-button, .right .workspace-switcher .workspace-add-button { + border-bottom-width: 1px; +} + +.workspace-switcher .workspace-item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.workspace-switcher .workspace-item.current-workspace { + background-color: alpha(currentColor, 0.1); +} + +.workspace-switcher .workspace-add-button:hover { + box-shadow: none; +} + +.workspace-switcher .workspace-add-button:active { + background-image: none; +} + +.workspace-switcher .workspace-add-button:active image { + margin: 1px 0 -1px; +} + +.budgie-panel .workspace-switcher .workspace-icon-button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 12px; +} + +.budgie-panel { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(30, 30, 46, 0.6); + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +.budgie-panel.transparent { + background-color: rgba(30, 30, 46, 0.75); +} + +.budgie-panel .icon-tasklist button.launcher:checked, .budgie-panel .icon-tasklist button.launcher:active { + color: #eff1f5; +} + +.top .budgie-panel.dock-mode { + border-radius: 0 0 12px 12px; +} + +.bottom .budgie-panel.dock-mode { + border-radius: 12px 12px 0 0; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:first-child > button.launcher { + border-top-left-radius: 12px; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:last-child > button.launcher { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode { + border-radius: 0 12px 12px 0; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-right-radius: 12px; +} + +.right .budgie-panel.dock-mode { + border-radius: 12px 0 0 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-left-radius: 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-left-radius: 12px; +} + +.budgie-panel button { + color: rgba(239, 241, 245, 0.7); + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 0; +} + +.budgie-panel button:hover { + color: #eff1f5; +} + +.budgie-panel button:active { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel button.budgie-menu-launcher { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel button.budgie-menu-launcher:focus { + box-shadow: none; + border: none; + color: #eff1f5; +} + +.budgie-panel button.raven-trigger { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel.horizontal button { + padding: 0 4px; +} + +.budgie-panel.vertical button { + padding: 4px 0; +} + +.budgie-panel separator { + background-color: rgba(239, 241, 245, 0.12); +} + +.budgie-panel .alert { + color: #d20f39; +} + +.budgie-panel > box > widget > widget > image, +.budgie-panel > box > widget > widget > stack > image, +.budgie-panel > box > widget > widget > box > image { + margin-left: 6px; + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > image + label { + margin-left: -4px; +} + +.budgie-panel > box > widget > widget > box > widget > image { + margin-left: 6px; +} + +.budgie-panel > box > widget > widget > box > stack > widget > label { + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > widget > widget > image { + margin-left: 2px; + margin-right: 2px; +} + +.budgie-panel .budgie-clock-applet > widget > box, +.budgie-panel .budgie-calendar-applet > widget > box { + padding-left: 3px; + padding-right: 3px; +} + +.budgie-panel .titlebar:not(headerbar) { + min-height: 0; + padding: 0; + box-shadow: none; + background-color: transparent; + color: #eff1f5; +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):hover, .budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):active { + color: #eff1f5; +} + +.budgie-panel menubar, +.budgie-panel .menubar { + color: rgba(239, 241, 245, 0.7); + box-shadow: none; + border: none; +} + +.budgie-panel menubar > menuitem, +.budgie-panel .menubar > menuitem { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel menubar > menuitem:hover, .budgie-panel menubar > menuitem:active, +.budgie-panel .menubar > menuitem:hover, +.budgie-panel .menubar > menuitem:active { + color: #eff1f5; +} + +.budgie-panel menubar menu separator, +.budgie-panel .menubar menu separator { + background-color: rgba(239, 241, 245, 0.12); +} + +.budgie-panel #tasklist-button { + padding: 0 4px; +} + +.budgie-panel.vertical #tasklist-button { + min-height: 32px; +} + +.budgie-panel button.flat.launcher { + padding: 0; +} + +.budgie-panel button.flat.launcher:not(:checked) { + color: rgba(239, 241, 245, 0.5); +} + +.budgie-panel button.flat.launcher:not(:checked):hover, .budgie-panel button.flat.launcher:not(:checked):active { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel button.flat.launcher:not(:checked):disabled { + color: rgba(239, 241, 245, 0.32); +} + +.top .budgie-panel .unpinned button.flat.launcher:checked, .top .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel .unpinned button.flat.launcher:checked, .bottom .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel .unpinned button.flat.launcher:checked, .left .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel .unpinned button.flat.launcher:checked, .right .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +.top .budgie-panel #tasklist-button, .budgie-panel .top #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.top .budgie-panel #tasklist-button:checked, .budgie-panel .top #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel #tasklist-button, .budgie-panel .bottom #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.bottom .budgie-panel #tasklist-button:checked, .budgie-panel .bottom #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel #tasklist-button, .budgie-panel .left #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.left .budgie-panel #tasklist-button:checked, .budgie-panel .left #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel #tasklist-button, .budgie-panel .right #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.right .budgie-panel #tasklist-button:checked, .budgie-panel .right #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +frame.raven-frame > border { + border-style: none; +} + +.top frame.raven-frame > border { + margin-bottom: 32px; +} + +.bottom frame.raven-frame > border { + margin-top: 32px; +} + +.left frame.raven-frame > border { + margin-right: 32px; +} + +.right frame.raven-frame > border { + margin-left: 32px; +} + +.raven { + background-color: #292c3c; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +.raven > box { + margin-bottom: -10px; +} + +.raven stackswitcher.linked { + margin: 6px 16px; +} + +.raven stackswitcher.linked > button:focus { + box-shadow: none; +} + +.raven .raven-header { + min-height: 34px; + padding: 3px; +} + +.raven .raven-header.top { + padding: 0; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.raven .raven-header.top stackswitcher button { + margin: -4px 0 -5px; + padding: 0 16px; + min-height: 24px; +} + +.raven .raven-header.bottom { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.raven stack .raven-header { + margin-top: -6px; +} + +.raven stack scrolledwindow .raven-header { + margin-top: -8px; +} + +.raven .raven-background { + border-style: solid none; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +.raven .raven-background > overlay > widget > image { + color: rgba(239, 241, 245, 0.12); +} + +.raven scrolledwindow.raven-background { + border-bottom-style: none; +} + +.raven .powerstrip button { + margin: 2px 0 1px; + padding: 11px; + border-radius: 9999px; +} + +.raven .option-subtitle { + font-size: smaller; +} + +.raven .audio-widget scale.marks-after { + padding-top: 0; + padding-bottom: 0; +} + +.raven .audio-widget scale.marks-after label { + font-size: 90%; + padding: 0; + margin: -10px 0 0 6px; +} + +.raven .audio-widget button.flat.expander-button { + margin-top: 4px; + margin-bottom: 4px; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked { + background-color: rgba(239, 241, 245, 0.06); + color: #eff1f5; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected label, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked label { + color: #eff1f5; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable label { + padding-left: 12px; +} + +.raven levelbar, +.raven levelbar trough, +.raven levelbar block { + border-radius: 9999px; +} + +calendar.raven-calendar { + border-style: none; + background-color: transparent; +} + +calendar.raven-calendar:selected { + border-radius: 12px; +} + +.raven-mpris { + background-color: #292c3c; + color: #eff1f5; +} + +.raven-mpris label { + min-height: 24px; +} + +.raven-mpris button.image-button { + padding: 11px; +} + +image.raven-mpris { + background-color: rgba(239, 241, 245, 0.12); + color: rgba(239, 241, 245, 0.7); + border-radius: 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame { + padding: 0; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable { + margin-left: -6px; + margin-right: -3px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable .raven-notifications-group-header { + padding: 0 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list { + padding: 6px; + background: none; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable { + border: none; + padding: 6px; + padding-left: 12px; + margin: 3px; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:selected { + background-color: rgba(239, 241, 245, 0.12); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:active, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:focus { + background: none; + box-shadow: none; +} + +.budgie-notification-window, .budgie-switcher-window, .budgie-osd-window { + background-color: transparent; +} + +.budgie-notification .notification-title, .budgie-switcher .notification-title { + font-size: 120%; +} + +.budgie-notification .notification-body, .budgie-switcher .notification-body { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-osd .budgie-osd-text { + font-size: 120%; +} + +.budgie-panel .lock-keys image:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.drop-shadow { + margin: 5px 9px; + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.drop-shadow .linked > button { + border-radius: 12px; +} + +.budgie-session-dialog, +.budgie-polkit-dialog, +.budgie-run-dialog { + background-color: #292c3c; + border: none; + padding: 0; +} + +.budgie-session-dialog > box > grid, +.budgie-polkit-dialog > box > grid, +.budgie-run-dialog > box > grid { + padding: 24px; +} + +.budgie-session-dialog.background, .budgie-session-dialog > decoration, +.budgie-polkit-dialog.background, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog.background, +.budgie-run-dialog > decoration { + border-radius: 12px; +} + +.budgie-session-dialog > decoration, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog > decoration { + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(30, 30, 46, 0.75); +} + +.budgie-session-dialog label:not(:last-child), +.budgie-session-dialog .dialog-title, +.budgie-polkit-dialog label:not(:last-child), +.budgie-polkit-dialog .dialog-title, +.budgie-run-dialog label:not(:last-child), +.budgie-run-dialog .dialog-title { + font-size: 120%; +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button { + padding: 8px 16px; + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0; +} + +.budgie-session-dialog .linked.horizontal > button:first-child, +.budgie-polkit-dialog .linked.horizontal > button:first-child, +.budgie-run-dialog .linked.horizontal > button:first-child { + border-bottom-left-radius: 12px; +} + +.budgie-session-dialog .linked.horizontal > button:last-child, +.budgie-polkit-dialog .linked.horizontal > button:last-child, +.budgie-run-dialog .linked.horizontal > button:last-child { + border-bottom-right-radius: 12px; +} + +.budgie-polkit-dialog .message { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-polkit-dialog .failure { + color: #d20f39; +} + +.budgie-polkit-dialog > box > grid { + padding-bottom: 0; +} + +.budgie-run-dialog entry.search { + font-size: 120%; + padding: 6px 14px; + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.budgie-run-dialog list .dim-label { + color: #eff1f5; +} + +.budgie-run-dialog scrolledwindow { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +/************** + * Xfce4 Apps * + **************/ +.XfceHeading { + background-color: #313244; +} + +/*************** + * xfce4-panel * + ***************/ +.xfce4-panel.background { + border: none; + background-color: rgba(30, 30, 46, 0.6); + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +.xfce4-panel.background button { + min-height: 16px; + min-width: 16px; + padding: 0 6px; + border-radius: 0; +} + +.xfce4-panel.background button.flat.toggle { + padding: 0 6px; +} + +.xfce4-panel.background .tasklist button image { + padding: 4px; +} + +wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +wnck-pager:selected { + background-color: #89b4fa; +} + +#xfce4-mpc-plugin-26 > frame > border { + border: none; +} + +#xfce-panel-button { + -gtk-icon-style: symbolic; +} + +XfdesktopIconView.view { + border-radius: 12px; + background-color: transparent; + color: #eff1f5; +} + +XfdesktopIconView.view:active { + box-shadow: none; +} + +XfdesktopIconView.view .rubberband { + border-radius: 0; +} + +window#whiskermenu-window { + border-radius: 12px; + background-color: transparent; + border: none; +} + +window#whiskermenu-window entry.search:focus { + background-color: #313244; +} + +window#whiskermenu-window > frame > border { + border-radius: 12px; + padding: 6px 8px 6px 9px; + margin: 6px; + border: none; + background-color: #292c3c; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa; +} + +window#whiskermenu-window box.categories > button.radio { + padding: 3px 6px; + margin: 1px 0; +} + +window#whiskermenu-window box.categories > button.radio:hover { + background-color: rgba(239, 241, 245, 0.12); +} + +window#whiskermenu-window box.categories > button.radio:checked, window#whiskermenu-window box.categories > button.radio:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +window#whiskermenu-window box.categories > button.radio:checked:hover, window#whiskermenu-window box.categories > button.radio:active:hover { + background-image: none; +} + +window#whiskermenu-window scrolledwindow.frame { + padding: 3px; + background-color: #313244; + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view { + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:not(:hover):not(:selected) { + background: none; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:selected:hover { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:checked, window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +#XfceNotifyWindow { + background-color: #313244; + border-radius: 12px; + border: 2px solid #89b4fa; +} + +#XfceNotifyWindow buttonbox { + padding: 0; +} + +#XfceNotifyWindow label#summary { + font-weight: bold; +} + +dialog.xfsm-logout-dialog { + border-radius: 12px; + background-color: rgba(41, 44, 60, 0.97); + border: 2px solid #89b4fa; +} + +#xfwm-tabwin { + padding: 12px; + border-radius: 12px; + -xfwmtabwinwidget-icon-size: 64px; + -xfwmtabwinwidget-preview-size: 64px; +} + +/********** + * Thunar * + **********/ +.thunar toolbar { + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.thunar .standard-view.frame { + border: none; +} + +.thunar scrolledwindow.frame.sidebar { + border-top: none; +} + +.thunar .path-bar.linked:not(.vertical) > button.path-bar-button { + margin-left: 2px; + margin-right: 2px; +} + +.thunar statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-top: none; +} + +window.background.csd.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-bottom-left-radius: 12px; +} + +menubar.-vala-panel-appmenu-private, +menubar.-vala-panel-background { + background: none; + border: none; + box-shadow: none; + animation: none; +} + +menubar.-vala-panel-appmenu-private > menuitem, +menubar.-vala-panel-background > menuitem { + color: rgba(239, 241, 245, 0.7); + font-weight: normal; +} + +menubar.-vala-panel-appmenu-private > menuitem:hover, +menubar.-vala-panel-background > menuitem:hover { + color: #eff1f5; + border-radius: 0; +} + +menubar.-vala-panel-appmenu-private > menuitem:disabled, +menubar.-vala-panel-background > menuitem:disabled { + color: rgba(239, 241, 245, 0.32); +} + +/************************ + * LightDM GTK+ Greeter * + ************************/ +#panel_window { + background-color: #313244; + color: #eff1f5; +} + +#panel_window menubar, +#panel_window separator { + background-color: transparent; +} + +#panel_window separator { + padding: 0 4px; +} + +#panel_window separator:first-child { + padding: 0 8px; +} + +#panel_window menubar > menuitem { + color: rgba(239, 241, 245, 0.7); +} + +#panel_window menubar > menuitem:hover { + color: #eff1f5; +} + +#panel_window menubar > menuitem:disabled label { + color: rgba(239, 241, 245, 0.32); +} + +#login_window, +#shutdown_dialog, +#restart_dialog { + margin: 8px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +#content_frame { + padding-bottom: 16px; +} + +/* // the buttons, alternatively this could also be done with a simple ".lightdm-gtk-greeter button" */ +/* #login_window button, */ +/* #shutdown_dialog button, */ +/* #restart_dialog button { */ +/* } */ +/* .lightdm-gtk-greeter button { */ +/* } */ +/* // the user's avatar box */ +/* #user_image { */ +/* } */ +/* // the border around the user's avatar box */ +/* #user_image_border { */ +/* } */ +#buttonbox_frame { + padding-top: 24px; +} + +#buttonbox_frame > box, +#buttonbox_frame > buttonbox { + margin: -16px; +} + +#buttonbox_frame button:not(:disabled) { + color: #89b4fa; +} + +/* // the shutdown button */ +/* #shutdown_button { */ +/* } */ +/* // the restart button */ +/* #restart_button { */ +/* } */ +/* // the warning, in case a wrong password is entered or something else goes wrong according to PAM */ +/* #greeter_infobar { */ +/* // font-weight: bold; */ +/* } */ +/******** + * Nemo * + ********/ +.nemo-window .primary-toolbar { + background-color: #1e1e2e; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.nemo-window .primary-toolbar entry { + min-height: 0; + margin: 0; +} + +.nemo-window .primary-toolbar > toolitem > .linked > button.image-button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar button.text-button { + padding-left: 8px; + padding-right: 8px; + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar button.text-button:hover, .nemo-window .primary-toolbar button.text-button:active, .nemo-window .primary-toolbar button.text-button:checked { + color: #eff1f5; +} + +.nemo-window .primary-toolbar button.text-button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar button.text-button:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button:checked { + box-shadow: none; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button { + border-radius: 6px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.nemo-window .primary-toolbar button:not(.text-button):not(.image-button) { + padding-left: 4px; + padding-right: 4px; +} + +.nemo-window scrolledwindow.frame { + border-style: none; +} + +.nemo-window scrolledwindow.frame .view:not(:selected) { + background-color: transparent; +} + +.nemo-window .nemo-inactive-pane .view:not(:selected) { + background-color: #313244; +} + +.nemo-window .nemo-window-pane widget.entry { + border-radius: 6px; + background-color: rgba(239, 241, 245, 0.04); +} + +.nemo-window .nemo-window-pane > notebook { + border-radius: 0; +} + +.places-treeview { + -nemoplacestreeview-disk-full-bg-color: #5d5d6a; + -nemoplacestreeview-disk-full-fg-color: #89b4fa; + -nemoplacestreeview-disk-full-bar-width: 2px; + -nemoplacestreeview-disk-full-bar-radius: 0; + -nemoplacestreeview-disk-full-bottom-padding: 1px; + -nemoplacestreeview-disk-full-max-length: 80px; + padding-top: 3px; + padding-bottom: 3px; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #eff1f5; +/* text color for entries, views and content in general */ +@define-color theme_text_color #eff1f5; +/* widget base background color */ +@define-color theme_bg_color #1e1e2e; +/* text widgets and the like base background color */ +@define-color theme_base_color #313244; +/* base background color of selections */ +@define-color theme_selected_bg_color #89b4fa; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(30, 30, 46, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #1e1e2e; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(239, 241, 245, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #313244; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #eff1f5; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #eff1f5; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #1e1e2e; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #313244; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #89b4fa; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(30, 30, 46, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(239, 241, 245, 0.5); +/* widgets main borders color */ +@define-color borders rgba(239, 241, 245, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(239, 241, 245, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #df8e1d; +@define-color error_color #d20f39; +@define-color success_color #40a02b; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #eff1f5; +@define-color wm_unfocused_title rgba(239, 241, 245, 0.7); +@define-color wm_highlight rgba(239, 241, 245, 0.1); +@define-color wm_border #0a0a0e; +@define-color wm_focused_bg #1e1e2e; +@define-color wm_unfocused_bg #1e1e2e; +@define-color wm_button_icon #eff1f5; +@define-color wm_button_focused_bg #2b2b3a; +@define-color wm_button_unfocused_bg #2b2b3a; +@define-color wm_button_hover_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_active_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_hover_bg #e6e9ef; +@define-color wm_button_active_bg #e7eaf0; +/* FIXME this is really an API */ +@define-color content_view_bg #313244; +@define-color placeholder_text_color #b6b8c0; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #313244; +@define-color budgie_tasklist_indicator_color rgba(121, 122, 133, 0.7); +@define-color budgie_tasklist_indicator_color_active #89b4fa; +@define-color budgie_tasklist_indicator_color_active_window rgba(108, 140, 195, 0.816); +@define-color budgie_tasklist_indicator_color_attention #df8e1d; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk.css b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk.css new file mode 100755 index 0000000..11d2255 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/gtk.css @@ -0,0 +1,8598 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #89b4fa 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #89b4fa 100%, transparent 0%); + } +} + +* { + background-clip: padding-box; + -gtktoolbutton-icon-spacing: 4; + -gtktextview-error-underline-color: #d20f39; + -gtkscrolledwindow-scrollbar-spacing: 0; + -gtktoolitemgroup-expander-size: 11; + -gtkwidget-text-handle-width: 20; + -gtkwidget-text-handle-height: 20; + -gtkdialog-button-spacing: 6; + -gtkdialog-action-area-border: 4; + -gtkdialog-content-area-border: 4; + outline-style: solid; + outline-width: 0; + outline-color: alpha(currentColor, 0.15); + outline-offset: -4px; + -gtk-outline-radius: 12px; + -gtk-secondary-caret-color: #89b4fa; +} + +.thunar .standard-view.frame widget.view:selected, XfdesktopIconView.view:active, calendar.raven-calendar:selected, box.vertical > widget > widget:selected, calendar:selected, modelbutton.flat:selected, +.menuitem.button.flat:selected, .background.csd .view:selected { + color: #eff1f5; + background-color: alpha(currentColor, 0.1); +} + +.nautilus-window notebook .view:not(treeview) selection, .nautilus-window notebook .view:not(treeview):selected, .nautilus-window flowboxchild:selected .icon-item-background, label selection, flowbox flowboxchild:selected { + color: #89b4fa; + background-color: rgba(137, 180, 250, 0.2); +} + +.nemo-window .nemo-window-pane widget.entry:selected, window.background.csd evview.view.content-view:selected, window.background.csd evview.view.content-view:selected:backdrop, .nautilus-window.background.csd notebook widget.view:selected, spinbutton.vertical selection, spinbutton:not(.vertical) selection, +entry selection, textview text selection:focus, textview text selection, widget.view:selected, .view:selected { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +treeview.view:selected { + color: rgba(30, 30, 46, 0.87); + background-color: #e6e9ef; +} + +.linked:not(.vertical) > button, .linked:not(.vertical) > spinbutton.vertical, .linked:not(.vertical) > spinbutton:not(.vertical), .linked:not(.vertical) > entry { + border-radius: 0; +} + +.linked:not(.vertical) > button:first-child, .linked:not(.vertical) > spinbutton.vertical:first-child, .linked:not(.vertical) > spinbutton:first-child:not(.vertical), .linked:not(.vertical) > entry:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > button:last-child, .linked:not(.vertical) > spinbutton.vertical:last-child, .linked:not(.vertical) > spinbutton:last-child:not(.vertical), .linked:not(.vertical) > entry:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > button:only-child, .linked:not(.vertical) > spinbutton.vertical:only-child, .linked:not(.vertical) > spinbutton:only-child:not(.vertical), .linked:not(.vertical) > entry:only-child { + border-radius: 12px; +} + +.linked.vertical > button, .linked.vertical > spinbutton.vertical, .linked.vertical > spinbutton:not(.vertical), .linked.vertical > entry { + border-radius: 0; +} + +.linked.vertical > button:first-child, .linked.vertical > spinbutton.vertical:first-child, .linked.vertical > spinbutton:first-child:not(.vertical), .linked.vertical > entry:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > button:last-child, .linked.vertical > spinbutton.vertical:last-child, .linked.vertical > spinbutton:last-child:not(.vertical), .linked.vertical > entry:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > button:only-child, .linked.vertical > spinbutton.vertical:only-child, .linked.vertical > spinbutton:only-child:not(.vertical), .linked.vertical > entry:only-child { + border-radius: 12px; +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #1e1e2e; + color: #eff1f5; +} + +.background.csd { + border-radius: 0 0 12px 12px; +} + +.background.maximized, .background.solid-csd { + border-radius: 0; +} + +*:disabled { + -gtk-icon-effect: dim; +} + +.gtkstyle-fallback { + background-color: #1e1e2e; + color: #eff1f5; +} + +.gtkstyle-fallback:hover { + background-color: #14141f; + color: #eff1f5; +} + +.gtkstyle-fallback:active { + background-color: #0a0a0f; + color: #eff1f5; +} + +.gtkstyle-fallback:disabled { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.5); +} + +.gtkstyle-fallback:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.view { + background-color: #313244; + color: #eff1f5; +} + +.view:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.view:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.view:selected:hover { + box-shadow: none; +} + +window.background.csd > stack.view { + border-radius: 0 0 12px 12px; +} + +textview text { + background-color: #313244; +} + +textview border { + background-color: #313244; + color: rgba(239, 241, 245, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 12px; +} + +flowbox rubberband, +.rubberband, +rubberband, +XfdesktopIconView.view .rubberband, +.content-view rubberband, +.content-view .rubberband, +treeview.view rubberband { + border: 1px solid #89b4fa; + background-color: rgba(137, 180, 250, 0.3); +} + +flowbox flowboxchild { + padding: 3px; + border-radius: 12px; + color: #eff1f5; +} + +flowbox flowboxchild button.osd.remove-button { + min-height: 28px; + min-width: 28px; + padding: 0; + margin: 6px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +label { + caret-color: currentColor; +} + +label.separator { + color: rgba(239, 241, 245, 0.7); +} + +label:disabled { + color: rgba(239, 241, 245, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; +} + +label.osd { + border-radius: 12px; + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; +} + +.dim-label { + color: rgba(239, 241, 245, 0.7); +} + +assistant .sidebar { + padding: 4px 0; +} + +assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(239, 241, 245, 0.5); + font-weight: 500; +} + +assistant .sidebar label.highlight { + color: #eff1f5; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + -gtk-icon-transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry { + background-color: rgba(30, 30, 46, 0.04); + color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus { + color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active) { + color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled { + background-color: rgba(30, 30, 46, 0.04); + color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image { + color: rgba(30, 30, 46, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled { + color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image { + color: rgba(30, 30, 46, 0.87); +} + +spinbutton.vertical, spinbutton:not(.vertical), +entry { + min-height: 34px; + padding: 0 8px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton.vertical:focus, spinbutton:focus:not(.vertical), +entry:focus { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #89b4fa; +} + +spinbutton.vertical:drop(active), spinbutton:drop(active):not(.vertical), +entry:drop(active) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + +spinbutton.vertical:disabled, spinbutton:disabled:not(.vertical), +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.flat.vertical, spinbutton.flat:not(.vertical), +entry.flat { + min-height: 0; + padding: 2px; + border-radius: 0; + background-color: transparent; +} + +spinbutton.vertical image, spinbutton:not(.vertical) image, +entry image { + color: rgba(239, 241, 245, 0.7); +} + +spinbutton.vertical image:hover, spinbutton:not(.vertical) image:hover, spinbutton.vertical image:active, spinbutton:not(.vertical) image:active, +entry image:hover, +entry image:active { + color: #eff1f5; +} + +spinbutton.vertical image:disabled, spinbutton:not(.vertical) image:disabled, +entry image:disabled { + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.vertical image.left, spinbutton:not(.vertical) image.left, +entry image.left { + margin-left: 1px; + margin-right: 6px; +} + +spinbutton.vertical image.right, spinbutton:not(.vertical) image.right, +entry image.right { + margin-left: 6px; + margin-right: 1px; +} + +spinbutton.vertical undershoot.left, spinbutton:not(.vertical) undershoot.left, +entry undershoot.left { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(239, 241, 245, 0.3) 50%); + padding-left: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: left top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.vertical undershoot.right, spinbutton:not(.vertical) undershoot.right, +entry undershoot.right { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(239, 241, 245, 0.3) 50%); + padding-right: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: right top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.error.vertical, spinbutton.error:not(.vertical), +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton.error.vertical:focus, spinbutton.error:focus:not(.vertical), +entry.error:focus { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #d20f39; +} + +spinbutton.error.vertical:disabled, spinbutton.error:disabled:not(.vertical), +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.warning.vertical, spinbutton.warning:not(.vertical), +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton.warning.vertical:focus, spinbutton.warning:focus:not(.vertical), +entry.warning:focus { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #df8e1d; +} + +spinbutton.warning.vertical:disabled, spinbutton.warning:disabled:not(.vertical), +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.vertical progress, spinbutton:not(.vertical) progress, +entry progress { + margin: 2px -8px; + border-bottom: 2px solid #89b4fa; + background-color: transparent; +} + +treeview entry.flat, treeview entry { + background-color: #313244; +} + +treeview entry.flat, treeview entry.flat:focus, treeview entry, treeview entry:focus { + border-image: none; + box-shadow: none; +} + +.entry-tag, .photos-entry-tag, .documents-entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.entry-tag:hover, .photos-entry-tag:hover, .documents-entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag, :dir(ltr) .photos-entry-tag, :dir(ltr) .documents-entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag, :dir(rtl) .photos-entry-tag, :dir(rtl) .documents-entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button, .button.photos-entry-tag, .button.documents-entry-tag { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active), .button.photos-entry-tag:not(:hover):not(:active), .button.documents-entry-tag:not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.001, to(#89b4fa), to(transparent)); + } + to { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(#89b4fa), to(transparent)); + } +} + +.xfce4-panel.background button, .raven-mpris button.image-button, .mate-panel-menu-bar button, infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button { + color: rgba(239, 241, 245, 0.7); +} + +.xfce4-panel.background button:focus, .raven-mpris button.image-button:focus, .mate-panel-menu-bar button:focus, infobar.warning > revealer > box button:focus, .xfce4-panel.background button:hover, .raven-mpris button.image-button:hover, .mate-panel-menu-bar button:hover, infobar.warning > revealer > box button:hover, .xfce4-panel.background button:active, .raven-mpris button.image-button:active, .mate-panel-menu-bar button:active, infobar.warning > revealer > box button:active, .xfce4-panel.background button:checked, .raven-mpris button.image-button:checked, .mate-panel-menu-bar button:checked, infobar.warning > revealer > box button:checked { + color: #eff1f5; +} + +.xfce4-panel.background button:disabled, .raven-mpris button.image-button:disabled, .mate-panel-menu-bar button:disabled, infobar.warning > revealer > box button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.xfce4-panel.background button:checked:disabled, .raven-mpris button.image-button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, infobar.warning > revealer > box button:checked:disabled { + color: rgba(239, 241, 245, 0.5); +} + +actionbar > revealer > box button:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: #313244; + color: #eff1f5; +} + +actionbar > revealer > box button:checked:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: rgba(30, 30, 46, 0.87); + color: #e6e9ef; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat, terminal-window notebook > header > box button.flat { + color: rgba(30, 30, 46, 0.6); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:hover, terminal-window notebook > header > box button.flat:hover, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:active, terminal-window notebook > header > box button.flat:active, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:focus, terminal-window notebook > header > box button.flat:focus { + color: rgba(30, 30, 46, 0.87); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:checked, terminal-window notebook > header > box button.flat:checked { + background-color: rgba(30, 30, 46, 0.87); + color: #e6e9ef; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:disabled, terminal-window notebook > header > box button.flat:disabled { + color: rgba(30, 30, 46, 0.3); +} + +button { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(239, 241, 245, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #eff1f5; +} + +button:focus { + box-shadow: 0 0 0 2px rgba(137, 180, 250, 0.35); +} + +button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +button:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +button:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +button:checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +button:checked:hover { + box-shadow: inset 0 0 0 9999px transparent; +} + +button:checked:disabled { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.1); + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +.raven .expander-button, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, .nautilus-window headerbar revealer > button, button.titlebutton:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, button.close, button.circular, .inline-toolbar button:not(.text-button) { + border-radius: 9999px; +} + +.raven .expander-button label, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle label, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat) label, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, .nautilus-window headerbar revealer > button label, button.titlebutton:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, button.close label, button.circular label, .inline-toolbar button:not(.text-button) label { + padding: 0; +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat, .gedit-document-panel row button.flat, .nautilus-window .floating-bar button, placessidebar.sidebar row button.sidebar-button, notebook > header tab button.flat, +notebook > header tab button.close-button, spinbutton.vertical button, spinbutton:not(.vertical) button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button, .drop-shadow button, .budgie-panel button, .budgie-popover row button, .budgie-settings-window buttonbox.inline-toolbar button, #mate-menu button, #MatePanelPopupWindow button, popover.messagepopover .popover-action-area button, tabbox > tab button, placessidebar.sidebar row button.sidebar-button, calendar.button, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular, treeview.view header button button.circular, row.activatable button.circular, notebook > header > tabs > arrow, modelbutton.flat, +.menuitem.button.flat, spinbutton.vertical button, spinbutton:not(.vertical) button, .nemo-window .toolbar button, #buttonbox_frame button, .xfce4-panel.background button, .raven stackswitcher.linked > button, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button, .lock-dialog button, .mate-panel-menu-bar button, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, layouttabbar button, filechooser #pathbarbox > stack > box > button, messagedialog .dialog-action-box button, +messagedialog .dialog-action-box .linked:not(.vertical) > button, .app-notification button, popover.background.menu button, +popover.background button.model, .nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action), button.flat { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: rgba(239, 241, 245, 0.7); +} + +.budgie-session-dialog .linked.horizontal > button:focus, +.budgie-polkit-dialog .linked.horizontal > button:focus, +.budgie-run-dialog .linked.horizontal > button:focus, .drop-shadow button:focus, .budgie-panel button:focus, .budgie-popover row button:focus, .budgie-settings-window buttonbox.inline-toolbar button:focus, #mate-menu button:focus, #MatePanelPopupWindow button:focus, popover.messagepopover .popover-action-area button:focus, tabbox > tab button:focus, placessidebar.sidebar row button.sidebar-button:focus, calendar.button:focus, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:focus, treeview.view header button button.circular:focus, row.activatable button.circular:focus, notebook > header > tabs > arrow:focus, modelbutton.flat:focus, +.menuitem.button.flat:focus, spinbutton.vertical button:focus, spinbutton:not(.vertical) button:focus, .nemo-window .toolbar button:focus, #buttonbox_frame button:focus, .xfce4-panel.background button:focus, .raven stackswitcher.linked > button:focus, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:focus, .lock-dialog button:focus, .mate-panel-menu-bar button:focus, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, layouttabbar button:focus, filechooser #pathbarbox > stack > box > button:focus, messagedialog .dialog-action-box button:focus, +messagedialog .dialog-action-box .linked:not(.vertical) > button:focus, .app-notification button:focus, popover.background.menu button:focus, +popover.background button.model:focus, .nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), button.flat:focus { + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + color: #eff1f5; +} + +.budgie-session-dialog .linked.horizontal > button:hover, +.budgie-polkit-dialog .linked.horizontal > button:hover, +.budgie-run-dialog .linked.horizontal > button:hover, .drop-shadow button:hover, .budgie-panel button:hover, .budgie-popover row button:hover, .budgie-settings-window buttonbox.inline-toolbar button:hover, #mate-menu button:hover, #MatePanelPopupWindow button:hover, popover.messagepopover .popover-action-area button:hover, tabbox > tab button:hover, placessidebar.sidebar row button.sidebar-button:hover, calendar.button:hover, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:hover, treeview.view header button button.circular:hover, row.activatable button.circular:hover, notebook > header > tabs > arrow:hover, modelbutton.flat:hover, +.menuitem.button.flat:hover, spinbutton.vertical button:hover, spinbutton:not(.vertical) button:hover, .nemo-window .toolbar button:hover, #buttonbox_frame button:hover, .xfce4-panel.background button:hover, .raven stackswitcher.linked > button:hover, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:hover, .lock-dialog button:hover, .mate-panel-menu-bar button:hover, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, layouttabbar button:hover, filechooser #pathbarbox > stack > box > button:hover, messagedialog .dialog-action-box button:hover, +messagedialog .dialog-action-box .linked:not(.vertical) > button:hover, .app-notification button:hover, popover.background.menu button:hover, +popover.background button.model:hover, .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), button.flat:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #eff1f5; +} + +.budgie-session-dialog .linked.horizontal > button:active, +.budgie-polkit-dialog .linked.horizontal > button:active, +.budgie-run-dialog .linked.horizontal > button:active, .drop-shadow button:active, .budgie-panel button:active, .budgie-popover row button:active, .budgie-settings-window buttonbox.inline-toolbar button:active, #mate-menu button:active, #MatePanelPopupWindow button:active, popover.messagepopover .popover-action-area button:active, tabbox > tab button:active, placessidebar.sidebar row button.sidebar-button:active, calendar.button:active, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:active, treeview.view header button button.circular:active, row.activatable button.circular:active, notebook > header > tabs > arrow:active, modelbutton.flat:active, +.menuitem.button.flat:active, spinbutton.vertical button:active, spinbutton:not(.vertical) button:active, .nemo-window .toolbar button:active, #buttonbox_frame button:active, .xfce4-panel.background button:active, .raven stackswitcher.linked > button:active, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:active, .lock-dialog button:active, .mate-panel-menu-bar button:active, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, layouttabbar button:active, filechooser #pathbarbox > stack > box > button:active, messagedialog .dialog-action-box button:active, +messagedialog .dialog-action-box .linked:not(.vertical) > button:active, .app-notification button:active, popover.background.menu button:active, +popover.background button.model:active, .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), button.flat:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #eff1f5; +} + +.budgie-session-dialog .linked.horizontal > button:disabled, +.budgie-polkit-dialog .linked.horizontal > button:disabled, +.budgie-run-dialog .linked.horizontal > button:disabled, .drop-shadow button:disabled, .budgie-panel button:disabled, .budgie-popover row button:disabled, .budgie-settings-window buttonbox.inline-toolbar button:disabled, #mate-menu button:disabled, #MatePanelPopupWindow button:disabled, popover.messagepopover .popover-action-area button:disabled, tabbox > tab button:disabled, placessidebar.sidebar row button.sidebar-button:disabled, calendar.button:disabled, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:disabled, treeview.view header button button.circular:disabled, row.activatable button.circular:disabled, notebook > header > tabs > arrow:disabled, modelbutton.flat:disabled, +.menuitem.button.flat:disabled, spinbutton.vertical button:disabled, spinbutton:not(.vertical) button:disabled, .nemo-window .toolbar button:disabled, #buttonbox_frame button:disabled, .xfce4-panel.background button:disabled, .raven stackswitcher.linked > button:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:disabled, .lock-dialog button:disabled, .mate-panel-menu-bar button:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, layouttabbar button:disabled, filechooser #pathbarbox > stack > box > button:disabled, messagedialog .dialog-action-box button:disabled, +messagedialog .dialog-action-box .linked:not(.vertical) > button:disabled, .app-notification button:disabled, popover.background.menu button:disabled, +popover.background button.model:disabled, .nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action), button.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .toolbar button:checked, #buttonbox_frame button:checked, .xfce4-panel.background button:checked, .raven stackswitcher.linked > button:checked, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked, .lock-dialog button:checked, .mate-panel-menu-bar button:checked, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, layouttabbar button:checked, filechooser #pathbarbox > stack > box > button:checked, messagedialog .dialog-action-box button:checked, +messagedialog .dialog-action-box .linked:not(.vertical) > button:checked, .app-notification button:checked, popover.background.menu button:checked, +popover.background button.model:checked, .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action), button.flat:checked, button.flat:checked:hover { + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +.nemo-window .toolbar button:checked:disabled, #buttonbox_frame button:checked:disabled, .xfce4-panel.background button:checked:disabled, .raven stackswitcher.linked > button:checked:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked:disabled, .lock-dialog button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, layouttabbar button:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, messagedialog .dialog-action-box button:checked:disabled, .app-notification button:checked:disabled, popover.background.menu button:checked:disabled, +popover.background button.model:checked:disabled, .nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(239, 241, 245, 0.5); +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child) { + margin: 0 4px; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + border-radius: 12px; +} + +button.osd { + min-width: 24px; + min-width: 24px; + padding: 5px; + background-color: #1e1e2e; + color: #eff1f5; +} + +button.osd:focus { + box-shadow: none; +} + +button.osd:hover { + background-color: #3d3e4c; + color: #eff1f5; +} + +button.osd:active { + background-color: #525360; + color: #eff1f5; +} + +button.osd:disabled { + opacity: 0; +} + +button.osd.image-button, button.osd.circular { + padding: 11px; +} + +button.osd.image-button > image, button.osd.circular > image { + padding: 0; +} + +button.suggested-action { + background-color: #1e66f5; + color: #eff1f5; + box-shadow: none; +} + +button.suggested-action:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(30, 102, 245, 0.2), 0 4px 3px 0 rgba(30, 102, 245, 0.14), 0 1px 6px 0 rgba(30, 102, 245, 0.12); +} + +button.suggested-action:checked { + background-color: #5d90f5; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(30, 102, 245, 0.3), 0 2px 3px -1px rgba(30, 102, 245, 0.24), 0 2px 5px 0 rgba(30, 102, 245, 0.12); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(30, 102, 245, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #1e66f5; +} + +button.suggested-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +button.suggested-action.flat:checked { + background-color: rgba(30, 102, 245, 0.3); +} + +button.destructive-action { + background-color: #d20f39; + color: #eff1f5; + box-shadow: none; +} + +button.destructive-action:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(210, 15, 57, 0.2), 0 4px 3px 0 rgba(210, 15, 57, 0.14), 0 1px 6px 0 rgba(210, 15, 57, 0.12); +} + +button.destructive-action:checked { + background-color: #db5371; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(210, 15, 57, 0.3), 0 2px 3px -1px rgba(210, 15, 57, 0.24), 0 2px 5px 0 rgba(210, 15, 57, 0.12); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(210, 15, 57, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #d20f39; +} + +button.destructive-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +button.destructive-action.flat:checked { + background-color: rgba(210, 15, 57, 0.3); +} + +.stack-switcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +.stack-switcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +.stack-switcher > button.needs-attention:checked > label, +.stack-switcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +.primary-toolbar button { + -gtk-icon-shadow: none; +} + +button.close, button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +stacksidebar.sidebar row.needs-attention > label, .stack-switcher > button.needs-attention > label, +.stack-switcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar.sidebar row.needs-attention > label:dir(rtl), .stack-switcher > button.needs-attention > label:dir(rtl), +.stack-switcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + +/********* + * Links * + *********/ +*:link, +link { + color: #8fcbe8; +} + +*:visited { + color: #8839ef; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #8fcbe8; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #8839ef; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton:not(.vertical) { + padding: 0; +} + +spinbutton:not(.vertical) entry { + min-width: 30px; + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +spinbutton:not(.vertical) button { + border: solid 6px transparent; +} + +spinbutton:not(.vertical) button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(239, 241, 245, 0.7); +} + +spinbutton:not(.vertical) button.up:dir(ltr), spinbutton:not(.vertical) button.down:dir(rtl) { + margin-left: -3px; +} + +spinbutton:not(.vertical) button.up:dir(rtl), spinbutton:not(.vertical) button.down:dir(ltr) { + margin-right: -3px; +} + +spinbutton.vertical { + padding: 0; +} + +spinbutton.vertical:disabled { + color: rgba(239, 241, 245, 0.5); +} + +spinbutton.vertical entry { + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical button { + padding: 0; + border: solid 6px transparent; +} + +spinbutton.vertical button:focus:not(:hover):not(:active) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(239, 241, 245, 0.7); +} + +spinbutton.vertical button.up { + margin: 0 3px; +} + +spinbutton.vertical button.down { + margin: 0 3px; +} + +treeview spinbutton:not(.vertical) { + min-height: 0; + border-style: none; + border-radius: 0; +} + +treeview spinbutton:not(.vertical) entry { + min-height: 0; + padding: 1px 2px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-radius: 0 9px 9px 0; + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #fab387; + box-shadow: inset 0 0 0 2px #fab387; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #eff1f5; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top), combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) { + background-color: transparent; + background-image: linear-gradient(to left, transparent 50%, rgba(239, 241, 245, 0.3) 50%); + padding-top: 1px; + background-size: 12px 1px; + background-repeat: repeat-x; + background-origin: content-box; + background-position: left top; + margin: 0 4px; +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +toolbar { + -gtkwidget-window-dragging: true; + padding: 2px 3px; + background-color: #1e1e2e; +} + +.osd toolbar { + background-color: transparent; +} + +frame.documents-dropdown, .app-notification, toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +frame.documents-dropdown:backdrop, .app-notification:backdrop, toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +frame.left.documents-dropdown, .left.app-notification, frame.right.documents-dropdown, .right.app-notification, frame.top.documents-dropdown, .top.app-notification, frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.left, toolbar.osd.right, toolbar.osd.top, toolbar.osd.bottom { + border-radius: 0; +} + +frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +toolbar.horizontal > separator { + margin: 2px; +} + +toolbar.vertical > separator { + margin: 2px; +} + +toolbar:not(.inline-toolbar):not(.osd) scale, +toolbar:not(.inline-toolbar):not(.osd) entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton, +toolbar:not(.inline-toolbar):not(.osd) button { + margin: 2px 1px; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:first-child) { + margin-left: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:last-child) { + margin-right: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) spinbutton entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton button { + margin: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) switch { + margin: 8px 2px; +} + +.toolbar { + background-color: #313244; +} + +frame .toolbar { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.inline-toolbar { + padding: 6px; + border-style: solid; + border-width: 0 1px 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +.frame .inline-toolbar { + border-width: 1px 0 0; + background-color: transparent; +} + +searchbar > revealer > box, +.location-bar { + padding: 6px; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; + background-clip: border-box; +} + +searchbar > revealer > box { + margin: -6px; +} + +/*************** + * Header bars * + ***************/ +.nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar .linked:not(.vertical) > button:not(.text-button), headerbar .linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + border-radius: 12px; +} + +.nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +.nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:not(.text-button), headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:focus:not(.text-button), headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:hover:not(.text-button), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:active:not(.text-button), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:disabled:not(.text-button), headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar button:backdrop:checked:not(.text-button), headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:checked:disabled:not(.text-button), headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar entry, .titlebar entry { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +.nemo-window .primary-toolbar entry:disabled, .titlebar entry:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar entry image, .titlebar entry image { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar entry image:hover, .titlebar entry image:hover, .nemo-window .primary-toolbar entry image:active, .titlebar entry image:active { + color: #eff1f5; +} + +.nemo-window .primary-toolbar entry image:disabled, .titlebar entry image:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.titlebar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 12px 12px 0 0; + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* @if $outline == 'false' { */ + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* } */ +} + +.titlebar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.titlebar:backdrop { + color: rgba(239, 241, 245, 0.7); +} + +.titlebar:backdrop:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.csd .titlebar:backdrop { + background-color: #1e1e2e; +} + +.titlebar .title { + padding: 0 12px; + font-weight: bold; +} + +.titlebar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +.titlebar .subtitle, +.titlebar .dim-label { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(239, 241, 245, 0.7); +} + +.titlebar .subtitle:backdrop, +.titlebar .dim-label:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +.titlebar .titlebar { + background-color: transparent; + box-shadow: none; +} + +.titlebar + separator, +.titlebar + separator.sidebar { + background-color: #1e1e2e; + background-image: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +.titlebar + separator:backdrop, +.titlebar + separator.sidebar:backdrop { + background-color: #1e1e2e; +} + +.titlebar.selection-mode + separator, .titlebar.selection-mode + separator.sidebar, .selection-mode .titlebar + separator, .selection-mode .titlebar + separator.sidebar { + background-color: #89b4fa; +} + +.titlebar.selection-mode + separator:backdrop, .titlebar.selection-mode + separator.sidebar:backdrop, .selection-mode .titlebar + separator:backdrop, .selection-mode .titlebar + separator.sidebar:backdrop { + background-color: #89b4fa; +} + +.background.csd.unified .titlebar + separator, .background.csd.unified .titlebar + separator.sidebar { + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.titlebar .linked:not(.vertical) > entry { + border-radius: 12px; + margin-left: 3px; + margin-right: 3px; +} + +.titlebar button.suggested-action:disabled, +.titlebar button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +.titlebar .path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; + padding-left: 5px; + padding-right: 5px; +} + +.titlebar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + animation: ripple-on-headerbar 225ms cubic-bezier(0, 0, 0.2, 1); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode:backdrop { + color: rgba(30, 30, 46, 0.6); + background-color: #a6c7fb; +} + +.titlebar.selection-mode .subtitle:link { + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):disabled { + color: rgba(30, 30, 46, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked { + color: rgba(30, 30, 46, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked:disabled { + color: rgba(30, 30, 46, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:not(.titlebutton) { + color: rgba(30, 30, 46, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:disabled { + color: rgba(30, 30, 46, 0.3); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked { + color: rgba(30, 30, 46, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked:disabled { + color: rgba(30, 30, 46, 0.3); +} + +.titlebar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +.titlebar.selection-mode .selection-menu arrow { + -gtkarrow-arrow-scaling: 1; +} + +.titlebar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +.tiled .titlebar, .tiled-top .titlebar, .tiled-right .titlebar, .tiled-bottom .titlebar, .tiled-left .titlebar, .maximized .titlebar, .fullscreen .titlebar { + border-radius: 0; +} + +.titlebar.default-decoration { + min-height: 24px; + padding: 6px 12px; + border-radius: 12px 12px 0 0; + border: none; + background-color: #1e1e2e; + background-image: none; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +.titlebar.default-decoration:backdrop { + background-color: #1e1e2e; +} + +.tiled .titlebar.default-decoration, .maximized .titlebar.default-decoration, .fullscreen .titlebar.default-decoration { + box-shadow: none; + border-radius: 0; +} + +.titlebar.default-decoration button.titlebutton { + min-height: 24px; + min-width: 24px; + margin: 0; + padding: 0; +} + +.background.csd .titlebar.default-decoration { + padding: 6px; + box-shadow: none; +} + +.background:not(.csd) .titlebar.default-decoration button.titlebutton:active { + background-size: 1000% 1000%; +} + +.solid-csd .titlebar:dir(rtl), .solid-csd .titlebar:dir(ltr) { + border-radius: 0; + box-shadow: none; +} + +headerbar { + min-height: 46px; + padding: 0 6px; +} + +box.vertical headerbar { + background-color: #1e1e2e; +} + +headerbar entry, +headerbar spinbutton, +headerbar button, +headerbar stackswitcher { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar button, +headerbar button.image-button { + border-radius: 12px; +} + +headerbar > box.left, +headerbar > box.right { + padding: 0 4px; +} + +headerbar separator.titlebutton, +headerbar separator.sidebar { + margin-top: 11.5px; + margin-bottom: 11.5px; + background-color: transparent; +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar spinbutton button { + margin-top: 0; + margin-bottom: 0; +} + +headerbar .entry-tag, headerbar .photos-entry-tag, headerbar .documents-entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar.windowhandle viewswitcher { + border-radius: 0 0 12px 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) { + border-radius: 9px; + margin: 6px 3px; + min-width: 120px; + padding: 0; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) > stack > box { + padding: 0 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +):focus { + box-shadow: none; +} + +headerbar.windowhandle > button.popup label, +headerbar.windowhandle > button.popup image { + min-height: 0; +} + +headerbar.windowhandle viewswitchertitle > squeezer { + margin-top: 0; + margin-bottom: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher { + margin: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher > box.horizontal > button.radio { + margin: 0; + padding: 0; + border-radius: 0; +} + +/************ + * Pathbars * + ************/ +.caja-pathbar button, +.path-bar.linked:not(.vertical) > button { + padding-left: 5px; + padding-right: 5px; + border-radius: 6px; + margin-left: 1px; + margin-right: 1px; + background-color: alpha(currentColor, 0.08); +} + +.caja-pathbar button:disabled, +.path-bar.linked:not(.vertical) > button:disabled { + background-color: alpha(currentColor, 0.05); +} + +.caja-pathbar button:first-child, +.path-bar.linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.caja-pathbar button:last-child, +.path-bar.linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.caja-pathbar button:checked, +.path-bar.linked:not(.vertical) > button:checked { + background-color: alpha(currentColor, 0.16); + color: #eff1f5; +} + +.caja-pathbar button label, +.caja-pathbar button image, +.path-bar.linked:not(.vertical) > button label, +.path-bar.linked:not(.vertical) > button image { + margin-left: 3px; + margin-right: 3px; +} + +.caja-pathbar button.slider-button, +.path-bar.linked:not(.vertical) > button.slider-button { + padding-left: 4px; + padding-right: 4px; +} + +/************** + * Tree Views * + **************/ +treeview.view { + border-left-color: rgba(239, 241, 245, 0.12); + border-top-color: rgba(239, 241, 245, 0.12); +} + +* { + -gtktreeview-horizontal-separator: 4; + -gtktreeview-grid-line-width: 1; + -gtktreeview-grid-line-pattern: ''; + -gtktreeview-tree-line-width: 1; + -gtktreeview-tree-line-pattern: ''; + -gtktreeview-expander-size: 16; +} + +.csd +treeview.view:not(:selected):not(:hover):not(.progressbar):not(.expander):not( +.trough +):not(.separator) { + background-color: transparent; +} + +treeview.view.separator { + min-height: 6px; + color: rgba(239, 241, 245, 0.12); +} + +treeview.view:drop(active) { + border-style: solid none; + border-width: 9999px; + border-color: alpha(currentColor, 0.08); +} + +treeview.view:drop(active).after { + border-top-style: none; +} + +treeview.view:drop(active).before { + border-bottom-style: none; +} + +treeview.view.expander { + color: rgba(239, 241, 245, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); +} + +treeview.view.expander:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view.expander:checked { + -gtk-icon-transform: unset; +} + +treeview.view.expander:hover, treeview.view.expander:active { + color: #eff1f5; +} + +treeview.view.expander:disabled { + color: rgba(239, 241, 245, 0.32); +} + +treeview.view.expander:selected { + color: rgba(30, 30, 46, 0.6); +} + +treeview.view.expander:selected:hover, treeview.view.expander:selected:active { + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.expander:selected:disabled { + color: rgba(30, 30, 46, 0.3); +} + +treeview.view.progressbar { + border: none; + box-shadow: none; + background-color: #89b4fa; + background-image: none; + border-radius: 9999px; + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.progressbar:selected, treeview.view.progressbar:selected:hover, treeview.view.progressbar:selected:focus { + box-shadow: none; + background-color: #98bdf9; + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.progressbar:selected:backdrop, treeview.view.progressbar:selected:hover:backdrop, treeview.view.progressbar:selected:focus:backdrop { + color: rgba(30, 30, 46, 0.87); +} + +treeview.view.progressbar:backdrop, treeview.view.progressbar:selected:backdrop { + background-color: rgba(239, 241, 245, 0.3); +} + +treeview.view.trough { + border: none; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); + background-image: none; + border-radius: 9999px; + padding: 0; + margin: 0; +} + +treeview.view.trough:selected, treeview.view.trough:selected:hover, treeview.view.trough:selected:focus { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); +} + +treeview.view.trough:backdrop, treeview.view.trough:selected:backdrop { + background-color: rgba(239, 241, 245, 0.12); +} + +treeview.view header button { + padding: 2px 6px; + border: none; + border-right: 1px solid transparent; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; + background-clip: border-box; + border-image: linear-gradient(to bottom, transparent 20%, rgba(239, 241, 245, 0.12) 20%, rgba(239, 241, 245, 0.12) 80%, transparent 80%) 0 1 0 0/0 1px 0 0 stretch; +} + +treeview.view header button:not(:focus):not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +treeview.view header button, treeview.view header button:disabled { + background-color: #313244; +} + +treeview.view header button:last-child { + border-right: none; + border-image: none; +} + +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #313244; + background-clip: border-box; + color: #89b4fa; +} + +treeview.view acceleditor > label { + background-color: #89b4fa; +} + +/********* + * Menus * + *********/ +menubar, +.menubar { + -gtkwidget-window-dragging: true; + padding: 0; + background-color: #1e1e2e; + color: #eff1f5; + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +menubar:backdrop, +.menubar:backdrop { + color: rgba(239, 241, 245, 0.7); + background-color: #1e1e2e; +} + +.csd menubar, .csd .menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > menuitem, +.menubar > menuitem { + transition: none; + min-height: 20px; + padding: 4px 8px; + color: rgba(239, 241, 245, 0.7); + border-radius: 12px; +} + +menubar > menuitem:hover, +.menubar > menuitem:hover { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +menubar > menuitem:backdrop, +.menubar > menuitem:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +menubar > menuitem:disabled, +.menubar > menuitem:disabled { + color: rgba(239, 241, 245, 0.32); +} + +menubar > menuitem label:disabled, +.menubar > menuitem label:disabled { + color: inherit; +} + +menubar > menuitem > window.popup.background > menu menuitem, +.menubar > menuitem > window.popup.background > menu menuitem { + transition: none; +} + +.background.popup { + background-color: transparent; +} + +menu { + margin: 6px; + padding: 6px; + background-color: #232634; + background-clip: border-box; + border-radius: 12px; + border: 2px solid #89b4fa; +} + +.csd menu { + border: none; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.1); +} + +menu menuitem { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + min-width: 40px; + padding: 4px 8px; + color: #eff1f5; + font: initial; + text-shadow: none; + border-radius: 12px; +} + +menu menuitem:hover { + background-color: alpha(currentColor, 0.08); +} + +menu menuitem:active { + background-color: alpha(currentColor, 0.12); +} + +menu menuitem:disabled { + color: rgba(239, 241, 245, 0.5); +} + +menu menuitem accelerator { + color: rgba(239, 241, 245, 0.7); +} + +menu menuitem:disabled accelerator { + color: rgba(239, 241, 245, 0.32); +} + +menu menuitem arrow { + min-height: 16px; + min-width: 16px; +} + +menu menuitem arrow:dir(ltr) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + margin-left: 8px; +} + +menu menuitem arrow:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); + margin-right: 8px; +} + +menu menuitem label:dir(rtl), menu menuitem label:dir(ltr) { + color: inherit; +} + +menu .view:selected { + background-color: #3d404f; +} + +menu > arrow { + min-height: 16px; + min-width: 16px; + padding: 4px; + background-color: #292c3c; + color: rgba(239, 241, 245, 0.7); +} + +menu > arrow.top { + margin-top: 0; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menu > arrow.bottom { + margin-top: 8px; + margin-bottom: -12px; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menu > arrow:hover { + background-image: image(alpha(currentColor, 0.08)); + color: #eff1f5; +} + +menu > arrow:disabled { + border-color: transparent; + background-color: transparent; + color: transparent; +} + +menu separator { + margin: 4px 0; +} + +/************ + * Popovers * + ************/ +popover.background { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 0; + background-color: #232634; + border-radius: 12px; +} + +popover.background, .csd popover.background { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +popover.background > stack { + margin: 0; +} + +popover.background > toolbar { + margin: 0; +} + +popover.background > list, +popover.background > .view, +popover.background > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover.background > scrolledwindow > viewport.frame > list { + background-color: transparent; + padding: 6px; +} + +popover.background > scrolledwindow > viewport.frame > list > row { + border-radius: 12px; + padding: 6px; +} + +popover.background .view:not(:selected), +popover.background toolbar { + background-color: #232634; +} + +popover.background button, +popover.background entry, +popover.background combobox { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio) { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):first-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):last-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.background.menu button, +popover.background button.model { + min-height: 32px; + padding: 0 8px; + border-radius: 12px; +} + +popover.background separator { + margin: 3px 0; + background-color: transparent; +} + +popover.background list separator { + margin: 0; +} + +modelbutton.flat, +.menuitem.button.flat { + min-height: 28px; + padding: 0 8px; + border-radius: 12px; + color: #eff1f5; +} + +modelbutton.flat arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +modelbutton.flat arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +/************* + * Notebooks * + *************/ +tabbox > tab, notebook > header tab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + padding: 3px 12px; + border: none; + outline: none; + background-clip: padding-box; + color: rgba(239, 241, 245, 0.7); + font-weight: 500; + border-radius: 9px; +} + +tabbox > tab:hover, notebook > header tab:hover { + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +tabbox > tab:disabled, notebook > header tab:disabled { + color: rgba(239, 241, 245, 0.32); +} + +tabbox > tab:checked, notebook > header tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbox > tab:checked:disabled, notebook > header tab:checked:disabled { + color: rgba(239, 241, 245, 0.5); +} + +notebook { + background-color: rgba(239, 241, 245, 0.04); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: transparent; +} + +notebook.frame { + border-radius: 15px; +} + +notebook.frame scrolledwindow.frame { + border: none; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(239, 241, 245, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header tab > box:drop(active) { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +notebook > header tab button.flat:last-child, +notebook > header tab button.close-button:last-child { + margin-left: 6px; + margin-right: -6px; +} + +notebook > header tab button.flat:first-child, +notebook > header tab button.close-button:first-child { + margin-left: -6px; + margin-right: 6px; +} + +notebook > header.top tabs > tab + tab, notebook > header.bottom tabs > tab + tab { + margin-left: 3px; +} + +notebook > header.top tabs:not(:only-child):first-child, notebook > header.bottom tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top tabs:not(:only-child):last-child, notebook > header.bottom tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top tabs tab.reorderable-page, notebook > header.bottom tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left tabs > tab + tab, notebook > header.right tabs > tab + tab { + margin-top: 3px; +} + +notebook > header.left tabs:not(:only-child):first-child, notebook > header.right tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left tabs:not(:only-child):last-child, notebook > header.right tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left tabs tab.reorderable-page, notebook > header.right tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > button.image-button { + min-height: 24px; + min-width: 24px; + padding: 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); +} + +* { + -gtkscrollbar-has-backward-stepper: false; + -gtkscrollbar-has-forward-stepper: false; +} + +scrollbar, +scrollbar button { + border: none; + min-width: 0; + min-height: 0; + padding: 0; + border-radius: 0; + background-color: transparent; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 12px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(239, 241, 245, 0.5); +} + +scrollbar slider:hover { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar slider:active { + background-color: rgba(239, 241, 245, 0.7); +} + +scrollbar slider:disabled { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar.fine-tune slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.fine-tune.horizontal slider { + border-width: 5px 4px; +} + +scrollbar.fine-tune.vertical slider { + border-width: 4px 5px; +} + +scrollbar.overlay-indicator trough { + background-color: rgba(239, 241, 245, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal slider { + min-width: 40px; +} + +scrollbar.vertical slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border: none; + border-radius: 9999px; + background-color: rgba(239, 241, 245, 0.5); + background-clip: padding-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #89b4fa; +} + +switch:disabled { + opacity: 0.5; +} + +switch slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #eff1f5; + border: none; + color: transparent; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12); +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; +} + +checkbutton.text-button, +radiobutton.text-button { + padding: 2px; +} + +checkbutton.text-button label:not(:only-child), +radiobutton.text-button label:not(:only-child) { + margin: 0 4px; +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate), +actionbar > revealer > box radio:not(:checked):not(:indeterminate) { + background-color: rgba(30, 30, 46, 0.12); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):hover, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):hover { + box-shadow: 0 0 0 6px rgba(30, 30, 46, 0.04); + background-color: rgba(30, 30, 46, 0.15); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):active, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):active { + box-shadow: 0 0 0 6px rgba(30, 30, 46, 0.12); + background-color: rgba(30, 30, 46, 0.2); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):disabled, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):disabled { + background-color: rgba(30, 30, 46, 0.04); +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + color: transparent; + background-color: rgba(239, 241, 245, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.04); + background-color: rgba(239, 241, 245, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(239, 241, 245, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(30, 30, 46, 0.6); + background-color: #89b4fa; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.15); + background-color: #bad3fc; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.2); + background-color: #89b4fa; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(30, 30, 46, 0.3); + background-color: rgba(137, 180, 250, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem radio { + transition: none; + margin: 0; + padding: 0; +} + +menu menuitem check:dir(ltr), menu menuitem radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +menu menuitem check:dir(rtl), menu menuitem radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem check:hover, menu menuitem check:disabled, menu menuitem check:checked:hover, menu menuitem check:indeterminate:hover, menu menuitem radio, menu menuitem radio:hover, menu menuitem radio:disabled, menu menuitem radio:checked:hover, menu menuitem radio:indeterminate:hover { + box-shadow: none; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic@2.svg"))); +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check, +menu menuitem check { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > checkbutton > check:checked, +menu menuitem check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check:indeterminate, +menu menuitem check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio, +menu menuitem radio { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > radiobutton > radio:checked, +menu menuitem radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio:indeterminate, +menu menuitem radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +check:not(:checked):indeterminate:active, +radio:not(:checked):indeterminate:active { + -gtk-icon-transform: scaleX(-1); +} + +treeview.view radio, +treeview.view check { + padding: 0; + margin: 0; + background-color: rgba(239, 241, 245, 0.12); +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view radio:selected:not(:disabled):not(:checked):not(:indeterminate), +treeview.view check:selected:not(:disabled):not(:checked):not(:indeterminate) { + background-color: rgba(30, 30, 46, 0.12); +} + +treeview.view radio:checked, treeview.view radio:indeterminate, +treeview.view check:checked, +treeview.view check:indeterminate { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + background-image: none; +} + +.view.content-view.check:not(list), +.content-view .tile check:not(list) { + min-height: 40px; + min-width: 40px; + margin: 0; + padding: 0; + border-radius: 9999px; +} + +.view.content-view.check:not(list):not(:checked), +.content-view .tile check:not(list):not(:checked) { + background-image: image(rgba(239, 241, 245, 0.25)); +} + +.view.content-view.check:not(list):hover, .view.content-view.check:not(list):checked, +.content-view .tile check:not(list):hover, +.content-view .tile check:not(list):checked { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1); +} + +.view.content-view.check:not(list):checked, +.content-view .tile check:not(list):checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale slider { + min-height: 18px; + min-width: 18px; + margin: -8px; +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune slider { + margin: -7px; +} + +scale trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(239, 241, 245, 0.3); +} + +scale trough:disabled { + background-color: rgba(239, 241, 245, 0.12); +} + +scale highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#89b4fa); +} + +scale highlight:disabled { + background-color: #1e1e2e; + background-image: image(rgba(239, 241, 245, 0.32)); +} + +scale fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.3); +} + +scale fill:disabled { + background-color: transparent; +} + +scale slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #89b4fa; + background-color: #313244; + box-shadow: inset 0 0 0 2px #89b4fa; +} + +scale slider:hover { + box-shadow: inset 0 0 0 2px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale slider:active { + box-shadow: inset 0 0 0 4px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale slider:disabled { + box-shadow: inset 0 0 0 2px rgba(239, 241, 245, 0.32); +} + +scale marks, +scale value { + color: rgba(239, 241, 245, 0.7); +} + +scale indicator { + background-color: rgba(239, 241, 245, 0.3); + color: transparent; +} + +scale.horizontal marks.top { + margin-bottom: 7px; + margin-top: -15px; +} + +scale.horizontal.fine-tune marks.top { + margin-bottom: 6px; + margin-top: -14px; +} + +scale.horizontal marks.bottom { + margin-top: 7px; + margin-bottom: -15px; +} + +scale.horizontal.fine-tune marks.bottom { + margin-top: 6px; + margin-bottom: -14px; +} + +scale.vertical marks.top { + margin-right: 7px; + margin-left: -15px; +} + +scale.vertical.fine-tune marks.top { + margin-right: 6px; + margin-left: -14px; +} + +scale.vertical marks.bottom { + margin-left: 7px; + margin-right: -15px; +} + +scale.vertical.fine-tune marks.bottom { + margin-left: 6px; + margin-right: -14px; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.horizontal.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-before:not(.marks-after) slider, scale.horizontal.marks-before:not(.marks-after) slider:hover, scale.horizontal.marks-before:not(.marks-after) slider:active, scale.horizontal.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-disabled-dark.svg"), url("assets/scale-horz-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-after:not(.marks-before) slider, scale.horizontal.marks-after:not(.marks-before) slider:hover, scale.horizontal.marks-after:not(.marks-before) slider:active, scale.horizontal.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-disabled-dark.svg"), url("assets/scale-horz-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-before:not(.marks-after) slider, scale.vertical.marks-before:not(.marks-after) slider:hover, scale.vertical.marks-before:not(.marks-after) slider:active, scale.vertical.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-disabled-dark.svg"), url("assets/scale-vert-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-after:not(.marks-before) slider, scale.vertical.marks-after:not(.marks-before) slider:hover, scale.vertical.marks-after:not(.marks-before) slider:active, scale.vertical.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-disabled-dark.svg"), url("assets/scale-vert-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal slider:dir(ltr), scale.color.horizontal slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(239, 241, 245, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #89b4fa; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #89b4fa; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #df8e1d; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #89b4fa; +} + +levelbar block.full { + background-color: #40a02b; +} + +levelbar block.empty { + background-color: rgba(239, 241, 245, 0.12); +} + +/**************** + * Print dialog * +*****************/ +printdialog paper { + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; + color: #eff1f5; +} + +printdialog .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame > border, .frame { + margin: 0; + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0; + box-shadow: none; +} + +.frame.view { + border-radius: 12px; +} + +.frame.flat { + border-style: none; +} + +frame.flat > border, frame > border.flat, statusbar frame > border { + border: none; +} + +actionbar > revealer > box { + margin: 6px 0 0 0; + padding: 6px; + border: none; + color: #eff1f5; + background-color: #1e1e2e; + border-radius: 0 0 12px 12px; +} + +actionbar > revealer > box button { + border-radius: 6px; +} + +actionbar > revealer > box button.combo:only-child { + border-radius: 6px; + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.04); +} + +actionbar > revealer > box button.combo:only-child:hover, actionbar > revealer > box button.combo:only-child:active { + color: #89b4fa; +} + +actionbar > revealer > box button.combo:only-child:disabled { + color: #89b4fa; +} + +actionbar > revealer > box stackswitcher { + background-color: rgba(30, 30, 46, 0.04); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + color: rgba(30, 30, 46, 0.6); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover, actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: rgba(30, 30, 46, 0.87); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + background-color: #313244; + color: #eff1f5; +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked:hover { + background-color: #313244; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +overshoot.top { + background-image: -gtk-gradient(radial, center top, 0, center top, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, center top, 0, center top, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center top; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.bottom { + background-image: -gtk-gradient(radial, center bottom, 0, center bottom, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, center bottom, 0, center bottom, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.left { + background-image: -gtk-gradient(radial, left center, 0, left center, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, left center, 0, left center, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: left center; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.right { + background-image: -gtk-gradient(radial, right center, 0, right center, 0.5, to(rgba(239, 241, 245, 0.12)), to(rgba(239, 241, 245, 0))), -gtk-gradient(radial, right center, 0, right center, 0.6, from(rgba(239, 241, 245, 0.07)), to(rgba(239, 241, 245, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: right center; + background-color: transparent; + border: none; + box-shadow: none; +} + +junction { + border-style: solid none none solid; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +junction:dir(rtl) { + border-style: solid solid none none; +} + +separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +preferences stacksidebar.sidebar list separator, placessidebar.sidebar list > separator, stacksidebar.sidebar + separator.vertical, +stacksidebar.sidebar separator.horizontal, button.font separator, button.file separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +/********* + * Lists * + *********/ +window.background.csd stack stack stack frame > list, +window.background.csd > stack > stack > box > frame > list, +window.background.csd > stack > stack > box > box > frame > list, +window.background.csd > stack > box > stack > box > frame > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > list, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list, window.background.csd > stack > list, +window.background.csd > stack > scrolledwindow > viewport > box > list, +window.background.csd > box > stack > scrolledwindow > viewport > box > list, preferencesgroup list, +.geary-accounts-editor-pane list, window.background.csd.unified > deck > deck > deck list, hdyleaflet list.view, +hdyleaflet list.frame, +leaflet list.view, +leaflet list.frame, +box.horizontal > stack.background list.view, +box.horizontal > stack.background list.frame, hdyleaflet stack.background scrolledwindow > viewport list, +hdyleaflet overlay scrolledwindow > viewport list, +leaflet stack.background scrolledwindow > viewport list, +leaflet overlay scrolledwindow > viewport list, +box.horizontal > stack.background stack.background scrolledwindow > viewport list, +box.horizontal > stack.background overlay scrolledwindow > viewport list, hdyleaflet frame:not(.view) list:not(.contacts-contact-list), +leaflet frame:not(.view) list:not(.contacts-contact-list), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list), list.tweak-group list, list.content:not(.conversation-listbox) { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.csd stack stack stack frame > list > separator, +window.background.csd > stack > stack > box > frame > list > separator, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list > separator, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list > separator, window.background.csd > stack > list > separator, +window.background.csd > stack > scrolledwindow > viewport > box > list > separator, preferencesgroup list > separator, +.geary-accounts-editor-pane list > separator, window.background.csd.unified > deck > deck > deck list > separator, hdyleaflet list.view > separator, +hdyleaflet list.frame > separator, +leaflet list.view > separator, +leaflet list.frame > separator, +box.horizontal > stack.background list.view > separator, +box.horizontal > stack.background list.frame > separator, hdyleaflet stack.background scrolledwindow > viewport list > separator, +hdyleaflet overlay scrolledwindow > viewport list > separator, +leaflet stack.background scrolledwindow > viewport list > separator, +leaflet overlay scrolledwindow > viewport list > separator, +box.horizontal > stack.background stack.background scrolledwindow > viewport list > separator, +box.horizontal > stack.background overlay scrolledwindow > viewport list > separator, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +leaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) > separator, list.tweak-group list > separator, list.content:not(.conversation-listbox) > separator { + background: none; + min-height: 0; +} + +window.background.csd stack stack stack frame > list row, +window.background.csd > stack > stack > box > frame > list row, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list row, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list row, window.background.csd > stack > list row, +window.background.csd > stack > scrolledwindow > viewport > box > list row, preferencesgroup list row, +.geary-accounts-editor-pane list row, window.background.csd.unified > deck > deck > deck list row, hdyleaflet list.view row, +hdyleaflet list.frame row, +leaflet list.view row, +leaflet list.frame row, +box.horizontal > stack.background list.view row, +box.horizontal > stack.background list.frame row, hdyleaflet stack.background scrolledwindow > viewport list row, +hdyleaflet overlay scrolledwindow > viewport list row, +leaflet stack.background scrolledwindow > viewport list row, +leaflet overlay scrolledwindow > viewport list row, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row, +box.horizontal > stack.background overlay scrolledwindow > viewport list row, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row, +leaflet frame:not(.view) list:not(.contacts-contact-list) row, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row, list.tweak-group list > row, list.content:not(.conversation-listbox) > row { + border-radius: 0; +} + +window.background.csd stack stack stack frame > list row:not(:first-child), window.background.csd > stack > list row:not(:first-child), preferencesgroup list row:not(:first-child), +.geary-accounts-editor-pane list row:not(:first-child), window.background.csd.unified > deck > deck > deck list row:not(:first-child), hdyleaflet list.view row:not(:first-child), +hdyleaflet list.frame row:not(:first-child), +leaflet list.view row:not(:first-child), +leaflet list.frame row:not(:first-child), +box.horizontal > stack.background list.view row:not(:first-child), +box.horizontal > stack.background list.frame row:not(:first-child), hdyleaflet stack.background scrolledwindow > viewport list row:not(:first-child), +hdyleaflet overlay scrolledwindow > viewport list row:not(:first-child), +leaflet stack.background scrolledwindow > viewport list row:not(:first-child), +leaflet overlay scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background overlay scrolledwindow > viewport list row:not(:first-child), hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +leaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), list.tweak-group list > row:not(:first-child), list.content:not(.conversation-listbox) > row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +window.background.csd stack stack stack frame > list row:first-child, window.background.csd > stack > list row:first-child, preferencesgroup list row:first-child, +.geary-accounts-editor-pane list row:first-child, window.background.csd.unified > deck > deck > deck list row:first-child, hdyleaflet list.view row:first-child, +hdyleaflet list.frame row:first-child, +leaflet list.view row:first-child, +leaflet list.frame row:first-child, +box.horizontal > stack.background list.view row:first-child, +box.horizontal > stack.background list.frame row:first-child, hdyleaflet stack.background scrolledwindow > viewport list row:first-child, +hdyleaflet overlay scrolledwindow > viewport list row:first-child, +leaflet stack.background scrolledwindow > viewport list row:first-child, +leaflet overlay scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:first-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:first-child, list.tweak-group list > row:first-child, list.content:not(.conversation-listbox) > row:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:last-child, window.background.csd > stack > list row:last-child, preferencesgroup list row:last-child, +.geary-accounts-editor-pane list row:last-child, window.background.csd.unified > deck > deck > deck list row:last-child, hdyleaflet list.view row:last-child, +hdyleaflet list.frame row:last-child, +leaflet list.view row:last-child, +leaflet list.frame row:last-child, +box.horizontal > stack.background list.view row:last-child, +box.horizontal > stack.background list.frame row:last-child, hdyleaflet stack.background scrolledwindow > viewport list row:last-child, +hdyleaflet overlay scrolledwindow > viewport list row:last-child, +leaflet stack.background scrolledwindow > viewport list row:last-child, +leaflet overlay scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:last-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:last-child, list.tweak-group list > row:last-child, list.content:not(.conversation-listbox) > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:only-child, window.background.csd > stack > list row:only-child, preferencesgroup list row:only-child, +.geary-accounts-editor-pane list row:only-child, window.background.csd.unified > deck > deck > deck list row:only-child, hdyleaflet list.view row:only-child, +hdyleaflet list.frame row:only-child, +leaflet list.view row:only-child, +leaflet list.frame row:only-child, +box.horizontal > stack.background list.view row:only-child, +box.horizontal > stack.background list.frame row:only-child, hdyleaflet stack.background scrolledwindow > viewport list row:only-child, +hdyleaflet overlay scrolledwindow > viewport list row:only-child, +leaflet stack.background scrolledwindow > viewport list row:only-child, +leaflet overlay scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:only-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:only-child, list.tweak-group list > row:only-child, list.content:not(.conversation-listbox) > row:only-child { + border-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:focus, window.background.csd > stack > list row:focus, preferencesgroup list row:focus, +.geary-accounts-editor-pane list row:focus, window.background.csd.unified > deck > deck > deck list row:focus, hdyleaflet list.view row:focus, +hdyleaflet list.frame row:focus, +leaflet list.view row:focus, +leaflet list.frame row:focus, +box.horizontal > stack.background list.view row:focus, +box.horizontal > stack.background list.frame row:focus, hdyleaflet stack.background scrolledwindow > viewport list row:focus, +hdyleaflet overlay scrolledwindow > viewport list row:focus, +leaflet stack.background scrolledwindow > viewport list row:focus, +leaflet overlay scrolledwindow > viewport list row:focus, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:focus, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:focus, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:focus, list.tweak-group list > row:focus, list.content:not(.conversation-listbox) > row:focus { + box-shadow: inset 0 0 0 1000px alpha(currentColor, 0.05); +} + +list { + border-color: rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); +} + +list row { + padding: 6px; + background-clip: padding-box; +} + +list.navigation-sidebar { + padding: 3px; +} + +list.navigation-sidebar > row { + border-radius: 12px; +} + +paned scrolledwindow > viewport.frame > list { + background-color: transparent; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable, treeview.view header button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:focus, treeview.view header button:focus, row.activatable:focus { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:hover, treeview.view header button:hover, row.activatable:hover { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.has-open-popup.activatable, treeview.view header button.has-open-popup, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:active, treeview.view header button:active, row.activatable.has-open-popup, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; +} + +row:selected { + color: inherit; + background-color: alpha(currentColor, 0.06); +} + +row:selected image, +row:selected label { + color: #eff1f5; +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled image, +row:selected:disabled label { + color: rgba(239, 241, 245, 0.5); +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 8px; + padding: 6px 15px; +} + +.app-notification button.flat:last-child { + margin-right: -9px; +} + +.app-notification button.text-button:not(:disabled) { + color: #89b4fa; +} + +.app-notification.frame, +.app-notification border { + border-style: none; +} + +/************* + * Expanders * + *************/ +expander title > arrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); + color: rgba(239, 241, 245, 0.7); +} + +expander title > arrow:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +expander title > arrow:checked { + -gtk-icon-transform: unset; +} + +expander title > arrow:hover, expander title > arrow:active { + color: #eff1f5; +} + +expander title > arrow:disabled { + color: rgba(239, 241, 245, 0.32); +} + +/************ + * Calendar * + ************/ +calendar { + padding: 1px; + border: 1px solid rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +calendar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +calendar:selected { + border-radius: 13px; +} + +calendar.header { + border-style: none none solid; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; +} + +calendar.highlight { + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +calendar:indeterminate { + color: rgba(239, 241, 245, 0.32); +} + +/*********** + * Dialogs * + ***********/ +messagedialog.background { + background-color: #1e1e2e; +} + +messagedialog.background .titlebar { + min-height: 12px; +} + +messagedialog.background .titlebar, messagedialog.background .titlebar:backdrop { + background-color: #1e1e2e; +} + +messagedialog.background.csd { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +messagedialog .titlebar, messagedialog.background.csd .titlebar { + border: none; + /* box-shadow: inset 0 1px highlight($surface); */ +} + +messagedialog .dialog-action-box { + margin-top: -6px; +} + +messagedialog .dialog-action-box button, messagedialog .dialog-action-box button:first-child, messagedialog .dialog-action-box button:last-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button, +messagedialog .dialog-action-box .linked:not(.vertical) > button:first-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button:last-child { + border-radius: 12px; +} + +messagedialog .dialog-action-box button:not(:last-child), +messagedialog .dialog-action-box .linked:not(.vertical) > button:not(:last-child) { + margin-right: 6px; +} + +messagedialog .dialog-action-box button.suggested-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.suggested-action:not(:disabled) { + color: #1e66f5; +} + +messagedialog .dialog-action-box button.destructive-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.destructive-action:not(:disabled) { + color: #d20f39; +} + +.csd filechooser { + background-color: #1e1e2e; + border-radius: 0 0 12px 12px; +} + +filechooser .dialog-action-box { + border-top: 1px solid transparent; +} + +filechooser treeview.view header > button { + background-color: #181825; +} + +filechooser #pathbarbox { + background-color: #181825; + border-radius: 12px 12px 0 0; + margin: 0 4px; +} + +filechooser stack.view { + background-color: transparent; + padding: 0 4px; +} + +filechooser stack.view scrolledwindow { + background-color: #181825; + border-radius: 0 0 12px 12px; +} + +filechooser stack.view scrolledwindow list { + background-color: transparent; +} + +filechooser stack.view > placesview { + background-color: transparent; + padding: 4px; +} + +filechooser stack.view frame > border { + border: none; +} + +.csd filechooser placessidebar { + background: none; + border-bottom-left-radius: 12px; +} + +filechooser paned > separator { + background: none; +} + +filechooser paned box.vertical { + background-color: #181825; + border-radius: 12px; + margin: 0 6px 0 1px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; +} + +stacksidebar.sidebar:dir(ltr) list, stacksidebar.sidebar.left list, stacksidebar.sidebar.left:dir(rtl) list, .sidebar:not(separator):dir(ltr), .sidebar:not(separator).left { + border-right: 1px solid rgba(239, 241, 245, 0.12); + border-left-style: none; +} + +stacksidebar.sidebar:dir(rtl) list, stacksidebar.sidebar.right list, .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { + border-left: 1px solid rgba(239, 241, 245, 0.12); + border-right-style: none; +} + +.sidebar list { + background-color: transparent; +} + +paned .sidebar.left, paned .sidebar.right, paned .sidebar.left:dir(rtl), paned .sidebar:dir(rtl), paned .sidebar:dir(ltr), paned .sidebar { + border-style: none; +} + +stacksidebar.sidebar list { + padding: 3px; + background-color: #313244; +} + +stacksidebar.sidebar row { + min-height: 34px; + padding: 0 3px; + border-radius: 12px; +} + +stacksidebar.sidebar row + row { + margin-top: 3px; +} + +stacksidebar.sidebar row:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + font-weight: 500; +} + +stacksidebar.sidebar row:selected label, +stacksidebar.sidebar row:selected image { + color: rgba(30, 30, 46, 0.87); +} + +stacksidebar.sidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +/**************** + * File chooser * + ****************/ +placessidebar.sidebar { + margin: 0 0 0 4px; + padding: 0; +} + +placessidebar.sidebar > viewport.frame { + border-style: none; +} + +placessidebar.sidebar list { + background-color: transparent; + color: #eff1f5; +} + +placessidebar.sidebar row { + min-height: 32px; + margin: 0; + padding: 0; + color: #eff1f5; + border-radius: 6px; +} + +placessidebar.sidebar row:hover, placessidebar.sidebar row:active { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #89b4fa; +} + +placessidebar.sidebar row > revealer { + padding: 0 8px 0 16px; +} + +placessidebar.sidebar row:selected { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #89b4fa; + font-weight: 500; +} + +placessidebar.sidebar row:disabled { + color: rgba(30, 30, 46, 0.3); +} + +placessidebar.sidebar row image.sidebar-icon { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar.sidebar row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar.sidebar row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar.sidebar row label.sidebar-label { + color: inherit; +} + +placessidebar.sidebar row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar.sidebar row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar.sidebar row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar.sidebar row.sidebar-new-bookmark-row { + color: #89b4fa; +} + +placessidebar.sidebar row.sidebar-new-bookmark-row image.sidebar-icon { + color: #89b4fa; +} + +placessidebar.sidebar row:drop(active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + padding-left: 8px; + padding-right: 8px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(rgba(239, 241, 245, 0.12)); + background-size: 1px 1px; + background-clip: content-box; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #1e1e2e; + background-image: image(rgba(239, 241, 245, 0.12)), image(rgba(239, 241, 245, 0.12)); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************** + * GtkInfoBar * + **************/ +infobar { + border: none; + margin-bottom: 0; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #313244; +} + +infobar.info > revealer > box, +infobar.info > revealer > box link:link, +infobar.info > revealer > box flowboxchild, infobar.info:hover > revealer > box, +infobar.info:hover > revealer > box link:link, +infobar.info:hover > revealer > box flowboxchild, infobar.info:backdrop > revealer > box, +infobar.info:backdrop > revealer > box link:link, +infobar.info:backdrop > revealer > box flowboxchild { + color: #89b4fa; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #89b4fa; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #89b4fa; +} + +infobar.action > revealer > box, +infobar.action > revealer > box link:link, +infobar.action > revealer > box flowboxchild, infobar.action:backdrop > revealer > box, +infobar.action:backdrop > revealer > box link:link, +infobar.action:backdrop > revealer > box flowboxchild, infobar.question > revealer > box, +infobar.question > revealer > box link:link, +infobar.question > revealer > box flowboxchild, infobar.question:backdrop > revealer > box, +infobar.question:backdrop > revealer > box link:link, +infobar.question:backdrop > revealer > box flowboxchild { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #71a4f9; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #df8e1d; +} + +infobar.warning > revealer > box, +infobar.warning > revealer > box link:link, +infobar.warning > revealer > box flowboxchild, infobar.warning:backdrop > revealer > box, +infobar.warning:backdrop > revealer > box link:link, +infobar.warning:backdrop > revealer > box flowboxchild { + color: #eff1f5; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.warning:hover > revealer > box { + background-color: #c8801a; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #d20f39; + color: #eff1f5; +} + +infobar.error > revealer > box, +infobar.error > revealer > box link:link, +infobar.error > revealer > box flowboxchild, infobar.error:backdrop > revealer > box, +infobar.error:backdrop > revealer > box link:link, +infobar.error:backdrop > revealer > box flowboxchild { + color: #eff1f5; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.error:hover > revealer > box { + background-color: #ba0d33; +} + +/************ + * Tooltips * + ************/ +tooltip { + box-shadow: none; +} + +tooltip.background { + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; + border-radius: 12px; +} + +tooltip.background.csd { + border-radius: 12px; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +tooltip decoration { + background-color: transparent; +} + +tooltip > box { + margin: -6px; + min-height: 24px; + padding: 4px 8px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #eff1f5; +} + +colorswatch.light { + color: rgba(30, 30, 46, 0.87); +} + +colorswatch overlay { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +colorswatch overlay:hover { + box-shadow: 0 0 0 2px #89b4fa; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(239, 241, 245, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(239, 241, 245, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #1e1e2e; +} + +/********************** + * Window Decorations * + **********************/ +decoration { + transition: none; + /* border-radius: $window-radius; */ + border-radius: 12px 12px 0 0; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; + margin: 10px; +} + +decoration:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +.tiled decoration, .tiled-top decoration, .tiled-right decoration, .tiled-bottom decoration, .tiled-left decoration { + border-radius: 0; +} + +.maximized decoration, .fullscreen decoration { + border-radius: 0; + box-shadow: none; +} + +.popup decoration { + box-shadow: none; + border: none; +} + +.ssd decoration { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #89b4fa; +} + +.ssd decoration:backdrop { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #292c3c; +} + +.metacity decoration { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border: none; +} + +.csd.popup decoration { + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa; +} + +tooltip.csd decoration { + border-radius: 12px; + box-shadow: none; + border: none; +} + +messagedialog.background.csd decoration { + border-radius: 12px; + border: 1px solid rgba(239, 241, 245, 0.1); + background-color: #292c3c; + background-clip: border-box; +} + +.solid-csd decoration { + margin: 0; + padding: 2px; + border-radius: 0; + box-shadow: none; + background-color: #1e1e2e; + border: 1px solid #4a4b5a; +} + +.solid-csd decoration:backdrop { + background-color: #1e1e2e; +} + +button.titlebutton:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + /* min-height: 22px; */ + /* min-width: 22px; */ + padding: 0; + margin: 0 0px; +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:not(.suggested-action):not(.destructive-action), button.close.titlebutton:not(.suggested-action):not(.destructive-action) { + background-color: rgba(239, 241, 245, 0.12); + color: rgba(239, 241, 245, 0.7); +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.maximize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.close.titlebutton:not(.suggested-action):not(.destructive-action) image { + padding: 0; + background: none; + box-shadow: none; +} + +button.minimize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; + background-color: alpha(currentColor, 0.15); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), inset 0 1px rgba(239, 241, 245, 0.1); +} + +button.minimize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.close.titlebutton:active:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; + background-color: alpha(currentColor, 0.2); +} + +button.minimize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +button.minimize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; + background-color: alpha(currentColor, 0.15); +} + +.monospace { + font-family: monospace; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #89b4fa; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.top:dir(ltr), cursor-handle.bottom:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +cursor-handle.bottom:dir(ltr), cursor-handle.top:dir(rtl) { + -gtk-icon-transform: unset; +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; + -gtk-icon-transform: rotate(45deg); +} + +.context-menu { + font: initial; +} + +.keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(239, 241, 245, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(239, 241, 245, 0.12); + background-color: #292c3c; + color: #eff1f5; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #89b4fa; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) + button { + margin-left: 3px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker.background entry { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +popover.emoji-picker.background entry:focus { + border-bottom: 1px solid #89b4fa; + box-shadow: inset 0 -1px #89b4fa; + background-color: transparent; +} + +popover.emoji-picker scrolledwindow { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +button.emoji-section { + margin: 4px; +} + +button.emoji-section:checked { + color: #89b4fa; +} + +button.emoji-section:not(:last-child) { + margin-right: 0; +} + +popover.emoji-picker .emoji { + min-width: 3em; + min-height: 3em; + padding: 0 8px; +} + +popover.emoji-picker .emoji widget { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker .emoji widget:hover { + background-color: alpha(currentColor, 0.08); +} + +popover.emoji-completion { + padding: 8px 0; +} + +popover.emoji-completion arrow { + border: none; + background: none; +} + +popover.emoji-completion .emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +popover.emoji-completion .emoji:hover { + background-color: alpha(currentColor, 0.08); +} + +/************ + * Nautilus * + ************/ +.nautilus-window.background.csd { + border-radius: 0 0 12px 12px; + background-color: #313244; +} + +.nautilus-window.background.csd:backdrop { + background-color: #313244; +} + +.nautilus-window.background.csd > grid.horizontal > paned.horizontal > separator, +.nautilus-window.background.csd > deck > box.vertical > paned.horizontal > separator { + margin-left: 0; +} + +.nautilus-window.background.csd placessidebar > viewport.frame > list > separator { + background: none; +} + +.nautilus-window.background.csd.unified notebook { + border-radius: 0; +} + +.nautilus-window.background.csd:not(.unified) .nautilus-list-view { + background-color: transparent; + border-bottom-right-radius: 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook { + background-color: #313244; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook > stack { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook scrolledwindow +> .view:not(:selected):not(:hover):not(:checked) { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > stack > frame > scrolledwindow > viewport > list { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar { + background-color: transparent; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar > revealer > box { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) paned > separator.wide { + min-width: 12px; + box-shadow: 12px 0 #313244; + background-color: #313244; + background-image: image(#4a4b5a); +} + +.nautilus-window.maximized, +.nautilus-window.maximized placessidebar { + border-radius: 0; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border: none; + border-radius: 12px; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(30, 30, 46, 0.87); +} + +.nautilus-canvas-item.dim-label, +.nautilus-list-dim-label { + color: rgba(239, 241, 245, 0.7); +} + +.nemo-desktop.nemo-canvas-item, .caja-desktop.caja-canvas-item, +.nautilus-desktop.nautilus-canvas-item { + color: #eff1f5; +} + +@keyframes nautilus-operations-button-needs-attention { + to { + background-color: alpha(currentColor, 0.08); + } +} + +.nautilus-operations-button-needs-attention { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 2 alternate; +} + +.nautilus-operations-button-needs-attention-multiple { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 6 alternate; +} + +.path-bar-box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border-radius: 12px; +} + +.path-bar-box button { + margin: 0; +} + +.path-bar-box.width-maximized { + background-color: rgba(239, 241, 245, 0.04); +} + +.path-bar-box.background.frame { + border-style: none; + background-color: rgba(239, 241, 245, 0.04); +} + +.path-bar-box .path-bar button label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .path-bar button label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) { + padding-left: 11px; + padding-right: 11px; + margin-left: 1px; + margin-right: 1px; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button.image-button image:not(:only-child) { + margin: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr), .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl) { + background-color: rgba(239, 241, 245, 0.08); +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr):disabled, .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl):disabled { + background-color: transparent; + color: rgba(239, 241, 245, 0.5); +} + +.windowhandle .linked.nautilus-path-bar { + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action) { + margin-top: 0; + margin-bottom: 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir { + color: #eff1f5; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:hover, .windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:active { + background: none; + box-shadow: none; +} + +.disk-space-display.unknown { + background-color: rgba(239, 241, 245, 0.3); + color: rgba(239, 241, 245, 0.3); +} + +.disk-space-display.used { + background-color: #89b4fa; + color: #89b4fa; +} + +.disk-space-display.free { + background-color: rgba(239, 241, 245, 0.12); + color: rgba(239, 241, 245, 0.12); +} + +.search-information { + padding: 2px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; + color: #eff1f5; +} + +.conflict-row:not(:selected) { + background-color: #654e38; +} + +.nautilus-window flowboxchild .icon-item-background { + padding: 4px; + border-radius: 6px; +} + +.nautilus-window flowboxchild:selected { + background-color: transparent; +} + +.nautilus-window notebook :not(treeview).view { + border-radius: 6px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > scrolledwindow.frame { + border-style: none; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child { + margin: -6px 0 0 -6px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > label { + margin: 0 8px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > box > button { + border-radius: 0; +} + +.nautilus-window > popover.menu:not(:last-child) { + padding: 3px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box { + margin-top: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box { + margin-bottom: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box.linked { + margin-top: 1px; +} + +.nautilus-window > popover.menu:not(:last-child) separator { + margin-bottom: -2px; +} + +.nautilus-menu-sort-heading { + margin: 1px 3px; + font-weight: 500; +} + +.nautilus-menu-sort-heading:disabled { + color: rgba(239, 241, 245, 0.7); +} + +.nautilus-window paned > separator { + background-color: #313244; +} + +/********* + * gedit * + *********/ +window.org-gnome-gedit > paned.titlebar > separator { + background-color: transparent; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > box.horizontal { + margin: 4px 0; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > scrolledwindow { + border-bottom-left-radius: 12px; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned stack scrolledwindow viewport.frame list.gedit-document-panel { + background: none; +} + +.open-document-selector-path-label { + color: rgba(239, 241, 245, 0.7); + font-size: smaller; +} + +.open-document-selector-match { + background-color: #df8e1d; + color: #eff1f5; +} + +.gedit-document-panel { + background-color: #313244; +} + +.gedit-document-panel row button.flat { + margin-top: 8px; + margin-bottom: 8px; +} + +.gedit-document-panel-group-row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.gedit-side-panel-paned statusbar { + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0 0 12px 12px; +} + +.gedit-search-slider { + margin: 0 6px 10px; + padding: 6px; + background-color: #292c3c; + border-radius: 0 0 12px 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05), 0 0 0 2px #e6e9ef; +} + +.gedit-search-slider .linked:not(.vertical) > entry .gedit-search-entry-occurrences-tag { + all: unset; + color: rgba(239, 241, 245, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) .gedit-search-entry-occurrences-tag { + margin-left: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) image.right { + margin-right: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) .gedit-search-entry-occurrences-tag { + margin-right: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) image.left { + margin-left: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:not(.error) { + background-color: #292c3c; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button { + color: rgba(239, 241, 245, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:hover, .gedit-search-slider .linked:not(.vertical) > entry.error ~ button:active { + color: #eff1f5; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +frame.gedit-map-frame > border:dir(ltr) { + border-style: none none none solid; +} + +frame.gedit-map-frame > border:dir(rtl) { + border-style: none solid none none; +} + +/********** + * Tweaks * + **********/ +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame { + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 12px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + background-color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:hover { + background-color: rgba(30, 30, 46, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:active { + background-color: rgba(30, 30, 46, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:disabled { + background-color: rgba(30, 30, 46, 0.3); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(30, 30, 46, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(30, 30, 46, 0.3); +} + +leaflet.unfolded > box.vertical:last-child > scrolledwindow > viewport.frame, +leaflet.unfolded > box.vertical:last-child > stack > scrolledwindow > viewport.frame { + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + padding: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > separator { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row { + padding: 0; + margin: -1px; + color: #eff1f5; + border-radius: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:active, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:focus { + color: #eff1f5; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected { + font-weight: 500; + background-color: rgba(239, 241, 245, 0.04); + border-radius: 9px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected label, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected image { + color: #89b4fa; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:focus { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row + row { + margin-top: 3px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + border: none; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar trough { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + border: 4px solid transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + border: none; + margin: 1px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.tweak { + padding: 3px; +} + +.tweak.title:hover { + box-shadow: none; +} + +.tweak-group-startup { + border: 1px solid rgba(239, 241, 245, 0.12); +} + +.tweak-group-startup > row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +row#Focus, +row#ClickMethod, +row#PrimaryWorkspaceTweak, +row#workspaces-only-on-primary { + margin-top: 4px; +} + +leaflet.titlebar > .titlebar.tweak-titlebar-left, +leaflet.titlebar > .titlebar.tweak-titlebar-right, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-left, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-right { + background-color: inherit; + box-shadow: inherit; + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + background-color: transparent; + margin: 0; +} + +/************************ + * Gnome Control Center * + ************************/ +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:not(:only-child) { + border-top-left-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:not(:only-child) { + border-top-right-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:only-child, window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:only-child { + border-top-right-radius: 12px; + border-top-left-radius: 12px; +} + +window.background.csd > stack:not(.titlebar) > stack.background { + border-radius: 0 0 12px 12px; +} + +window.background.csd > leaflet > stack.background, +window.background.csd > hdyleaflet > stack.background, +window.background.csd > box.horizontal > stack.background { + background: none; +} + +window.background.csd > leaflet > stack.background frame > border, +window.background.csd > hdyleaflet > stack.background frame > border, +window.background.csd > box.horizontal > stack.background frame > border { + border: none; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame { + background-color: #313244; + border-bottom-right-radius: 12px; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view { + background: none; +} + +window.background.csd > leaflet frame.view, +window.background.csd > hdyleaflet frame.view, +window.background.csd > box.horizontal frame.view { + border-radius: 12px; + background: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + margin: 6px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list { + border-top-width: 0; + border-bottom-width: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list > row { + border-radius: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list { + border-top-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list > row { + border-radius: 12px 12px 0 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list { + border-bottom-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list > row { + border-radius: 0 0 12px 12px; +} + +window.background.csd hdycolumn stack frame.view > stack > stack list > separator { + background-color: rgba(239, 241, 245, 0.12); +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack > box.horizontal > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list { + background: none; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list > row:not(:hover):not(:active):not(:selected) { + background-color: transparent; +} + +/************************ + * Gnome system monitor * + ************************/ +window#gnome-system-monitor.background.csd > box.vertical > stack { + background-color: #313244; + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background.csd > box.vertical > stack > box.vertical > revealer > actionbar > revealer > box { + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background:not(.csd) > box.vertical > headerbar { + box-shadow: none; +} + +/************************ + * Gnome Sound Recorder * + ************************/ +stack > grid.vertical > scrolledwindow { + border: none; + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical > scrolledwindow > viewport.frame list { + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical scrolledwindow.frame.emptyGrid { + border: none; +} + +/****************** + * Gnome Contacts * + ******************/ +window.background.csd scrolledwindow.contacts-contact-form { + border-bottom-right-radius: 12px; +} + +/************************ + * Epiphany (Gnome Web) * + ************************/ +tabbox { + border: none; + background-color: rgba(239, 241, 245, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +tabbox > tab button { + min-height: 24px; + min-width: 24px; + border-radius: 9999px; + border: none; + padding: 0; + margin-right: -6px; +} + +/***************** + * Gnome Weather * + *****************/ +#weather-page, +#weekly-forecast-frame { + border-bottom-right-radius: 12px; +} + +#weather-page-content-view { + border-bottom-right-radius: 12px; + border-bottom-left-radius: 12px; +} + +/*************** + * Gnome Music * + ***************/ +window.background.csd box.vertical > overlay > stack.background { + border-radius: 0 0 12px 12px; +} + +/**************** + * Gnome Clocks * + ****************/ +/************* + * Rhythmbox * + *************/ +window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.background > box.vertical > toolbar.primary-toolbar > toolitem button.flat.scale, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + min-height: 24px; + min-width: 24px; + padding: 5px; + margin: 0; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.12); +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button { + border-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:first-child), .sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:last-child) { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):first-child { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):last-child { + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button > widget > box > image { + padding: 0; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal { + padding: 6px; + margin: -1px 0; + border-bottom: none; + border-top: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: transparent; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + margin: 6px 0; +} + +window.csd > box.vertical > box.vertical > frame, +window.solid-csd > box.vertical > box.vertical > frame { + margin: -1px 0; + padding: 0; +} + +window.csd > box.vertical > box.vertical > frame > border, +window.solid-csd > box.vertical > box.vertical > frame > border { + border: none; +} + +window.background > box.vertical > toolbar.primary-toolbar { + padding: 0 12px 0 6px; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(239, 241, 245, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #eff1f5; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:disabled { + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised > widget > box > image { + padding: 0 3px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + padding: 6px; + margin: -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > box { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + padding: 0 6px 6px; + margin: 0 -6px -6px 0; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(239, 241, 245, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + padding: 3px; + margin: -1px -6px -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(239, 241, 245, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > paned > box:first-child > box { + padding: 0 6px 6px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +/********** + * Polari * + **********/ +.polari-room-list .sidebar { + background: none; +} + +.polari-room-list .sidebar > row.activatable:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +stack.view.polari-entry-area { + background-color: #1e1e2e; + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-bottom-right-radius: 12px; +} + +stack:disabled.view.polari-entry-area { + background-image: image(#1e1e2e); +} + +/*********** + * Builder * + ***********/ +layouttabbar { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; +} + +layouttabbar > box > button { + margin: 3px 0; +} + +layouttab { + margin: 0 8px; + border-style: none solid; + border-width: 1px; + border-color: rgba(30, 30, 46, 0.2); + box-shadow: inset 0 -2px #89b4fa; + background-color: #313244; +} + +layouttab separator.vertical { + margin: 8px 4px; +} + +layouttab button.text-button, layouttab button.image-button, layouttab button { + margin-top: 8px; + margin-bottom: 8px; + padding: 0 4px; +} + +layout { + border: 1px solid rgba(30, 30, 46, 0.2); + -pnldockbin-handle-size: 1; +} + +entry.search-missing { + background-color: #d20f39; + color: #eff1f5; +} + +window.workbench treeview.image { + color: rgba(239, 241, 245, 0.7); +} + +popover.popover-selector list { + padding: 6px; +} + +popover.popover-selector list row { + border-radius: 12px; +} + +popover.popover-selector list row image:dir(ltr) { + margin-right: 6px; +} + +popover.popover-selector list row image:dir(rtl) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(ltr) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(rtl) { + margin-right: 6px; +} + +omnibar.linked:not(.vertical) entry { + border-radius: 12px; +} + +omnibar:not(:hover):not(:active) entry { + color: rgba(239, 241, 245, 0.7); +} + +popover.omnibar list row:not(:last-child) { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +entry.preferences-search { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: #313244; +} + +preferences stacksidebar.sidebar list { + background-color: #313244; +} + +preferences stacksidebar.sidebar:dir(ltr) list, preferences stacksidebar.sidebar:dir(rtl) list { + border-style: none; +} + +preferences > box > box:dir(ltr) { + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +preferences > box > box:dir(rtl) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +popover.messagepopover.background { + padding: 0; +} + +popover.messagepopover .popover-action-area button { + padding: 8px 16px; + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0; +} + +popover.messagepopover .popover-action-area button:first-child { + border-bottom-left-radius: 12px; +} + +popover.messagepopover .popover-action-area button:last-child { + border-bottom-right-radius: 12px; +} + +popover.messagepopover .popover-content-area { + margin: 16px; +} + +popover.transfers list { + background-color: transparent; +} + +popover.transfers list row:not(:first-child) { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +popover.transfers list row > box { + padding: 10px; +} + +dockbin { + border: 1px solid rgba(30, 30, 46, 0.2); + -pnldockbin-handle-size: 1; +} + +dockpaned { + border: 1px solid rgba(30, 30, 46, 0.2); +} + +eggsearchbar box.search-bar { + padding: 0 8px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; +} + +docktabstrip { + padding: 0 8px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; +} + +docktab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + margin-bottom: -1px; + padding: 6px 6px; + border-width: 1px; + border-color: transparent; + box-shadow: inset 0 -2px transparent; + background-image: radial-gradient(circle, #89b4fa 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 0% 0%; + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +docktab:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +docktab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 225ms cubic-bezier(0, 0, 0.2, 1), background-image 525ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 -2px #89b4fa; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-size: 1000% 1000%; + color: #eff1f5; +} + +dockoverlayedge { + background-color: #1e1e2e; +} + +dockoverlayedge docktabstrip { + padding: 0; + border: none; +} + +dockoverlayedge.left-edge docktab:checked { + box-shadow: inset -2px 0 #89b4fa; +} + +dockoverlayedge.right-edge docktab:checked { + box-shadow: inset 2px 0 #89b4fa; +} + +pillbox { + background-color: #1e1e2e; + border-radius: 12px; +} + +layoutpane entry.search { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: #313244; +} + +editortweak entry.search { + margin-bottom: -1px; + box-shadow: none; + background-color: transparent; +} + +.gb-search-entry-occurrences-tag { + box-shadow: none; + background-color: transparent; +} + +docktabstrip { + min-height: 39px; +} + +window.workbench preferences preferencesgroup list entry { + padding-top: 8px; + padding-bottom: 8px; +} + +button.run-arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.dzlmenubutton image { + min-width: 28px; +} + +button.dzlmenubutton image.arrow { + min-width: 25px; +} + +button.dzlmenubuttonitem { + color: #eff1f5; + font-weight: normal; +} + +button.dzlmenubuttonitem:disabled { + color: rgba(239, 241, 245, 0.5); +} + +idelayoutstackheader { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +idelayoutstackheader button:checked { + color: #eff1f5; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher { + padding: 8px 0; + background-color: #1e1e2e; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(ltr) { + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(rtl) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button { + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:active { + background-image: radial-gradient(circle, rgba(137, 180, 250, 0.7) 10%, transparent 0%); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:checked { + background-color: transparent; + color: #eff1f5; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr) { + margin-right: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr):checked { + box-shadow: inset -2px 0 #89b4fa; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl) { + margin-left: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl):checked { + box-shadow: inset 2px 0 #89b4fa; +} + +ideeditorsidebar notebook header { + background: transparent; +} + +popover.messagepopover list { + border: 1px solid rgba(239, 241, 245, 0.12); +} + +popover.messagepopover list row:not(:last-child) { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +/********** + * Photos * + **********/ +GdMainIconView.content-view { + -gdmainiconview-icon-size: 48; +} + +.documents-counter { + margin: 8px; + border-radius: 9999px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + font-weight: bold; +} + +.documents-scrolledwin.frame { + border-style: none; +} + +.documents-scrolledwin.frame frame.content-view > border { + border-style: none; +} + +.photos-fade-in { + opacity: 1; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.photos-fade-out { + opacity: 0; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +button.photos-filter-preview { + color: #eff1f5; + font-weight: normal; +} + +button.photos-filter-preview:checked { + background-color: alpha(currentColor, 0.06); + color: #eff1f5; +} + +button.photos-filter-preview:checked image { + color: #eff1f5; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(ltr) { + border-style: none none none solid; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(rtl) { + border-style: none solid none none; +} + +/********* + * Music * + *********/ +.side-panel:dir(ltr) { + border-style: solid; + border-color: rgba(239, 241, 245, 0.12); +} + +.side-panel:dir(rtl) { + border-style: solid; + border-color: rgba(239, 241, 245, 0.12); +} + +.side-panel .view { + background-image: image(#313244); +} + +.side-panel .view:hover { + background-image: image(#404152); +} + +.side-panel .view:selected { + background-image: image(#89b4fa); +} + +.side-panel .view:selected:hover { + background-image: image(rgba(130, 171, 237, 0.9896)); +} + +.songs-list:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +frame.documents-dropdown { + margin: 8px; +} + +frame.documents-dropdown > border { + border: none; +} + +box.vertical > revealer > toolbar.search-bar { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; +} + +box.vertical > revealer > toolbar.search-bar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +/************* + * Documents * + *************/ +.documents-scrolledwin { + background-color: transparent; +} + +.documents-scrolledwin .content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) border { + border: none; +} + +window.background.csd > stack > box > revealer > actionbar > revealer > box { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +/******************* + * Document Viewer * + *******************/ +window.background.csd evview.view.content-view { + border-radius: 0 0 12px 12px; +} + +/********************************* + * Archive Manager (File roller) * + *********************************/ +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #313244; +} + +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow > treeview.view:not(:hover):not(:selected):not(:selected):not( +:hover +):not(.progressbar):not(.expander):not(.trough):not( +.separator +) { + background-color: #313244; +} + +.background.csd > grid.horizontal > paned.horizontal > box.vertical > scrolledwindow { + border-radius: 0 0 0 12px; + background-color: #1e1e2e; +} + +/************ + * Terminal * + ************/ +terminal-window decoration { + border-radius: 12px 12px 0 0; +} + +terminal-window.background.csd, terminal-window.background.csd.maximized { + border-radius: 0; +} + +terminal-window notebook > header > box { + margin: -2px -2px -2px 1px; +} + +terminal-window notebook > header > box button.flat { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; +} + +window.background > box.vertical > box.horizontal > frame > border { + border: none; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list { + /* border-radius: $corner-radius; */ + margin: 0 6px 6px; + background-color: #1e1e2e; + color: #eff1f5; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row { + padding: 0 2px; + margin: 2px 0; + border-radius: 12px; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:selected, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:hover { + color: #89b4fa; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:active { + color: #eff1f5; +} + +window.background > box.vertical > box.horizontal > stack > widget > notebook.frame { + margin: 0 6px 6px 0; +} + +.terminal-window { + background-color: #1e1e2e; +} + +.terminal-window tabbar tabbox { + background-color: #313244; + margin: 0; + border-radius: 0; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; +} + +/********* + * To Do * + *********/ +task-list-view taskrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 0 -8px; +} + +task-list-view taskrow:hover { + transition: none; +} + +task-list-view taskrow label { + margin: 0 8px; +} + +task-list-view taskrow image.dim-label { + min-width: 16px; +} + +task-list-view > box > revealer > box > button { + margin: -5px; +} + +task-list-view > box > revealer > box > button .dim-label { + color: inherit; +} + +tasklistview taskrow { + outline: none; +} + +tasklistview taskrow entry, tasklistview taskrow entry:focus, tasklistview taskrow entry:disabled { + box-shadow: none; +} + +tasklistview taskrow image.dim-label { + min-width: 16px; +} + +tasklistview > box > revealer > box > button { + margin: -5px; +} + +tasklistview > box > revealer > box > button .dim-label { + color: inherit; +} + +/******* + * Eog * + *******/ +#eog-thumb-nav scrolledwindow { + border-top: none; +} + +/************* + * Evolution * + *************/ +frame.taskbar > border { + border-style: solid none none; +} + +box.vertical > paned.horizontal notebook widget .frame { + border-style: none; +} + +/*********** + * Fractal * + ***********/ +.background.csd.main-window .sidebar.rooms-sidebar { + border-bottom-left-radius: 12px; +} + +/******** + * Gitg * + ********/ +frame.commit-frame > border { + border-style: solid none none; +} + +/************** + * Characters * + **************/ +box.dialog-vbox scrolledwindow.related { + border: 1px solid rgba(30, 30, 46, 0.2); +} + +list.categories { + background-image: image(#313244); +} + +/********* + * Boxes * + *********/ +.transparent-bg + stack overlay > label { + min-height: 24px; + padding: 0 4px; + border-radius: 12px; + background-color: #292c3c; + color: #eff1f5; +} + +/************** + * Calculator * + **************/ +button.title label { + min-height: 34px; +} + +/********* + * Geary * + *********/ +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer, +window#GearyMainWindow.background.csd stack#conversation_viewer { + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox, +window#GearyMainWindow.background.csd stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox { + background: none; + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded { + animation: none; + background-image: none; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box { + border-radius: 0; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar { + color: #eff1f5; + background-color: #1e1e2e; + box-shadow: none; + border-bottom: 1px solid rgba(30, 30, 46, 0.2); +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-composer-box actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-composer-box actionbar > revealer > box { + border-bottom-left-radius: 0; +} + +.geary-accounts-editor-pane frame:not(.geary-signature) > border, +.geary-accounts-editor-pane scrolledwindow.frame { + border: none; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout { + background-color: #313244; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar { + background-color: #1e1e2e; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar:backdrop, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar:backdrop { + background-color: #1e1e2e; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > box.vertical + separator.sidebar { + min-width: 1px; + background-color: rgba(239, 241, 245, 0.12); +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow { + padding: 3px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view { + border: 1px solid transparent; + border-radius: 12px; + padding: 6px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:selected, .geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:active { + border-radius: 12px; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.geary-main-window.unified separator.geary-sidebar-pane-separator { + min-width: 1px; + background-color: rgba(239, 241, 245, 0.12); +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable { + border: 1px solid rgba(239, 241, 245, 0.12); + border-bottom-width: 0; + background-color: #313244; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane { + border-radius: 0 0 8px 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background { + background-color: transparent; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background > revealer > box { + border-radius: 0 0 6px 6px; +} + +/************** + * Extensions * + **************/ +window.background.csd stack stack stack frame > border, +window.background.csd > stack > stack > box > frame > border, +window.background.csd > stack > stack > box > box > frame > border, +window.background.csd > stack > box > stack > box > frame > border, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > border, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > border, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > border { + border: none; +} + +window.background.csd > stack > box > box > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport > list { + border-bottom-left-radius: 12px; +} + +window.background.csd > stack > box > .sidebar > scrolledwindow > viewport > list { + padding: 0 0; +} + +/*********** + * Dialogs * + ***********/ +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:first-child { + border-radius: 0 0 0 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:last-child { + border-radius: 0 0 12px 0; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow, +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #313244; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active), +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list row.activatable:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack toolbar.toolbar { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd stack scrolledwindow.frame { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view > text { + background: none; +} + +dialog.background.csd stack scrolledwindow viewport.frame.view { + border-radius: 12px; +} + +window.background.csd.unified { + background-color: #1e1e2e; +} + +window.background.csd.unified headerbar { + box-shadow: none; +} + +window.background.csd.unified > decoration-overlay { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +window.background.csd.unified, +window.background.csd.unified > decoration, +window.background.csd.unified > decoration-overlay { + border-radius: 12px; +} + +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen > decoration-overlay { + box-shadow: none; +} + +window.background.csd.unified.tiled, +window.background.csd.unified.tiled > decoration, +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top, +window.background.csd.unified.tiled-top > decoration, +window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right, +window.background.csd.unified.tiled-right > decoration, +window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom, +window.background.csd.unified.tiled-bottom > decoration, +window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left, +window.background.csd.unified.tiled-left > decoration, +window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized, +window.background.csd.unified.maximized > decoration, +window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen, +window.background.csd.unified.fullscreen > decoration, +window.background.csd.unified.fullscreen > decoration-overlay { + border-radius: 0; +} + +/********* + * Tilix * + *********/ +overlay > revealer.left > scrolledwindow.frame, overlay > revealer.right > scrolledwindow.frame { + border-style: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +overlay > revealer.left > scrolledwindow.frame { + margin-right: 32px; +} + +overlay > revealer.right > scrolledwindow.frame { + margin-left: 32px; +} + +.terminix-session-sidebar, +.tilix-session-sidebar { + background-image: image(#292c3c); +} + +.terminal-titlebar button { + border-radius: 0; +} + +button.image-button.session-new-button { + min-width: 30px; +} + +notebook.tilix-background tab > box > stack { + margin: -6px; +} + +button.flat.tilix-small-button { + min-height: 20px; + min-width: 16px; +} + +/************** + * Terminator * + **************/ +.terminator-terminal-window paned > separator { + background-color: #1e1e2e; +} + +.terminator-terminal-window notebook.frame { + border-style: none; +} + +/************* + * Ubitquity * + *************/ +#live_installer .menubar progressbar trough { + border-radius: 4px; + background-color: rgba(239, 241, 245, 0.12); +} + +/********* + * Meld * + ********/ +.meld-notebook, +.meld-notebook > stack { + background: none; + border-radius: 0 0 12px 12px; +} + +.meld-notebook-child { + background-color: #313244; + border-radius: 0 0 12px 12px; +} + +statusbar.meld-status-bar { + background: none; +} + +/*********** + * Eclipse * + ***********/ +window.background > box.vertical > scrolledwindow > widget toolbar { + padding: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar separator, +window.background > box.vertical > scrolledwindow > widget toolbar button { + margin: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar button { + border-radius: 12px; +} + +/************ + * Chromium * + ************/ +window.background.chromium { + background-color: #313244; + color: #eff1f5; +} + +window.background.chromium headerbar.titlebar { + padding: 0 12px; + /* border-radius: $corner-radius $corner-radius 0 0; */ +} + +window.background.chromium headerbar.titlebar button.toggle { + border: none; + background-color: transparent; + background-image: none; +} + +window.background.chromium headerbar.titlebar button.toggle:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #eff1f5; +} + +window.background.chromium headerbar.titlebar button.toggle:checked, window.background.chromium headerbar.titlebar button.toggle:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #eff1f5; +} + +window.background.chromium headerbar.titlebar button.titlebutton { + min-width: 16px; + min-height: 16px; + margin: 0; + padding: 0; + background-size: 16px 16px; + border: none; +} + +window.background.chromium button { + border-width: 1px; + border-style: solid; + border-color: #4a4b5a; + background-color: #1e1e2e; + color: #eff1f5; +} + +window.background.chromium entry.chromium { + background-color: rgba(239, 241, 245, 0.06); +} + +window.background.chromium entry.chromium, window.background.chromium entry.chromium:focus { + border-image: none; + color: #eff1f5; +} + +window.background.chromium > textview.view, +window.background.chromium textview { + background-color: rgba(239, 241, 245, 0.06); + color: #eff1f5; +} + +window.background.chromium > menubar { + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.chromium menu { + background-color: #232634; + /* border: 0px solid if($variant == 'light', $solid-border, $window-border); */ + border-radius: 0; +} + +window.background.chromium menu menuitem { + border-radius: 0; + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.chromium menu menuitem:hover { + background-color: #292c3c; + color: #89b4fa; +} + +/*********** + * Firefox * + ***********/ +#MozillaGtkWidget decoration { + border: none; +} + +#MozillaGtkWidget > widget text { + background-color: #1e1e2e; +} + +#MozillaGtkWidget > widget text:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +#MozillaGtkWidget > widget > separator { + color: #4a4b5a; +} + +#MozillaGtkWidget > widget > scrollbar { + background-clip: border-box; +} + +#MozillaGtkWidget > widget > frame > border { + border-color: #4a4b5a; +} + +#MozillaGtkWidget > widget > entry, +#MozillaGtkWidget > widget > button > button { + border: 1px solid #4a4b5a; + border-radius: 12px; + box-shadow: none; +} + +#MozillaGtkWidget > widget > entry:disabled, +#MozillaGtkWidget > widget > button > button:disabled { + border-color: rgba(239, 241, 245, 0.12); +} + +#MozillaGtkWidget > widget > entry { + min-height: 30px; + background-color: #313244; +} + +#MozillaGtkWidget > widget > entry:focus { + border-color: #89b4fa; + box-shadow: inset 0 0 0 1px #89b4fa; +} + +#MozillaGtkWidget > widget > entry:disabled { + background-color: #313244; +} + +#MozillaGtkWidget > widget > button > button { + padding: 4px 8px; + background-size: auto; +} + +#MozillaGtkWidget > widget > button > button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +#MozillaGtkWidget > widget > button > button:active { + background-image: image(alpha(currentColor, 0.12)); +} + +#MozillaGtkWidget > widget > checkbutton > check, +#MozillaGtkWidget > widget > radiobutton > radio { + margin: 0; + padding: 0; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate), +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate) { + color: #414559; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):hover, #MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):active, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):hover, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):active { + color: #6c7086; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):disabled, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):disabled { + color: rgba(65, 69, 89, 0.5); +} + +#MozillaGtkWidget menu { + border: none; +} + +#MozillaGtkWidget > widget > menubar { + color: rgba(239, 241, 245, 0.7); +} + +#MozillaGtkWidget > widget > menubar:hover { + color: #eff1f5; +} + +#MozillaGtkWidget > widget > menubar:disabled { + color: rgba(239, 241, 245, 0.32); +} + +#MozillaGtkWidget > widget > frame { + color: #4a4b5a; +} + +#MozillaGtkWidget menu > separator { + color: #4a4b5a; +} + +window.background:not(.csd) > window > menu menuitem { + transition: none; +} + +/************ + * Inkscape * + ************/ +#ToolboxCommon > #AuxToolbox #StyleSwatch { + font-size: smaller; +} + +#ToolboxCommon > #AuxToolbox #Kludge { + padding: 0; +} + +#ToolboxCommon > #AuxToolbox spinbutton, +#ToolboxCommon > #AuxToolbox entry { + min-height: 32px; +} + +#ToolboxCommon > #AuxToolbox button:not(.up):not(.down) { + min-height: 24px; + min-width: 16px; + padding: 4px 8px; +} + +#ToolboxCommon > #AuxToolbox spinbutton button { + border-width: 4px; +} + +#ToolboxCommon > toolbar.vertical { + margin-top: -4px; +} + +#ToolboxCommon > toolbar.vertical button { + min-height: 24px; + min-width: 24px; + padding: 4px; +} + +#CanvasTable button { + min-height: 16px; + min-width: 16px; + padding: 0; +} + +#CanvasTable #HorizontalScrollbar { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(ltr) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(rtl) { + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +#Canvas_and_Dock frame > border { + border: none; +} + +#Canvas_and_Dock widget > widget > button.flat { + min-height: 16px; + min-width: 16px; + padding: 4px; +} + +#Canvas_and_Dock widget > widget > box.horizontal image { + padding: 4px; +} + +#Canvas_and_Dock box.horizontal > box.vertical > button.flat { + min-height: 16px; + min-width: 24px; + padding: 8px 4px; +} + +scrolledwindow#DialogNotebook > viewport.frame > notebook.frame button.close-button image { + padding: 4px; +} + +#InKscapeCanvas { + background-color: #313244; + border-radius: 12px; +} + +/*********** + * Synapse * + ***********/ +/*************** + * Libreoffice * + ***************/ +window.background > grid +> widget +> widget +> scrolledwindow +> viewport +> grid +> box +> box +> frame +> box { + background-color: #1e1e2e; +} + +/********* + * Pamac * + *********/ +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list { + border: none; + border-radius: 0; +} + +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list > row.activatable { + border-radius: 12px; +} + +dialog-host > floating-sheet > sheet > widget.response-area { + padding: 6px; +} + +window.background:not(.csd):not(.solid-csd) > button:not(:hover):not(:active):not(:checked):not(:disabled):not(.flat) { + /* background-color: if($variant == 'light', $grey-100, $grey-900); */ + background-color: #1e1e2e; +} + +window.background:not(.csd) > box +> widget +> widget +> widget +> widget +> widget +> widget +> widget +> scrolledwindow entry:focus { + background-color: #292938; +} + +/********* + * Unity * + *********/ +UnityDecoration { + -unitydecoration-extents: 28px 0 0 0; + -unitydecoration-input-extents: 8px; + -unitydecoration-shadow-offset-x: 0; + -unitydecoration-shadow-offset-y: 3px; + -unitydecoration-active-shadow-color: rgba(0, 0, 0, 0.48); + -unitydecoration-active-shadow-radius: 18px; + -unitydecoration-inactive-shadow-color: rgba(0, 0, 0, 0.32); + -unitydecoration-inactive-shadow-radius: 6px; + -unitydecoration-glow-size: 8px; + -unitydecoration-glow-color: #89b4fa; + -unitydecoration-title-indent: 4px; + -unitydecoration-title-fade: 32px; + -unitydecoration-title-alignment: 0; +} + +UnityDecoration .top { + padding: 0 2px; + border-style: none; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #1e1e2e; + color: #eff1f5; +} + +UnityDecoration .top:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.7); +} + +UnityDecoration .menuitem { + color: rgba(239, 241, 245, 0.7); +} + +UnityDecoration .menuitem:hover { + box-shadow: inset 0 -2px #e6e9ef; + background-color: transparent; + color: #eff1f5; +} + +.background:not(.csd) headerbar:not(.titlebar) { + border-radius: 0; + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +.background:not(.csd) headerbar:not(.titlebar).inline-toolbar { + border-style: none; +} + +UnityPanelWidget, +.unity-panel { + background-color: #1e1e2e; + color: #eff1f5; +} + +UnityPanelWidget:backdrop, +.unity-panel:backdrop { + color: rgba(239, 241, 245, 0.7); +} + +.unity-panel.menuitem, +.unity-panel .menuitem { + color: rgba(239, 241, 245, 0.7); +} + +.unity-panel.menubar.menuitem:hover, +.unity-panel.menubar .menuitem *:hover { + box-shadow: inset 0 -2px #e6e9ef; + background-color: transparent; + color: #eff1f5; +} + +.menu IdoPlaybackMenuItem.menuitem:active { + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); + animation: spin 1s linear infinite; + color: #89b4fa; +} + +/************** + * Mate-Panel * + **************/ +.mate-panel-menu-bar menubar, +#PanelApplet-window-menu-applet-button { + background-color: transparent; +} + +.mate-panel-menu-bar { + background-color: rgba(30, 30, 46, 0.6); + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +.mate-panel-menu-bar button { + min-height: 16px; + min-width: 16px; + padding: 0; + border-radius: 0; +} + +PanelToplevel.horizontal > grid > button { + min-width: 24px; +} + +PanelToplevel.vertical > grid > button { + min-height: 24px; +} + +PanelSeparator { + color: rgba(239, 241, 245, 0.12); +} + +MatePanelAppletFrameDBus { + border-style: solid; + border-color: rgba(239, 241, 245, 0.12); +} + +.mate-panel-menu-bar.horizontal MatePanelAppletFrameDBus { + border-width: 0 1px; +} + +.mate-panel-menu-bar.vertical MatePanelAppletFrameDBus { + border-width: 1px 0; +} + +.mate-panel-menu-bar menubar > menuitem { + color: rgba(239, 241, 245, 0.7); +} + +.mate-panel-menu-bar menubar > menuitem:hover { + color: #eff1f5; +} + +.mate-panel-menu-bar menubar > menuitem:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.mate-panel-menu-bar.horizontal menubar > menuitem { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical menubar > menuitem { + padding: 8px 0; +} + +.mate-panel-menu-bar menubar menu > menuitem { + min-height: 28px; + padding: 0 6px; +} + +.mate-panel-menu-bar #PanelApplet button { + -gtkwidget-window-dragging: true; +} + +.mate-panel-menu-bar #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0/0 0 0px; +} + +.mate-panel-menu-bar #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2/0 0 2px; +} + +.mate-panel-menu-bar #tasklist-button image:dir(ltr), +.mate-panel-menu-bar #tasklist-button label:dir(rtl) { + padding-left: 4px; +} + +.mate-panel-menu-bar #tasklist-button label:dir(ltr), +.mate-panel-menu-bar #tasklist-button image:dir(rtl) { + padding-right: 4px; +} + +.mate-panel-menu-bar.vertical #tasklist-button { + min-height: 32px; +} + +.mate-panel-menu-bar.horizontal #showdesktop-button image { + min-width: 24px; + padding: 0 4px; +} + +.mate-panel-menu-bar.vertical #showdesktop-button image { + min-height: 24px; + padding: 4px 0; +} + +PanelApplet.wnck-applet .wnck-pager { + background-color: transparent; + color: #89b4fa; +} + +PanelApplet.wnck-applet .wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +PanelApplet.wnck-applet .wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +PanelApplet.wnck-applet .wnck-pager:selected { + background-color: #89b4fa; +} + +.mate-panel-menu-bar.horizontal #clock-applet-button label { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical #clock-applet-button label { + padding: 8px 0; +} + +#MatePanelPopupWindow { + border: 1px solid rgba(30, 30, 46, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +#MatePanelPopupWindow frame > border { + border-style: none; +} + +#MatePanelPopupWindow calendar { + border-style: none; +} + +#MatePanelPopupWindow calendar:not(:selected) { + background-color: transparent; +} + +#MatePanelPopupWindow calendar + box { + margin-top: -5px; + padding-top: 5px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +#MatePanelPopupWindow expander > title { + min-height: 32px; +} + +#MatePanelPopupWindow button { + padding: 4px 16px; +} + +#MatePanelPopupWindow > frame > box > box > box > widget { + color: rgba(239, 241, 245, 0.12); +} + +na-tray-applet { + -natrayapplet-icon-padding: 3px; + -natrayapplet-icon-size: 16; +} + +.mate-panel-menu-bar { + -panelmenubar-icon-visible: true; +} + +.mate-panel-applet-slider { + border: 1px solid rgba(30, 30, 46, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.mate-panel-applet-slider frame > border { + border-style: none; +} + +#PanelApplet:not(:selected) > box { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +#PanelApplet:selected > box { + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +#mate-menu { + border: 1px solid rgba(30, 30, 46, 0.2); + background-color: #292c3c; +} + +#mate-menu button { + min-height: 24px; + min-width: 24px; + padding: 4px 0; + color: #eff1f5; + font-weight: normal; +} + +#mate-menu button:not(.flat) { + background-color: alpha(currentColor, 0.1); +} + +#mate-menu button image, +#mate-menu button label + label { + color: rgba(239, 241, 245, 0.7); +} + +#mate-menu entry { + margin: 0 0 4px; +} + +#mate-menu entry image { + margin: 0; +} + +#mate-menu entry + button { + margin: 0 4px 4px; + padding: 5px; +} + +.brisk-menu { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.brisk-menu entry { + margin-bottom: -2px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.brisk-menu entry + box > box:dir(ltr) { + margin-right: -2px; + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +.brisk-menu entry + box > box:dir(rtl) { + margin-left: -2px; + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +.brisk-menu .categories-list { + padding-top: 4px; +} + +.brisk-menu .categories-list button { + margin: 0 4px; +} + +.brisk-menu .categories-list button:checked { + color: #89b4fa; +} + +.brisk-menu .session-button { + padding: 11px; +} + +.brisk-menu .frame { + border-style: none; +} + +.brisk-menu .apps-list { + padding: 4px 0; + background-color: transparent; +} + +.brisk-menu .apps-list row { + padding: 0; +} + +.brisk-menu .apps-list row:hover { + box-shadow: none; +} + +.brisk-menu .apps-list button { + border-radius: 0; + color: #eff1f5; + font-weight: normal; +} + +/********************* + * CAJA File manager * + *********************/ +.caja-navigation-window button.toggle.image-button { + border-radius: 12px; +} + +.caja-pathbar button { + margin: 0 -1px 0 -2px; +} + +.caja-pathbar button.slider-button { + min-width: 24px; +} + +.caja-pathbar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.caja-side-pane notebook viewport.frame, +.caja-side-pane notebook widget .vertical { + background-color: #313244; +} + +.caja-side-pane notebook, +.caja-notebook { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.caja-side-pane notebook .frame, +.caja-notebook .frame { + border-style: none; +} + +.caja-canvas-item { + border-radius: 12px; +} + +.caja-desktop.view .entry, +.caja-navigation-window .view .entry { + border: none; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + background-image: none; + color: #eff1f5; +} + +.caja-desktop.view .entry:selected, +.caja-navigation-window .view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-desktop.view .entry { + background-color: #313244; + color: #eff1f5; + caret-color: currentColor; +} + +.caja-desktop.view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-navigation-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.caja-notebook frame > border { + border-style: none; +} + +#caja-extra-view-widget { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +#caja-extra-view-widget > box > box > label { + font-weight: bold; +} + +/********* + * Pluma * + *********/ +.pluma-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.pluma-window statusbar frame > border { + border-style: none; +} + +.pluma-window statusbar frame button.flat { + padding: 0 4px; + border-radius: 0; +} + +.pluma-window statusbar frame button.flat widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.pluma-print-preview toolbar { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat { + margin: 1px; +} + +.pluma-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.pluma-window paned.horizontal box.vertical notebook.frame { + margin-top: -1px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.pluma-window paned.horizontal box.vertical notebook.frame box.vertical toolbar.horizontal { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +/********* + * Atril * + *********/ +.atril-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.atril-window paned.horizontal box.vertical notebook .frame { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +/* mate-screensaver lock dialog */ +.lock-dialog { + border: 1px solid rgba(30, 30, 46, 0.2); + border-radius: 13px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.lock-dialog frame > border { + border-style: none; +} + +.lock-dialog button:not(:disabled) { + color: #89b4fa; +} + +/* multimedia OSD */ +MsdOsdWindow.background.osd { + border-radius: 12px; + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; +} + +MsdOsdWindow.background.osd .trough { + border-radius: 0; + background-color: rgba(239, 241, 245, 0.12); +} + +MsdOsdWindow.background.osd .progressbar { + border-radius: 0; + background-color: #89b4fa; +} + +/****************** + * Budgie Desktop * + ******************/ +.budgie-container { + background-color: transparent; +} + +.budgie-settings-window list.sidebar { + background: none; + border-radius: 0 0 0 12px; +} + +.budgie-settings-window buttonbox.inline-toolbar { + border-style: none none solid; +} + +.budgie-settings-window buttonbox.inline-toolbar button { + border-radius: 12px; +} + +.budgie-popover { + border-color: #292c3c; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #e6e9ef; + background-clip: border-box; + background-color: #292c3c; + border-radius: 12px; +} + +.budgie-popover frame.container { + padding: 6px; + border: none; +} + +.budgie-popover frame.container .container { + padding: 0; +} + +.budgie-popover list, +.budgie-popover row { + padding: 0; +} + +.budgie-popover separator { + margin: 3px 0; +} + +.budgie-popover border { + border: none; +} + +.budgie-popover list { + background-color: transparent; +} + +.budgie-popover row:hover { + box-shadow: none; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) { + background-color: rgba(239, 241, 245, 0.04); + border-right: none; + border-bottom-left-radius: 12px; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable { + padding: 6px 8px; +} + +.budgie-popover treeview.view.sidebar { + border-right: none; + background: none; +} + +.budgie-popover treeview.view.sidebar:hover { + background-color: alpha(currentColor, 0.08); +} + +.budgie-popover treeview.view.sidebar:selected { + background-color: alpha(currentColor, 0.12); +} + +.budgie-popover.bottom scrolledwindow.sidebar:not(.categories) { + padding-top: 12px; + border-top-left-radius: 12px; + border-bottom-left-radius: 0; +} + +.budgie-popover > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.budgie-popover.bottom > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: none; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.budgie-popover.budgie-menu .container { + padding: 0; +} + +.budgie-popover.budgie-menu .sidebar, +.budgie-popover.budgie-menu scrollbar, +.budgie-popover.budgie-menu entry.search { + background-color: transparent; +} + +.budgie-popover.budgie-menu entry.search { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + font-size: 120%; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories { + background-color: rgba(239, 241, 245, 0.04); + padding-bottom: 12px; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button { + border-radius: 0; +} + +.budgie-popover.budgie-menu scrolledwindow > viewport.frame > list > row.activatable > button.flat { + border-radius: 0; +} + +.budgie-popover.budgie-menu list.left-overlay-menu { + border-radius: 12px; + background-color: #313244; + padding: 6px; + margin: 6px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #e6e9ef; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable { + border-radius: 12px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable:not(:last-child) { + margin-bottom: 3px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable button.menuitem { + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer { + border-top: 1px solid rgba(239, 241, 245, 0.12); + padding: 6px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat { + padding: 3px; + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat.image-button { + border-radius: 9999px; + padding: 6px; + min-height: 16px; + min-width: 16px; + margin-left: 6px; + background-clip: border-box; +} + +.budgie-popover.user-menu list, +.budgie-popover.user-menu row { + border: none; + background: none; + box-shadow: none; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child { + margin-bottom: 0; + outline-width: 0; + border-radius: 12px; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child button.indicator-item { + transition: none; + animation: none; +} + +.budgie-popover.night-light-indicator .view-header { + margin: 0 6px; +} + +.budgie-popover.places-menu .name-button image:dir(ltr) { + margin-right: 3px; +} + +.budgie-popover.places-menu .name-button image:dir(rtl) { + margin-left: 3px; +} + +.budgie-popover.places-menu .unmount-button { + margin: 2px; + padding: 0; +} + +.budgie-popover.places-menu .places-list:not(.always-expand) { + margin-top: 3px; + padding-top: 3px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.budgie-popover.places-menu .alternative-label { + padding: 3px; + font-size: 15px; +} + +.budgie-popover.workspace-popover flowboxchild { + padding: 0; +} + +.workspace-switcher .workspace-layout { + border: 0 solid rgba(239, 241, 245, 0.12); +} + +.top .workspace-switcher .workspace-layout:dir(ltr), .bottom .workspace-switcher .workspace-layout:dir(ltr) { + border-left-width: 1px; +} + +.top .workspace-switcher .workspace-layout:dir(rtl), .bottom .workspace-switcher .workspace-layout:dir(rtl) { + border-right-width: 1px; +} + +.left .workspace-switcher .workspace-layout, .right .workspace-switcher .workspace-layout { + border-top-width: 1px; +} + +.workspace-switcher .workspace-item, +.workspace-switcher .workspace-add-button { + border: 0 solid rgba(239, 241, 245, 0.12); +} + +.top .workspace-switcher .workspace-item:dir(ltr), .bottom .workspace-switcher .workspace-item:dir(ltr), .top .workspace-switcher .workspace-add-button:dir(ltr), .bottom .workspace-switcher .workspace-add-button:dir(ltr) { + border-right-width: 1px; +} + +.top .workspace-switcher .workspace-item:dir(rtl), .bottom .workspace-switcher .workspace-item:dir(rtl), .top .workspace-switcher .workspace-add-button:dir(rtl), .bottom .workspace-switcher .workspace-add-button:dir(rtl) { + border-left-width: 1px; +} + +.left .workspace-switcher .workspace-item, .right .workspace-switcher .workspace-item, .left .workspace-switcher .workspace-add-button, .right .workspace-switcher .workspace-add-button { + border-bottom-width: 1px; +} + +.workspace-switcher .workspace-item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.workspace-switcher .workspace-item.current-workspace { + background-color: alpha(currentColor, 0.1); +} + +.workspace-switcher .workspace-add-button:hover { + box-shadow: none; +} + +.workspace-switcher .workspace-add-button:active { + background-image: none; +} + +.workspace-switcher .workspace-add-button:active image { + margin: 1px 0 -1px; +} + +.budgie-panel .workspace-switcher .workspace-icon-button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 12px; +} + +.budgie-panel { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(30, 30, 46, 0.6); + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +.budgie-panel.transparent { + background-color: rgba(30, 30, 46, 0.75); +} + +.budgie-panel .icon-tasklist button.launcher:checked, .budgie-panel .icon-tasklist button.launcher:active { + color: #eff1f5; +} + +.top .budgie-panel.dock-mode { + border-radius: 0 0 12px 12px; +} + +.bottom .budgie-panel.dock-mode { + border-radius: 12px 12px 0 0; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:first-child > button.launcher { + border-top-left-radius: 12px; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:last-child > button.launcher { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode { + border-radius: 0 12px 12px 0; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-right-radius: 12px; +} + +.right .budgie-panel.dock-mode { + border-radius: 12px 0 0 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-left-radius: 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-left-radius: 12px; +} + +.budgie-panel button { + color: rgba(239, 241, 245, 0.7); + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 0; +} + +.budgie-panel button:hover { + color: #eff1f5; +} + +.budgie-panel button:active { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel button.budgie-menu-launcher { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel button.budgie-menu-launcher:focus { + box-shadow: none; + border: none; + color: #eff1f5; +} + +.budgie-panel button.raven-trigger { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel.horizontal button { + padding: 0 4px; +} + +.budgie-panel.vertical button { + padding: 4px 0; +} + +.budgie-panel separator { + background-color: rgba(239, 241, 245, 0.12); +} + +.budgie-panel .alert { + color: #d20f39; +} + +.budgie-panel > box > widget > widget > image, +.budgie-panel > box > widget > widget > stack > image, +.budgie-panel > box > widget > widget > box > image { + margin-left: 6px; + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > image + label { + margin-left: -4px; +} + +.budgie-panel > box > widget > widget > box > widget > image { + margin-left: 6px; +} + +.budgie-panel > box > widget > widget > box > stack > widget > label { + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > widget > widget > image { + margin-left: 2px; + margin-right: 2px; +} + +.budgie-panel .budgie-clock-applet > widget > box, +.budgie-panel .budgie-calendar-applet > widget > box { + padding-left: 3px; + padding-right: 3px; +} + +.budgie-panel .titlebar:not(headerbar) { + min-height: 0; + padding: 0; + box-shadow: none; + background-color: transparent; + color: #eff1f5; +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):hover, .budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):active { + color: #eff1f5; +} + +.budgie-panel menubar, +.budgie-panel .menubar { + color: rgba(239, 241, 245, 0.7); + box-shadow: none; + border: none; +} + +.budgie-panel menubar > menuitem, +.budgie-panel .menubar > menuitem { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel menubar > menuitem:hover, .budgie-panel menubar > menuitem:active, +.budgie-panel .menubar > menuitem:hover, +.budgie-panel .menubar > menuitem:active { + color: #eff1f5; +} + +.budgie-panel menubar menu separator, +.budgie-panel .menubar menu separator { + background-color: rgba(239, 241, 245, 0.12); +} + +.budgie-panel #tasklist-button { + padding: 0 4px; +} + +.budgie-panel.vertical #tasklist-button { + min-height: 32px; +} + +.budgie-panel button.flat.launcher { + padding: 0; +} + +.budgie-panel button.flat.launcher:not(:checked) { + color: rgba(239, 241, 245, 0.5); +} + +.budgie-panel button.flat.launcher:not(:checked):hover, .budgie-panel button.flat.launcher:not(:checked):active { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-panel button.flat.launcher:not(:checked):disabled { + color: rgba(239, 241, 245, 0.32); +} + +.top .budgie-panel .unpinned button.flat.launcher:checked, .top .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel .unpinned button.flat.launcher:checked, .bottom .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel .unpinned button.flat.launcher:checked, .left .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel .unpinned button.flat.launcher:checked, .right .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +.top .budgie-panel #tasklist-button, .budgie-panel .top #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.top .budgie-panel #tasklist-button:checked, .budgie-panel .top #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel #tasklist-button, .budgie-panel .bottom #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.bottom .budgie-panel #tasklist-button:checked, .budgie-panel .bottom #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel #tasklist-button, .budgie-panel .left #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.left .budgie-panel #tasklist-button:checked, .budgie-panel .left #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel #tasklist-button, .budgie-panel .right #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.right .budgie-panel #tasklist-button:checked, .budgie-panel .right #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +frame.raven-frame > border { + border-style: none; +} + +.top frame.raven-frame > border { + margin-bottom: 32px; +} + +.bottom frame.raven-frame > border { + margin-top: 32px; +} + +.left frame.raven-frame > border { + margin-right: 32px; +} + +.right frame.raven-frame > border { + margin-left: 32px; +} + +.raven { + background-color: #292c3c; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +.raven > box { + margin-bottom: -10px; +} + +.raven stackswitcher.linked { + margin: 6px 16px; +} + +.raven stackswitcher.linked > button:focus { + box-shadow: none; +} + +.raven .raven-header { + min-height: 34px; + padding: 3px; +} + +.raven .raven-header.top { + padding: 0; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.raven .raven-header.top stackswitcher button { + margin: -4px 0 -5px; + padding: 0 16px; + min-height: 24px; +} + +.raven .raven-header.bottom { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.raven stack .raven-header { + margin-top: -6px; +} + +.raven stack scrolledwindow .raven-header { + margin-top: -8px; +} + +.raven .raven-background { + border-style: solid none; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #313244; +} + +.raven .raven-background > overlay > widget > image { + color: rgba(239, 241, 245, 0.12); +} + +.raven scrolledwindow.raven-background { + border-bottom-style: none; +} + +.raven .powerstrip button { + margin: 2px 0 1px; + padding: 11px; + border-radius: 9999px; +} + +.raven .option-subtitle { + font-size: smaller; +} + +.raven .audio-widget scale.marks-after { + padding-top: 0; + padding-bottom: 0; +} + +.raven .audio-widget scale.marks-after label { + font-size: 90%; + padding: 0; + margin: -10px 0 0 6px; +} + +.raven .audio-widget button.flat.expander-button { + margin-top: 4px; + margin-bottom: 4px; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked { + background-color: rgba(239, 241, 245, 0.06); + color: #eff1f5; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected label, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked label { + color: #eff1f5; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable label { + padding-left: 12px; +} + +.raven levelbar, +.raven levelbar trough, +.raven levelbar block { + border-radius: 9999px; +} + +calendar.raven-calendar { + border-style: none; + background-color: transparent; +} + +calendar.raven-calendar:selected { + border-radius: 12px; +} + +.raven-mpris { + background-color: #292c3c; + color: #eff1f5; +} + +.raven-mpris label { + min-height: 24px; +} + +.raven-mpris button.image-button { + padding: 11px; +} + +image.raven-mpris { + background-color: rgba(239, 241, 245, 0.12); + color: rgba(239, 241, 245, 0.7); + border-radius: 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame { + padding: 0; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable { + margin-left: -6px; + margin-right: -3px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable .raven-notifications-group-header { + padding: 0 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list { + padding: 6px; + background: none; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable { + border: none; + padding: 6px; + padding-left: 12px; + margin: 3px; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:selected { + background-color: rgba(239, 241, 245, 0.12); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:active, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:focus { + background: none; + box-shadow: none; +} + +.budgie-notification-window, .budgie-switcher-window, .budgie-osd-window { + background-color: transparent; +} + +.budgie-notification .notification-title, .budgie-switcher .notification-title { + font-size: 120%; +} + +.budgie-notification .notification-body, .budgie-switcher .notification-body { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-osd .budgie-osd-text { + font-size: 120%; +} + +.budgie-panel .lock-keys image:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.drop-shadow { + margin: 5px 9px; + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +.drop-shadow .linked > button { + border-radius: 12px; +} + +.budgie-session-dialog, +.budgie-polkit-dialog, +.budgie-run-dialog { + background-color: #292c3c; + border: none; + padding: 0; +} + +.budgie-session-dialog > box > grid, +.budgie-polkit-dialog > box > grid, +.budgie-run-dialog > box > grid { + padding: 24px; +} + +.budgie-session-dialog.background, .budgie-session-dialog > decoration, +.budgie-polkit-dialog.background, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog.background, +.budgie-run-dialog > decoration { + border-radius: 12px; +} + +.budgie-session-dialog > decoration, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog > decoration { + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(30, 30, 46, 0.75); +} + +.budgie-session-dialog label:not(:last-child), +.budgie-session-dialog .dialog-title, +.budgie-polkit-dialog label:not(:last-child), +.budgie-polkit-dialog .dialog-title, +.budgie-run-dialog label:not(:last-child), +.budgie-run-dialog .dialog-title { + font-size: 120%; +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button { + padding: 8px 16px; + border-top: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 0; +} + +.budgie-session-dialog .linked.horizontal > button:first-child, +.budgie-polkit-dialog .linked.horizontal > button:first-child, +.budgie-run-dialog .linked.horizontal > button:first-child { + border-bottom-left-radius: 12px; +} + +.budgie-session-dialog .linked.horizontal > button:last-child, +.budgie-polkit-dialog .linked.horizontal > button:last-child, +.budgie-run-dialog .linked.horizontal > button:last-child { + border-bottom-right-radius: 12px; +} + +.budgie-polkit-dialog .message { + color: rgba(239, 241, 245, 0.7); +} + +.budgie-polkit-dialog .failure { + color: #d20f39; +} + +.budgie-polkit-dialog > box > grid { + padding-bottom: 0; +} + +.budgie-run-dialog entry.search { + font-size: 120%; + padding: 6px 14px; + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.budgie-run-dialog list .dim-label { + color: #eff1f5; +} + +.budgie-run-dialog scrolledwindow { + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +/************** + * Xfce4 Apps * + **************/ +.XfceHeading { + background-color: #313244; +} + +/*************** + * xfce4-panel * + ***************/ +.xfce4-panel.background { + border: none; + background-color: rgba(30, 30, 46, 0.6); + color: rgba(239, 241, 245, 0.7); + font-weight: 500; +} + +.xfce4-panel.background button { + min-height: 16px; + min-width: 16px; + padding: 0 6px; + border-radius: 0; +} + +.xfce4-panel.background button.flat.toggle { + padding: 0 6px; +} + +.xfce4-panel.background .tasklist button image { + padding: 4px; +} + +wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +wnck-pager:selected { + background-color: #89b4fa; +} + +#xfce4-mpc-plugin-26 > frame > border { + border: none; +} + +#xfce-panel-button { + -gtk-icon-style: symbolic; +} + +XfdesktopIconView.view { + border-radius: 12px; + background-color: transparent; + color: #eff1f5; +} + +XfdesktopIconView.view:active { + box-shadow: none; +} + +XfdesktopIconView.view .rubberband { + border-radius: 0; +} + +window#whiskermenu-window { + border-radius: 12px; + background-color: transparent; + border: none; +} + +window#whiskermenu-window entry.search:focus { + background-color: #313244; +} + +window#whiskermenu-window > frame > border { + border-radius: 12px; + padding: 6px 8px 6px 9px; + margin: 6px; + border: none; + background-color: #292c3c; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa; +} + +window#whiskermenu-window box.categories > button.radio { + padding: 3px 6px; + margin: 1px 0; +} + +window#whiskermenu-window box.categories > button.radio:hover { + background-color: rgba(239, 241, 245, 0.12); +} + +window#whiskermenu-window box.categories > button.radio:checked, window#whiskermenu-window box.categories > button.radio:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +window#whiskermenu-window box.categories > button.radio:checked:hover, window#whiskermenu-window box.categories > button.radio:active:hover { + background-image: none; +} + +window#whiskermenu-window scrolledwindow.frame { + padding: 3px; + background-color: #313244; + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view { + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:not(:hover):not(:selected) { + background: none; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:selected:hover { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:checked, window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:active { + background-color: rgba(239, 241, 245, 0.3); + color: #eff1f5; +} + +#XfceNotifyWindow { + background-color: #313244; + border-radius: 12px; + border: 2px solid #89b4fa; +} + +#XfceNotifyWindow buttonbox { + padding: 0; +} + +#XfceNotifyWindow label#summary { + font-weight: bold; +} + +dialog.xfsm-logout-dialog { + border-radius: 12px; + background-color: rgba(41, 44, 60, 0.97); + border: 2px solid #89b4fa; +} + +#xfwm-tabwin { + padding: 12px; + border-radius: 12px; + -xfwmtabwinwidget-icon-size: 64px; + -xfwmtabwinwidget-preview-size: 64px; +} + +/********** + * Thunar * + **********/ +.thunar toolbar { + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.thunar .standard-view.frame { + border: none; +} + +.thunar scrolledwindow.frame.sidebar { + border-top: none; +} + +.thunar .path-bar.linked:not(.vertical) > button.path-bar-button { + margin-left: 2px; + margin-right: 2px; +} + +.thunar statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-top: none; +} + +window.background.csd.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-bottom-left-radius: 12px; +} + +menubar.-vala-panel-appmenu-private, +menubar.-vala-panel-background { + background: none; + border: none; + box-shadow: none; + animation: none; +} + +menubar.-vala-panel-appmenu-private > menuitem, +menubar.-vala-panel-background > menuitem { + color: rgba(239, 241, 245, 0.7); + font-weight: normal; +} + +menubar.-vala-panel-appmenu-private > menuitem:hover, +menubar.-vala-panel-background > menuitem:hover { + color: #eff1f5; + border-radius: 0; +} + +menubar.-vala-panel-appmenu-private > menuitem:disabled, +menubar.-vala-panel-background > menuitem:disabled { + color: rgba(239, 241, 245, 0.32); +} + +/************************ + * LightDM GTK+ Greeter * + ************************/ +#panel_window { + background-color: #313244; + color: #eff1f5; +} + +#panel_window menubar, +#panel_window separator { + background-color: transparent; +} + +#panel_window separator { + padding: 0 4px; +} + +#panel_window separator:first-child { + padding: 0 8px; +} + +#panel_window menubar > menuitem { + color: rgba(239, 241, 245, 0.7); +} + +#panel_window menubar > menuitem:hover { + color: #eff1f5; +} + +#panel_window menubar > menuitem:disabled label { + color: rgba(239, 241, 245, 0.32); +} + +#login_window, +#shutdown_dialog, +#restart_dialog { + margin: 8px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +#content_frame { + padding-bottom: 16px; +} + +/* // the buttons, alternatively this could also be done with a simple ".lightdm-gtk-greeter button" */ +/* #login_window button, */ +/* #shutdown_dialog button, */ +/* #restart_dialog button { */ +/* } */ +/* .lightdm-gtk-greeter button { */ +/* } */ +/* // the user's avatar box */ +/* #user_image { */ +/* } */ +/* // the border around the user's avatar box */ +/* #user_image_border { */ +/* } */ +#buttonbox_frame { + padding-top: 24px; +} + +#buttonbox_frame > box, +#buttonbox_frame > buttonbox { + margin: -16px; +} + +#buttonbox_frame button:not(:disabled) { + color: #89b4fa; +} + +/* // the shutdown button */ +/* #shutdown_button { */ +/* } */ +/* // the restart button */ +/* #restart_button { */ +/* } */ +/* // the warning, in case a wrong password is entered or something else goes wrong according to PAM */ +/* #greeter_infobar { */ +/* // font-weight: bold; */ +/* } */ +/******** + * Nemo * + ********/ +.nemo-window .primary-toolbar { + background-color: #1e1e2e; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.nemo-window .primary-toolbar entry { + min-height: 0; + margin: 0; +} + +.nemo-window .primary-toolbar > toolitem > .linked > button.image-button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar button.text-button { + padding-left: 8px; + padding-right: 8px; + color: rgba(239, 241, 245, 0.7); +} + +.nemo-window .primary-toolbar button.text-button:hover, .nemo-window .primary-toolbar button.text-button:active, .nemo-window .primary-toolbar button.text-button:checked { + color: #eff1f5; +} + +.nemo-window .primary-toolbar button.text-button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +.nemo-window .primary-toolbar button.text-button:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button:checked { + box-shadow: none; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button { + border-radius: 6px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.nemo-window .primary-toolbar button:not(.text-button):not(.image-button) { + padding-left: 4px; + padding-right: 4px; +} + +.nemo-window scrolledwindow.frame { + border-style: none; +} + +.nemo-window scrolledwindow.frame .view:not(:selected) { + background-color: transparent; +} + +.nemo-window .nemo-inactive-pane .view:not(:selected) { + background-color: #313244; +} + +.nemo-window .nemo-window-pane widget.entry { + border-radius: 6px; + background-color: rgba(239, 241, 245, 0.04); +} + +.nemo-window .nemo-window-pane > notebook { + border-radius: 0; +} + +.places-treeview { + -nemoplacestreeview-disk-full-bg-color: #5d5d6a; + -nemoplacestreeview-disk-full-fg-color: #89b4fa; + -nemoplacestreeview-disk-full-bar-width: 2px; + -nemoplacestreeview-disk-full-bar-radius: 0; + -nemoplacestreeview-disk-full-bottom-padding: 1px; + -nemoplacestreeview-disk-full-max-length: 80px; + padding-top: 3px; + padding-bottom: 3px; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #eff1f5; +/* text color for entries, views and content in general */ +@define-color theme_text_color #eff1f5; +/* widget base background color */ +@define-color theme_bg_color #1e1e2e; +/* text widgets and the like base background color */ +@define-color theme_base_color #313244; +/* base background color of selections */ +@define-color theme_selected_bg_color #89b4fa; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(30, 30, 46, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #1e1e2e; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(239, 241, 245, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #313244; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #eff1f5; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #eff1f5; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #1e1e2e; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #313244; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #89b4fa; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(30, 30, 46, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(239, 241, 245, 0.5); +/* widgets main borders color */ +@define-color borders rgba(239, 241, 245, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(239, 241, 245, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #df8e1d; +@define-color error_color #d20f39; +@define-color success_color #40a02b; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #eff1f5; +@define-color wm_unfocused_title rgba(239, 241, 245, 0.7); +@define-color wm_highlight rgba(239, 241, 245, 0.1); +@define-color wm_border #0a0a0e; +@define-color wm_focused_bg #1e1e2e; +@define-color wm_unfocused_bg #1e1e2e; +@define-color wm_button_icon #eff1f5; +@define-color wm_button_focused_bg #2b2b3a; +@define-color wm_button_unfocused_bg #2b2b3a; +@define-color wm_button_hover_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_active_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_hover_bg #e6e9ef; +@define-color wm_button_active_bg #e7eaf0; +/* FIXME this is really an API */ +@define-color content_view_bg #313244; +@define-color placeholder_text_color #b6b8c0; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #313244; +@define-color budgie_tasklist_indicator_color rgba(121, 122, 133, 0.7); +@define-color budgie_tasklist_indicator_color_active #89b4fa; +@define-color budgie_tasklist_indicator_color_active_window rgba(108, 140, 195, 0.816); +@define-color budgie_tasklist_indicator_color_attention #df8e1d; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/thumbnail.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/thumbnail.png new file mode 100755 index 0000000..3cd7c7c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-3.0/thumbnail.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic.svg new file mode 100755 index 0000000..c3eedb0 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic.svg @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..96be359 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-checked-symbolic@2.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..f016658 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..1bc6987 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg @@ -0,0 +1,50 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/close.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/close.svg new file mode 100755 index 0000000..06201c3 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/close.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/cursor-handle-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/cursor-handle-symbolic.svg new file mode 100755 index 0000000..e2a252b --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/cursor-handle-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/maximize.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/maximize.svg new file mode 100755 index 0000000..39316eb --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/maximize.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/minimize.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/minimize.svg new file mode 100755 index 0000000..f3683b9 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/minimize.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic.svg new file mode 100755 index 0000000..d13b029 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic@2.svg new file mode 100755 index 0000000..ed8d87a --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-checked-symbolic@2.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic.svg new file mode 120000 index 0000000..79b7355 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..b68859d --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..de0d789 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..7f0235f --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg @@ -0,0 +1,47 @@ + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic.svg new file mode 100755 index 0000000..993f308 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg new file mode 100755 index 0000000..740bc8b --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic.svg new file mode 100755 index 0000000..73a1dbe --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic.svg @@ -0,0 +1,40 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic@2.svg new file mode 100755 index 0000000..bec2ee4 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-slider-symbolic@2.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..37d9c04 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..1bc5cb6 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic.svg new file mode 100755 index 0000000..caed76f --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic.svg @@ -0,0 +1,45 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..58aa5ff --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg @@ -0,0 +1,46 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..0e477a9 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..d0980e2 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg @@ -0,0 +1,49 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic.svg new file mode 100755 index 0000000..0fdb530 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic@2.svg new file mode 100755 index 0000000..251e2f5 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-checked-symbolic@2.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic.svg new file mode 120000 index 0000000..86dfcec --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..bafb558 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/unmaximize.svg b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/unmaximize.svg new file mode 100755 index 0000000..492d47a --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/assets/unmaximize.svg @@ -0,0 +1,46 @@ + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk-dark.css b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk-dark.css new file mode 100755 index 0000000..17ddad3 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk-dark.css @@ -0,0 +1,8518 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #89b4fa 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #89b4fa 100%, transparent 100%); + } +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #1e1e2e; + color: #eff1f5; +} + +#desktopwindow.background { + background-color: transparent; +} + +dnd { + color: #eff1f5; +} + +.normal-icons { + -gtk-icon-size: 16px; +} + +.large-icons { + -gtk-icon-size: 32px; +} + +.aboutdialog .large-icons { + -gtk-icon-size: 128px; +} + +spinner:disabled, +arrow:disabled, +scrollbar:disabled, +check:disabled, +radio:disabled, +treeview.expander:disabled { + -gtk-icon-filter: opacity(0.5); +} + +iconview, +.view { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +iconview:disabled, +.view:disabled { + color: rgba(239, 241, 245, 0.5); +} + +iconview:selected, +.view:selected { + color: #eff1f5; +} + +textview text { + background-color: #313244; +} + +textview border { + background-color: #313244; + color: rgba(239, 241, 245, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 6px; +} + +rubberband, .content-view rubberband, .content-view columnview.view > rubberband, +.content-view treeview.view > rubberband, +.content-view .rubberband, columnview.view > rubberband, +.content-view columnview.view > .rubberband, +treeview.view > rubberband, +.content-view treeview.view > .rubberband, gridview > rubberband, flowbox > rubberband { + border: 1px solid #89b4fa; + background-color: rgba(137, 180, 250, 0.3); +} + +flowbox > flowboxchild { + padding: 4px; + border-radius: 12px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +gridview > child { + padding: 3px; +} + +gridview > child:selected { + outline-color: alpha(currentColor, 0.06); +} + +gridview > child box { + border-spacing: 8px; + margin: 12px; +} + +coverflow cover { + color: #eff1f5; + background-color: #313244; + border: 1px solid black; +} + +label.separator { + color: rgba(239, 241, 245, 0.7); +} + +label:disabled { + opacity: 1; + color: rgba(239, 241, 245, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; + opacity: 1; +} + +label.osd { + border-radius: 12px; + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; +} + + +.dim-label, +row.expander image.expander-row-arrow, +row.property > box.header > box.title > .title, +row label.subtitle { + color: rgba(239, 241, 245, 0.7); + opacity: 1; +} + +.accent { + color: #89b4fa; +} + +.success { + color: #40a02b; +} + +.warning { + color: #df8e1d; +} + +.error { + color: #d20f39; +} + +.large-title { + font-weight: 300; + font-size: 24pt; +} + +.title-1 { + font-weight: 800; + font-size: 20pt; +} + +.title-2 { + font-weight: 800; + font-size: 15pt; +} + +.title-3 { + font-weight: 700; + font-size: 15pt; +} + +.title-4 { + font-weight: 700; + font-size: 13pt; +} + +.heading { + font-weight: 700; + font-size: 11pt; +} + +.body { + font-weight: 400; + font-size: 11pt; +} + +.caption, row.property > box.header > box.title > .title { + font-weight: 400; + font-size: 9pt; +} + +.caption-heading { + font-weight: 700; + font-size: 9pt; +} + +window.assistant .sidebar { + padding: 4px 0; +} + +window.assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(239, 241, 245, 0.5); + font-weight: 500; +} + +window.assistant .sidebar label.highlight { + color: #eff1f5; +} + +.osd .scale-popup > arrow, +.osd .scale-popup > contents, .osd popover > arrow, +.osd popover > contents, popover.touch-selection > arrow, +popover.touch-selection > contents, popover.magnifier > arrow, +popover.magnifier > contents, .osd { + color: #eff1f5; + background-color: #313244; + background-clip: padding-box; + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +.osd { + padding: 6px; + margin: 6px; +} + +.osd.circular { + border-radius: 9999px; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ + +entry headerbar popover.background entry, +headerbar popover.background entry entry, +entry { + min-height: 34px; + padding: 0 8px; + border-spacing: 6px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + + +entry headerbar popover.background entry:focus-within, +headerbar popover.background entry entry:focus-within, +entry:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #89b4fa; +} + + +entry headerbar popover.background entry:drop(active), +headerbar popover.background entry entry:drop(active), +entry headerbar popover.background entry:hover:not(:focus-within), +headerbar popover.background entry entry:hover:not(:focus-within), +entry:drop(active), +entry:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + + +entry headerbar popover.background entry:disabled, +headerbar popover.background entry entry:disabled, +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + + +entry headerbar popover.background entry > text > placeholder, +headerbar popover.background entry entry > text > placeholder, +entry > text > placeholder { + color: rgba(239, 241, 245, 0.5); +} + + +entry headerbar popover.background entry > text > block-cursor, +headerbar popover.background entry entry > text > block-cursor, +entry > text > block-cursor { + color: rgba(239, 241, 245, 0.04); + background-color: #eff1f5; +} + + +entry headerbar popover.background entry.flat:focus-within, +headerbar popover.background entry entry.flat:focus-within, +entry headerbar popover.background entry.flat:disabled, +headerbar popover.background entry entry.flat:disabled, +entry headerbar popover.background entry.flat:hover, +headerbar popover.background entry entry.flat:hover, +entry headerbar popover.background entry.flat, +headerbar popover.background entry entry.flat, +entry.flat:focus-within, +entry.flat:disabled, +entry.flat:hover, +entry.flat { + min-height: 0; + padding: 2px; + background-color: transparent; + box-shadow: none; + border-radius: 0; + outline: none; +} + + +entry headerbar popover.background entry > image, +headerbar popover.background entry entry > image, +entry > image { + color: rgba(239, 241, 245, 0.7); +} + + +entry headerbar popover.background entry > image:hover, +headerbar popover.background entry entry > image:hover, +entry headerbar popover.background entry > image:active, +headerbar popover.background entry entry > image:active, +entry > image:hover, +entry > image:active { + color: #eff1f5; +} + + +entry headerbar popover.background entry > image:disabled, +headerbar popover.background entry entry > image:disabled, +entry > image:disabled { + color: rgba(239, 241, 245, 0.5); +} + + +entry headerbar popover.background entry > image.left, +headerbar popover.background entry entry > image.left, +entry > image.left { + margin: 0 6px 0 1px; +} + + +entry headerbar popover.background entry > image.right, +headerbar popover.background entry entry > image.right, +entry > image.right { + margin: 0 1px 0 6px; +} + + +entry headerbar popover.background entry.password image.caps-lock-indicator, +headerbar popover.background entry entry.password image.caps-lock-indicator, +entry.password image.caps-lock-indicator { + opacity: 0.35; +} + + +entry headerbar popover.background entry.error, +headerbar popover.background entry entry.error, +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + outline: none; +} + + +entry headerbar popover.background entry.error:focus-within, +headerbar popover.background entry entry.error:focus-within, +entry.error:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #d20f39; + outline: none; +} + + +entry headerbar popover.background entry.error:drop(active), +headerbar popover.background entry entry.error:drop(active), +entry headerbar popover.background entry.error:hover:not(:focus-within), +headerbar popover.background entry entry.error:hover:not(:focus-within), +entry.error:drop(active), +entry.error:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.error:disabled, +headerbar popover.background entry entry.error:disabled, +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.error > text > selection, +headerbar popover.background entry entry.error > text > selection, +entry.error > text > selection { + background-color: rgba(210, 15, 57, 0.25); + color: #d20f39; +} + + +entry headerbar popover.background entry.error > text > cursor-handle > contents, +headerbar popover.background entry entry.error > text > cursor-handle > contents, +entry.error > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.error > image, +headerbar popover.background entry entry.error > image, +entry.error > image { + color: rgba(210, 15, 57, 0.75); +} + + +entry headerbar popover.background entry.error > image:hover, +headerbar popover.background entry entry.error > image:hover, +entry headerbar popover.background entry.error > image:active, +headerbar popover.background entry entry.error > image:active, +entry.error > image:hover, +entry.error > image:active { + color: #d20f39; +} + + +entry headerbar popover.background entry.error > image:disabled, +headerbar popover.background entry entry.error > image:disabled, +entry.error > image:disabled { + color: rgba(210, 15, 57, 0.35); +} + + +entry headerbar popover.background entry.warning, +headerbar popover.background entry entry.warning, +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + outline: none; +} + + +entry headerbar popover.background entry.warning:focus-within, +headerbar popover.background entry entry.warning:focus-within, +entry.warning:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #df8e1d; + outline: none; +} + + +entry headerbar popover.background entry.warning:drop(active), +headerbar popover.background entry entry.warning:drop(active), +entry headerbar popover.background entry.warning:hover:not(:focus-within), +headerbar popover.background entry entry.warning:hover:not(:focus-within), +entry.warning:drop(active), +entry.warning:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.warning:disabled, +headerbar popover.background entry entry.warning:disabled, +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.warning > text > selection, +headerbar popover.background entry entry.warning > text > selection, +entry.warning > text > selection { + background-color: rgba(223, 142, 29, 0.25); + color: #df8e1d; +} + + +entry headerbar popover.background entry.warning > text > cursor-handle > contents, +headerbar popover.background entry entry.warning > text > cursor-handle > contents, +entry.warning > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.warning > image, +headerbar popover.background entry entry.warning > image, +entry.warning > image { + color: rgba(223, 142, 29, 0.75); +} + + +entry headerbar popover.background entry.warning > image:hover, +headerbar popover.background entry entry.warning > image:hover, +entry headerbar popover.background entry.warning > image:active, +headerbar popover.background entry entry.warning > image:active, +entry.warning > image:hover, +entry.warning > image:active { + color: #df8e1d; +} + + +entry headerbar popover.background entry.warning > image:disabled, +headerbar popover.background entry entry.warning > image:disabled, +entry.warning > image:disabled { + color: rgba(223, 142, 29, 0.35); +} + + +entry headerbar popover.background entry.success, +headerbar popover.background entry entry.success, +entry.success { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + outline: none; +} + + +entry headerbar popover.background entry.success:focus-within, +headerbar popover.background entry entry.success:focus-within, +entry.success:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #40a02b; + outline: none; +} + + +entry headerbar popover.background entry.success:drop(active), +headerbar popover.background entry entry.success:drop(active), +entry headerbar popover.background entry.success:hover:not(:focus-within), +headerbar popover.background entry entry.success:hover:not(:focus-within), +entry.success:drop(active), +entry.success:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.success:disabled, +headerbar popover.background entry entry.success:disabled, +entry.success:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.success > text > selection, +headerbar popover.background entry entry.success > text > selection, +entry.success > text > selection { + background-color: rgba(64, 160, 43, 0.25); + color: #40a02b; +} + + +entry headerbar popover.background entry.success > text > cursor-handle > contents, +headerbar popover.background entry entry.success > text > cursor-handle > contents, +entry.success > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.success > image, +headerbar popover.background entry entry.success > image, +entry.success > image { + color: rgba(64, 160, 43, 0.75); +} + + +entry headerbar popover.background entry.success > image:hover, +headerbar popover.background entry entry.success > image:hover, +entry headerbar popover.background entry.success > image:active, +headerbar popover.background entry entry.success > image:active, +entry.success > image:hover, +entry.success > image:active { + color: #40a02b; +} + + +entry headerbar popover.background entry.success > image:disabled, +headerbar popover.background entry entry.success > image:disabled, +entry.success > image:disabled { + color: rgba(64, 160, 43, 0.35); +} + + +entry > progress, +entry progress > trough > progress { + margin: 0 -4px; + border-bottom: 2px solid #89b4fa; + background-color: transparent; +} + +.osd entry > progress > trough > progress { + border-color: rgba(239, 241, 245, 0.04); +} + + +entry button.image-button { + min-height: 24px; + min-width: 24px; + padding: 0; +} + +treeview entry.flat, treeview entry { + background-color: #313244; +} + +treeview entry.flat, treeview entry.flat:focus-within, treeview entry, treeview entry:focus-within { + border-image: none; + box-shadow: none; +} + +.entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +editablelabel > stack > text { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: radial-gradient(farthest-side, #89b4fa 0%, rgba(137, 180, 250, 0) 0%); + } + to { + background-image: radial-gradient(farthest-side, #89b4fa 95%, rgba(137, 180, 250, 0)); + } +} + +infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button, popover.touch-selection button, popover.magnifier button, headerbar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +infobar.warning > revealer > box button:focus, popover.touch-selection button:focus, popover.magnifier button:focus, headerbar.selection-mode button:focus:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:hover, popover.touch-selection button:hover, popover.magnifier button:hover, headerbar.selection-mode button:hover:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:active, popover.touch-selection button:active, popover.magnifier button:active, headerbar.selection-mode button:active:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:checked, popover.touch-selection button:checked, popover.magnifier button:checked, headerbar.selection-mode button:checked:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +infobar.warning > revealer > box button:disabled, popover.touch-selection button:disabled, popover.magnifier button:disabled, headerbar.selection-mode button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +infobar.warning > revealer > box button:checked:disabled, popover.touch-selection button:checked:disabled, popover.magnifier button:checked:disabled, headerbar.selection-mode button:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.5); +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button, button { + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:focus:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:focus, button:focus { + background-color: alpha(currentColor, 0.08); + outline: 2px solid rgba(137, 180, 250, 0.35); + outline-offset: 0; +} + +row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:hover:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:hover, button:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; + -gtk-icon-filter: brightness(1.2); +} + +row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button.keyboard-activating:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button.keyboard-activating, button.keyboard-activating, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:active:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:active, button:active { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:disabled:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:disabled, button:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + outline-color: transparent; +} + +row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:checked, button:checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:hover:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:hover { + outline-color: transparent; + background-color: #a1c4fb; + color: rgba(30, 30, 46, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:disabled:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:disabled { + outline-color: transparent; + background-color: rgba(137, 180, 250, 0.35); + color: rgba(30, 30, 46, 0.38); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button, calendar > header > button, notebook > header > tabs > arrow, popover modelbutton, .pathbar button, spinbutton > button, splitbutton.flat > button, +splitbutton.flat > menubutton > button { + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:focus:not(:hover):not(:active), calendar > header > button:focus:not(:hover):not(:active), notebook > header > tabs > arrow:focus:not(:hover):not(:active), popover modelbutton:focus:not(:hover):not(:active), .pathbar button:focus:not(:hover):not(:active), spinbutton > button:focus:not(:hover):not(:active), splitbutton.flat > button:focus:not(:hover):not(:active), +splitbutton.flat > menubutton > button:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 2px solid rgba(239, 241, 245, 0.04); + outline-offset: -2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:hover, calendar > header > button:hover, notebook > header > tabs > arrow:hover, popover modelbutton:hover, .pathbar button:hover, spinbutton > button:hover, splitbutton.flat > button:hover, +splitbutton.flat > menubutton > button:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:active, calendar > header > button:active, notebook > header > tabs > arrow:active, popover modelbutton:active, .pathbar button:active, spinbutton > button:active, splitbutton.flat > button:active, +splitbutton.flat > menubutton > button:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:disabled, calendar > header > button:disabled, notebook > header > tabs > arrow:disabled, popover modelbutton:disabled, .pathbar button:disabled, spinbutton > button:disabled, splitbutton.flat > button:disabled, +splitbutton.flat > menubutton > button:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +#NautilusPathButton, filechooser #pathbarbox > stack > box > button, window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button, .app-notification button, headerbar button:not(.suggested-action):not(.destructive-action), .toolbar button, splitbutton.suggested-action > button, +splitbutton.suggested-action > menubutton > button, splitbutton.destructive-action > button, +splitbutton.destructive-action > menubutton > button, splitbutton.opaque > button, +splitbutton.opaque > menubutton > button, menubutton.suggested-action > button, menubutton.destructive-action > button, menubutton.opaque > button, menubutton.flat > button, button.flat { + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +#NautilusPathButton:focus:not(:hover):not(:active), filechooser #pathbarbox > stack > box > button:focus:not(:hover):not(:active), window.messagedialog .response-area button:focus:not(:hover):not(:active), window.dialog.message .dialog-action-area > button:focus:not(:hover):not(:active), .app-notification button:focus:not(:hover):not(:active), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), .toolbar button:focus:not(:hover):not(:active), splitbutton.suggested-action > button:focus:not(:hover):not(:active), +splitbutton.suggested-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.destructive-action > button:focus:not(:hover):not(:active), +splitbutton.destructive-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.opaque > button:focus:not(:hover):not(:active), +splitbutton.opaque > menubutton > button:focus:not(:hover):not(:active), menubutton.suggested-action > button:focus:not(:hover):not(:active), menubutton.destructive-action > button:focus:not(:hover):not(:active), menubutton.opaque > button:focus:not(:hover):not(:active), menubutton.flat > button:focus:not(:hover):not(:active), button.flat:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 2px solid rgba(239, 241, 245, 0.04); + outline-offset: -2px; +} + +#NautilusPathButton:hover, filechooser #pathbarbox > stack > box > button:hover, window.messagedialog .response-area button:hover, window.dialog.message .dialog-action-area > button:hover, .app-notification button:hover, headerbar button:hover:not(.suggested-action):not(.destructive-action), .toolbar button:hover, splitbutton.suggested-action > button:hover, +splitbutton.suggested-action > menubutton > button:hover, splitbutton.destructive-action > button:hover, +splitbutton.destructive-action > menubutton > button:hover, splitbutton.opaque > button:hover, +splitbutton.opaque > menubutton > button:hover, menubutton.suggested-action > button:hover, menubutton.destructive-action > button:hover, menubutton.opaque > button:hover, menubutton.flat > button:hover, button.flat:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +#NautilusPathButton:active, filechooser #pathbarbox > stack > box > button:active, window.messagedialog .response-area button:active, window.dialog.message .dialog-action-area > button:active, .app-notification button:active, headerbar button:active:not(.suggested-action):not(.destructive-action), .toolbar button:active, splitbutton.suggested-action > button:active, +splitbutton.suggested-action > menubutton > button:active, splitbutton.destructive-action > button:active, +splitbutton.destructive-action > menubutton > button:active, splitbutton.opaque > button:active, +splitbutton.opaque > menubutton > button:active, menubutton.suggested-action > button:active, menubutton.destructive-action > button:active, menubutton.opaque > button:active, menubutton.flat > button:active, button.flat:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; +} + +#NautilusPathButton:disabled, filechooser #pathbarbox > stack > box > button:disabled, window.messagedialog .response-area button:disabled, window.dialog.message .dialog-action-area > button:disabled, .app-notification button:disabled, headerbar button:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:disabled, splitbutton.suggested-action > button:disabled, +splitbutton.suggested-action > menubutton > button:disabled, splitbutton.destructive-action > button:disabled, +splitbutton.destructive-action > menubutton > button:disabled, splitbutton.opaque > button:disabled, +splitbutton.opaque > menubutton > button:disabled, menubutton.suggested-action > button:disabled, menubutton.destructive-action > button:disabled, menubutton.opaque > button:disabled, menubutton.flat > button:disabled, button.flat:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +#NautilusPathButton:checked, filechooser #pathbarbox > stack > box > button:checked, window.messagedialog .response-area button:checked, window.dialog.message .dialog-action-area > button:checked, .app-notification button:checked, headerbar button:checked:not(.suggested-action):not(.destructive-action), .toolbar button:checked, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button:checked, menubutton.suggested-action > button:checked, menubutton.destructive-action > button:checked, menubutton.opaque > button:checked, menubutton.flat > button:checked, button.flat:checked { + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +#NautilusPathButton:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, window.messagedialog .response-area button:checked:disabled, window.dialog.message .dialog-action-area > button:checked:disabled, .app-notification button:checked:disabled, headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:checked:disabled, splitbutton.suggested-action > button:checked:disabled, +splitbutton.suggested-action > menubutton > button:checked:disabled, splitbutton.destructive-action > button:checked:disabled, +splitbutton.destructive-action > menubutton > button:checked:disabled, splitbutton.opaque > button:checked:disabled, +splitbutton.opaque > menubutton > button:checked:disabled, menubutton.suggested-action > button:checked:disabled, menubutton.destructive-action > button:checked:disabled, menubutton.opaque > button:checked:disabled, menubutton.flat > button:checked:disabled, button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(239, 241, 245, 0.5); +} + +button.opaque { + box-shadow: none; +} + +.osd button.opaque:focus:focus-visible { + outline-color: rgba(239, 241, 245, 0.15); +} + +button.opaque:hover { + background-image: image(alpha(currentColor, 0.1)); +} + +button.keyboard-activating.opaque, button.opaque:active { + background-image: image(rgba(0, 0, 0, 0.2)); +} + +button.opaque:checked { + background-image: image(rgba(0, 0, 0, 0.15)); +} + +button.opaque:checked:hover { + background-image: image(rgba(0, 0, 0, 0.05)); +} + +button.opaque:checked.keyboard-activating, button.opaque:checked:active { + background-image: image(rgba(0, 0, 0, 0.3)); +} + +.nautilus-window .floating-bar button, placessidebar list.navigation-sidebar > row button.sidebar-button, notebook > header > tabs > tab button.flat, popover.menu box.circular-buttons button.circular.image-button.model, spinbutton > button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + +button separator { + margin: 4px 1px; +} + +button.opaque { + background-color: #484856; + color: #eff1f5; +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button, button.image-text-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button > box, +button.text-button.image-button > box > box, button.image-text-button > box, +button.image-text-button > box > box { + border-spacing: 4px; +} + +button.text-button.image-button > box > label, +button.text-button.image-button > box > box > label, button.image-text-button > box > label, +button.image-text-button > box > box > label { + padding-left: 2px; + padding-right: 2px; +} + +button.text-button.image-button label:first-child, button.image-text-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child, button.image-text-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child, button.image-text-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child, button.image-text-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child), button.image-text-button image:not(:only-child) { + margin: 0 4px; +} + +button.arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.arrow-button > box { + border-spacing: 4px; +} + +button.arrow-button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +button.arrow-button.text-button > box { + border-spacing: 6px; +} + +menubutton.pill > button, button.pill { + padding: 9px 30px; + border-radius: 9999px; +} + +button.card { + background-color: #313244; + background-clip: padding-box; + font-weight: inherit; + border: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; +} + +button.card:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + +button.card.keyboard-activating, button.card:active { + background-image: none; + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +button.card:checked { + background-image: none; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + border-color: #89b4fa; +} + +button.card:checked:hover { + background-image: none; + outline-color: transparent; + background-color: #a1c4fb; + color: rgba(30, 30, 46, 0.87); +} + +button.card:checked:disabled { + outline-color: transparent; + background-color: rgba(137, 180, 250, 0.35); + color: rgba(30, 30, 46, 0.38); +} + +button.card:checked.keyboard-activating, button.card:checked:active { + background-image: none; +} + +button.card:checked.has-open-popup { + background-image: none; +} + +button.card:drop(active) { + color: #fab387; + box-shadow: inset 0 0 0 1px #fab387; +} + +.linked:not(.vertical) > button:focus, .linked.vertical > button:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + background-color: alpha(currentColor, 0.05); +} + +.linked:not(.vertical) > button.flat:focus, .linked.vertical > button.flat:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > menubutton > button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +button.osd { + min-height: 24px; + min-width: 24px; + padding: 5px; + box-shadow: none; + background-color: rgba(0, 0, 0, 0.35); + color: #eff1f5; + margin: 0; +} + +button.osd > image { + padding: 0; +} + +button.osd.remove-button { + padding: 0; +} + +button.osd:focus { + outline-color: transparent; +} + +button.osd:hover { + background-color: rgba(0, 0, 0, 0.45); + color: #eff1f5; +} + +button.osd:active { + background-color: rgba(0, 0, 0, 0.65); + color: #eff1f5; +} + +button.osd:disabled { + background-color: rgba(0, 0, 0, 0.15); + color: rgba(239, 241, 245, 0.35); +} + +button.suggested-action { + background-color: #1e66f5; + color: #eff1f5; + box-shadow: none; +} + +button.suggested-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + outline-color: transparent; +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:checked { + background-color: #5d90f5; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(30, 102, 245, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #1e66f5; +} + +button.suggested-action.flat:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +button.suggested-action.flat:checked { + background-color: rgba(30, 102, 245, 0.3); +} + +button.destructive-action { + background-color: #d20f39; + color: #eff1f5; + box-shadow: none; +} + +button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + outline-color: transparent; +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:checked { + background-color: #db5371; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(210, 15, 57, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #d20f39; +} + +button.destructive-action.flat:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +button.destructive-action.flat:checked { + background-color: rgba(210, 15, 57, 0.3); +} + +stackswitcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +stackswitcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +stackswitcher > button.needs-attention:checked > label, +stackswitcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +button.font > box, button.file > box { + border-spacing: 6px; +} + +button.font > box > box > label, button.file > box > box > label { + font-weight: bold; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar button.star, menubutton.circular > button, button.close, button.circular { + border-radius: 9999px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque) label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child label, headerbar button.star label, menubutton.circular > button label, button.close label, button.circular label { + padding: 0; +} + +menubutton.osd { + background: none; + color: inherit; +} + +menubutton.suggested-action { + background-color: #1e66f5; + color: #eff1f5; +} + +menubutton.destructive-action { + background-color: #d20f39; + color: #eff1f5; +} + +menubutton.opaque { + background-color: #484856; + color: #eff1f5; +} + +menubutton.suggested-action, menubutton.destructive-action, menubutton.opaque { + border-radius: 12px; +} + +menubutton.suggested-action.circular, menubutton.suggested-action.pill, menubutton.destructive-action.circular, menubutton.destructive-action.pill, menubutton.opaque.circular, menubutton.opaque.pill { + border-radius: 9999px; +} + +menubutton.suggested-action > button, menubutton.suggested-action > button:checked, menubutton.destructive-action > button, menubutton.destructive-action > button:checked, menubutton.opaque > button, menubutton.opaque > button:checked { + background-color: transparent; + color: inherit; +} + +menubutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +menubutton arrow { + min-height: 16px; + min-width: 16px; +} + +menubutton arrow.none { + -gtk-icon-source: -gtk-icontheme("open-menu-symbolic"); +} + +menubutton arrow.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menubutton arrow.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menubutton arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +menubutton arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +splitbutton { + border-radius: 12px; +} + +splitbutton, splitbutton > separator { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + transition-property: background; +} + +splitbutton > separator { + margin-top: 6px; + margin-bottom: 6px; + background: none; +} + +splitbutton > menubutton > button { + padding: 5px 9px; +} + +splitbutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +splitbutton.text-button.image-button > button, splitbutton.image-text-button > button { + padding-left: 9px; + padding-right: 9px; +} + +splitbutton.text-button.image-button > button > box, splitbutton.image-text-button > button > box { + border-spacing: 6px; +} + +splitbutton > button:dir(ltr), +splitbutton > menubutton > button:dir(rtl) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: -1px; +} + +splitbutton > button:dir(rtl), +splitbutton > menubutton > button:dir(ltr) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin-left: -1px; +} + +splitbutton.flat > separator { + background: rgba(239, 241, 245, 0.12); +} + +splitbutton.flat:hover, splitbutton.flat:active, splitbutton.flat:checked { + background: alpha(currentColor, 0.07); +} + +splitbutton.flat:hover > separator, splitbutton.flat:active > separator, splitbutton.flat:checked > separator { + background: none; +} + +splitbutton.flat:focus-within:focus-visible > separator { + background: none; +} + +splitbutton.flat > button, +splitbutton.flat > menubutton > button { + border-radius: 12px; +} + +splitbutton.suggested-action { + background-color: #1e66f5; + color: #eff1f5; +} + +splitbutton.destructive-action { + background-color: #d20f39; + color: #eff1f5; +} + +splitbutton.opaque { + background-color: #484856; + color: #eff1f5; +} + +splitbutton.suggested-action > button, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button, +splitbutton.opaque > menubutton > button:checked { + color: inherit; + background-color: transparent; +} + +splitbutton.suggested-action > menubutton > button:dir(ltr), splitbutton.destructive-action > menubutton > button:dir(ltr), splitbutton.opaque > menubutton > button:dir(ltr) { + box-shadow: inset 1px 0 rgba(239, 241, 245, 0.12); +} + +splitbutton.suggested-action > menubutton > button:dir(rtl), splitbutton.destructive-action > menubutton > button:dir(rtl), splitbutton.opaque > menubutton > button:dir(rtl) { + box-shadow: inset -1px 0 rgba(239, 241, 245, 0.12); +} + +splitbutton > menubutton > button > arrow.none { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +buttoncontent { + border-spacing: 6px; +} + +buttoncontent > label { + font-weight: bold; +} + +buttoncontent > label:dir(ltr) { + padding-right: 2px; +} + +buttoncontent > label:dir(rtl) { + padding-left: 2px; +} + +.arrow-button > box > buttoncontent > label:dir(ltr), splitbutton > button > buttoncontent > label:dir(ltr) { + padding-right: 0; +} + +.arrow-button > box > buttoncontent > label:dir(rtl), splitbutton > button > buttoncontent > label:dir(rtl) { + padding-left: 0; +} + +stacksidebar row.needs-attention > label, stackswitcher > button.needs-attention > label, +stackswitcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar row.needs-attention > label:dir(rtl), stackswitcher > button.needs-attention > label:dir(rtl), +stackswitcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +.linked:not(.vertical) > entry, .linked:not(.vertical) > button, .linked:not(.vertical) > button.image-button { + border-radius: 0; +} + +.linked:not(.vertical) > entry:first-child, .linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > entry:last-child, .linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > entry:only-child, .linked:not(.vertical) > button:only-child { + border-radius: 12px; +} + +.linked.vertical > entry, .linked.vertical > button, .linked.vertical > button.image-button { + border-radius: 0; +} + +.linked.vertical > entry:first-child, .linked.vertical > button:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > entry:last-child, .linked.vertical > button:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > entry:only-child, .linked.vertical > button:only-child { + border-radius: 12px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + + +list > row button.image-button:not(.flat) { + background-color: transparent; + box-shadow: none; + border: none; +} + + +list > row button.image-button:not(.flat):hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + + +list > row button.image-button:not(.flat):active, +list > row button.image-button:not(.flat):checked { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + + +list > row button.image-button:not(.flat).suggested-action { + background-color: #1e66f5; + color: #eff1f5; +} + + +list > row button.image-button:not(.flat).destructive-action { + background-color: #d20f39; + color: #eff1f5; +} + +/********* + * Links * + *********/ +link { + color: #8fcbe8; +} + +link:visited { + color: #8839ef; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #8fcbe8; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #8839ef; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton { + border-radius: 9px; + padding: 0; + border-spacing: 0; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #89b4fa; +} + +spinbutton:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton > text { + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + margin: 0; +} + +spinbutton > button { + border: none; +} + +spinbutton > button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: none; +} + +spinbutton:not(.vertical) > text { + min-width: 30px; + padding-left: 12px; +} + +spinbutton:not(.vertical) > button { + padding: 0; + margin: 6px; +} + +spinbutton:not(.vertical) > button.up:dir(ltr), spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 3px; +} + +spinbutton:not(.vertical) > button.up:dir(rtl), spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 3px; +} + +cell.activatable spinbutton:not(.vertical) { + margin: 3px 0; +} + +cell.activatable spinbutton:not(.vertical) > button { + margin: 0; + padding: 0; + min-height: 24px; + border-radius: 0; +} + +cell.activatable spinbutton:not(.vertical) > button:last-child { + border-radius: 0 12px 12px 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(ltr), cell.activatable spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(rtl), cell.activatable spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 0; +} + +spinbutton.vertical > text { + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical > button { + padding: 0; + margin: 6px 8px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #fab387; + box-shadow: inset 0 0 0 2px #fab387; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #eff1f5; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top, combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +.toolbar { + padding: 6px; + /* background-color: $background; */ + border-spacing: 6px; +} + +.osd .toolbar { + background-color: transparent; +} + +.app-notification, .toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 18px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; + color: #eff1f5; +} + +.app-notification:backdrop, .toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +.left.app-notification, .right.app-notification, .top.app-notification, .bottom.app-notification, .toolbar.osd.left, .toolbar.osd.right, .toolbar.osd.top, .toolbar.osd.bottom { + border-radius: 0; +} + +.bottom.app-notification, .toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +.toolbar.horizontal > separator { + margin: 2px; +} + +.toolbar.vertical > separator { + margin: 2px; +} + +.toolbar entry, +.toolbar spinbutton, +.toolbar splitbutton, +.toolbar separator:not(.sidebar), +.toolbar button, +.toolbar menubutton, +.toolbar scalebutton { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar menubutton > button, +.toolbar splitbutton > button, +.toolbar splitbutton > menubutton, +.toolbar scalebutton > button { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar switch { + margin-top: 4px; + margin-bottom: 4px; +} + +.toolbar spinbutton entry, +.toolbar spinbutton button { + margin: 0; +} + +.toolbar popover.menu separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +searchbar > revealer > box { + padding: 6px; + border-spacing: 0; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; + background-clip: border-box; + box-shadow: none; +} + +searchbar > revealer > box entry, +searchbar > revealer > box button, +searchbar > revealer > box menubutton { + margin: 0; +} + +/*************** + * Header bars * + ***************/ +headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); + border: none; +} + +headerbar button:hover:not(.suggested-action):not(.destructive-action), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), headerbar button:active:not(.suggested-action):not(.destructive-action), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(239, 241, 245, 0.5); +} + +headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.5); +} + +headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +headerbar entry { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.7); +} + +headerbar entry:hover, headerbar entry:focus-within { + color: #eff1f5; +} + +headerbar entry:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +headerbar entry > text > placeholder { + color: rgba(239, 241, 245, 0.5); +} + +headerbar entry > text > block-cursor { + color: rgba(239, 241, 245, 0.04); + background-color: #eff1f5; +} + +headerbar entry > image { + color: rgba(239, 241, 245, 0.7); +} + +headerbar entry > image:hover, headerbar entry > image:active { + color: #eff1f5; +} + +headerbar entry > image:disabled { + color: rgba(239, 241, 245, 0.5); +} + +headerbar { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: transparent; + color: #eff1f5; + min-height: 46px; + border: none; + box-shadow: none; + padding: 0; + margin: 0; +} + +headerbar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +headerbar:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.7); + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +headerbar:backdrop:disabled { + color: rgba(239, 241, 245, 0.32); +} + +headerbar.flat, headerbar.flat:backdrop { + background: none; + box-shadow: none; + transition: none; +} + +headerbar .title { + padding-left: 6px; + padding-right: 6px; + margin: 0 -13px; + font-weight: bold; +} + +headerbar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +headerbar .subtitle, +headerbar .dim-label, +headerbar row.expander image.expander-row-arrow, +row.expander headerbar image.expander-row-arrow, +headerbar row.property > box.header > box.title > .title, +headerbar row label.subtitle, +row headerbar label.subtitle { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(239, 241, 245, 0.7); +} + +headerbar .subtitle:backdrop, +headerbar .dim-label:backdrop, +headerbar row.expander image.expander-row-arrow:backdrop, +row.expander headerbar image.expander-row-arrow:backdrop, +headerbar row.property > box.header > box.title > .title:backdrop, +headerbar row label.subtitle:backdrop, +row headerbar label.subtitle:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +headerbar .titlebar { + background-color: transparent; + box-shadow: none; +} + +headerbar headerbar + separator { + background-color: rgba(239, 241, 245, 0.12); +} + +headerbar > windowhandle > box { + padding: 0 6px; +} + +headerbar > windowhandle > box, +headerbar > windowhandle > box > box.start, +headerbar > windowhandle > box > box.end { + border-spacing: 6px; +} + +headerbar entry, +headerbar spinbutton, +headerbar splitbutton, +headerbar button, +headerbar menubutton, +headerbar stackswitcher, +headerbar separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar menubutton > button, +headerbar spinbutton > button, +headerbar splitbutton > button, +headerbar splitbutton > menubutton, +headerbar .linked > menubutton, +headerbar entry > menubutton { + margin-top: 0; + margin-bottom: 0; +} + +headerbar button.suggested-action:disabled, +headerbar button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + opacity: 1; +} + +headerbar button.star { + min-height: 24px; + min-width: 24px; + padding: 5px; +} + +headerbar .linked:not(.vertical) > entry:not(:only-child) { + border-radius: 12px; +} + +headerbar .entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar popover.background button.suggested-action:disabled, +headerbar popover.background button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +headerbar popover.background entry, +headerbar popover.background spinbutton, +headerbar popover.background button, +headerbar popover.background menubutton, +headerbar popover.background stackswitcher { + margin-top: 0; + margin-bottom: 0; +} + +headerbar separator:not(.sidebar) { + background-color: rgba(239, 241, 245, 0.12); +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +headerbar.selection-mode:backdrop { + color: rgba(30, 30, 46, 0.6); +} + +headerbar.selection-mode .subtitle:link { + color: rgba(30, 30, 46, 0.87); +} + +headerbar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +headerbar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +headerbar.default-decoration { + min-height: 34px; + padding: 0; + margin: 0; + border: none; + outline: none; +} + +headerbar.default-decoration windowcontrols > button { + min-width: 16px; + min-height: 16px; + margin: 0 4px; + padding: 0; + /* @if $window_button == 'mac' { */ + /* min-width: 16px; */ + /* min-height: 16px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } @else { */ + /* min-width: 22px; */ + /* min-height: 22px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } */ +} + +headerbar.default-decoration windowcontrols menubutton button { + min-height: 20px; + min-width: 20px; + margin: 0; + padding: 4px; +} + +.maximized headerbar, .fullscreen headerbar, .tiled headerbar, .tiled-top headerbar, .tiled-right headerbar, .tiled-bottom headerbar, .tiled-left headerbar { + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.maximized headerbar.default-decoration, .fullscreen headerbar.default-decoration, .tiled headerbar.default-decoration, .tiled-top headerbar.default-decoration, .tiled-right headerbar.default-decoration, .tiled-bottom headerbar.default-decoration, .tiled-left headerbar.default-decoration { + box-shadow: none; +} + +.solid-csd headerbar:dir(rtl), .solid-csd headerbar:dir(ltr) { + border-radius: 0; + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.titlebar:not(headerbar) { + box-shadow: none; +} + +window.devel headerbar { + background: #1e1e2e cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, linear-gradient(to right, transparent 65%, rgba(137, 180, 250, 0.1)), linear-gradient(to top, #242437 3px, #28283d); +} + +window.devel headerbar:backdrop { + background: #1e1e2e cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, image(#1e1e2e); + /* background-color would flash */ +} + +/************ + * Pathbars * + ************/ +.pathbar { + background-color: alpha(currentColor, 0.08); + border-radius: 12px; + padding: 0; +} + +.pathbar button { + margin: 0; +} + +headerbar .pathbar button { + margin: 0; +} + +/************** + * Tree Views * + **************/ +columnview.view, +treeview.view { + border-left-color: #4a4b5a; + border-top-color: #4a4b5a; +} + +columnview.view:hover, columnview.view:selected, +treeview.view:hover, +treeview.view:selected { + border-radius: 0; +} + +columnview.view:focus, +treeview.view:focus { + box-shadow: none; + outline: none; +} + +columnview.view.separator, +treeview.view.separator { + min-height: 5px; + color: rgba(239, 241, 245, 0.12); +} + +columnview.view:drop(active), +treeview.view:drop(active) { + box-shadow: none; +} + +columnview.view:drop(active).after, +treeview.view:drop(active).after { + border-top-style: none; +} + +columnview.view:drop(active).before, +treeview.view:drop(active).before { + border-bottom-style: none; +} + +columnview.view > dndtarget:drop(active), +treeview.view > dndtarget:drop(active) { + border-style: solid none; + border-width: 1px; + border-color: alpha(currentColor, 0.06); +} + +columnview.view > dndtarget:drop(active).after, +treeview.view > dndtarget:drop(active).after { + border-top-style: none; +} + +columnview.view > dndtarget:drop(active).before, +treeview.view > dndtarget:drop(active).before { + border-bottom-style: none; +} + +columnview.view.expander, +treeview.view.expander { + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + color: rgba(239, 241, 245, 0.7); +} + +columnview.view.expander:dir(rtl), +treeview.view.expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +columnview.view.expander:hover, +treeview.view.expander:hover { + color: #eff1f5; +} + +columnview.view.expander:selected, +treeview.view.expander:selected { + color: #eff1f5; +} + +columnview.view.expander:selected:hover, +treeview.view.expander:selected:hover { + color: #eff1f5; +} + +columnview.view.expander:checked, +treeview.view.expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +columnview.view.expander:disabled, +treeview.view.expander:disabled { + color: rgba(239, 241, 245, 0.32); +} + +columnview.view.progressbar, +treeview.view.progressbar { + border-bottom: 6px solid #89b4fa; + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.progressbar:selected:hover, +treeview.view.progressbar:selected:hover { + box-shadow: none; +} + +columnview.view.trough, +treeview.view.trough { + border-bottom: 6px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.trough:selected:hover, +treeview.view.trough:selected:hover { + box-shadow: none; +} + +columnview.view > header > button, +treeview.view > header > button { + padding: 2px 6px; + border-style: none solid solid none; + border-width: 0 1px 0 0; + border-color: transparent; + border-radius: 0; + background-clip: border-box; +} + +columnview.view > header > button:not(:focus):not(:hover):not(:active), +treeview.view > header > button:not(:focus):not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +columnview.view > header > button, columnview.view > header > button:disabled, +treeview.view > header > button, +treeview.view > header > button:disabled { + background-color: transparent; +} + +columnview.view > header > button:last-child, +treeview.view > header > button:last-child { + border-right-style: none; +} + +columnview.view button.dnd, +columnview.view header.button.dnd, +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #313244; + background-clip: border-box; + color: #89b4fa; +} + +columnview.view acceleditor > label, +treeview.view acceleditor > label { + background-color: #89b4fa; +} + +stack.view treeview.view { + min-height: 34px; +} + +/********* + * Menus * + *********/ +menubar { + padding: 0; + background-color: #1e1e2e; + color: #eff1f5; +} + +menubar:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.7); +} + +.csd menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + padding: 4px 8px; + color: rgba(239, 241, 245, 0.7); +} + +menubar > item:selected { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +menubar > item:disabled { + color: rgba(239, 241, 245, 0.32); +} + +menubar > item label:disabled { + color: inherit; +} + +menubar > item popover.menu popover.menu { + margin-left: 9px; +} + +menubar > item popover.menu.background popover.menu.background > contents { + margin: 0; + border-radius: 12px; +} + +/********************** + * Popover Base Menus * + **********************/ +popover.menu box.inline-buttons { + color: #eff1f5; + padding: 0 6px; +} + +popover.menu box.inline-buttons button.image-button.model { + min-height: 28px; + min-width: 28px; + padding: 0; + border: none; + outline: none; + transition: none; +} + +popover.menu box.inline-buttons button.image-button.model:selected { + background: image(alpha(currentColor, 0.06)); +} + +popover.menu box.circular-buttons { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model:focus { + background-color: alpha(currentColor, 0.06); +} + +popover.menu arrow.left, +popover.menu radio.left, +popover.menu check.left { + margin-left: 0; + margin-right: 0; +} + +popover.menu arrow.right, +popover.menu radio.right, +popover.menu check.right { + margin-left: 0; + margin-right: 0; +} + +popover.menu label.title { + font-weight: bold; + padding: 4px 26px; +} + +/************ + * Popovers * + ************/ +popover.background { + font: initial; +} + +popover.background, popover.background:backdrop { + background-color: transparent; +} + +popover > arrow, +popover > contents { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + background-color: #232634; + border-radius: 12px; + color: #eff1f5; + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +popover > arrow { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +popover > contents > list, +popover > contents > .view, +popover > contents > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover > contents separator { + background-color: rgba(239, 241, 245, 0.12); + margin: 15px 10px; +} + +popover > contents list separator { + margin: 0; +} + +popover > contents list > row { + border-radius: 12px; +} + +popover > contents stack > box { + padding: 0; +} + +popover > contents > box > button { + margin: 0; +} + +popover .view:not(:selected), +popover toolbar { + background-color: #232634; +} + +popover button, +popover entry, +popover combobox { + border-radius: 12px; +} + +popover .linked > button:not(.radio) { + border-radius: 0; +} + +popover .linked > button:not(.radio):first-child { + border-radius: 12px 0 0 12px; +} + +popover .linked > button:not(.radio):last-child { + border-radius: 0 12px 12px 0; +} + +popover .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.menu button, +popover button.model { + min-height: 32px; + padding: 0 8px; +} + +popover modelbutton { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 22px; + min-width: 56px; + padding: 3px 9px; + color: #eff1f5; + font: initial; + border-radius: 12px; +} + +popover modelbutton:hover { + transition: none; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +popover modelbutton:hover accelerator { + color: #89b4fa; +} + +popover modelbutton:hover accelerator:disabled { + color: rgba(239, 241, 245, 0.5); +} + +popover modelbutton:focus:not(:hover) { + transition: none; + box-shadow: none; + outline: none; +} + +popover modelbutton:disabled { + color: rgba(239, 241, 245, 0.5); +} + +popover modelbutton accelerator { + color: rgba(239, 241, 245, 0.5); + margin-left: 30px; +} + +popover modelbutton accelerator:disabled { + color: rgba(239, 241, 245, 0.12); +} + +popover modelbutton arrow.left { + -gtk-icon-source: -gtk-icontheme("go-previous-symbolic"); +} + +popover modelbutton arrow.right { + -gtk-icon-source: -gtk-icontheme("go-next-symbolic"); +} + +.osd popover, popover.touch-selection, popover.magnifier { + background-color: transparent; +} + +magnifier { + background-color: #313244; +} + +/************* + * Notebooks * + *************/ +notebook > header > tabs > tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +notebook > header > tabs > tab:hover:not(:checked):not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +notebook > header > tabs > tab:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +notebook > header > tabs > tab:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; + background-color: #313244; + color: #eff1f5; + box-shadow: none; +} + +notebook > header > tabs > tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +notebook > header > tabs > tab:checked:disabled { + color: rgba(239, 241, 245, 0.5); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: rgba(239, 241, 245, 0.04); +} + +notebook, notebook.frame { + background-color: #313244; + background-color: rgba(239, 241, 245, 0.04); + border-radius: 15px; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(239, 241, 245, 0.04); + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header > tabs > tab { + margin: 3px; +} + +notebook > header > tabs > tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header > tabs > tab > box:drop(active) { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +notebook > header > tabs > tab button.flat:last-child { + margin-left: 6px; + margin-right: -3px; +} + +notebook > header > tabs > tab button.flat:first-child { + margin-left: -3px; + margin-right: 6px; +} + +notebook > header > tabs > tab button.close-button { + min-width: 24px; + min-height: 24px; +} + +notebook > header.top > tabs, notebook > header.bottom > tabs { + padding-left: 0; + padding-right: 0; +} + +notebook > header.top > tabs:not(:only-child):first-child, notebook > header.bottom > tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top > tabs:not(:only-child):last-child, notebook > header.bottom > tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top > tabs > tab:not(:last-child), notebook > header.bottom > tabs > tab:not(:last-child) { + margin-right: 0; +} + +notebook > header.top > tabs tab.reorderable-page, notebook > header.bottom > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left > tabs, notebook > header.right > tabs { + padding-top: 0; + padding-bottom: 0; +} + +notebook > header.left > tabs:not(:only-child):first-child, notebook > header.right > tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left > tabs:not(:only-child):last-child, notebook > header.right > tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left > tabs > tab:not(:last-child), notebook > header.right > tabs > tab:not(:last-child) { + margin-bottom: 0; +} + +notebook > header.left > tabs tab.reorderable-page, notebook > header.right > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > menubutton > button.image-button { + padding: 3px; + min-width: 24px; + min-height: 24px; + margin: 0 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +tabbar tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(239, 241, 245, 0.7); +} + +tabbar tab:hover:not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +tabbar tab:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +tabbar tab:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; + box-shadow: none; + color: #eff1f5; +} + +tabbar tab:selected:not(:active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbar tab:selected:not(:active):disabled { + color: rgba(239, 241, 245, 0.5); +} + +tabbar > revealer > box { + box-shadow: none; +} + +tabbar .box { + background-color: #1e1e2e; + background-image: none; + padding: 0; + margin: 0; + border-radius: 0; + min-height: 34px; + border: none; + /* box-shadow: inset 0 -1px $border; */ +} + +tabbar .box:backdrop { + background-color: #1e1e2e; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabbar .box:backdrop > scrolledwindow, +tabbar .box:backdrop > .start-action, +tabbar .box:backdrop > .end-action { + filter: none; + transition: none; +} + +tabbar tabbox { + padding: 0; + margin: 0; + min-height: 34px; +} + +tabbar tabbox > background { + background: none; +} + +tabbar tabbox > separator { + margin: 9px 0; + transition: opacity 150ms ease-in-out; +} + +tabbar tabbox > separator.hidden { + opacity: 0; +} + +tabbar tabbox > tabboxchild { + padding: 0; + margin: 0; +} + +tabbar tab { + padding: 6px; + margin: 6px 2px; +} + +tabbar tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#89b4fa, 0.4) 10%, alpha(#89b4fa, 0) 30%); +} + +tabbar tab.needs-attention:hover { + background-image: image(alpha(currentColor, 0.03)), radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#89b4fa, 0.4) 10%, alpha(#89b4fa, 0) 30%); +} + +tabbar tabbox.single-tab tab, tabbar tabbox.single-tab tab:hover, tabbar tabbox.single-tab tab:active { + background: none; +} + +tabbar undershoot { + transition: background 150ms ease-in-out; +} + +tabbar undershoot.left { + background: linear-gradient(to right, #313244, rgba(0, 0, 0, 0) 20px); +} + +tabbar undershoot.right { + background: linear-gradient(to left, #313244, rgba(0, 0, 0, 0) 20px); +} + +tabbar .needs-attention-left undershoot.left { + background: linear-gradient(to right, alpha(#89b4fa, 0.5), alpha(#89b4fa, 0.3) 1px, alpha(#89b4fa, 0) 20px); +} + +tabbar .needs-attention-right undershoot.right { + background: linear-gradient(to left, alpha(#89b4fa, 0.5), alpha(#89b4fa, 0.3) 1px, alpha(#89b4fa, 0) 20px); +} + +tabbar .start-action, +tabbar .end-action { + padding: 6px 5px; +} + +tabbar .start-action:dir(ltr), +tabbar .end-action:dir(rtl) { + padding-right: 0; +} + +tabbar .start-action:dir(rtl), +tabbar .end-action:dir(ltr) { + padding-left: 0; +} + +tabbar.inline .box { + background-color: transparent; + color: inherit; + box-shadow: none; + padding-bottom: 0; +} + +tabbar.inline .box:backdrop { + background-color: transparent; + transition: none; +} + +tabbar.inline .box:backdrop > scrolledwindow, +tabbar.inline .box:backdrop > .start-action, +tabbar.inline .box:backdrop > .end-action { + filter: none; + transition: none; +} + +dnd tab { + min-height: 24px; + background-color: #1e1e2e; + color: #eff1f5; + box-shadow: 0 1px 5px 1px rgba(0, 0, 0, 0.09), 0 2px 14px 3px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.05); + outline: 1px solid rgba(30, 30, 46, 0.75); + outline-offset: -1px; + margin: 24px; +} + +dnd tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#89b4fa, 0.4) 10%, alpha(#89b4fa, 0) 30%); +} + +tabbar tab, +dnd tab { + padding: 6px; +} + +tabbar tab button.image-button, +dnd tab button.image-button { + padding: 0; + margin: 0; + min-width: 24px; + min-height: 24px; + border-radius: 9999px; + color: rgba(239, 241, 245, 0.7); +} + +tabbar tab button.image-button:hover, tabbar tab button.image-button:active, +dnd tab button.image-button:hover, +dnd tab button.image-button:active { + color: #eff1f5; +} + +tabbar tab button.image-button:disabled, +dnd tab button.image-button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +tabbar tab indicator, +dnd tab indicator { + min-height: 2px; + border-radius: 2px; + background: alpha(#89b4fa, 0.5); + transform: translateY(4px); +} + +tabthumbnail { + border-radius: 12px; + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabthumbnail > box { + margin: 6px; +} + +tabthumbnail:drop(active) { + box-shadow: inset 0 0 0 2px alpha(#fab387, 0.4); + background-color: alpha(#fab387, 0.1); +} + +tabthumbnail .needs-attention:dir(ltr) { + transform: translate(8px, -8px); +} + +tabthumbnail .needs-attention:dir(rtl) { + transform: translate(-8px, -8px); +} + +tabthumbnail .needs-attention > widget { + background: #89b4fa; + min-width: 12px; + min-height: 12px; + border-radius: 9px; + margin: 3px; + box-shadow: 0 1px 2px alpha(#89b4fa, 0.4); +} + +tabthumbnail .card { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +tabthumbnail .card picture { + outline: 1px solid rgba(239, 241, 245, 0.12); + outline-offset: -1px; + border-radius: 12px; +} + +tabthumbnail.pinned .card { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +tabthumbnail .icon-title-box { + border-spacing: 6px; +} + +tabthumbnail .tab-unpin-icon { + margin: 6px; + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular { + margin: 6px; + background-color: rgba(239, 241, 245, 0.04); + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular:hover { + background-color: alpha(currentColor, 0.08); +} + +tabthumbnail button.circular:active { + background-color: alpha(currentColor, 0.12); +} + +taboverview > .overview .new-tab-button { + margin: 18px; +} + +tabview:drop(active), +tabbox:drop(active), +tabgrid:drop(active) { + box-shadow: none; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); + outline: none; +} + +scrollbar, +scrollbar button { + border: none; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar > range > trough { + background: none; + padding: 0; + margin: 0; + border: none; + outline: none; + transition: none; +} + +scrollbar > range > trough > slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 9999px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(239, 241, 245, 0.5); +} + +scrollbar > range > trough > slider:hover { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar > range > trough > slider:active { + background-color: rgba(239, 241, 245, 0.7); +} + +scrollbar > range > trough > slider:disabled { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar > range.fine-tune > trough > slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.overlay-indicator { + background: none; + color: inherit; + box-shadow: none; + padding: 0; +} + +scrollbar.overlay-indicator > range > trough { + outline: none; + background-color: rgba(239, 241, 245, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator > range > trough > slider { + outline: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; + border-color: transparent; + background-color: transparent; + box-shadow: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough { + background-color: transparent; + border: none; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough > slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical > range > trough > slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.vertical > range > trough > slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + padding: 0; + border: none; + border-radius: 9999px; + background-color: rgba(239, 241, 245, 0.5); + background-clip: border-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #89b4fa; +} + +switch:disabled { + opacity: 0.5; +} + +switch > slider { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 0 0 0 transparent, 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #eff1f5; + border: none; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12), 0 3px 3px -2px transparent, 0 2px 3px -1px transparent, 0 1px 4px 0 transparent; +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; + border-spacing: 3px; +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + border: none; + color: transparent; + background-color: rgba(239, 241, 245, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.04); + background-color: rgba(239, 241, 245, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(239, 241, 245, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(30, 30, 46, 0.6); + background-color: #89b4fa; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.15); + background-color: #bad3fc; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.2); + background-color: #89b4fa; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(30, 30, 46, 0.6); + background-color: rgba(137, 180, 250, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu radio { + transition: none; + margin: 0; + padding: 0; +} + +popover.menu check:dir(ltr), popover.menu radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +popover.menu check:dir(rtl), popover.menu radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu check:hover, popover.menu check:disabled, popover.menu check:checked:hover, popover.menu check:indeterminate:hover, popover.menu radio, popover.menu radio:hover, popover.menu radio:disabled, popover.menu radio:checked:hover, popover.menu radio:indeterminate:hover { + box-shadow: none; +} + + +check { + -gtk-icon-size: 20px; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/checkbox-mixed-symbolic@2.svg"))); +} + + +radio { + -gtk-icon-size: 20px; +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/radio-mixed-symbolic@2.svg"))); +} + + +popover.menu check { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-checked-symbolic@2.svg"))); +} + + +popover.menu check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-mixed-symbolic@2.svg"))); +} + + +popover.menu radio { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/small-radio-checked-symbolic@2.svg"))); +} + + +popover.menu radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view radio, +treeview.view check, +columnview.view radio, +columnview.view check { + padding: 0; + margin: 0; + transition: none; +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover, +columnview.view radio, +columnview.view radio:hover, +columnview.view radio:disabled, +columnview.view radio:checked:hover, +columnview.view radio:indeterminate:hover, +columnview.view check, +columnview.view check:hover, +columnview.view check:disabled, +columnview.view check:checked:hover, +columnview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view:hover check, +treeview.view:hover radio, treeview.view:selected check, +treeview.view:selected radio, treeview.view:focus check, +treeview.view:focus radio, +columnview.view:hover check, +columnview.view:hover radio, +columnview.view:selected check, +columnview.view:selected radio, +columnview.view:focus check, +columnview.view:focus radio { + box-shadow: none; +} + +treeview.view:hover check:checked, +treeview.view:hover radio:checked, treeview.view:selected check:checked, +treeview.view:selected radio:checked, treeview.view:focus check:checked, +treeview.view:focus radio:checked, +columnview.view:hover check:checked, +columnview.view:hover radio:checked, +columnview.view:selected check:checked, +columnview.view:selected radio:checked, +columnview.view:focus check:checked, +columnview.view:focus radio:checked { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +checkbutton.selection-mode { + border-radius: 9999px; +} + +checkbutton.selection-mode check, +checkbutton.selection-mode radio { + padding: 6px; + border-radius: 9999px; +} + +checkbutton.selection-mode check:checked, checkbutton.selection-mode check:indeterminate, +checkbutton.selection-mode radio:checked, +checkbutton.selection-mode radio:indeterminate { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +checkbutton.selection-mode label:dir(ltr) { + margin-right: 6px; +} + +checkbutton.selection-mode label:dir(rtl) { + margin-left: 6px; +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale > trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(239, 241, 245, 0.3); +} + +scale > trough:disabled { + background-color: rgba(239, 241, 245, 0.12); +} + +scale > trough > highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#89b4fa); +} + +scale > trough > highlight:disabled { + background-color: #1e1e2e; + background-image: image(rgba(239, 241, 245, 0.32)); +} + +scale > trough > fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.3); +} + +scale > trough > fill:disabled { + background-color: transparent; +} + +scale > trough > slider { + min-height: 18px; + min-width: 18px; + margin: -8px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #89b4fa; + background-color: #313244; + box-shadow: inset 0 0 0 2px #89b4fa; +} + +scale > trough > slider:hover { + box-shadow: inset 0 0 0 2px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale > trough > slider:active { + box-shadow: inset 0 0 0 4px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale > trough > slider:disabled { + box-shadow: inset 0 0 0 2px rgba(239, 241, 245, 0.32); +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune > trough > slider { + margin: -7px; +} + +scale > marks, +scale > value { + color: rgba(239, 241, 245, 0.7); +} + +scale indicator { + background-color: rgba(239, 241, 245, 0.3); + color: transparent; +} + +scale.marks-before:not(.marks-after) > trough > slider, scale.marks-after:not(.marks-before) > trough > slider { + transform: rotate(45deg); + border-bottom-right-radius: 0; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal > trough > slider:dir(ltr), scale.color.horizontal > trough > slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) > trough > slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(239, 241, 245, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #89b4fa; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; + box-shadow: none; + margin: 0; + padding: 0; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #89b4fa; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #df8e1d; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #89b4fa; +} + +levelbar block.full { + background-color: #40a02b; +} + +levelbar block.empty { + background-color: rgba(239, 241, 245, 0.12); +} + +/**************** + * Print dialog * +*****************/ +window.dialog.print drawing { + color: #eff1f5; + background: none; + border: none; + padding: 0; +} + +window.dialog.print drawing paper { + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; + color: #eff1f5; +} + +window.dialog.print .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame, +.frame { + border: 1px solid rgba(239, 241, 245, 0.12); +} + +frame > list, +.frame > list { + border: none; +} + +frame.view, +.frame.view { + border-radius: 12px; +} + +frame.flat, +.frame.flat { + border-style: none; +} + +frame { + border-radius: 12px; +} + +frame > label { + margin: 4px; +} + +frame.flat > border, statusbar frame > border { + border: none; +} + +actionbar { + box-shadow: none; +} + +actionbar > revealer > box { + padding: 6px; + border-spacing: 6px; + box-shadow: none; + /* background-color: $base; */ + background-color: rgba(239, 241, 245, 0.04); + background-clip: border-box; + border: none; + color: #eff1f5; +} + +actionbar > revealer > box button, +actionbar > revealer > box entry, +actionbar > revealer > box menubutton, +actionbar > revealer > box menubutton > button, +actionbar > revealer > box splitbutton, +actionbar > revealer > box splitbutton > button, +actionbar > revealer > box spinbutton { + margin: 0; +} + +statusbar { + padding: 6px 18px; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +scrolledwindow > overshoot.top { + background-image: radial-gradient(farthest-side at top, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at top, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: top; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.bottom { + background-image: radial-gradient(farthest-side at bottom, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at bottom, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.left { + background-image: radial-gradient(farthest-side at left, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at left, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: left; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.right { + background-image: radial-gradient(farthest-side at right, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at right, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: right; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow.undershoot-top > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 0px 0px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow > undershoot { + background-image: none; + box-shadow: none; + border: none; +} + +separator { + min-width: 1px; + min-height: 1px; + background-color: transparent; +} + +stacksidebar + separator.vertical, +stacksidebar separator.horizontal, button.font separator, button.file separator, separator.spacer, separator.sidebar { + min-width: 0; + min-height: 0; + background-color: transparent; + background-image: none; +} + +/********* + * Lists * + *********/ +list.content, +list.boxed-list { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); +} + +listview, +list { + border-color: rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); + background-clip: padding-box; +} + +listview > row, +list > row { + padding: 6px; + background-clip: padding-box; +} + +listview > row.expander, +list > row.expander { + padding: 0px; +} + +listview > row.expander .row-header, +list > row.expander .row-header { + padding: 2px; +} + +listview.horizontal row.separator:not(:last-child), listview.separators.horizontal > row:not(.separator):not(:last-child), +list.horizontal row.separator:not(:last-child), +list.separators.horizontal > row:not(.separator):not(:last-child) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +listview:not(.horizontal) row.separator:not(:last-child), listview.separators:not(.horizontal) > row:not(.separator):not(:last-child), +list:not(.horizontal) row.separator:not(:last-child), +list.separators:not(.horizontal) > row:not(.separator):not(:last-child) { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +list.frame { + border-radius: 12px; +} + +listview.view { + color: #eff1f5; + background-color: transparent; +} + +popover.menu listview.view { + padding: 0; + border-radius: 12px; +} + +popover.menu listview.view > row { + margin-left: 0; + margin-right: 0; + border-radius: 12px; +} + +row { + color: rgba(239, 241, 245, 0.7); + background-clip: padding-box; +} + +.nautilus-window .nautilus-grid-view child.activatable, +.nautilus-window .nautilus-list-view child.activatable, columnview.view > header > button, +treeview.view > header > button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), font-weight 0; + outline: none; + box-shadow: none; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.nautilus-window .nautilus-grid-view child.activatable:focus, +.nautilus-window .nautilus-list-view child.activatable:focus, columnview.view > header > button:focus, +treeview.view > header > button:focus, row.activatable:focus { + color: #eff1f5; + background-color: transparent; + box-shadow: none; + outline: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:hover, +.nautilus-window .nautilus-list-view child.activatable:hover, columnview.view > header > button:hover, +treeview.view > header > button:hover, .nautilus-window .nautilus-grid-view child.has-open-popup.activatable, +.nautilus-window .nautilus-list-view child.has-open-popup.activatable, columnview.view > header > button.has-open-popup, +treeview.view > header > button.has-open-popup, row.activatable:hover, row.activatable.has-open-popup { + color: #eff1f5; + background-color: alpha(currentColor, 0.05); + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:active, +.nautilus-window .nautilus-list-view child.activatable:active, columnview.view > header > button:active, +treeview.view > header > button:active, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, font-weight 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; + background-color: alpha(currentColor, 0.05); + color: #eff1f5; + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:selected, +.nautilus-window .nautilus-list-view child.activatable:selected, columnview.view > header > button:selected, +treeview.view > header > button:selected, row.activatable:selected { + background-color: alpha(currentColor, 0.06); +} + +.nautilus-window .nautilus-grid-view child.activatable:selected:hover, +.nautilus-window .nautilus-list-view child.activatable:selected:hover, columnview.view > header > button:selected:hover, +treeview.view > header > button:selected:hover, row.activatable:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +button row.activatable:focus, button row.activatable:hover, button row.activatable:active { + box-shadow: none; + background: none; +} + +button:checked row.activatable { + color: rgba(30, 30, 46, 0.87); +} + +row:selected { + background-color: alpha(currentColor, 0.06); + color: #eff1f5; + box-shadow: none; +} + +row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus, row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus:hover, row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.rich-list { + /* rich lists usually containing other widgets than just labels/text */ +} + +.rich-list > row { + padding: 9px 12px; + min-height: 32px; + /* should be tall even when only containing a label */ +} + +.rich-list > row:last-child { + border-bottom: none; +} + +.rich-list > row > box { + border-spacing: 12px; +} + +row label.subtitle { + font-size: smaller; +} + +row > box.header { + margin-left: 12px; + margin-right: 12px; + border-spacing: 6px; + min-height: 50px; +} + +row > box.header > .icon:disabled { + filter: opacity(0.45); +} + +row > box.header > box.title { + margin-top: 6px; + margin-bottom: 6px; + border-spacing: 3px; + padding: 0; +} + +row > box.header > box.title, +row > box.header > box.title > .title, +row > box.header > box.title > .subtitle { + padding: 0; + font-weight: inherit; +} + +row > box.header > .prefixes, +row > box.header > .suffixes { + border-spacing: 6px; +} + +row > box.header > .icon:dir(ltr), +row > box.header > .prefixes:dir(ltr) { + margin-right: 6px; +} + +row > box.header > .icon:dir(rtl), +row > box.header > .prefixes:dir(rtl) { + margin-left: 6px; +} + +row.property > box.header > box.title > .subtitle { + font-size: inherit; + opacity: 1; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry:disabled text { + opacity: 0.45; +} + +row.entry:disabled .dim-label, row.entry:disabled row.expander image.expander-row-arrow, row.expander row.entry:disabled image.expander-row-arrow, row.entry:disabled row.property > box.header > box.title > .title, +row.entry:disabled .subtitle { + opacity: 1; +} + +row.entry .edit-icon, +row.entry .indicator { + min-width: 24px; + min-height: 24px; + padding: 5px; +} + +row.entry .edit-icon:disabled { + opacity: 0.5; +} + +row.entry .indicator { + opacity: 0.65; +} + +row.entry.monospace { + font-family: inherit; +} + +row.entry.monospace text { + font-family: monospace; +} + +row.spin:not(:selected).activatable.focused:hover, row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.spin spinbutton { + background: none; + border-spacing: 6px; + box-shadow: none; +} + +row.spin spinbutton, row.spin spinbutton:focus { + outline: none; +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child { + min-width: 30px; + min-height: 30px; + margin: 10px 2px; + border: none; +} + +row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child:disabled { + filter: none; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active, +row.spin:not(:selected).activatable.focused:hover, +row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry.error text > selection:focus-within, +row.spin.error text > selection:focus-within { + background-color: alpha(#d20f39, 0.2); +} + +row.entry.error text > cursor-handle > contents, +row.spin.error text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.error .dim-label, row.entry.error row.expander image.expander-row-arrow, row.expander row.entry.error image.expander-row-arrow, row.entry.error row.property > box.header > box.title > .title, +row.entry.error .subtitle, +row.spin.error .dim-label, +row.spin.error row.expander image.expander-row-arrow, +row.expander row.spin.error image.expander-row-arrow, +row.spin.error row.property > box.header > box.title > .title, +row.spin.error .subtitle { + opacity: 1; +} + +row.entry.error .suggested-action, +row.spin.error .suggested-action { + background-color: #d20f39; + color: #eff1f5; +} + +row.entry.warning text > selection:focus-within, +row.spin.warning text > selection:focus-within { + background-color: alpha(#df8e1d, 0.2); +} + +row.entry.warning text > cursor-handle > contents, +row.spin.warning text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.warning .dim-label, row.entry.warning row.expander image.expander-row-arrow, row.expander row.entry.warning image.expander-row-arrow, row.entry.warning row.property > box.header > box.title > .title, +row.entry.warning .subtitle, +row.spin.warning .dim-label, +row.spin.warning row.expander image.expander-row-arrow, +row.expander row.spin.warning image.expander-row-arrow, +row.spin.warning row.property > box.header > box.title > .title, +row.spin.warning .subtitle { + opacity: 1; +} + +row.entry.warning .suggested-action, +row.spin.warning .suggested-action { + background-color: #df8e1d; + color: #eff1f5; +} + +row.entry.success text > selection:focus-within, +row.spin.success text > selection:focus-within { + background-color: alpha(#40a02b, 0.2); +} + +row.entry.success text > cursor-handle > contents, +row.spin.success text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.success .dim-label, row.entry.success row.expander image.expander-row-arrow, row.expander row.entry.success image.expander-row-arrow, row.entry.success row.property > box.header > box.title > .title, +row.entry.success .subtitle, +row.spin.success .dim-label, +row.spin.success row.expander image.expander-row-arrow, +row.expander row.spin.success image.expander-row-arrow, +row.spin.success row.property > box.header > box.title > .title, +row.spin.success .subtitle { + opacity: 1; +} + +row.entry.success .suggested-action, +row.spin.success .suggested-action { + background-color: #40a02b; + color: #eff1f5; +} + +row.combo image.dropdown-arrow:disabled { + filter: opacity(0.45); +} + +row.combo listview.inline { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +row.combo listview.inline, row.combo listview.inline:disabled { + background: none; + color: inherit; +} + +row.combo popover > contents { + min-width: 120px; +} + +row.combo popover > contents .combo-searchbar { + margin: 6px; +} + +row.combo popover > contents .combo-searchbar + scrolledwindow > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(239, 241, 245, 0.12), 0.75), transparent 4px); +} + +list.content > row, list.content > row.expander row.header, +list.boxed-list > row, +list.boxed-list > row.expander row.header, row.expander list.nested > row { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +list.content > row:not(:selected).activatable:hover, list.content > row.expander row.header:not(:selected).activatable:hover, +list.boxed-list > row:not(:selected).activatable:hover, +list.boxed-list > row.expander row.header:not(:selected).activatable:hover, row.expander list.nested > row:not(:selected).activatable:hover { + background-color: alpha(currentColor, 0.08); +} + +list.content > row:not(:selected).activatable:active, list.content > row.expander row.header:not(:selected).activatable:active, +list.boxed-list > row:not(:selected).activatable:active, +list.boxed-list > row.expander row.header:not(:selected).activatable:active, row.expander list.nested > row:not(:selected).activatable:active { + background-color: alpha(currentColor, 0.12); +} + +list.content > row:not(:selected).activatable.has-open-popup, list.content > row.expander row.header:not(:selected).activatable.has-open-popup, +list.boxed-list > row:not(:selected).activatable.has-open-popup, +list.boxed-list > row.expander row.header:not(:selected).activatable.has-open-popup, row.expander list.nested > row:not(:selected).activatable.has-open-popup { + background-color: alpha(currentColor, 0.03); +} + +row.expander { + background: none; + padding: 0px; +} + +row.expander > box > list { + background: none; + color: inherit; +} + +row.expander list.nested { + color: inherit; +} + +row.expander image.expander-row-arrow { + transition: -gtk-icon-transform 200ms cubic-bezier(0, 0, 0.2, 1); +} + +row.expander image.expander-row-arrow:dir(ltr) { + margin-left: 6px; +} + +row.expander image.expander-row-arrow:dir(rtl) { + margin-right: 6px; +} + +row.expander image.expander-row-arrow:dir(ltr) { + -gtk-icon-transform: rotate(0.5turn); +} + +row.expander image.expander-row-arrow:dir(rtl) { + -gtk-icon-transform: rotate(-0.5turn); +} + +row.expander image.expander-row-arrow:disabled { + filter: opacity(0.45); +} + +row.expander:checked image.expander-row-arrow { + -gtk-icon-transform: rotate(0turn); + opacity: 1; +} + +row.expander:checked image.expander-row-arrow:not(:disabled) { + color: #89b4fa; +} + +.osd row.expander:checked image.expander-row-arrow:not(:disabled) { + color: inherit; +} + +list.content > row.expander, +list.boxed-list > row.expander { + border: none; +} + +list.content > row:first-child, list.content > row:first-child.expander row.header, +list.boxed-list > row:first-child, +list.boxed-list > row:first-child.expander row.header { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +list.content > row:last-child, list.content > row:last-child.expander:not(:checked), list.content > row:last-child.expander:not(:checked) row.header, list.content > row:last-child.expander:checked list.nested, list.content > row:last-child.expander:checked list.nested > row:last-child, +list.boxed-list > row:last-child, +list.boxed-list > row:last-child.expander:not(:checked), +list.boxed-list > row:last-child.expander:not(:checked) row.header, +list.boxed-list > row:last-child.expander:checked list.nested, +list.boxed-list > row:last-child.expander:checked list.nested > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; + border-bottom-width: 0; +} + +columnview > listview > row { + padding: 0; +} + +columnview > listview > row > cell { + padding: 8px 6px; +} + +columnview > listview > row > cell:not(:first-child) { + border-left: 1px solid transparent; +} + +columnview.column-separators > listview > row > cell { + border-left-color: rgba(239, 241, 245, 0.12); +} + +columnview.data-table > listview > row > cell { + padding-top: 2px; + padding-bottom: 2px; +} + +treeexpander { + border-spacing: 6px; +} + +columnview row:not(:selected) cell editablelabel:not(.editing):focus-within { + outline: 2px solid alpha(currentColor, 0.06); +} + +columnview row:not(:selected) cell editablelabel.editing:focus-within { + outline: 2px solid #89b4fa; +} + +columnview row:not(:selected) cell editablelabel.editing text selection { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 6px; + border-spacing: 0; + padding: 0; + border: none; + background-image: none; +} + +.app-notification button.text-button:not(:disabled) { + color: #89b4fa; +} + +.app-notification > box > label { + margin-left: 9px; +} + +.app-notification.frame, +.app-notification border { + border: none; +} + +/************* + * Expanders * + *************/ +expander { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + color: rgba(239, 241, 245, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +expander:hover, expander:active { + color: #eff1f5; +} + +expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +expander:disabled { + color: rgba(239, 241, 245, 0.32); +} + +expander-widget > box > title { + border-radius: 12px; +} + +expander-widget > box > title:hover > expander { + color: rgba(239, 241, 245, 0.7); +} + +.navigation-sidebar:not(decoration):not(window):drop(active):focus, .navigation-sidebar:not(decoration):not(window):drop(active), +placessidebar:not(decoration):not(window):drop(active):focus, +placessidebar:not(decoration):not(window):drop(active), +stackswitcher:not(decoration):not(window):drop(active):focus, +stackswitcher:not(decoration):not(window):drop(active), +expander-widget:not(decoration):not(window):drop(active):focus, +expander-widget:not(decoration):not(window):drop(active) { + box-shadow: none; +} + +/************ + * Calendar * + ************/ +calendar { + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 12px; + color: #eff1f5; +} + +calendar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +calendar:selected { + border-radius: 12px; +} + +calendar > header { + padding: 3px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +calendar > header > button { + min-height: 24px; +} + +calendar > grid { + margin: 3px; +} + +calendar > grid > label { + border-radius: 12px; + margin: 0; +} + +calendar > grid > label.today:selected { + box-shadow: none; +} + +calendar > grid > label:focus { + outline-style: none; +} + +calendar > grid > label.day-number { + padding: 6px; +} + +calendar > grid > label.day-number.other-month { + color: alpha(currentColor, 0.3); +} + +/*********** + * Dialogs * + ***********/ +window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button { + border-radius: 9px; + min-height: 28px; + padding: 6px 12px; + margin: 0; + border: none; +} + +window.dialog.message.background { + background-color: #1e1e2e; +} + +window.dialog.message box.dialog-vbox.vertical { + margin-top: 6px; +} + +window.dialog.message box.dialog-vbox.vertical > box > box > box > label.title { + font-weight: 800; + font-size: 15pt; +} + +window.dialog.message .titlebar { + min-height: 24px; + border-style: none; + /* box-shadow: inset 0 1px highlight($surface); */ + background-color: #1e1e2e; + color: #eff1f5; +} + +window.dialog.message .titlebar:backdrop { + background-color: #292c3c; + color: rgba(239, 241, 245, 0.7); +} + +window.dialog.message .dialog-action-area { + padding: 18px; + border-spacing: 18px; +} + +window.dialog.message .dialog-action-area > button { + background-color: rgba(239, 241, 245, 0.08); + border: 0 solid transparent; + outline: 0 solid transparent; +} + +window.dialog.message .dialog-action-area > button:not(:last-child):hover { + background-color: rgba(239, 241, 245, 0.1); +} + +window.dialog.message .dialog-action-area > button.suggested-action:not(:disabled) { + background-color: #0a52e0; + color: #eff1f5; +} + +window.dialog.message .dialog-action-area > button.destructive-action:not(:disabled) { + background-color: #a20c2c; + color: #eff1f5; +} + +window.aboutdialog.background.csd scrolledwindow.frame, +window.aboutdialog.background.csd scrolledwindow.frame > viewport.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view > text { + border-radius: 12px; +} + +/******************** + * AdwMessageDialog * + ********************/ +window.messagedialog { + background-color: #292c3c; + color: #eff1f5; + padding: 6px; +} + +window.messagedialog .message-area { + padding: 24px 30px; + border-spacing: 10px; +} + +window.messagedialog .response-area { + border-spacing: 6px; +} + +window.messagedialog .response-area button.suggested { + background-color: #0a52e0; + color: #eff1f5; + /* color: $primary; */ +} + +window.messagedialog .response-area button.destructive { + background-color: #a20c2c; + color: #eff1f5; + /* color: $destructive; */ +} + +window.messagedialog .response-area separator { + background: none; + margin: 3px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; + background-color: #313244; +} + +.sidebar listview.view, +.sidebar list { + background-color: transparent; + color: inherit; +} + +stacksidebar.sidebar:dir(ltr), stacksidebar.sidebar.left, stacksidebar.sidebar.left:dir(rtl) { + box-shadow: inset -1px 0 rgba(239, 241, 245, 0.12); +} + +stacksidebar.sidebar:dir(rtl), stacksidebar.sidebar.right, stacksidebar.sidebar.right:dir(ltr) { + box-shadow: inset 1px 0 rgba(239, 241, 245, 0.12); +} + +.sidebar-pane stacksidebar.sidebar, leaflet.unfolded > box > stacksidebar.sidebar { + box-shadow: none; +} + +stacksidebar list { + padding: 6px; + background-color: #313244; +} + +stacksidebar row { + min-height: 24px; + padding: 6px; + border-radius: 12px; +} + +stacksidebar row:selected { + font-weight: 500; +} + +stacksidebar row + row { + margin-top: 4px; +} + +stacksidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +separator.sidebar { + background-color: rgba(239, 241, 245, 0.12); + border-right: none; +} + +separator.sidebar.selection-mode, .selection-mode separator.sidebar { + background-color: rgba(255, 255, 255, 0.12); +} + +/********************** + * Navigation Sidebar * + **********************/ +.navigation-sidebar { + padding: 2px 4px; + border-right: none; +} + +.navigation-sidebar, .navigation-sidebar.view, .navigation-sidebar.background { + background-color: transparent; + color: inherit; +} + +.navigation-sidebar > separator { + background-color: rgba(239, 241, 245, 0.12); + margin: 10px 15px; +} + +.navigation-sidebar row.activatable label.dim-label { + color: rgba(239, 241, 245, 0.32); +} + +.navigation-sidebar > row { + min-height: 24px; + /* padding: 0 $space-size 0 $space-size; */ + padding: 0 6px; + margin: 0; + border-radius: 9px; +} + +.navigation-sidebar > row:hover, .navigation-sidebar > row:focus-visible:focus-within { + background-color: alpha(currentColor, 0.08); + color: #89b4fa; +} + +.navigation-sidebar > row:active { + background-color: alpha(currentColor, 0.12); +} + +.navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + box-shadow: none; +} + +.navigation-sidebar > row:selected label, +.navigation-sidebar > row:selected image { + color: #89b4fa; + font-weight: 700; +} + +.navigation-sidebar > row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +.navigation-sidebar > row:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.navigation-sidebar > row:not(:first-child) { + margin-top: 3px; +} + +/**************** + * File chooser * + ****************/ +filechooser paned > separator { + background: rgba(239, 241, 245, 0.12); +} + +filechooser paned > box #pathbarbox.view, +filechooser paned > box stack.view, +filechooser paned > box columnview.view, +filechooser paned > box gridview.view { + background-color: transparent; + color: #eff1f5; +} + +filechooser .dialog-action-box { + border: none; +} + +filechooser #pathbarbox { + border: none; + background-color: transparent; +} + +filechooser stack.view frame > border { + border: none; +} + +filechooserbutton > button > box { + border-spacing: 6px; +} + +filechooserbutton:drop(active) { + box-shadow: none; + border-color: transparent; +} + +filechooser child.activatable filelistcell.dim-label { + color: rgba(239, 241, 245, 0.7); +} + +placessidebar { + background-color: transparent; +} + +placessidebar > viewport.frame { + border-style: none; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon { + color: inherit; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label { + color: inherit; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button { + /* @extend %button-on-indicator; */ +} + +placessidebar list.navigation-sidebar > row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row { + color: #89b4fa; +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row image.sidebar-icon { + color: #89b4fa; +} + +placessidebar list.navigation-sidebar > row:drop(active) { + background-color: alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + border-spacing: 6px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(#4a4b5a); + background-size: 1px 1px; + background-clip: content-box; + box-shadow: none; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #1e1e2e; + background-image: image(#4a4b5a), image(#4a4b5a); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************ + * GtkVideo * + ************/ +video { + background: black; + border-radius: 12px; +} + +video image.osd { + min-width: 64px; + min-height: 64px; + border-radius: 9999px; + border: none; +} + +/************** + * GtkInfoBar * + **************/ +infobar > revealer > box { + padding: 6px; + border-spacing: 12px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #313244; + color: #eff1f5; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #89b4fa; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action > revealer > box *:link, infobar.action:backdrop > revealer > box *:link, infobar.question > revealer > box *:link, infobar.question:backdrop > revealer > box *:link { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #71a4f9; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #df8e1d; + color: #eff1f5; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.warning > revealer > box *:link, infobar.warning:backdrop > revealer > box *:link { + color: #eff1f5; +} + +infobar.warning:hover > revealer > box { + background-color: #c8801a; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #d20f39; + color: #eff1f5; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.error > revealer > box *:link, infobar.error:backdrop > revealer > box *:link { + color: #eff1f5; +} + +infobar.error:hover > revealer > box { + background-color: #ba0d33; +} + +/************ + * Tooltips * + ************/ +tooltip { + padding: 6px 12px; + box-shadow: none; + border: none; +} + +tooltip.background { + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05); + border-radius: 12px; + margin: 2px 6px 8px 6px; +} + +tooltip > box { + border-spacing: 6px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #eff1f5; +} + +colorswatch.light { + color: rgba(30, 30, 46, 0.87); +} + +colorchooser colorswatch:hover { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 0 0 2px #89b4fa; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; + color: #eff1f5; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(239, 241, 245, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(239, 241, 245, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #1e1e2e; +} + +/********************** + * Window Decorations * + **********************/ +window { + border: none; +} + +window.csd { + border-radius: 12px; + margin: 0; + transition: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +window.csd:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +window.csd.maximized, window.csd.fullscreen, window.csd.tiled, window.csd.tiled-top, window.csd.tiled-right, window.csd.tiled-bottom, window.csd.tiled-left { + border-radius: 0; + transition: none; +} + +window.csd.maximized, window.csd.fullscreen { + box-shadow: none; + outline: none; +} + +window.solid-csd { + margin: 0; + padding: 2px; + border-radius: 0; + background-color: #1e1e2e; + border: 1px solid #4a4b5a; +} + +window.solid-csd:backdrop { + background-color: #1e1e2e; +} + +window.ssd { + box-shadow: 0 0 0 1px rgba(239, 241, 245, 0.12); +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + padding: 9px 0; + margin-left: 0px; + margin-right: 0px; + /* min-height: 22px; */ + /* min-width: 22px; */ + /* padding: ($medium-size - 22px) / 2 0; */ + /* margin-left: $space-size - 7px; */ + /* margin-right: $space-size - 7px; */ +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + background: none; + box-shadow: none; +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:not(.suggested-action):not(.destructive-action) > image { + padding: 1px; + background-color: alpha(currentColor, 0.1); +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.15); +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.2); +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) > image { + background-color: #313244; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: rgba(239, 241, 245, 0.3); +} + +/* $window-space: if($window_button == 'mac', $space-size * 1.5, $space-size); */ +windowcontrols { + border-spacing: 6px; +} + +windowcontrols:not(.empty).start:dir(ltr), windowcontrols:not(.empty).end:dir(rtl) { + margin-right: 6px; + margin-left: 6px; +} + +windowcontrols:not(.empty).start:dir(rtl), windowcontrols:not(.empty).end:dir(ltr) { + margin-left: 6px; + margin-right: 6px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) > image { + border-radius: 100%; + padding: 0; +} + + +.view:selected, iconview:selected, gridview > child:selected, columnview.view:selected, +treeview.view:selected, calendar:selected, calendar > grid > label.day-number:selected { + background-color: alpha(currentColor, 0.06); +} + +flowbox > flowboxchild:selected, calendar > grid > label.today { + color: #89b4fa; + background-color: rgba(137, 180, 250, 0.2); +} + +textview text selection:focus, textview text selection, label > selection, +entry > text > selection, spinbutton > text > selection, +entry headerbar popover.background entry > text > selection, +headerbar popover.background entry entry > text > selection, calendar > grid > label.today:selected { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #89b4fa; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; +} + +shortcuts-section { + margin: 20px; +} + +.shortcuts-search-results { + margin: 20px; + border-spacing: 24px; +} + +shortcut { + border-spacing: 6px; +} + +shortcut > .keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(239, 241, 245, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(239, 241, 245, 0.12); + background-color: #292c3c; + color: #eff1f5; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #89b4fa; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0 2px; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/************* + * App Icons * + *************/ +.lowres-icon { + -gtk-icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.icon-dropshadow { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 1px 6px rgba(0, 0, 0, 0.1); +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker > contents { + padding: 0; +} + +.emoji-searchbar { + padding: 6px; + border-spacing: 6px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background: none; +} + +.emoji-searchbar entry text { + background: none; + box-shadow: none; +} + +.emoji-toolbar { + padding: 0; + border-spacing: 3px; + border-top: 1px solid rgba(239, 241, 245, 0.12); + background: none; +} + +button.emoji-section { + margin: 0; + padding: 6px; + border-radius: 12px; +} + +button.emoji-section:checked { + color: #89b4fa; +} + +popover.emoji-picker emoji { + font-size: x-large; + padding: 6px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker emoji:focus, popover.emoji-picker emoji:hover { + background: alpha(currentColor, 0.08); +} + +emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +emoji-completion-row > box { + border-spacing: 6px; + padding: 2px 6px; +} + +emoji-completion-row:focus, emoji-completion-row:hover, +emoji-completion-row emoji:hover, +emoji-completion-row emoji:focus { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +popover.entry-completion > contents { + padding: 0; +} + +.nautilus-window.view { + background-color: #1e1e2e; +} + +.nautilus-window .sidebar-pane, +.nautilus-window .content-pane { + background-color: #1e1e2e; + color: #eff1f5; +} + +.nautilus-window .sidebar-pane:backdrop, +.nautilus-window .content-pane:backdrop { + background-color: #1e1e2e; + transition: none; +} + +.nautilus-window .sidebar-pane:dir(ltr), +.nautilus-window .sidebar-pane:dir(ltr) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(rtl), +.nautilus-window .sidebar-pane.end:dir(rtl) banner > revealer > widget { + box-shadow: none; + border-right: none; +} + +.nautilus-window .sidebar-pane:dir(rtl), +.nautilus-window .sidebar-pane:dir(rtl) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(ltr), +.nautilus-window .sidebar-pane.end:dir(ltr) banner > revealer > widget { + box-shadow: none; + border-left: none; +} + +.nautilus-window placesview label { + color: rgba(239, 241, 245, 0.7); +} + +.nautilus-window flap > separator { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view .view, +.nautilus-window .nautilus-list-view .view { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell { + padding: 0; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell > widget#NautilusViewCell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell > widget#NautilusViewCell { + padding: 3px 9px; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable:nth-child(odd):not(:disabled), +.nautilus-window .nautilus-list-view listview.view > row.activatable:nth-child(odd):not(:disabled) { + background-image: image(alpha(currentColor, 0.03)); +} + +.nautilus-window .nautilus-grid-view gridview.view, +.nautilus-window .nautilus-list-view gridview.view { + margin: 10px 5px; + padding: 10px 5px; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border-style: none; + border-radius: 9px; + background-color: rgba(49, 50, 68, 0.95); + color: #89b4fa; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(30, 30, 46, 0.87); +} + +.nautilus-window banner > revealer > widget { + background-color: rgba(49, 50, 68, 0.4); + color: #eff1f5; + border-radius: 9px; + margin: 9px; +} + +.nautilus-window banner > revealer > widget button { + background-color: rgba(137, 180, 250, 0.3); + color: rgba(30, 30, 46, 0.87); +} + +.nautilus-window banner > revealer > widget button:hover { + background-color: rgba(137, 180, 250, 0.6); +} + +#NautilusQueryEditor > menubutton > button.image-button { + min-width: 24px; + min-height: 24px; + padding: 3px; + margin-right: -5px; +} + +#NautilusQueryEditor > menubutton > button.image-button:checked image { + color: rgba(30, 30, 46, 0.87); +} + +#NautilusQueryEditor > text, +#NautilusQueryEditor > box, +#NautilusQueryEditor > menubutton { + margin: 3px 0; +} + +#NautilusQueryEditorTag { + background-color: rgba(239, 241, 245, 0.12); +} + +#NautilusQueryEditorTag > button.image-button { + margin: 0; + padding: 0; +} + +#NautilusPathBar { + /* background-color: if($variant == 'light', $grey-100, $titlebar-fill); */ + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +#NautilusPathButton { + margin: 0 3px; + border-radius: 12px; +} + +#NautilusPathButton.current-dir { + color: #89b4fa; +} + +#NautilusPathButton.current-dir:hover, #NautilusPathButton.current-dir:active { + background: none; + box-shadow: none; +} + +#NautilusPathButton:first-child { + margin-left: 0; +} + +#NautilusViewCell clamp box { + margin: 0; + border-spacing: 0; +} + +#NautilusFileChooser gridview.view { + background-color: transparent; + margin: 10px 5px; + padding: 10px 5px; +} + +#NautilusFileChooser columnview.view, +row.activatable > cell { + background-color: transparent; + padding: 1px 10px; +} + +#NautilusProgressIndicator popover label { + color: rgba(239, 241, 245, 0.7); +} + +#NautilusProgressIndicator popover image { + color: rgba(239, 241, 245, 0.7); +} + +/* Nautilus Progress Indicator */ +windowhandle box.vertical box.toolbar { + background-color: #1e1e2e; + border: none; + outline: none; +} + +windowhandle box.toolbar menubutton button.toggle { + background-color: #1e1e2e; + border: none; + outline: none; +} + +window.dialog > box > stack > box > box > notebook.frame { + border-width: 0 0 0 1px; + border-radius: 0; +} + +.display-container.card { + background-color: #313244; +} + +.small .display-container.card { + border-radius: 0; + box-shadow: none; + border-width: 0 0 1px 0; +} + +.display-container .history-view { + background-color: transparent; +} + +.display-container #displayitem { + padding: 0 12px 8px 0; + font-size: 1.4em; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.math-buttons button { + font-size: 1.1em; + padding: 2px 6px; +} + +.math-buttons button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +leaflet button.number-button { + background-color: rgba(239, 241, 245, 0.1); +} + +leaflet button.number-button:hover { + background-color: rgba(239, 241, 245, 0.2); +} + +leaflet button.number-button:active { + background-color: rgba(239, 241, 245, 0.3); +} + +label.primary-label, label.month-name, label.secondary-label { + font-size: 16pt; + font-weight: bold; + padding: 12px; +} + +label.primary-label, label.month-name { + color: #89b4fa; +} + +label.secondary-label { + color: rgba(239, 241, 245, 0.5); +} + +toastoverlay datechooser.view, +toastoverlay agenda-view.view, +toastoverlay agenda-view.view list, +toastoverlay stack.view { + background-color: transparent; +} + +calendar-view { + font-size: 10pt; +} + +calendar-view:selected { + color: #89b4fa; + font-weight: bold; +} + +calendar-view.header, +label.header { + font-size: 10pt; + font-weight: bold; + color: rgba(239, 241, 245, 0.5); +} + +calendar-view.current, +weekgrid.current { + background-color: alpha(#89b4fa, 0.3); +} + +popover.events { + background-color: #292c3c; + padding: 0; +} + +popover.events box { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +popover.events list { + background-color: #313244; + border-radius: 12px; +} + +popover.events scrolledwindow { + border-width: 0; +} + +popover.events button { + border-radius: 12px; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-style: solid none none; + box-shadow: none; +} + +event { + margin: 1px; + font-size: 0.9rem; +} + +event widget.content { + margin: 4px; +} + +event.timed, event:not(.slanted):not(.slanted-start):not(.slanted-end) { + border-radius: 12px; +} + +event.timed widget.edge { + border-radius: 6px; + min-width: 5px; +} + +event.slanted-start, event.slanted-end:dir(rtl) { + padding-left: 16px; + border-radius: 0 6px 6px 0; +} + +event.slanted-end, event.slanted-start:dir(rtl) { + padding-right: 16px; + border-radius: 6px 0 0 6px; +} + +event:not(.timed).color-dark { + color: white; + outline-color: rgba(0, 0, 0, 0.3); +} + +event.timed, event:not(.timed).color-light { + color: alpha(black, 0.75); + outline-color: rgba(255, 255, 255, 0.5); +} + +popover.event-popover, +popover.event-popover > contents { + padding: 0; +} + +.search-viewport { + background-color: #313244; +} + +.calendar-list { + background-color: transparent; +} + +.calendar-list > list { + border-radius: 4px; +} + +menubutton.flat.sources-button { + margin-top: 0; + margin-bottom: 0; + border-radius: 0; + border-top-style: none; + border-bottom-style: none; +} + +menubutton.flat.sources-button:hover:not(:backdrop) { + background-image: none; + text-shadow: none; +} + +menubutton.flat.sources-button > button { + border-radius: 0 0 12px 12px; +} + +.calendar-color-image { + -gtk-icon-filter: none; +} + +image.calendar-color-image, +button:active:not(:backdrop) .calendar-color-image, +button:checked:not(:backdrop) .calendar-color-image, +.calendars-list .calendar-color-image:not(:backdrop):not(:disabled), +.calendar-list .calendar-color-image:not(:backdrop):not(:disabled), +.sources-button:not(:backdrop):not(:disabled) .calendar-color-image { + -gtk-icon-shadow: 0 1px alpha(black, 0.1); +} + +datechooser { + padding: 6px; +} + +datechooser .current-week { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; + border-radius: 12px; +} + +datechooser navigator { + margin-right: 6px; + margin-left: 6px; + margin-bottom: 6px; +} + +datechooser navigator label { + font-weight: bold; +} + +datechooser navigator button.flat, +datechooser navigator button.image-button { + min-height: 34px; + min-width: 34px; + padding: 0; +} + +datechooser .weeknum, +datechooser .weekday { + color: rgba(239, 241, 245, 0.5); + font-size: smaller; +} + +datechooser button.day { + font-size: 10pt; + font-weight: normal; + margin: 3px; + padding: 0; + min-height: 34px; + min-width: 34px; + transition: none; +} + +datechooser button.day dot { + background-color: #eff1f5; + border-radius: 50%; + min-height: 3px; + min-width: 3px; +} + +datechooser button.day:selected, datechooser button.day.today:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + font-weight: bold; +} + +datechooser button.day:selected dot, datechooser button.day.today:selected dot { + background-color: rgba(30, 30, 46, 0.87); +} + +datechooser button.day.today { + color: #89b4fa; +} + +datechooser button.day.today dot { + background-color: #89b4fa; +} + +datechooser button.day.other-month:not(:hover), datechooser button.day.other-month:backdrop { + color: rgba(239, 241, 245, 0.32); +} + +datechooser button.day.other-month:not(:hover) dot, datechooser button.day.other-month:backdrop dot { + background-color: rgba(239, 241, 245, 0.32); +} + +datechooser button.day.other-month:hover:not(:backdrop) { + color: rgba(239, 241, 245, 0.5); +} + +datechooser button.day.other-month:hover:not(:backdrop) dot { + background-color: rgba(239, 241, 245, 0.5); +} + +.week-header { + padding: 0; +} + +.week-header > box:first-child { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.week-header .week-number { + font-size: 16pt; + font-weight: bold; + padding: 12px 12px 18px 12px; + color: rgba(239, 241, 245, 0.3); +} + +.week-header.week-temperature { + font-size: 10pt; + font-weight: bold; + color: rgba(239, 241, 245, 0.5); +} + +.week-header.lines { + color: rgba(239, 241, 245, 0.12); +} + +weekhourbar > label { + font-size: 10pt; + padding: 4px 6px; +} + +.week-view .lines { + color: rgba(239, 241, 245, 0.12); +} + +weekgrid > widget.now-strip { + background-color: alpha(#89b4fa, 0.8); + margin: 0 0 0 1px; + min-height: 3px; +} + +weekgrid:selected, weekgrid.dnd, +.week-header:selected, +.week-header.dnd { + background-color: alpha(#89b4fa, 0.25); +} + +monthcell { + border: solid 1px rgba(239, 241, 245, 0.12); + border-width: 1px 0 0 1px; + background-color: transparent; + transition: background-color 200ms; +} + +monthcell:hover:not(.out-of-month):not(.today) { + background-color: #313244; + transition: background-color 200ms; + color: #eff1f5; +} + +monthcell:selected { + background-color: alpha(#89b4fa, 0.1); +} + +monthcell:selected:hover { + background-color: alpha(#89b4fa, 0.2); +} + +monthcell:selected label.day-label { + font-weight: bold; +} + +monthcell:nth-child(7n + 1) { + border-left-width: 0; +} + +monthcell.today { + background-color: alpha(#89b4fa, 0.2); +} + +monthcell.today:hover { + background-color: alpha(#89b4fa, 0.3); + color: #89b4fa; +} + +monthcell.today:selected { + background-color: alpha(#89b4fa, 0.25); +} + +monthcell.today:selected:hover { + background-color: alpha(#89b4fa, 0.35); +} + +monthcell label { + color: #eff1f5; + font-size: 0.9rem; +} + +monthcell label.day-label { + font-size: 1rem; +} + +monthcell.out-of-month { + background-color: rgba(239, 241, 245, 0.04); +} + +monthcell.out-of-month label { + color: rgba(239, 241, 245, 0.7); +} + +monthcell button { + padding: 0 6px; + border-radius: 0; + border-bottom: none; + border-right: none; +} + +monthpopover > box { + margin: 0; + padding: 0; + background-color: transparent; +} + +.notes-section box > textview { + border-radius: 12px; + padding: 6px; +} + +.notes-section box > textview > text { + background: none; +} + +agenda-view list.background > row { + padding: 2px 12px; +} + +agenda-view list.background > label { + padding: 6px 12px; +} + +label.no-events { + font-style: italic; +} + +searchbutton > popover > arrow { + background: none; + border: none; +} + +menubutton stack > box { + border-spacing: 6px; +} + +#TweakPreferencesPage.tweak-group label.subtitle { + color: rgba(239, 241, 245, 0.32); +} + +#TweakPreferencesPage label.dim-label { + color: rgba(239, 241, 245, 0.32); +} + +.sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow .dim-label, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row label.subtitle, row .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow label.subtitle, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.expander image.expander-row-arrow, row.expander .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow image.expander-row-arrow { + color: rgba(30, 30, 46, 0.38); +} + +.details-page { + margin: 24px 0px; +} + +.installed-overlay-box { + font-size: smaller; + background-color: #89b4fa; + border-radius: 0; + color: rgba(30, 30, 46, 0.87); + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); +} + +screenshot-carousel box.frame { + border-width: 1px 0; + border-radius: 0; +} + +screenshot-carousel button, +.featured-carousel button { + margin: 12px; +} + +carousel.card { + border: none; + background-color: rgba(239, 241, 245, 0.04); +} + +.smaller { + font-size: smaller; +} + +.screenshot-image-main .image1, +.screenshot-image-main .image2 { + margin-top: 6px; + margin-bottom: 12px; + margin-left: 6px; + margin-right: 6px; +} + +.app-tile-label { + font-size: 105%; +} + +gs-summary-tile image.loading-icon { + background-color: rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.review-row > box { + margin: 12px; + border-spacing: 3px; +} + +.review-row textview { + background: none; +} + +.review-row .edit-icon { + min-width: 24px; + min-height: 24px; + padding: 6px; +} + +.review-textbox { + padding: 6px; +} + +.origin-rounded-box { + background-color: rgba(239, 241, 245, 0.12); + border-radius: 9999px; + padding: 4px; +} + +.origin-beta { + color: #df8e1d; +} + +.origin-button > button { + padding: 3px 9px; +} + +clamp.medium .category-tile:not(.category-tile-iconless) { + font-size: large; +} + +clamp.large .category-tile:not(.category-tile-iconless) { + font-size: larger; +} + +flowboxchild.card:not(.category-tile) { + padding: 0; + box-shadow: none; + border: none; + background-color: transparent; + background-image: none; +} + +.category-tile.card { + padding: 21px; + border: none; + border-radius: 12px; + min-width: 140px; + font-weight: 900; + font-size: larger; +} + +.category-tile.card:not(.category-tile-iconless), .category-tile.card:not(.category-tile-iconless):active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + animation: none; +} + +.category-tile.card.category-tile-iconless { + padding: 9px 15px; + min-width: 130px; + font-size: 105%; + font-weight: normal; +} + +.category-tile.card.category-create { + background: linear-gradient(180deg, #ce8cd7 0%, #2861c6 100%); + color: white; +} + +.category-tile.card.category-create:hover { + background: linear-gradient(180deg, shade(#ce8cd7, 1.07) 0%, shade(#2861c6, 1.1) 100%); + color: white; +} + +.category-tile.card.category-create:active { + background: linear-gradient(180deg, shade(#ce8cd7, 0.95) 0%, shade(#2861c6, 0.95) 100%); + color: white; +} + +.category-tile.card.category-develop { + background-color: #5e5c64; + color: white; +} + +.category-tile.card.category-develop:hover { + background-color: shade(#5e5c64, 1.2); + color: white; +} + +.category-tile.card.category-develop:active { + background-color: shade(#5e5c64, 0.95); + color: white; +} + +.category-tile.card.category-learn { + background: linear-gradient(180deg, #2ec27e 30%, #27a66c 100%); + color: white; +} + +.category-tile.card.category-learn:hover { + background: linear-gradient(180deg, shade(#2ec27e, 1.06) 30%, shade(#27a66c, 1.06) 100%); + color: white; +} + +.category-tile.card.category-learn:active { + background: linear-gradient(180deg, shade(#2ec27e, 0.95) 30%, shade(#27a66c, 0.95) 100%); + color: white; +} + +.category-tile.card.category-play { + background: linear-gradient(75deg, #f9e2a7 0%, #eb5ec3 50%, #6d53e0 100%); + color: #393484; +} + +.category-tile.card.category-play:hover { + background: linear-gradient(75deg, shade(#f9e2a7, 1.07) 0%, shade(#eb5ec3, 1.07) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-play:active { + background: linear-gradient(75deg, shade(#f9e2a7, 0.97) 0%, shade(#eb5ec3, 0.95) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-socialize { + background: linear-gradient(90deg, #ef4e9b 0%, #f77466 100%); + color: rgba(239, 241, 245, 0.7); +} + +.category-tile.card.category-socialize:hover { + background: linear-gradient(90deg, shade(#ef4e9b, 1.08) 0%, shade(#f77466, 1.08) 100%); +} + +.category-tile.card.category-socialize:active { + background: linear-gradient(90deg, shade(#ef4e9b, 0.95) 0%, shade(#f77466, 0.95) 100%); +} + +.category-tile.card.category-work { + padding: 1px; + /* FIXME: work around https://gitlab.gnome.org/GNOME/gtk/-/issues/4324 */ + color: #1c71d8; + background-color: #fdf8d7; + background-image: linear-gradient(rgba(239, 241, 245, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(239, 241, 245, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.category-tile.card.category-work:hover { + color: #1c71d8; + background-color: #fefcef; + background-image: linear-gradient(rgba(239, 241, 245, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(239, 241, 245, 0.12) 1px, transparent 1px); +} + +.category-tile.card.category-work:active { + color: #1c71d8; + background-color: #fcf4bf; + background-image: linear-gradient(rgba(239, 241, 245, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(239, 241, 245, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.featured-tile { + padding: 0; + box-shadow: none; + color: #eff1f5; +} + +.featured-tile label.title-1 { + margin-top: 6px; + margin-bottom: 6px; +} + +.featured-tile.narrow label.title-1 { + font-size: 16pt; +} + +.application-details-infobar, .application-details-infobar.info { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; + border: 1px solid rgba(239, 241, 245, 0.12); +} + +.application-details-infobar.warning { + background-color: #df8e1d; + color: #eff1f5; + border: 1px solid rgba(239, 241, 245, 0.12); +} + +.card.info { + background-color: #1f1f2f; + color: #eff1f5; +} + +.card.warning { + background-color: #1f1f2e; + color: #eff1f5; +} + +.infobox { + border-spacing: 6px; + padding: 12px; +} + +@keyframes install-progress-unknown-move { + 0% { + background-position: 0%; + } + 50% { + background-position: 100%; + } + 100% { + background-position: 0%; + } +} + +.application-details-description .button { + padding-left: 24px; + padding-right: 24px; +} + +.install-progress { + background-image: linear-gradient(to top, #89b4fa 2px, alpha(#89b4fa, 0) 2px); + background-repeat: no-repeat; + background-position: 0 bottom; + background-size: 0; + transition: none; +} + +.install-progress:dir(rtl) { + background-position: 100% bottom; +} + +.review-row > * { + margin: 12px; +} + +.review-row button { + font-size: smaller; +} + +.review-row .vote-buttons button { + margin-right: -1px; +} + +.review-row .vote-buttons button:not(:first-child) { + border-image: linear-gradient(to top, rgba(239, 241, 245, 0.12), rgba(239, 241, 245, 0.12)) 0 0 0 1/5px 0 5px 1px; +} + +.review-row .vote-buttons button:hover, +.review-row .vote-buttons button:active, +.review-row .vote-buttons button:hover + button, +.review-row .vote-buttons button:active + button { + border-image: none; +} + +review-bar { + color: rgba(239, 241, 245, 0.5); + background-image: none; + background-color: rgba(239, 241, 245, 0.3); +} + +.review-histogram star-image { + color: rgba(239, 241, 245, 0.5); +} + +.version-arrow-label { + font-size: x-small; +} + +.overview-more-button { + font-size: smaller; + padding: 0 16px; +} + +.app-row-origin-text { + font-size: smaller; +} + +.app-listbox-header { + padding: 6px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.image-list { + background-color: transparent; +} + +box.star { + background-color: transparent; + background-image: none; +} + +button.star { + outline-offset: 0; + background-color: transparent; + background-image: none; + border-image: none; + border-radius: 0; + border-width: 0; + padding: 0; + box-shadow: none; + outline-offset: -1px; +} + +flowboxchild { + padding: 0px; +} + +star-image > image.starred { + color: #f9e2af; + transition-duration: 200ms; +} + +star-image > image.starred:hover { + color: #df8e1d; +} + +star-image > image.non-starred { + opacity: 0.2; + transition-duration: 200ms; +} + +star-image > image.non-starred:hover { + color: #f9e2af; + opacity: 0.7; +} + +.dimmer-label { + opacity: 0.25; +} + +.update-failed-details { + font-family: Monospace; + font-size: smaller; + padding: 16px; +} + +.upgrade-banner { + padding: 0px; + border-radius: 12px; + border: none; +} + +.upgrade-banner-background { + background: linear-gradient(to bottom, #40a02b, #1e66f5); + color: white; +} + +.upgrade-buttons #button_upgrades_install, +.upgrade-buttons #button_upgrades_install_cancel { + padding-left: 16px; + padding-right: 16px; +} + +scrolledwindow.list-page > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +.update-preferences preferencesgroup > box > box { + margin-top: 18px; +} + +.section > label:not(:first-child) { + margin-top: 6px; +} + +.section > box:not(:first-child) { + margin-top: 12px; +} + +clamp.status-page { + margin: 36px 12px; +} + +clamp.status-page .iconbox { + min-height: 128px; + min-width: 128px; +} + +clamp.status-page .icon { + color: rgba(239, 241, 245, 0.5); + min-height: 32px; + min-width: 32px; +} + +clamp.status-page .icon:not(:last-child) { + margin-bottom: 36px; +} + +clamp.status-page .title:not(:last-child) { + margin-bottom: 12px; +} + +app-context-bar .context-tile { + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: transparent; + border-radius: 0; + padding: 24px 12px 21px 12px; + outline-offset: 5px; + transition-property: outline, outline-offset, background-image; + border-bottom: none; + border-right: none; +} + +app-context-bar .context-tile:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); +} + +app-context-bar .context-tile.keyboard-activating, app-context-bar .context-tile:active { + background-color: alpha(currentColor, 0.12); +} + +app-context-bar .context-tile:focus:focus-visible { + outline-offset: -1px; +} + +app-context-bar.horizontal box:first-child .context-tile:first-child, app-context-bar.vertical .context-tile:first-child { + border-left: none; +} + +app-context-bar.horizontal .context-tile, app-context-bar.vertical box:first-child .context-tile { + border-top: none; +} + +app-context-bar > box:not(:first-child) > button.flat { + border-radius: 0; +} + +app-context-bar > box:not(:first-child) > button.flat:last-child { + border-radius: 0 12px 12px 0; +} + +app-context-bar > box:first-child > button.flat { + border-radius: 0; +} + +app-context-bar > box:first-child > button.flat:first-child { + border-radius: 12px 0 0 12px; +} + +app-context-bar > box > button.flat { + border-left-color: rgba(239, 241, 245, 0.12); +} + +.context-tile-lozenge { + min-height: 28px; + min-width: 28px; + padding: 6px; + font-size: 18px; + font-weight: bold; + border-radius: 9999px; +} + +.context-tile-lozenge.large { + font-size: 24px; + padding: 16px; + min-width: 24px; + /* 60px minus the left and right padding */ + min-height: 24px; + /* 60px minus the top and bottom padding */ +} + +.context-tile-lozenge.wide-image image { + margin-top: -28px; + margin-bottom: -28px; +} + +.context-tile-lozenge image { + -gtk-icon-style: symbolic; +} + +.context-tile-lozenge.grey { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.context-tile-lozenge.green, .context-tile-lozenge.details-rating-0 { + color: #28641b; + background-color: rgba(64, 160, 43, 0.15); +} + +.context-tile-lozenge.blue, .context-tile-lozenge.details-rating-5 { + color: #1e66f5; + background-color: rgba(30, 102, 245, 0.15); +} + +.context-tile-lozenge.yellow, .context-tile-lozenge.details-rating-12 { + color: #9b6314; + background-color: rgba(223, 142, 29, 0.15); +} + +.context-tile-lozenge.details-rating-15 { + color: #fe640b; + background-color: rgba(254, 100, 11, 0.15); +} + +.context-tile-lozenge.red, .context-tile-lozenge.details-rating-18 { + color: #8b0a26; + background-color: rgba(210, 15, 57, 0.15); +} + +.eol-red { + font-weight: bold; + color: #d20f39; +} + +window.narrow .app-title { + font-size: 16pt; +} + +window.narrow .app-developer { + font-size: small; +} + +.install-progress-label { + font-size: smaller; + font-feature-settings: 'tnum'; +} + +scrolledwindow.fake-adw-status-page > viewport > box { + margin: 36px 12px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp:not(:last-child) +> box { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .icon:not(:last-child) { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .title:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.icon-dropshadow image.icon { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 -1px rgba(0, 0, 0, 0.05), 1px 0 rgba(0, 0, 0, 0.1), 0 1px rgba(0, 0, 0, 0.3), -1px 0 rgba(0, 0, 0, 0.1); +} + +window.info scrollbar.vertical { + margin-top: 48px; + background: none; + box-shadow: none; +} + +window.info scrollbar.vertical trough { + margin-top: 0; +} + +row.app > box.header { + margin-left: 12px; + margin-right: 12px; +} + +row.app > box.header { + border-spacing: 12px; +} + +row.app > box.header > image { + margin-top: 12px; + margin-bottom: 12px; +} + +row.app label.warning { + color: #d20f39; +} + +@keyframes pre-delay { + from { + opacity: 0; + } + to { + opacity: 0; + } +} + +@keyframes fade-in { + from { + filter: opacity(0%); + } +} + +/* Give a fade-in animation to spinners. */ +spinner.fade-in:checked { + animation: pre-delay 0.5s linear 1, fade-in 1s linear 1, spin 1s linear infinite; + animation-delay: 0s, 0.5s, 0.5s; +} + +window > contents > leaflet > box > stack.background { + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, transparent 46px, #1e1e2e 46px, #1e1e2e); +} + +@define-color weather_temp_chart_fill_color rgba(223, 142, 29, 0.5); +@define-color weather_temp_chart_stroke_color #b27117; +@define-color weather_thermometer_warm_color #df8e1d; +@define-color weather_thermometer_cold_color #1e66f5; +#places-label { + font-weight: bold; +} + +#temperature-label { + font-size: 32pt; + font-weight: 900; + margin-left: 9px; +} + +#conditions-grid *:backdrop { + color: rgba(239, 241, 245, 0.7); +} + +.content-view.cell { + font-weight: bold; +} + +#locationEntry { + margin: 6px; +} + +.weather-popover { + margin-top: 6px; +} + +.forecast-card { + transition: border-radius 100ms ease-out; + border-radius: 12px; +} + +.forecast-card separator { + background-color: #1e1e2e; +} + +#daily-forecast-box > separator:last-child { + background-color: transparent; + min-width: 0; +} + +#conditions-grid, +#attributionGrid { + margin-left: 18px; + margin-right: 18px; +} + +#weather-page .small .forecast-card { + margin-left: 0; + margin-right: 0; + border-radius: 0; + border-width: 1px 0; +} + +.forecast-temperature-label { + font-weight: bold; + color: #ae7b03; +} + +WeatherThermometer { + margin-bottom: 12px; +} + +WeatherThermometer > label.high { + font-weight: bold; + color: #df8e1d; +} + +WeatherThermometer > label.low { + font-weight: bold; + color: #1e66f5; +} + +.forecast-button { + margin: 0 12px; +} + +.forecast-graphic { + margin: 18px; +} + +button.osd.circular { + border-radius: 9999px; + min-width: 24px; + min-height: 24px; +} + +button.osd.circular > image { + padding: 0; +} + +scrolledwindow.inline list, +scrolledwindow.inline listview { + background: none; + color: inherit; +} + +scrolledwindow.inline undershoot.top { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.12); +} + +.search-view { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.search-view menubutton button:focus:focus-visible { + outline-color: rgba(255, 255, 255, 0.3); +} + +image.circular { + min-width: 34px; + min-height: 34px; + padding: 0; + border-radius: 9999px; +} + +#gnome-system-monitor.background.csd { + background-color: #1e1e2e; +} + +.large-button { + padding: 6px; +} + +.alarm-time { + font-size: 2.5em; + font-weight: 300; +} + +.clocks-ampm-toggle-button, +.clocks-secondary-standalone-label { + font-size: 18pt; +} + +.clocks-standalone-label, +.clocks-ringing-label { + font-size: 6em; + font-weight: 300; +} + +.clocks-ringing-title { + font-size: 1.5em; + font-weight: bold; +} + +.clocks-alarm-setup-time { + font-size: 32pt; +} + +.clocks-timer-label, +.clocks-spinbutton { + font-size: 48pt; +} + +.timer-panel .timer-header { + font-size: 20pt; + font-weight: 300; +} + +.timer-countdown { + font-size: 40pt; + font-weight: 300; +} + +/* Stopwatch Panel */ +.lap-time { + font-weight: bold; +} + +.stopped-stopwatch label, +.running-stopwatch label, +.paused-stopwatch label { + font-size: 70px; + font-weight: lighter; +} + +.stopped-stopwatch .seconds-label { + font-weight: 300; +} + +.running-stopwatch .seconds-label, +.running-stopwatch .miliseconds-label { + color: #89b4fa; +} + +.stopped-stopwatch .miliseconds-label, +.running-stopwatch .miliseconds-label, +.paused-stopwatch .miliseconds-label { + font-size: 50px; +} + +.running-stopwatch .seconds-label, +.paused-stopwatch .seconds-label { + font-weight: 300; +} + +.clock-location { + font-weight: bolder; +} + +.hidden { + opacity: 0; +} + +.clock-time { + font-size: 2em; + padding: 0.2em 0.5em; + border-radius: 1em; +} + +.none .clock-time { + background: alpha(currentColor, 0.2); +} + +.night .clock-time { + color: #89b4fa; + background-color: alpha(#1e66f5, 0.25); +} + +.naut .clock-time, +.astro .clock-time { + color: #fab387; + background-color: alpha(#fe640b, 0.25); +} + +.civil .clock-time, +.day .clock-time { + color: #f9e2af; + background: alpha(#df8e1d, 0.25); +} + +headerbar splitbutton notification button { + margin: 0; + min-height: 24px; + min-width: 24px; + padding: 0; +} + +popover.background.global-search > arrow, +popover.background.global-search > contents { + padding: 0; +} + +panelframeswitcher { + padding: 3px; +} + +.frameheader.header { + min-height: 24px; + background-color: #313244; +} + +.frameheader.header > button { + border: none; + margin: 0; + padding: 3px; +} + +.frameheader.header tabbar.inline > revealer > box { + min-height: 24px; +} + +.frameheader.header tabbar.inline > revealer > box .start-action { + padding: 0; + border: none; +} + +.frameheader.header tabbar.inline > revealer > box .end-action { + padding: 0; + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +.frameheader.header tabbar.inline > revealer > box tabbox { + border: none; + background: none; +} + +panelstatusbar > menubutton > button, +panelstatusbar > paneltogglebutton button { + border-radius: 0; +} + +.style-variant { + padding: 0 12px; +} + +.style-variant button.toggle { + padding: 0; +} + +.style-variant button.toggle, .style-variant button.toggle:hover, .style-variant button.toggle:focus, .style-variant button.toggle:active, .style-variant button.toggle:checked { + background: none; + outline: none; + border: none; + box-shadow: none; +} + +.style-variant button.toggle > stylevariantpreview > .wallpaper { + border-radius: 12px; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; + box-shadow: none; +} + +.style-variant button.toggle:hover > stylevariantpreview > .wallpaper { + outline-color: rgba(239, 241, 245, 0.04); +} + +.style-variant button.toggle:active > stylevariantpreview > .wallpaper { + outline-color: rgba(239, 241, 245, 0.3); +} + +.style-variant button.toggle:checked > stylevariantpreview > .wallpaper { + outline-color: #89b4fa; +} + +playlistview scrollbar.overlay-indicator.dragging, playlistview scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +playlistview queuerow picture.cover, +playlistview queuerow image.card { + border: none; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list { + border: none; + border-radius: 0; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:first-child, window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:last-child { + border-radius: 0; +} + +/* Tagger */ +list.music-list { + margin: -40px 0; + background-color: transparent; +} + +/* Nicotine+ */ +notebook scrolledwindow treeview.treeview-spacing { + background-color: #1e1e2e; +} + +.account-switcher-row label { + color: #eff1f5; +} + +.account-switcher-row label.dim-label { + color: rgba(239, 241, 245, 0.7); +} + +window.background.chromium { + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.chromium headerbar.header-bar.titlebar { + padding: 0 12px; + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px 0 rgba(239, 241, 245, 0.1); +} + +window.background.chromium headerbar.header-bar.titlebar:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.5); +} + +window.background.chromium headerbar.header-bar.titlebar button.titlebutton { + margin: 0 0px; +} + +.nautilus-window placessidebar > scrolledwindow { + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 0; + /* margin: 0 6px 0 0; */ +} + +.nautilus-window placessidebar > scrolledwindow .dim-label, .nautilus-window placessidebar > scrolledwindow row label.subtitle, row .nautilus-window placessidebar > scrolledwindow label.subtitle, .nautilus-window placessidebar > scrolledwindow row.property > box.header > box.title > .title, .nautilus-window placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander .nautilus-window placessidebar > scrolledwindow image.expander-row-arrow { + color: rgba(30, 30, 46, 0.38); +} + +.nautilus-window .nautilus-grid-view, +.nautilus-window .nautilus-list-view { + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 0 6px 6px 6px; +} + +calendar-view { + margin: 6px; +} + +.sidebar-pane .sidebar > scrolledwindow, +.sidebar-pane toolbarview > scrolledwindow, +.sidebar-pane navigation-view-page stack > scrolledwindow, .sidebar-pane, filechooser paned > box, placessidebar > scrolledwindow, agenda-view list.background, .tweak-titlebar-left, .tweak-titlebar-left:backdrop, leaflet.unfolded > box > scrolledwindow, leaflet.unfolded .contacts-contact-list > scrolledwindow, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow { + background-color: #181825; + color: #eff1f5; + border-radius: 0; + margin: 0; +} + +.sidebar-pane .sidebar > scrolledwindow .dim-label, +.sidebar-pane toolbarview > scrolledwindow .dim-label, +.sidebar-pane navigation-view-page stack > scrolledwindow .dim-label, .sidebar-pane .dim-label, filechooser paned > box .dim-label, placessidebar > scrolledwindow .dim-label, agenda-view list.background .dim-label, .tweak-titlebar-left .dim-label, leaflet.unfolded > box > scrolledwindow .dim-label, leaflet.unfolded .contacts-contact-list > scrolledwindow .dim-label, .sidebar-pane row label.subtitle, row .sidebar-pane label.subtitle, filechooser paned > box row label.subtitle, row filechooser paned > box label.subtitle, placessidebar > scrolledwindow row label.subtitle, row placessidebar > scrolledwindow label.subtitle, agenda-view list.background row label.subtitle, row agenda-view list.background label.subtitle, .tweak-titlebar-left row label.subtitle, row .tweak-titlebar-left label.subtitle, leaflet.unfolded > box > scrolledwindow row label.subtitle, row leaflet.unfolded > box > scrolledwindow label.subtitle, leaflet.unfolded .contacts-contact-list > scrolledwindow row label.subtitle, row leaflet.unfolded .contacts-contact-list > scrolledwindow label.subtitle, .sidebar-pane row.property > box.header > box.title > .title, placessidebar > scrolledwindow row.property > box.header > box.title > .title, agenda-view list.background row.property > box.header > box.title > .title, .tweak-titlebar-left row.property > box.header > box.title > .title, leaflet.unfolded > box > scrolledwindow row.property > box.header > box.title > .title, leaflet.unfolded .contacts-contact-list > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane row.expander image.expander-row-arrow, row.expander .sidebar-pane image.expander-row-arrow, filechooser paned > box row.expander image.expander-row-arrow, row.expander filechooser paned > box image.expander-row-arrow, placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander placessidebar > scrolledwindow image.expander-row-arrow, agenda-view list.background row.expander image.expander-row-arrow, row.expander agenda-view list.background image.expander-row-arrow, .tweak-titlebar-left row.expander image.expander-row-arrow, row.expander .tweak-titlebar-left image.expander-row-arrow, leaflet.unfolded > box > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded > box > scrolledwindow image.expander-row-arrow, leaflet.unfolded .contacts-contact-list > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded .contacts-contact-list > scrolledwindow image.expander-row-arrow { + color: rgba(30, 30, 46, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider, placessidebar > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar > range > trough > slider { + background-color: rgba(239, 241, 245, 0.5); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:hover, placessidebar > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:hover { + background-color: rgba(239, 241, 245, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:active, placessidebar > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:active { + background-color: rgba(239, 241, 245, 0.7); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:disabled, placessidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:disabled { + background-color: rgba(239, 241, 245, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(30, 30, 46, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(30, 30, 46, 0.3); +} + +placessidebar list.navigation-sidebar, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar { + padding: 6px 0 6px 6px; + background: none; + color: rgba(239, 241, 245, 0.7); +} + +placessidebar list.navigation-sidebar > separator, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > separator, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > separator { + background-color: rgba(239, 241, 245, 0.12); + margin: 10px 15px; +} + +placessidebar list.navigation-sidebar > row, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row { + color: rgba(30, 30, 46, 0.6); + border-radius: 9px; + color: #eff1f5; + padding: 6px 0; +} + +placessidebar list.navigation-sidebar > row:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:hover, placessidebar list.navigation-sidebar > row:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:active, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:active, placessidebar list.navigation-sidebar > row:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:focus { + color: #d2e3fd; +} + +placessidebar list.navigation-sidebar > row:selected, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + color: #89b4fa; + font-weight: 500; +} + +placessidebar list.navigation-sidebar > row:selected:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:hover, placessidebar list.navigation-sidebar > row:selected:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:focus { + color: #bad3fc; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.top, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.top, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.top, filechooser paned > box scrolledwindow scrollbar.top, placessidebar > scrolledwindow > scrollbar.top, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.top, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.top, leaflet.unfolded > box > scrolledwindow > scrollbar.top, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.top, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.top { + border-bottom: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.bottom, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.bottom, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.bottom, filechooser paned > box scrolledwindow scrollbar.bottom, placessidebar > scrolledwindow > scrollbar.bottom, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.bottom, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.bottom, leaflet.unfolded > box > scrolledwindow > scrollbar.bottom, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.bottom, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.bottom { + border-top: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.left, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.left, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.left, filechooser paned > box scrolledwindow scrollbar.left, placessidebar > scrolledwindow > scrollbar.left, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.left, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.left, leaflet.unfolded > box > scrolledwindow > scrollbar.left, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.left, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.left { + border-right: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.right, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.right, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.right, filechooser paned > box scrolledwindow scrollbar.right, placessidebar > scrolledwindow > scrollbar.right, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.right, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.right, leaflet.unfolded > box > scrolledwindow > scrollbar.right, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.right, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.right { + border-left: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.dragging, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.dragging, placessidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.dragging, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.dragging, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.dragging, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.hovering, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.hovering, placessidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.hovering, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.hovering, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.hovering, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.hovering, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-top > undershoot.top, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-top > undershoot.top { + border-radius: 12px 12px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-bottom > undershoot.bottom, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 12px 12px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +avatar { + border-radius: 9999px; + font-weight: bold; +} + +avatar.color1 { + background-image: linear-gradient(#83b6ec, #337fdc); + color: #cfe1f5; +} + +avatar.color2 { + background-image: linear-gradient(#7ad9f1, #0f9ac8); + color: #caeaf2; +} + +avatar.color3 { + background-image: linear-gradient(#8de6b1, #29ae74); + color: #cef8d8; +} + +avatar.color4 { + background-image: linear-gradient(#b5e98a, #6ab85b); + color: #e6f9d7; +} + +avatar.color5 { + background-image: linear-gradient(#f8e359, #d29d09); + color: #f9f4e1; +} + +avatar.color6 { + background-image: linear-gradient(#ffcb62, #d68400); + color: #ffead1; +} + +avatar.color7 { + background-image: linear-gradient(#ffa95a, #ed5b00); + color: #ffe5c5; +} + +avatar.color8 { + background-image: linear-gradient(#f78773, #e62d42); + color: #f8d2ce; +} + +avatar.color9 { + background-image: linear-gradient(#e973ab, #e33b6a); + color: #fac7de; +} + +avatar.color10 { + background-image: linear-gradient(#cb78d4, #9945b5); + color: #e7c2e8; +} + +avatar.color11 { + background-image: linear-gradient(#9e91e8, #7a59ca); + color: #d5d2f5; +} + +avatar.color12 { + background-image: linear-gradient(#e3cf9c, #b08952); + color: #f2eade; +} + +avatar.color13 { + background-image: linear-gradient(#be916d, #785336); + color: #e5d6ca; +} + +avatar.color14 { + background-image: linear-gradient(#c0bfbc, #6e6d71); + color: #d8d7d3; +} + +avatar.contrasted { + color: #eff1f5; +} + +avatar.image { + background: none; +} + +.card { + border-radius: 12px; + border: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; + color: rgba(239, 241, 245, 0.7); + box-shadow: none; + outline: none; + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +.card.activatable { + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.04); +} + +.card.activatable:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + +.card.activatable:active { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +toast { + margin: 12px; + margin-bottom: 24px; + border-radius: 9999px; + border-spacing: 6px; + padding: 6px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; + color: #eff1f5; + border: none; +} + +toast:dir(ltr) { + padding-left: 12px; +} + +toast:dir(rtl) { + padding-right: 12px; +} + +toast > label { + margin: 0 6px; +} + +viewswitcher { + min-height: 0; + padding: 3px; + margin: 6px 0; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + border: none; +} + +viewswitcher.wide { + margin-top: 6px; + margin-bottom: 6px; +} + +viewswitcher.wide button.toggle { + margin: 0; + border-radius: 9px; +} + +viewswitcher.narrow button.toggle { + border-radius: 0; + margin: 0; +} + +viewswitcher.narrow button.toggle:focus-within, viewswitcher.narrow button.toggle:focus { + box-shadow: none; +} + +viewswitcher button.toggle { + font-weight: bold; + padding: 0; +} + +viewswitcher button.toggle > stack > box.narrow { + font-size: 0.75rem; + padding-top: 6px; + padding-bottom: 4px; + border-spacing: 4px; +} + +viewswitcher button.toggle > stack > box.narrow > stack > label { + padding-left: 6px; + padding-right: 6px; +} + +viewswitcher button.toggle > stack > box.wide { + padding: 2px 12px; + border-spacing: 6px; +} + +viewswitcherbar actionbar > revealer > box { + padding: 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle { + border-radius: 12px; + margin: 3px 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 5px; + padding-bottom: 1px; + border-spacing: 0; +} + +viewswitchertitle { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher { + margin-left: 12px; + margin-right: 12px; +} + +viewswitchertitle viewswitcher.narrow { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 0; + padding-bottom: 0; + border-spacing: 0; +} + +viewswitchertitle viewswitcher.wide { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle windowtitle { + margin-top: 0; + margin-bottom: 0; +} + +indicatorbin > indicator, +indicatorbin > mask { + min-width: 6px; + min-height: 6px; + border-radius: 9999px; +} + +indicatorbin > indicator { + margin: 1px; + background-color: alpha(currentColor, 0.4); +} + +indicatorbin > indicator > label { + font-size: 0.6rem; + font-weight: bold; + padding: 1px 4px; + color: #eff1f5; +} + +indicatorbin > mask { + padding: 1px; + background: black; +} + +indicatorbin.needs-attention > indicator { + background-color: #89b4fa; +} + +indicatorbin.needs-attention > indicator > label { + color: rgba(30, 30, 46, 0.87); +} + +preferencespage > scrolledwindow > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +preferencesgroup > box background-preview widget.sidebar, +preferencesgroup > box widget.header-bar:not(.editable-area) { + background-color: #11111b; +} + +preferencesgroup > box, +preferencesgroup > box .labels { + border-spacing: 6px; +} + +preferencesgroup > box > box.header:not(.single-line) { + margin-bottom: 6px; +} + +preferencesgroup > box > box.single-line { + min-height: 34px; +} + +preferencesgroup > box button.background-preview-button.toggle { + padding: 0; + background: none; + box-shadow: none; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; +} + +preferencesgroup > box button.background-preview-button.toggle, +preferencesgroup > box button.background-preview-button.toggle > background-preview { + border-radius: 12px; +} + +preferencesgroup > box button.background-preview-button.toggle:hover { + outline-color: rgba(239, 241, 245, 0.04); +} + +preferencesgroup > box button.background-preview-button.toggle:active { + outline-color: rgba(239, 241, 245, 0.3); +} + +preferencesgroup > box button.background-preview-button.toggle:checked { + outline-color: #89b4fa; +} + +preferencesgroup > box .cutout-button { + background-color: #313244; +} + +preferencesgroup > box button.accent-button { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; + background: var(--accent-bg-color); + outline: none; + background-clip: content-box; + box-shadow: none; +} + +preferencesgroup > box button.accent-button:hover { + box-shadow: 0 0 0 3px alpha(currentColor, 0.08); +} + +preferencesgroup > box button.accent-button:checked { + box-shadow: 0 0 0 3px #89b4fa; +} + +preferencesgroup > box button.accent-button.blue, preferencesgroup > box button.accent-button.teal, preferencesgroup > box button.accent-button.green, preferencesgroup > box button.accent-button.yellow, preferencesgroup > box button.accent-button.orange, preferencesgroup > box button.accent-button.red, preferencesgroup > box button.accent-button.pink, preferencesgroup > box button.accent-button.purple, preferencesgroup > box button.accent-button.slate { + --accent-color: oklab( + from var(--accent-bg-color) var(--standalone-color-oklab) + ); +} + +preferencesgroup > box button.accent-button.blue { + --accent-bg-color: var(--accent-blue); +} + +preferencesgroup > box button.accent-button.teal { + --accent-bg-color: var(--accent-teal); +} + +preferencesgroup > box button.accent-button.green { + --accent-bg-color: var(--accent-green); +} + +preferencesgroup > box button.accent-button.yellow { + --accent-bg-color: var(--accent-yellow); +} + +preferencesgroup > box button.accent-button.orange { + --accent-bg-color: var(--accent-orange); +} + +preferencesgroup > box button.accent-button.red { + --accent-bg-color: var(--accent-red); +} + +preferencesgroup > box button.accent-button.pink { + --accent-bg-color: var(--accent-pink); +} + +preferencesgroup > box button.accent-button.purple { + --accent-bg-color: var(--accent-purple); +} + +preferencesgroup > box button.accent-button.slate { + --accent-bg-color: var(--accent-slate); +} + +preferencesgroup > box box > list.boxed-list-separate { + background-color: transparent; + border-radius: 12px; + border: 1px solid rgba(239, 241, 245, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row { + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px 12px 0 0; + margin-top: 0px; + margin-bottom: 0px; +} + +preferencesgroup > box box > list.boxed-list-separate row:first-child { + border-radius: 12px 12px 0 0; + box-shadow: 0 1px rgba(239, 241, 245, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row:last-child { + border-radius: 0 0 12px 12px; +} + +preferencesgroup > box box > list.boxed-list-separate row:hover, preferencesgroup > box box > list.boxed-list-separate row:focus { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); +} + +window.about .main-page > viewport > clamp > box { + margin: 12px; + border-spacing: 6px; +} + +window.about .main-page > viewport > clamp > box > box { + margin-top: 18px; + border-spacing: 18px; + margin-bottom: 6px; +} + +window.about .main-page .app-version { + padding: 3px 18px; + color: #89b4fa; + border-radius: 12px; + margin-top: 3px; +} + +window.about .subpage > viewport > clamp > box { + margin: 18px 12px; + border-spacing: 18px; +} + +window.about .subpage > clamp > textview { + background: none; + color: inherit; +} + +statuspage > scrolledwindow > viewport > box { + margin: 36px 12px; + border-spacing: 36px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box { + border-spacing: 12px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 128px; + color: alpha(currentColor, 0.55); +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:disabled { + opacity: 0.35; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box { + margin: 24px 12px; + border-spacing: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 96px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .title { + font-size: 18pt; +} + +flap > dimming, +leaflet > dimming, +navigation-view > dimming, +overlay-split-view > dimming { + background-color: rgba(30, 30, 46, 0.2); + background-image: none; +} + +flap > border, +leaflet > border, +navigation-view > border, +overlay-split-view > border { + background-color: transparent; + background-image: none; +} + +flap > shadow, +leaflet > shadow, +navigation-view > shadow, +overlay-split-view > shadow { + min-width: 56px; + min-height: 56px; +} + +flap > shadow.left, +leaflet > shadow.left, +navigation-view > shadow.left, +overlay-split-view > shadow.left { + background-image: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +flap > shadow.right, +leaflet > shadow.right, +navigation-view > shadow.right, +overlay-split-view > shadow.right { + background-image: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +flap > shadow.up, +leaflet > shadow.up, +navigation-view > shadow.up, +overlay-split-view > shadow.up { + background-image: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +flap > shadow.down, +leaflet > shadow.down, +navigation-view > shadow.down, +overlay-split-view > shadow.down { + background-image: linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +.sidebar-pane { + color: #eff1f5; + border-top-left-radius: 12px; +} + +.sidebar-pane .sidebar-pane { + background-color: transparent; + color: inherit; +} + +.sidebar-pane headerbar, +.sidebar-pane .navigation-sidebar, +.sidebar-pane searchbar > revealer > box { + background-color: transparent; + box-shadow: none; + border: none; +} + +.sidebar-pane .navigation-sidebar { + padding: 2px 4px; + background: none; + color: rgba(239, 241, 245, 0.7); +} + +.sidebar-pane:dir(ltr), +.sidebar-pane:dir(ltr) banner > revealer > widget, .sidebar-pane.end:dir(rtl), +.sidebar-pane.end:dir(rtl) banner > revealer > widget { + /* box-shadow: inset 0 1px highlight($base-alt); */ + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +/* Middle pane in three-pane setups */ +.content-pane .sidebar-pane, +.sidebar-pane .content-pane { + background-color: transparent; + color: #eff1f5; +} + +.content-pane .sidebar-pane:backdrop, +.sidebar-pane .content-pane:backdrop { + background-color: transparent; + transition: none; +} + +.content-pane { + background-color: #1e1e2e; + color: #eff1f5; + border-top-right-radius: 12px; + /* box-shadow: inset 0 1px highlight($background); */ +} + +.content-pane headerbar, .content-pane headerbar:backdrop { + background-color: transparent; + box-shadow: none; + border: none; +} + +.maximized .content-pane, .fullscreen .content-pane, .tiled .content-pane, .tiled-top .content-pane, .tiled-right .content-pane, .tiled-bottom .content-pane, .tiled-left .content-pane { + border-radius: 0; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +.top-bar { + box-shadow: none; + background: none; + border: none; +} + +.top-bar headerbar, .top-bar headerbar:backdrop { + background-color: transparent; + box-shadow: none; +} + +.top-bar .collapse-spacing { + padding: 0; +} + +themeselector, +panelthemeselector { + margin: 9px; +} + +themeselector checkbutton, +panelthemeselector checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.12); +} + +themeselector checkbutton.follow:checked, themeselector checkbutton.light:checked, themeselector checkbutton.dark:checked, +panelthemeselector checkbutton.follow:checked, +panelthemeselector checkbutton.light:checked, +panelthemeselector checkbutton.dark:checked { + box-shadow: inset 0 0 0 2px #89b4fa; +} + +themeselector checkbutton.follow, +panelthemeselector checkbutton.follow { + background-image: linear-gradient(to bottom right, #eff1f5 50%, #292c3c 50%); +} + +themeselector checkbutton.light, +panelthemeselector checkbutton.light { + background-color: #eff1f5; +} + +themeselector checkbutton.dark, +panelthemeselector checkbutton.dark { + background-color: #292c3c; +} + +themeselector checkbutton.theme-selector radio, +panelthemeselector checkbutton.theme-selector radio { + -gtk-icon-source: none; + border: none; + background: none; + box-shadow: none; + min-height: 20px; + min-width: 20px; + padding: 0; +} + +themeselector checkbutton.theme-selector radio:hover, themeselector checkbutton.theme-selector radio:active, themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:hover, +panelthemeselector checkbutton.theme-selector radio:active, +panelthemeselector checkbutton.theme-selector radio:checked { + background-color: transparent; +} + +themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked { + -gtk-icon-size: 20px; + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +themeselector checkbutton.theme-selector radio:checked, themeselector checkbutton.theme-selector radio:checked:hover, themeselector checkbutton.theme-selector radio:checked:active, +panelthemeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked:hover, +panelthemeselector checkbutton.theme-selector radio:checked:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher { + padding: 6px; +} + +themeswitcher .check { + min-height: 20px; + min-width: 20px; + background: none; + padding: 0; + margin: 0; + border-radius: 9999px; + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +themeswitcher .check, themeswitcher .check:hover, themeswitcher .check:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.12); +} + +themeswitcher checkbutton:checked { + box-shadow: inset 0 0 0 2px #89b4fa; +} + +themeswitcher checkbutton radio, themeswitcher checkbutton radio:hover, themeswitcher checkbutton radio:active, themeswitcher checkbutton radio:checked, themeswitcher checkbutton radio:checked:hover, themeswitcher checkbutton radio:checked:active { + background-color: transparent; + border: none; + background: none; + box-shadow: none; + color: transparent; + -gtk-icon-source: none; + -gtk-icon-size: 0; +} + +themeswitcher checkbutton.system { + background: linear-gradient(-45deg, #1e1e2e 50%, #eff1f5 50%); +} + +themeswitcher checkbutton.light { + color: alpha(black, 0.8); + background-color: #eff1f5; +} + +themeswitcher checkbutton.dark { + color: #eff1f5; + background-color: #1e1e2e; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #eff1f5; +/* text color for entries, views and content in general */ +@define-color theme_text_color #eff1f5; +/* widget base background color */ +@define-color theme_bg_color #1e1e2e; +/* text widgets and the like base background color */ +@define-color theme_base_color #313244; +/* base background color of selections */ +@define-color theme_selected_bg_color #89b4fa; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(30, 30, 46, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #1e1e2e; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(239, 241, 245, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #313244; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #eff1f5; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #eff1f5; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #1e1e2e; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #313244; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #89b4fa; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(30, 30, 46, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(239, 241, 245, 0.5); +/* widgets main borders color */ +@define-color borders rgba(239, 241, 245, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(239, 241, 245, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #df8e1d; +@define-color error_color #d20f39; +@define-color success_color #40a02b; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #eff1f5; +@define-color wm_unfocused_title rgba(239, 241, 245, 0.7); +@define-color wm_highlight rgba(239, 241, 245, 0.1); +@define-color wm_border #0a0a0e; +@define-color wm_focused_bg #1e1e2e; +@define-color wm_unfocused_bg #1e1e2e; +@define-color wm_button_icon #eff1f5; +@define-color wm_button_focused_bg #2b2b3a; +@define-color wm_button_unfocused_bg #2b2b3a; +@define-color wm_button_hover_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_active_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_hover_bg #e6e9ef; +@define-color wm_button_active_bg #e7eaf0; +/* FIXME this is really an API */ +@define-color content_view_bg #313244; +@define-color placeholder_text_color #b6b8c0; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #313244; +@define-color budgie_tasklist_indicator_color rgba(121, 122, 133, 0.7); +@define-color budgie_tasklist_indicator_color_active #89b4fa; +@define-color budgie_tasklist_indicator_color_active_window rgba(108, 140, 195, 0.816); +@define-color budgie_tasklist_indicator_color_attention #df8e1d; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; +@define-color blue_1 #99c1f1; +@define-color blue_2 #62a0ea; +@define-color blue_3 #3584e4; +@define-color blue_4 #1c71d8; +@define-color blue_5 #1a5fb4; +@define-color green_1 #8ff0a4; +@define-color green_2 #57e389; +@define-color green_3 #33d17a; +@define-color green_4 #2ec27e; +@define-color green_5 #26a269; +@define-color yellow_1 #f9f06b; +@define-color yellow_2 #f8e45c; +@define-color yellow_3 #f6d32d; +@define-color yellow_4 #f5c211; +@define-color yellow_5 #e5a50a; +@define-color orange_1 #ffbe6f; +@define-color orange_2 #ffa348; +@define-color orange_3 #ff7800; +@define-color orange_4 #e66100; +@define-color orange_5 #c64600; +@define-color red_1 #f66151; +@define-color red_2 #ed333b; +@define-color red_3 #e01b24; +@define-color red_4 #c01c28; +@define-color red_5 #a51d2d; +@define-color purple_1 #dc8add; +@define-color purple_2 #c061cb; +@define-color purple_3 #9141ac; +@define-color purple_4 #813d9c; +@define-color purple_5 #613583; +@define-color brown_1 #cdab8f; +@define-color brown_2 #b5835a; +@define-color brown_3 #986a44; +@define-color brown_4 #865e3c; +@define-color brown_5 #63452c; +@define-color light_1 #ffffff; +@define-color light_2 #f6f5f4; +@define-color light_3 #deddda; +@define-color light_4 #c0bfbc; +@define-color light_5 #9a9996; +@define-color dark_1 #77767b; +@define-color dark_2 #5e5c64; +@define-color dark_3 #3d3846; +@define-color dark_4 #241f31; +@define-color dark_5 #000000; +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +@define-color accent_bg_color #89b4fa; +@define-color accent_fg_color rgba(30, 30, 46, 0.87); +@define-color accent_color #89b4fa; +@define-color destructive_bg_color #d20f39; +@define-color destructive_fg_color #eff1f5; +@define-color destructive_color #d20f39; +@define-color success_bg_color #40a02b; +@define-color success_fg_color #eff1f5; +@define-color success_color #40a02b; +@define-color warning_bg_color #df8e1d; +@define-color warning_fg_color #eff1f5; +@define-color warning_color #df8e1d; +@define-color error_bg_color #d20f39; +@define-color error_fg_color #eff1f5; +@define-color error_color #d20f39; +@define-color window_bg_color #1e1e2e; +@define-color window_fg_color #eff1f5; +@define-color view_bg_color #313244; +@define-color view_fg_color #eff1f5; +@define-color headerbar_bg_color #1e1e2e; +@define-color headerbar_fg_color #eff1f5; +@define-color headerbar_border_color rgba(239, 241, 245, 0.12); +@define-color headerbar_backdrop_color #1e1e2e; +@define-color headerbar_shade_color rgba(239, 241, 245, 0.12); +@define-color card_bg_color #313244; +@define-color card_fg_color #eff1f5; +@define-color card_shade_color rgba(239, 241, 245, 0.12); +@define-color dialog_bg_color #313244; +@define-color dialog_fg_color #eff1f5; +@define-color popover_bg_color #292c3c; +@define-color popover_fg_color #eff1f5; +@define-color shade_color rgba(239, 241, 245, 0.12); +@define-color scrollbar_outline_color rgba(239, 241, 245, 0.12); diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk.css b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk.css new file mode 100755 index 0000000..17ddad3 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/gtk.css @@ -0,0 +1,8518 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #89b4fa 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #89b4fa 100%, transparent 100%); + } +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #1e1e2e; + color: #eff1f5; +} + +#desktopwindow.background { + background-color: transparent; +} + +dnd { + color: #eff1f5; +} + +.normal-icons { + -gtk-icon-size: 16px; +} + +.large-icons { + -gtk-icon-size: 32px; +} + +.aboutdialog .large-icons { + -gtk-icon-size: 128px; +} + +spinner:disabled, +arrow:disabled, +scrollbar:disabled, +check:disabled, +radio:disabled, +treeview.expander:disabled { + -gtk-icon-filter: opacity(0.5); +} + +iconview, +.view { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +iconview:disabled, +.view:disabled { + color: rgba(239, 241, 245, 0.5); +} + +iconview:selected, +.view:selected { + color: #eff1f5; +} + +textview text { + background-color: #313244; +} + +textview border { + background-color: #313244; + color: rgba(239, 241, 245, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 6px; +} + +rubberband, .content-view rubberband, .content-view columnview.view > rubberband, +.content-view treeview.view > rubberband, +.content-view .rubberband, columnview.view > rubberband, +.content-view columnview.view > .rubberband, +treeview.view > rubberband, +.content-view treeview.view > .rubberband, gridview > rubberband, flowbox > rubberband { + border: 1px solid #89b4fa; + background-color: rgba(137, 180, 250, 0.3); +} + +flowbox > flowboxchild { + padding: 4px; + border-radius: 12px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +gridview > child { + padding: 3px; +} + +gridview > child:selected { + outline-color: alpha(currentColor, 0.06); +} + +gridview > child box { + border-spacing: 8px; + margin: 12px; +} + +coverflow cover { + color: #eff1f5; + background-color: #313244; + border: 1px solid black; +} + +label.separator { + color: rgba(239, 241, 245, 0.7); +} + +label:disabled { + opacity: 1; + color: rgba(239, 241, 245, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; + opacity: 1; +} + +label.osd { + border-radius: 12px; + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; +} + + +.dim-label, +row.expander image.expander-row-arrow, +row.property > box.header > box.title > .title, +row label.subtitle { + color: rgba(239, 241, 245, 0.7); + opacity: 1; +} + +.accent { + color: #89b4fa; +} + +.success { + color: #40a02b; +} + +.warning { + color: #df8e1d; +} + +.error { + color: #d20f39; +} + +.large-title { + font-weight: 300; + font-size: 24pt; +} + +.title-1 { + font-weight: 800; + font-size: 20pt; +} + +.title-2 { + font-weight: 800; + font-size: 15pt; +} + +.title-3 { + font-weight: 700; + font-size: 15pt; +} + +.title-4 { + font-weight: 700; + font-size: 13pt; +} + +.heading { + font-weight: 700; + font-size: 11pt; +} + +.body { + font-weight: 400; + font-size: 11pt; +} + +.caption, row.property > box.header > box.title > .title { + font-weight: 400; + font-size: 9pt; +} + +.caption-heading { + font-weight: 700; + font-size: 9pt; +} + +window.assistant .sidebar { + padding: 4px 0; +} + +window.assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(239, 241, 245, 0.5); + font-weight: 500; +} + +window.assistant .sidebar label.highlight { + color: #eff1f5; +} + +.osd .scale-popup > arrow, +.osd .scale-popup > contents, .osd popover > arrow, +.osd popover > contents, popover.touch-selection > arrow, +popover.touch-selection > contents, popover.magnifier > arrow, +popover.magnifier > contents, .osd { + color: #eff1f5; + background-color: #313244; + background-clip: padding-box; + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +.osd { + padding: 6px; + margin: 6px; +} + +.osd.circular { + border-radius: 9999px; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ + +entry headerbar popover.background entry, +headerbar popover.background entry entry, +entry { + min-height: 34px; + padding: 0 8px; + border-spacing: 6px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + + +entry headerbar popover.background entry:focus-within, +headerbar popover.background entry entry:focus-within, +entry:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #89b4fa; +} + + +entry headerbar popover.background entry:drop(active), +headerbar popover.background entry entry:drop(active), +entry headerbar popover.background entry:hover:not(:focus-within), +headerbar popover.background entry entry:hover:not(:focus-within), +entry:drop(active), +entry:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + + +entry headerbar popover.background entry:disabled, +headerbar popover.background entry entry:disabled, +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + + +entry headerbar popover.background entry > text > placeholder, +headerbar popover.background entry entry > text > placeholder, +entry > text > placeholder { + color: rgba(239, 241, 245, 0.5); +} + + +entry headerbar popover.background entry > text > block-cursor, +headerbar popover.background entry entry > text > block-cursor, +entry > text > block-cursor { + color: rgba(239, 241, 245, 0.04); + background-color: #eff1f5; +} + + +entry headerbar popover.background entry.flat:focus-within, +headerbar popover.background entry entry.flat:focus-within, +entry headerbar popover.background entry.flat:disabled, +headerbar popover.background entry entry.flat:disabled, +entry headerbar popover.background entry.flat:hover, +headerbar popover.background entry entry.flat:hover, +entry headerbar popover.background entry.flat, +headerbar popover.background entry entry.flat, +entry.flat:focus-within, +entry.flat:disabled, +entry.flat:hover, +entry.flat { + min-height: 0; + padding: 2px; + background-color: transparent; + box-shadow: none; + border-radius: 0; + outline: none; +} + + +entry headerbar popover.background entry > image, +headerbar popover.background entry entry > image, +entry > image { + color: rgba(239, 241, 245, 0.7); +} + + +entry headerbar popover.background entry > image:hover, +headerbar popover.background entry entry > image:hover, +entry headerbar popover.background entry > image:active, +headerbar popover.background entry entry > image:active, +entry > image:hover, +entry > image:active { + color: #eff1f5; +} + + +entry headerbar popover.background entry > image:disabled, +headerbar popover.background entry entry > image:disabled, +entry > image:disabled { + color: rgba(239, 241, 245, 0.5); +} + + +entry headerbar popover.background entry > image.left, +headerbar popover.background entry entry > image.left, +entry > image.left { + margin: 0 6px 0 1px; +} + + +entry headerbar popover.background entry > image.right, +headerbar popover.background entry entry > image.right, +entry > image.right { + margin: 0 1px 0 6px; +} + + +entry headerbar popover.background entry.password image.caps-lock-indicator, +headerbar popover.background entry entry.password image.caps-lock-indicator, +entry.password image.caps-lock-indicator { + opacity: 0.35; +} + + +entry headerbar popover.background entry.error, +headerbar popover.background entry entry.error, +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + outline: none; +} + + +entry headerbar popover.background entry.error:focus-within, +headerbar popover.background entry entry.error:focus-within, +entry.error:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #d20f39; + outline: none; +} + + +entry headerbar popover.background entry.error:drop(active), +headerbar popover.background entry entry.error:drop(active), +entry headerbar popover.background entry.error:hover:not(:focus-within), +headerbar popover.background entry entry.error:hover:not(:focus-within), +entry.error:drop(active), +entry.error:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.error:disabled, +headerbar popover.background entry entry.error:disabled, +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.error > text > selection, +headerbar popover.background entry entry.error > text > selection, +entry.error > text > selection { + background-color: rgba(210, 15, 57, 0.25); + color: #d20f39; +} + + +entry headerbar popover.background entry.error > text > cursor-handle > contents, +headerbar popover.background entry entry.error > text > cursor-handle > contents, +entry.error > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.error > image, +headerbar popover.background entry entry.error > image, +entry.error > image { + color: rgba(210, 15, 57, 0.75); +} + + +entry headerbar popover.background entry.error > image:hover, +headerbar popover.background entry entry.error > image:hover, +entry headerbar popover.background entry.error > image:active, +headerbar popover.background entry entry.error > image:active, +entry.error > image:hover, +entry.error > image:active { + color: #d20f39; +} + + +entry headerbar popover.background entry.error > image:disabled, +headerbar popover.background entry entry.error > image:disabled, +entry.error > image:disabled { + color: rgba(210, 15, 57, 0.35); +} + + +entry headerbar popover.background entry.warning, +headerbar popover.background entry entry.warning, +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + outline: none; +} + + +entry headerbar popover.background entry.warning:focus-within, +headerbar popover.background entry entry.warning:focus-within, +entry.warning:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #df8e1d; + outline: none; +} + + +entry headerbar popover.background entry.warning:drop(active), +headerbar popover.background entry entry.warning:drop(active), +entry headerbar popover.background entry.warning:hover:not(:focus-within), +headerbar popover.background entry entry.warning:hover:not(:focus-within), +entry.warning:drop(active), +entry.warning:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.warning:disabled, +headerbar popover.background entry entry.warning:disabled, +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.warning > text > selection, +headerbar popover.background entry entry.warning > text > selection, +entry.warning > text > selection { + background-color: rgba(223, 142, 29, 0.25); + color: #df8e1d; +} + + +entry headerbar popover.background entry.warning > text > cursor-handle > contents, +headerbar popover.background entry entry.warning > text > cursor-handle > contents, +entry.warning > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.warning > image, +headerbar popover.background entry entry.warning > image, +entry.warning > image { + color: rgba(223, 142, 29, 0.75); +} + + +entry headerbar popover.background entry.warning > image:hover, +headerbar popover.background entry entry.warning > image:hover, +entry headerbar popover.background entry.warning > image:active, +headerbar popover.background entry entry.warning > image:active, +entry.warning > image:hover, +entry.warning > image:active { + color: #df8e1d; +} + + +entry headerbar popover.background entry.warning > image:disabled, +headerbar popover.background entry entry.warning > image:disabled, +entry.warning > image:disabled { + color: rgba(223, 142, 29, 0.35); +} + + +entry headerbar popover.background entry.success, +headerbar popover.background entry entry.success, +entry.success { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + outline: none; +} + + +entry headerbar popover.background entry.success:focus-within, +headerbar popover.background entry entry.success:focus-within, +entry.success:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #40a02b; + outline: none; +} + + +entry headerbar popover.background entry.success:drop(active), +headerbar popover.background entry entry.success:drop(active), +entry headerbar popover.background entry.success:hover:not(:focus-within), +headerbar popover.background entry entry.success:hover:not(:focus-within), +entry.success:drop(active), +entry.success:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.success:disabled, +headerbar popover.background entry entry.success:disabled, +entry.success:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.success > text > selection, +headerbar popover.background entry entry.success > text > selection, +entry.success > text > selection { + background-color: rgba(64, 160, 43, 0.25); + color: #40a02b; +} + + +entry headerbar popover.background entry.success > text > cursor-handle > contents, +headerbar popover.background entry entry.success > text > cursor-handle > contents, +entry.success > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.success > image, +headerbar popover.background entry entry.success > image, +entry.success > image { + color: rgba(64, 160, 43, 0.75); +} + + +entry headerbar popover.background entry.success > image:hover, +headerbar popover.background entry entry.success > image:hover, +entry headerbar popover.background entry.success > image:active, +headerbar popover.background entry entry.success > image:active, +entry.success > image:hover, +entry.success > image:active { + color: #40a02b; +} + + +entry headerbar popover.background entry.success > image:disabled, +headerbar popover.background entry entry.success > image:disabled, +entry.success > image:disabled { + color: rgba(64, 160, 43, 0.35); +} + + +entry > progress, +entry progress > trough > progress { + margin: 0 -4px; + border-bottom: 2px solid #89b4fa; + background-color: transparent; +} + +.osd entry > progress > trough > progress { + border-color: rgba(239, 241, 245, 0.04); +} + + +entry button.image-button { + min-height: 24px; + min-width: 24px; + padding: 0; +} + +treeview entry.flat, treeview entry { + background-color: #313244; +} + +treeview entry.flat, treeview entry.flat:focus-within, treeview entry, treeview entry:focus-within { + border-image: none; + box-shadow: none; +} + +.entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +.entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +editablelabel > stack > text { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: radial-gradient(farthest-side, #89b4fa 0%, rgba(137, 180, 250, 0) 0%); + } + to { + background-image: radial-gradient(farthest-side, #89b4fa 95%, rgba(137, 180, 250, 0)); + } +} + +infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button, popover.touch-selection button, popover.magnifier button, headerbar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +infobar.warning > revealer > box button:focus, popover.touch-selection button:focus, popover.magnifier button:focus, headerbar.selection-mode button:focus:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:hover, popover.touch-selection button:hover, popover.magnifier button:hover, headerbar.selection-mode button:hover:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:active, popover.touch-selection button:active, popover.magnifier button:active, headerbar.selection-mode button:active:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:checked, popover.touch-selection button:checked, popover.magnifier button:checked, headerbar.selection-mode button:checked:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +infobar.warning > revealer > box button:disabled, popover.touch-selection button:disabled, popover.magnifier button:disabled, headerbar.selection-mode button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +infobar.warning > revealer > box button:checked:disabled, popover.touch-selection button:checked:disabled, popover.magnifier button:checked:disabled, headerbar.selection-mode button:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.5); +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button, button { + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:focus:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:focus, button:focus { + background-color: alpha(currentColor, 0.08); + outline: 2px solid rgba(137, 180, 250, 0.35); + outline-offset: 0; +} + +row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:hover:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:hover, button:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; + -gtk-icon-filter: brightness(1.2); +} + +row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button.keyboard-activating:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button.keyboard-activating, button.keyboard-activating, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:active:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:active, button:active { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:disabled:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:disabled, button:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + outline-color: transparent; +} + +row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:checked, button:checked { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:hover:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:hover { + outline-color: transparent; + background-color: #a1c4fb; + color: rgba(30, 30, 46, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:disabled:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:disabled { + outline-color: transparent; + background-color: rgba(137, 180, 250, 0.35); + color: rgba(30, 30, 46, 0.38); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button, calendar > header > button, notebook > header > tabs > arrow, popover modelbutton, .pathbar button, spinbutton > button, splitbutton.flat > button, +splitbutton.flat > menubutton > button { + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:focus:not(:hover):not(:active), calendar > header > button:focus:not(:hover):not(:active), notebook > header > tabs > arrow:focus:not(:hover):not(:active), popover modelbutton:focus:not(:hover):not(:active), .pathbar button:focus:not(:hover):not(:active), spinbutton > button:focus:not(:hover):not(:active), splitbutton.flat > button:focus:not(:hover):not(:active), +splitbutton.flat > menubutton > button:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 2px solid rgba(239, 241, 245, 0.04); + outline-offset: -2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:hover, calendar > header > button:hover, notebook > header > tabs > arrow:hover, popover modelbutton:hover, .pathbar button:hover, spinbutton > button:hover, splitbutton.flat > button:hover, +splitbutton.flat > menubutton > button:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:active, calendar > header > button:active, notebook > header > tabs > arrow:active, popover modelbutton:active, .pathbar button:active, spinbutton > button:active, splitbutton.flat > button:active, +splitbutton.flat > menubutton > button:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:disabled, calendar > header > button:disabled, notebook > header > tabs > arrow:disabled, popover modelbutton:disabled, .pathbar button:disabled, spinbutton > button:disabled, splitbutton.flat > button:disabled, +splitbutton.flat > menubutton > button:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +#NautilusPathButton, filechooser #pathbarbox > stack > box > button, window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button, .app-notification button, headerbar button:not(.suggested-action):not(.destructive-action), .toolbar button, splitbutton.suggested-action > button, +splitbutton.suggested-action > menubutton > button, splitbutton.destructive-action > button, +splitbutton.destructive-action > menubutton > button, splitbutton.opaque > button, +splitbutton.opaque > menubutton > button, menubutton.suggested-action > button, menubutton.destructive-action > button, menubutton.opaque > button, menubutton.flat > button, button.flat { + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +#NautilusPathButton:focus:not(:hover):not(:active), filechooser #pathbarbox > stack > box > button:focus:not(:hover):not(:active), window.messagedialog .response-area button:focus:not(:hover):not(:active), window.dialog.message .dialog-action-area > button:focus:not(:hover):not(:active), .app-notification button:focus:not(:hover):not(:active), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), .toolbar button:focus:not(:hover):not(:active), splitbutton.suggested-action > button:focus:not(:hover):not(:active), +splitbutton.suggested-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.destructive-action > button:focus:not(:hover):not(:active), +splitbutton.destructive-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.opaque > button:focus:not(:hover):not(:active), +splitbutton.opaque > menubutton > button:focus:not(:hover):not(:active), menubutton.suggested-action > button:focus:not(:hover):not(:active), menubutton.destructive-action > button:focus:not(:hover):not(:active), menubutton.opaque > button:focus:not(:hover):not(:active), menubutton.flat > button:focus:not(:hover):not(:active), button.flat:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 2px solid rgba(239, 241, 245, 0.04); + outline-offset: -2px; +} + +#NautilusPathButton:hover, filechooser #pathbarbox > stack > box > button:hover, window.messagedialog .response-area button:hover, window.dialog.message .dialog-action-area > button:hover, .app-notification button:hover, headerbar button:hover:not(.suggested-action):not(.destructive-action), .toolbar button:hover, splitbutton.suggested-action > button:hover, +splitbutton.suggested-action > menubutton > button:hover, splitbutton.destructive-action > button:hover, +splitbutton.destructive-action > menubutton > button:hover, splitbutton.opaque > button:hover, +splitbutton.opaque > menubutton > button:hover, menubutton.suggested-action > button:hover, menubutton.destructive-action > button:hover, menubutton.opaque > button:hover, menubutton.flat > button:hover, button.flat:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +#NautilusPathButton:active, filechooser #pathbarbox > stack > box > button:active, window.messagedialog .response-area button:active, window.dialog.message .dialog-action-area > button:active, .app-notification button:active, headerbar button:active:not(.suggested-action):not(.destructive-action), .toolbar button:active, splitbutton.suggested-action > button:active, +splitbutton.suggested-action > menubutton > button:active, splitbutton.destructive-action > button:active, +splitbutton.destructive-action > menubutton > button:active, splitbutton.opaque > button:active, +splitbutton.opaque > menubutton > button:active, menubutton.suggested-action > button:active, menubutton.destructive-action > button:active, menubutton.opaque > button:active, menubutton.flat > button:active, button.flat:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; +} + +#NautilusPathButton:disabled, filechooser #pathbarbox > stack > box > button:disabled, window.messagedialog .response-area button:disabled, window.dialog.message .dialog-action-area > button:disabled, .app-notification button:disabled, headerbar button:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:disabled, splitbutton.suggested-action > button:disabled, +splitbutton.suggested-action > menubutton > button:disabled, splitbutton.destructive-action > button:disabled, +splitbutton.destructive-action > menubutton > button:disabled, splitbutton.opaque > button:disabled, +splitbutton.opaque > menubutton > button:disabled, menubutton.suggested-action > button:disabled, menubutton.destructive-action > button:disabled, menubutton.opaque > button:disabled, menubutton.flat > button:disabled, button.flat:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +#NautilusPathButton:checked, filechooser #pathbarbox > stack > box > button:checked, window.messagedialog .response-area button:checked, window.dialog.message .dialog-action-area > button:checked, .app-notification button:checked, headerbar button:checked:not(.suggested-action):not(.destructive-action), .toolbar button:checked, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button:checked, menubutton.suggested-action > button:checked, menubutton.destructive-action > button:checked, menubutton.opaque > button:checked, menubutton.flat > button:checked, button.flat:checked { + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +#NautilusPathButton:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, window.messagedialog .response-area button:checked:disabled, window.dialog.message .dialog-action-area > button:checked:disabled, .app-notification button:checked:disabled, headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:checked:disabled, splitbutton.suggested-action > button:checked:disabled, +splitbutton.suggested-action > menubutton > button:checked:disabled, splitbutton.destructive-action > button:checked:disabled, +splitbutton.destructive-action > menubutton > button:checked:disabled, splitbutton.opaque > button:checked:disabled, +splitbutton.opaque > menubutton > button:checked:disabled, menubutton.suggested-action > button:checked:disabled, menubutton.destructive-action > button:checked:disabled, menubutton.opaque > button:checked:disabled, menubutton.flat > button:checked:disabled, button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(239, 241, 245, 0.5); +} + +button.opaque { + box-shadow: none; +} + +.osd button.opaque:focus:focus-visible { + outline-color: rgba(239, 241, 245, 0.15); +} + +button.opaque:hover { + background-image: image(alpha(currentColor, 0.1)); +} + +button.keyboard-activating.opaque, button.opaque:active { + background-image: image(rgba(0, 0, 0, 0.2)); +} + +button.opaque:checked { + background-image: image(rgba(0, 0, 0, 0.15)); +} + +button.opaque:checked:hover { + background-image: image(rgba(0, 0, 0, 0.05)); +} + +button.opaque:checked.keyboard-activating, button.opaque:checked:active { + background-image: image(rgba(0, 0, 0, 0.3)); +} + +.nautilus-window .floating-bar button, placessidebar list.navigation-sidebar > row button.sidebar-button, notebook > header > tabs > tab button.flat, popover.menu box.circular-buttons button.circular.image-button.model, spinbutton > button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + +button separator { + margin: 4px 1px; +} + +button.opaque { + background-color: #484856; + color: #eff1f5; +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button, button.image-text-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button > box, +button.text-button.image-button > box > box, button.image-text-button > box, +button.image-text-button > box > box { + border-spacing: 4px; +} + +button.text-button.image-button > box > label, +button.text-button.image-button > box > box > label, button.image-text-button > box > label, +button.image-text-button > box > box > label { + padding-left: 2px; + padding-right: 2px; +} + +button.text-button.image-button label:first-child, button.image-text-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child, button.image-text-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child, button.image-text-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child, button.image-text-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child), button.image-text-button image:not(:only-child) { + margin: 0 4px; +} + +button.arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.arrow-button > box { + border-spacing: 4px; +} + +button.arrow-button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +button.arrow-button.text-button > box { + border-spacing: 6px; +} + +menubutton.pill > button, button.pill { + padding: 9px 30px; + border-radius: 9999px; +} + +button.card { + background-color: #313244; + background-clip: padding-box; + font-weight: inherit; + border: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; +} + +button.card:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + +button.card.keyboard-activating, button.card:active { + background-image: none; + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +button.card:checked { + background-image: none; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + border-color: #89b4fa; +} + +button.card:checked:hover { + background-image: none; + outline-color: transparent; + background-color: #a1c4fb; + color: rgba(30, 30, 46, 0.87); +} + +button.card:checked:disabled { + outline-color: transparent; + background-color: rgba(137, 180, 250, 0.35); + color: rgba(30, 30, 46, 0.38); +} + +button.card:checked.keyboard-activating, button.card:checked:active { + background-image: none; +} + +button.card:checked.has-open-popup { + background-image: none; +} + +button.card:drop(active) { + color: #fab387; + box-shadow: inset 0 0 0 1px #fab387; +} + +.linked:not(.vertical) > button:focus, .linked.vertical > button:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + background-color: alpha(currentColor, 0.05); +} + +.linked:not(.vertical) > button.flat:focus, .linked.vertical > button.flat:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > menubutton > button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +button.osd { + min-height: 24px; + min-width: 24px; + padding: 5px; + box-shadow: none; + background-color: rgba(0, 0, 0, 0.35); + color: #eff1f5; + margin: 0; +} + +button.osd > image { + padding: 0; +} + +button.osd.remove-button { + padding: 0; +} + +button.osd:focus { + outline-color: transparent; +} + +button.osd:hover { + background-color: rgba(0, 0, 0, 0.45); + color: #eff1f5; +} + +button.osd:active { + background-color: rgba(0, 0, 0, 0.65); + color: #eff1f5; +} + +button.osd:disabled { + background-color: rgba(0, 0, 0, 0.15); + color: rgba(239, 241, 245, 0.35); +} + +button.suggested-action { + background-color: #1e66f5; + color: #eff1f5; + box-shadow: none; +} + +button.suggested-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + outline-color: transparent; +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:checked { + background-color: #5d90f5; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(30, 102, 245, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #1e66f5; +} + +button.suggested-action.flat:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +button.suggested-action.flat:checked { + background-color: rgba(30, 102, 245, 0.3); +} + +button.destructive-action { + background-color: #d20f39; + color: #eff1f5; + box-shadow: none; +} + +button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + outline-color: transparent; +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:checked { + background-color: #db5371; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(210, 15, 57, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #d20f39; +} + +button.destructive-action.flat:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +button.destructive-action.flat:checked { + background-color: rgba(210, 15, 57, 0.3); +} + +stackswitcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +stackswitcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +stackswitcher > button.needs-attention:checked > label, +stackswitcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +button.font > box, button.file > box { + border-spacing: 6px; +} + +button.font > box > box > label, button.file > box > box > label { + font-weight: bold; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar button.star, menubutton.circular > button, button.close, button.circular { + border-radius: 9999px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque) label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child label, headerbar button.star label, menubutton.circular > button label, button.close label, button.circular label { + padding: 0; +} + +menubutton.osd { + background: none; + color: inherit; +} + +menubutton.suggested-action { + background-color: #1e66f5; + color: #eff1f5; +} + +menubutton.destructive-action { + background-color: #d20f39; + color: #eff1f5; +} + +menubutton.opaque { + background-color: #484856; + color: #eff1f5; +} + +menubutton.suggested-action, menubutton.destructive-action, menubutton.opaque { + border-radius: 12px; +} + +menubutton.suggested-action.circular, menubutton.suggested-action.pill, menubutton.destructive-action.circular, menubutton.destructive-action.pill, menubutton.opaque.circular, menubutton.opaque.pill { + border-radius: 9999px; +} + +menubutton.suggested-action > button, menubutton.suggested-action > button:checked, menubutton.destructive-action > button, menubutton.destructive-action > button:checked, menubutton.opaque > button, menubutton.opaque > button:checked { + background-color: transparent; + color: inherit; +} + +menubutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +menubutton arrow { + min-height: 16px; + min-width: 16px; +} + +menubutton arrow.none { + -gtk-icon-source: -gtk-icontheme("open-menu-symbolic"); +} + +menubutton arrow.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menubutton arrow.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menubutton arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +menubutton arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +splitbutton { + border-radius: 12px; +} + +splitbutton, splitbutton > separator { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + transition-property: background; +} + +splitbutton > separator { + margin-top: 6px; + margin-bottom: 6px; + background: none; +} + +splitbutton > menubutton > button { + padding: 5px 9px; +} + +splitbutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +splitbutton.text-button.image-button > button, splitbutton.image-text-button > button { + padding-left: 9px; + padding-right: 9px; +} + +splitbutton.text-button.image-button > button > box, splitbutton.image-text-button > button > box { + border-spacing: 6px; +} + +splitbutton > button:dir(ltr), +splitbutton > menubutton > button:dir(rtl) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: -1px; +} + +splitbutton > button:dir(rtl), +splitbutton > menubutton > button:dir(ltr) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin-left: -1px; +} + +splitbutton.flat > separator { + background: rgba(239, 241, 245, 0.12); +} + +splitbutton.flat:hover, splitbutton.flat:active, splitbutton.flat:checked { + background: alpha(currentColor, 0.07); +} + +splitbutton.flat:hover > separator, splitbutton.flat:active > separator, splitbutton.flat:checked > separator { + background: none; +} + +splitbutton.flat:focus-within:focus-visible > separator { + background: none; +} + +splitbutton.flat > button, +splitbutton.flat > menubutton > button { + border-radius: 12px; +} + +splitbutton.suggested-action { + background-color: #1e66f5; + color: #eff1f5; +} + +splitbutton.destructive-action { + background-color: #d20f39; + color: #eff1f5; +} + +splitbutton.opaque { + background-color: #484856; + color: #eff1f5; +} + +splitbutton.suggested-action > button, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button, +splitbutton.opaque > menubutton > button:checked { + color: inherit; + background-color: transparent; +} + +splitbutton.suggested-action > menubutton > button:dir(ltr), splitbutton.destructive-action > menubutton > button:dir(ltr), splitbutton.opaque > menubutton > button:dir(ltr) { + box-shadow: inset 1px 0 rgba(239, 241, 245, 0.12); +} + +splitbutton.suggested-action > menubutton > button:dir(rtl), splitbutton.destructive-action > menubutton > button:dir(rtl), splitbutton.opaque > menubutton > button:dir(rtl) { + box-shadow: inset -1px 0 rgba(239, 241, 245, 0.12); +} + +splitbutton > menubutton > button > arrow.none { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +buttoncontent { + border-spacing: 6px; +} + +buttoncontent > label { + font-weight: bold; +} + +buttoncontent > label:dir(ltr) { + padding-right: 2px; +} + +buttoncontent > label:dir(rtl) { + padding-left: 2px; +} + +.arrow-button > box > buttoncontent > label:dir(ltr), splitbutton > button > buttoncontent > label:dir(ltr) { + padding-right: 0; +} + +.arrow-button > box > buttoncontent > label:dir(rtl), splitbutton > button > buttoncontent > label:dir(rtl) { + padding-left: 0; +} + +stacksidebar row.needs-attention > label, stackswitcher > button.needs-attention > label, +stackswitcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar row.needs-attention > label:dir(rtl), stackswitcher > button.needs-attention > label:dir(rtl), +stackswitcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +.linked:not(.vertical) > entry, .linked:not(.vertical) > button, .linked:not(.vertical) > button.image-button { + border-radius: 0; +} + +.linked:not(.vertical) > entry:first-child, .linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > entry:last-child, .linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > entry:only-child, .linked:not(.vertical) > button:only-child { + border-radius: 12px; +} + +.linked.vertical > entry, .linked.vertical > button, .linked.vertical > button.image-button { + border-radius: 0; +} + +.linked.vertical > entry:first-child, .linked.vertical > button:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > entry:last-child, .linked.vertical > button:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > entry:only-child, .linked.vertical > button:only-child { + border-radius: 12px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + + +list > row button.image-button:not(.flat) { + background-color: transparent; + box-shadow: none; + border: none; +} + + +list > row button.image-button:not(.flat):hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + + +list > row button.image-button:not(.flat):active, +list > row button.image-button:not(.flat):checked { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + + +list > row button.image-button:not(.flat).suggested-action { + background-color: #1e66f5; + color: #eff1f5; +} + + +list > row button.image-button:not(.flat).destructive-action { + background-color: #d20f39; + color: #eff1f5; +} + +/********* + * Links * + *********/ +link { + color: #8fcbe8; +} + +link:visited { + color: #8839ef; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #8fcbe8; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #8839ef; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton { + border-radius: 9px; + padding: 0; + border-spacing: 0; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; +} + +spinbutton:focus-within { + background-color: rgba(239, 241, 245, 0.08); + box-shadow: inset 0 0 0 2px #89b4fa; +} + +spinbutton:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(239, 241, 245, 0.08); + color: rgba(239, 241, 245, 0.5); +} + +spinbutton > text { + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + margin: 0; +} + +spinbutton > button { + border: none; +} + +spinbutton > button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: none; +} + +spinbutton:not(.vertical) > text { + min-width: 30px; + padding-left: 12px; +} + +spinbutton:not(.vertical) > button { + padding: 0; + margin: 6px; +} + +spinbutton:not(.vertical) > button.up:dir(ltr), spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 3px; +} + +spinbutton:not(.vertical) > button.up:dir(rtl), spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 3px; +} + +cell.activatable spinbutton:not(.vertical) { + margin: 3px 0; +} + +cell.activatable spinbutton:not(.vertical) > button { + margin: 0; + padding: 0; + min-height: 24px; + border-radius: 0; +} + +cell.activatable spinbutton:not(.vertical) > button:last-child { + border-radius: 0 12px 12px 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(ltr), cell.activatable spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(rtl), cell.activatable spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 0; +} + +spinbutton.vertical > text { + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical > button { + padding: 0; + margin: 6px 8px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #fab387; + box-shadow: inset 0 0 0 2px #fab387; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #eff1f5; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top, combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +.toolbar { + padding: 6px; + /* background-color: $background; */ + border-spacing: 6px; +} + +.osd .toolbar { + background-color: transparent; +} + +.app-notification, .toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 18px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; + color: #eff1f5; +} + +.app-notification:backdrop, .toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +.left.app-notification, .right.app-notification, .top.app-notification, .bottom.app-notification, .toolbar.osd.left, .toolbar.osd.right, .toolbar.osd.top, .toolbar.osd.bottom { + border-radius: 0; +} + +.bottom.app-notification, .toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +.toolbar.horizontal > separator { + margin: 2px; +} + +.toolbar.vertical > separator { + margin: 2px; +} + +.toolbar entry, +.toolbar spinbutton, +.toolbar splitbutton, +.toolbar separator:not(.sidebar), +.toolbar button, +.toolbar menubutton, +.toolbar scalebutton { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar menubutton > button, +.toolbar splitbutton > button, +.toolbar splitbutton > menubutton, +.toolbar scalebutton > button { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar switch { + margin-top: 4px; + margin-bottom: 4px; +} + +.toolbar spinbutton entry, +.toolbar spinbutton button { + margin: 0; +} + +.toolbar popover.menu separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +searchbar > revealer > box { + padding: 6px; + border-spacing: 0; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(239, 241, 245, 0.12); + background-color: #1e1e2e; + background-clip: border-box; + box-shadow: none; +} + +searchbar > revealer > box entry, +searchbar > revealer > box button, +searchbar > revealer > box menubutton { + margin: 0; +} + +/*************** + * Header bars * + ***************/ +headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); + border: none; +} + +headerbar button:hover:not(.suggested-action):not(.destructive-action), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), headerbar button:active:not(.suggested-action):not(.destructive-action), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(239, 241, 245, 0.5); +} + +headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.5); +} + +headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.32); +} + +headerbar entry { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.7); +} + +headerbar entry:hover, headerbar entry:focus-within { + color: #eff1f5; +} + +headerbar entry:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +headerbar entry > text > placeholder { + color: rgba(239, 241, 245, 0.5); +} + +headerbar entry > text > block-cursor { + color: rgba(239, 241, 245, 0.04); + background-color: #eff1f5; +} + +headerbar entry > image { + color: rgba(239, 241, 245, 0.7); +} + +headerbar entry > image:hover, headerbar entry > image:active { + color: #eff1f5; +} + +headerbar entry > image:disabled { + color: rgba(239, 241, 245, 0.5); +} + +headerbar { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: transparent; + color: #eff1f5; + min-height: 46px; + border: none; + box-shadow: none; + padding: 0; + margin: 0; +} + +headerbar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +headerbar:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.7); + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +headerbar:backdrop:disabled { + color: rgba(239, 241, 245, 0.32); +} + +headerbar.flat, headerbar.flat:backdrop { + background: none; + box-shadow: none; + transition: none; +} + +headerbar .title { + padding-left: 6px; + padding-right: 6px; + margin: 0 -13px; + font-weight: bold; +} + +headerbar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +headerbar .subtitle, +headerbar .dim-label, +headerbar row.expander image.expander-row-arrow, +row.expander headerbar image.expander-row-arrow, +headerbar row.property > box.header > box.title > .title, +headerbar row label.subtitle, +row headerbar label.subtitle { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(239, 241, 245, 0.7); +} + +headerbar .subtitle:backdrop, +headerbar .dim-label:backdrop, +headerbar row.expander image.expander-row-arrow:backdrop, +row.expander headerbar image.expander-row-arrow:backdrop, +headerbar row.property > box.header > box.title > .title:backdrop, +headerbar row label.subtitle:backdrop, +row headerbar label.subtitle:backdrop { + color: rgba(239, 241, 245, 0.5); +} + +headerbar .titlebar { + background-color: transparent; + box-shadow: none; +} + +headerbar headerbar + separator { + background-color: rgba(239, 241, 245, 0.12); +} + +headerbar > windowhandle > box { + padding: 0 6px; +} + +headerbar > windowhandle > box, +headerbar > windowhandle > box > box.start, +headerbar > windowhandle > box > box.end { + border-spacing: 6px; +} + +headerbar entry, +headerbar spinbutton, +headerbar splitbutton, +headerbar button, +headerbar menubutton, +headerbar stackswitcher, +headerbar separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar menubutton > button, +headerbar spinbutton > button, +headerbar splitbutton > button, +headerbar splitbutton > menubutton, +headerbar .linked > menubutton, +headerbar entry > menubutton { + margin-top: 0; + margin-bottom: 0; +} + +headerbar button.suggested-action:disabled, +headerbar button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); + opacity: 1; +} + +headerbar button.star { + min-height: 24px; + min-width: 24px; + padding: 5px; +} + +headerbar .linked:not(.vertical) > entry:not(:only-child) { + border-radius: 12px; +} + +headerbar .entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar popover.background button.suggested-action:disabled, +headerbar popover.background button.destructive-action:disabled { + background-color: rgba(239, 241, 245, 0.04); + color: rgba(239, 241, 245, 0.5); +} + +headerbar popover.background entry, +headerbar popover.background spinbutton, +headerbar popover.background button, +headerbar popover.background menubutton, +headerbar popover.background stackswitcher { + margin-top: 0; + margin-bottom: 0; +} + +headerbar separator:not(.sidebar) { + background-color: rgba(239, 241, 245, 0.12); +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +headerbar.selection-mode:backdrop { + color: rgba(30, 30, 46, 0.6); +} + +headerbar.selection-mode .subtitle:link { + color: rgba(30, 30, 46, 0.87); +} + +headerbar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +headerbar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +headerbar.default-decoration { + min-height: 34px; + padding: 0; + margin: 0; + border: none; + outline: none; +} + +headerbar.default-decoration windowcontrols > button { + min-width: 16px; + min-height: 16px; + margin: 0 4px; + padding: 0; + /* @if $window_button == 'mac' { */ + /* min-width: 16px; */ + /* min-height: 16px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } @else { */ + /* min-width: 22px; */ + /* min-height: 22px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } */ +} + +headerbar.default-decoration windowcontrols menubutton button { + min-height: 20px; + min-width: 20px; + margin: 0; + padding: 4px; +} + +.maximized headerbar, .fullscreen headerbar, .tiled headerbar, .tiled-top headerbar, .tiled-right headerbar, .tiled-bottom headerbar, .tiled-left headerbar { + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.maximized headerbar.default-decoration, .fullscreen headerbar.default-decoration, .tiled headerbar.default-decoration, .tiled-top headerbar.default-decoration, .tiled-right headerbar.default-decoration, .tiled-bottom headerbar.default-decoration, .tiled-left headerbar.default-decoration { + box-shadow: none; +} + +.solid-csd headerbar:dir(rtl), .solid-csd headerbar:dir(ltr) { + border-radius: 0; + box-shadow: inset 0 -1px rgba(239, 241, 245, 0.12); +} + +.titlebar:not(headerbar) { + box-shadow: none; +} + +window.devel headerbar { + background: #1e1e2e cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, linear-gradient(to right, transparent 65%, rgba(137, 180, 250, 0.1)), linear-gradient(to top, #242437 3px, #28283d); +} + +window.devel headerbar:backdrop { + background: #1e1e2e cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, image(#1e1e2e); + /* background-color would flash */ +} + +/************ + * Pathbars * + ************/ +.pathbar { + background-color: alpha(currentColor, 0.08); + border-radius: 12px; + padding: 0; +} + +.pathbar button { + margin: 0; +} + +headerbar .pathbar button { + margin: 0; +} + +/************** + * Tree Views * + **************/ +columnview.view, +treeview.view { + border-left-color: #4a4b5a; + border-top-color: #4a4b5a; +} + +columnview.view:hover, columnview.view:selected, +treeview.view:hover, +treeview.view:selected { + border-radius: 0; +} + +columnview.view:focus, +treeview.view:focus { + box-shadow: none; + outline: none; +} + +columnview.view.separator, +treeview.view.separator { + min-height: 5px; + color: rgba(239, 241, 245, 0.12); +} + +columnview.view:drop(active), +treeview.view:drop(active) { + box-shadow: none; +} + +columnview.view:drop(active).after, +treeview.view:drop(active).after { + border-top-style: none; +} + +columnview.view:drop(active).before, +treeview.view:drop(active).before { + border-bottom-style: none; +} + +columnview.view > dndtarget:drop(active), +treeview.view > dndtarget:drop(active) { + border-style: solid none; + border-width: 1px; + border-color: alpha(currentColor, 0.06); +} + +columnview.view > dndtarget:drop(active).after, +treeview.view > dndtarget:drop(active).after { + border-top-style: none; +} + +columnview.view > dndtarget:drop(active).before, +treeview.view > dndtarget:drop(active).before { + border-bottom-style: none; +} + +columnview.view.expander, +treeview.view.expander { + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + color: rgba(239, 241, 245, 0.7); +} + +columnview.view.expander:dir(rtl), +treeview.view.expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +columnview.view.expander:hover, +treeview.view.expander:hover { + color: #eff1f5; +} + +columnview.view.expander:selected, +treeview.view.expander:selected { + color: #eff1f5; +} + +columnview.view.expander:selected:hover, +treeview.view.expander:selected:hover { + color: #eff1f5; +} + +columnview.view.expander:checked, +treeview.view.expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +columnview.view.expander:disabled, +treeview.view.expander:disabled { + color: rgba(239, 241, 245, 0.32); +} + +columnview.view.progressbar, +treeview.view.progressbar { + border-bottom: 6px solid #89b4fa; + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.progressbar:selected:hover, +treeview.view.progressbar:selected:hover { + box-shadow: none; +} + +columnview.view.trough, +treeview.view.trough { + border-bottom: 6px solid rgba(239, 241, 245, 0.12); + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.trough:selected:hover, +treeview.view.trough:selected:hover { + box-shadow: none; +} + +columnview.view > header > button, +treeview.view > header > button { + padding: 2px 6px; + border-style: none solid solid none; + border-width: 0 1px 0 0; + border-color: transparent; + border-radius: 0; + background-clip: border-box; +} + +columnview.view > header > button:not(:focus):not(:hover):not(:active), +treeview.view > header > button:not(:focus):not(:hover):not(:active) { + color: rgba(239, 241, 245, 0.7); +} + +columnview.view > header > button, columnview.view > header > button:disabled, +treeview.view > header > button, +treeview.view > header > button:disabled { + background-color: transparent; +} + +columnview.view > header > button:last-child, +treeview.view > header > button:last-child { + border-right-style: none; +} + +columnview.view button.dnd, +columnview.view header.button.dnd, +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(239, 241, 245, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #313244; + background-clip: border-box; + color: #89b4fa; +} + +columnview.view acceleditor > label, +treeview.view acceleditor > label { + background-color: #89b4fa; +} + +stack.view treeview.view { + min-height: 34px; +} + +/********* + * Menus * + *********/ +menubar { + padding: 0; + background-color: #1e1e2e; + color: #eff1f5; +} + +menubar:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.7); +} + +.csd menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + padding: 4px 8px; + color: rgba(239, 241, 245, 0.7); +} + +menubar > item:selected { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #eff1f5; +} + +menubar > item:disabled { + color: rgba(239, 241, 245, 0.32); +} + +menubar > item label:disabled { + color: inherit; +} + +menubar > item popover.menu popover.menu { + margin-left: 9px; +} + +menubar > item popover.menu.background popover.menu.background > contents { + margin: 0; + border-radius: 12px; +} + +/********************** + * Popover Base Menus * + **********************/ +popover.menu box.inline-buttons { + color: #eff1f5; + padding: 0 6px; +} + +popover.menu box.inline-buttons button.image-button.model { + min-height: 28px; + min-width: 28px; + padding: 0; + border: none; + outline: none; + transition: none; +} + +popover.menu box.inline-buttons button.image-button.model:selected { + background: image(alpha(currentColor, 0.06)); +} + +popover.menu box.circular-buttons { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model:focus { + background-color: alpha(currentColor, 0.06); +} + +popover.menu arrow.left, +popover.menu radio.left, +popover.menu check.left { + margin-left: 0; + margin-right: 0; +} + +popover.menu arrow.right, +popover.menu radio.right, +popover.menu check.right { + margin-left: 0; + margin-right: 0; +} + +popover.menu label.title { + font-weight: bold; + padding: 4px 26px; +} + +/************ + * Popovers * + ************/ +popover.background { + font: initial; +} + +popover.background, popover.background:backdrop { + background-color: transparent; +} + +popover > arrow, +popover > contents { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + background-color: #232634; + border-radius: 12px; + color: #eff1f5; + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +popover > arrow { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +popover > contents > list, +popover > contents > .view, +popover > contents > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover > contents separator { + background-color: rgba(239, 241, 245, 0.12); + margin: 15px 10px; +} + +popover > contents list separator { + margin: 0; +} + +popover > contents list > row { + border-radius: 12px; +} + +popover > contents stack > box { + padding: 0; +} + +popover > contents > box > button { + margin: 0; +} + +popover .view:not(:selected), +popover toolbar { + background-color: #232634; +} + +popover button, +popover entry, +popover combobox { + border-radius: 12px; +} + +popover .linked > button:not(.radio) { + border-radius: 0; +} + +popover .linked > button:not(.radio):first-child { + border-radius: 12px 0 0 12px; +} + +popover .linked > button:not(.radio):last-child { + border-radius: 0 12px 12px 0; +} + +popover .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.menu button, +popover button.model { + min-height: 32px; + padding: 0 8px; +} + +popover modelbutton { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 22px; + min-width: 56px; + padding: 3px 9px; + color: #eff1f5; + font: initial; + border-radius: 12px; +} + +popover modelbutton:hover { + transition: none; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +popover modelbutton:hover accelerator { + color: #89b4fa; +} + +popover modelbutton:hover accelerator:disabled { + color: rgba(239, 241, 245, 0.5); +} + +popover modelbutton:focus:not(:hover) { + transition: none; + box-shadow: none; + outline: none; +} + +popover modelbutton:disabled { + color: rgba(239, 241, 245, 0.5); +} + +popover modelbutton accelerator { + color: rgba(239, 241, 245, 0.5); + margin-left: 30px; +} + +popover modelbutton accelerator:disabled { + color: rgba(239, 241, 245, 0.12); +} + +popover modelbutton arrow.left { + -gtk-icon-source: -gtk-icontheme("go-previous-symbolic"); +} + +popover modelbutton arrow.right { + -gtk-icon-source: -gtk-icontheme("go-next-symbolic"); +} + +.osd popover, popover.touch-selection, popover.magnifier { + background-color: transparent; +} + +magnifier { + background-color: #313244; +} + +/************* + * Notebooks * + *************/ +notebook > header > tabs > tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +notebook > header > tabs > tab:hover:not(:checked):not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +notebook > header > tabs > tab:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; +} + +notebook > header > tabs > tab:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; + background-color: #313244; + color: #eff1f5; + box-shadow: none; +} + +notebook > header > tabs > tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +notebook > header > tabs > tab:checked:disabled { + color: rgba(239, 241, 245, 0.5); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: rgba(239, 241, 245, 0.04); +} + +notebook, notebook.frame { + background-color: #313244; + background-color: rgba(239, 241, 245, 0.04); + border-radius: 15px; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(239, 241, 245, 0.04); + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header > tabs > tab { + margin: 3px; +} + +notebook > header > tabs > tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header > tabs > tab > box:drop(active) { + background-color: rgba(239, 241, 245, 0.12); + color: #eff1f5; +} + +notebook > header > tabs > tab button.flat:last-child { + margin-left: 6px; + margin-right: -3px; +} + +notebook > header > tabs > tab button.flat:first-child { + margin-left: -3px; + margin-right: 6px; +} + +notebook > header > tabs > tab button.close-button { + min-width: 24px; + min-height: 24px; +} + +notebook > header.top > tabs, notebook > header.bottom > tabs { + padding-left: 0; + padding-right: 0; +} + +notebook > header.top > tabs:not(:only-child):first-child, notebook > header.bottom > tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top > tabs:not(:only-child):last-child, notebook > header.bottom > tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top > tabs > tab:not(:last-child), notebook > header.bottom > tabs > tab:not(:last-child) { + margin-right: 0; +} + +notebook > header.top > tabs tab.reorderable-page, notebook > header.bottom > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left > tabs, notebook > header.right > tabs { + padding-top: 0; + padding-bottom: 0; +} + +notebook > header.left > tabs:not(:only-child):first-child, notebook > header.right > tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left > tabs:not(:only-child):last-child, notebook > header.right > tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left > tabs > tab:not(:last-child), notebook > header.right > tabs > tab:not(:last-child) { + margin-bottom: 0; +} + +notebook > header.left > tabs tab.reorderable-page, notebook > header.right > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > menubutton > button.image-button { + padding: 3px; + min-width: 24px; + min-height: 24px; + margin: 0 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +tabbar tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(239, 241, 245, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(239, 241, 245, 0.7); +} + +tabbar tab:hover:not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + box-shadow: none; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; +} + +tabbar tab:disabled { + color: rgba(239, 241, 245, 0.32); + background-color: transparent; + color: rgba(239, 241, 245, 0.32); +} + +tabbar tab:active { + background-color: alpha(currentColor, 0.12); + color: #eff1f5; + box-shadow: none; + color: #eff1f5; +} + +tabbar tab:selected:not(:active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(239, 241, 245, 0.04); + color: #89b4fa; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbar tab:selected:not(:active):disabled { + color: rgba(239, 241, 245, 0.5); +} + +tabbar > revealer > box { + box-shadow: none; +} + +tabbar .box { + background-color: #1e1e2e; + background-image: none; + padding: 0; + margin: 0; + border-radius: 0; + min-height: 34px; + border: none; + /* box-shadow: inset 0 -1px $border; */ +} + +tabbar .box:backdrop { + background-color: #1e1e2e; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabbar .box:backdrop > scrolledwindow, +tabbar .box:backdrop > .start-action, +tabbar .box:backdrop > .end-action { + filter: none; + transition: none; +} + +tabbar tabbox { + padding: 0; + margin: 0; + min-height: 34px; +} + +tabbar tabbox > background { + background: none; +} + +tabbar tabbox > separator { + margin: 9px 0; + transition: opacity 150ms ease-in-out; +} + +tabbar tabbox > separator.hidden { + opacity: 0; +} + +tabbar tabbox > tabboxchild { + padding: 0; + margin: 0; +} + +tabbar tab { + padding: 6px; + margin: 6px 2px; +} + +tabbar tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#89b4fa, 0.4) 10%, alpha(#89b4fa, 0) 30%); +} + +tabbar tab.needs-attention:hover { + background-image: image(alpha(currentColor, 0.03)), radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#89b4fa, 0.4) 10%, alpha(#89b4fa, 0) 30%); +} + +tabbar tabbox.single-tab tab, tabbar tabbox.single-tab tab:hover, tabbar tabbox.single-tab tab:active { + background: none; +} + +tabbar undershoot { + transition: background 150ms ease-in-out; +} + +tabbar undershoot.left { + background: linear-gradient(to right, #313244, rgba(0, 0, 0, 0) 20px); +} + +tabbar undershoot.right { + background: linear-gradient(to left, #313244, rgba(0, 0, 0, 0) 20px); +} + +tabbar .needs-attention-left undershoot.left { + background: linear-gradient(to right, alpha(#89b4fa, 0.5), alpha(#89b4fa, 0.3) 1px, alpha(#89b4fa, 0) 20px); +} + +tabbar .needs-attention-right undershoot.right { + background: linear-gradient(to left, alpha(#89b4fa, 0.5), alpha(#89b4fa, 0.3) 1px, alpha(#89b4fa, 0) 20px); +} + +tabbar .start-action, +tabbar .end-action { + padding: 6px 5px; +} + +tabbar .start-action:dir(ltr), +tabbar .end-action:dir(rtl) { + padding-right: 0; +} + +tabbar .start-action:dir(rtl), +tabbar .end-action:dir(ltr) { + padding-left: 0; +} + +tabbar.inline .box { + background-color: transparent; + color: inherit; + box-shadow: none; + padding-bottom: 0; +} + +tabbar.inline .box:backdrop { + background-color: transparent; + transition: none; +} + +tabbar.inline .box:backdrop > scrolledwindow, +tabbar.inline .box:backdrop > .start-action, +tabbar.inline .box:backdrop > .end-action { + filter: none; + transition: none; +} + +dnd tab { + min-height: 24px; + background-color: #1e1e2e; + color: #eff1f5; + box-shadow: 0 1px 5px 1px rgba(0, 0, 0, 0.09), 0 2px 14px 3px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.05); + outline: 1px solid rgba(30, 30, 46, 0.75); + outline-offset: -1px; + margin: 24px; +} + +dnd tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#89b4fa, 0.4) 10%, alpha(#89b4fa, 0) 30%); +} + +tabbar tab, +dnd tab { + padding: 6px; +} + +tabbar tab button.image-button, +dnd tab button.image-button { + padding: 0; + margin: 0; + min-width: 24px; + min-height: 24px; + border-radius: 9999px; + color: rgba(239, 241, 245, 0.7); +} + +tabbar tab button.image-button:hover, tabbar tab button.image-button:active, +dnd tab button.image-button:hover, +dnd tab button.image-button:active { + color: #eff1f5; +} + +tabbar tab button.image-button:disabled, +dnd tab button.image-button:disabled { + color: rgba(239, 241, 245, 0.32); +} + +tabbar tab indicator, +dnd tab indicator { + min-height: 2px; + border-radius: 2px; + background: alpha(#89b4fa, 0.5); + transform: translateY(4px); +} + +tabthumbnail { + border-radius: 12px; + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabthumbnail > box { + margin: 6px; +} + +tabthumbnail:drop(active) { + box-shadow: inset 0 0 0 2px alpha(#fab387, 0.4); + background-color: alpha(#fab387, 0.1); +} + +tabthumbnail .needs-attention:dir(ltr) { + transform: translate(8px, -8px); +} + +tabthumbnail .needs-attention:dir(rtl) { + transform: translate(-8px, -8px); +} + +tabthumbnail .needs-attention > widget { + background: #89b4fa; + min-width: 12px; + min-height: 12px; + border-radius: 9px; + margin: 3px; + box-shadow: 0 1px 2px alpha(#89b4fa, 0.4); +} + +tabthumbnail .card { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +tabthumbnail .card picture { + outline: 1px solid rgba(239, 241, 245, 0.12); + outline-offset: -1px; + border-radius: 12px; +} + +tabthumbnail.pinned .card { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +tabthumbnail .icon-title-box { + border-spacing: 6px; +} + +tabthumbnail .tab-unpin-icon { + margin: 6px; + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular { + margin: 6px; + background-color: rgba(239, 241, 245, 0.04); + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular:hover { + background-color: alpha(currentColor, 0.08); +} + +tabthumbnail button.circular:active { + background-color: alpha(currentColor, 0.12); +} + +taboverview > .overview .new-tab-button { + margin: 18px; +} + +tabview:drop(active), +tabbox:drop(active), +tabgrid:drop(active) { + box-shadow: none; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); + outline: none; +} + +scrollbar, +scrollbar button { + border: none; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar > range > trough { + background: none; + padding: 0; + margin: 0; + border: none; + outline: none; + transition: none; +} + +scrollbar > range > trough > slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 9999px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(239, 241, 245, 0.5); +} + +scrollbar > range > trough > slider:hover { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar > range > trough > slider:active { + background-color: rgba(239, 241, 245, 0.7); +} + +scrollbar > range > trough > slider:disabled { + background-color: rgba(239, 241, 245, 0.32); +} + +scrollbar > range.fine-tune > trough > slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.overlay-indicator { + background: none; + color: inherit; + box-shadow: none; + padding: 0; +} + +scrollbar.overlay-indicator > range > trough { + outline: none; + background-color: rgba(239, 241, 245, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator > range > trough > slider { + outline: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; + border-color: transparent; + background-color: transparent; + box-shadow: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough { + background-color: transparent; + border: none; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough > slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical > range > trough > slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.vertical > range > trough > slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + padding: 0; + border: none; + border-radius: 9999px; + background-color: rgba(239, 241, 245, 0.5); + background-clip: border-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #89b4fa; +} + +switch:disabled { + opacity: 0.5; +} + +switch > slider { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 0 0 0 transparent, 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #eff1f5; + border: none; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12), 0 3px 3px -2px transparent, 0 2px 3px -1px transparent, 0 1px 4px 0 transparent; +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; + border-spacing: 3px; +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + border: none; + color: transparent; + background-color: rgba(239, 241, 245, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.04); + background-color: rgba(239, 241, 245, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(239, 241, 245, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(30, 30, 46, 0.6); + background-color: #89b4fa; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.15); + background-color: #bad3fc; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(137, 180, 250, 0.2); + background-color: #89b4fa; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(30, 30, 46, 0.6); + background-color: rgba(137, 180, 250, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu radio { + transition: none; + margin: 0; + padding: 0; +} + +popover.menu check:dir(ltr), popover.menu radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +popover.menu check:dir(rtl), popover.menu radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu check:hover, popover.menu check:disabled, popover.menu check:checked:hover, popover.menu check:indeterminate:hover, popover.menu radio, popover.menu radio:hover, popover.menu radio:disabled, popover.menu radio:checked:hover, popover.menu radio:indeterminate:hover { + box-shadow: none; +} + + +check { + -gtk-icon-size: 20px; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/checkbox-mixed-symbolic@2.svg"))); +} + + +radio { + -gtk-icon-size: 20px; +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/radio-mixed-symbolic@2.svg"))); +} + + +popover.menu check { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-checked-symbolic@2.svg"))); +} + + +popover.menu check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-mixed-symbolic@2.svg"))); +} + + +popover.menu radio { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/small-radio-checked-symbolic@2.svg"))); +} + + +popover.menu radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view radio, +treeview.view check, +columnview.view radio, +columnview.view check { + padding: 0; + margin: 0; + transition: none; +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover, +columnview.view radio, +columnview.view radio:hover, +columnview.view radio:disabled, +columnview.view radio:checked:hover, +columnview.view radio:indeterminate:hover, +columnview.view check, +columnview.view check:hover, +columnview.view check:disabled, +columnview.view check:checked:hover, +columnview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view:hover check, +treeview.view:hover radio, treeview.view:selected check, +treeview.view:selected radio, treeview.view:focus check, +treeview.view:focus radio, +columnview.view:hover check, +columnview.view:hover radio, +columnview.view:selected check, +columnview.view:selected radio, +columnview.view:focus check, +columnview.view:focus radio { + box-shadow: none; +} + +treeview.view:hover check:checked, +treeview.view:hover radio:checked, treeview.view:selected check:checked, +treeview.view:selected radio:checked, treeview.view:focus check:checked, +treeview.view:focus radio:checked, +columnview.view:hover check:checked, +columnview.view:hover radio:checked, +columnview.view:selected check:checked, +columnview.view:selected radio:checked, +columnview.view:focus check:checked, +columnview.view:focus radio:checked { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +checkbutton.selection-mode { + border-radius: 9999px; +} + +checkbutton.selection-mode check, +checkbutton.selection-mode radio { + padding: 6px; + border-radius: 9999px; +} + +checkbutton.selection-mode check:checked, checkbutton.selection-mode check:indeterminate, +checkbutton.selection-mode radio:checked, +checkbutton.selection-mode radio:indeterminate { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +checkbutton.selection-mode label:dir(ltr) { + margin-right: 6px; +} + +checkbutton.selection-mode label:dir(rtl) { + margin-left: 6px; +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale > trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(239, 241, 245, 0.3); +} + +scale > trough:disabled { + background-color: rgba(239, 241, 245, 0.12); +} + +scale > trough > highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#89b4fa); +} + +scale > trough > highlight:disabled { + background-color: #1e1e2e; + background-image: image(rgba(239, 241, 245, 0.32)); +} + +scale > trough > fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.3); +} + +scale > trough > fill:disabled { + background-color: transparent; +} + +scale > trough > slider { + min-height: 18px; + min-width: 18px; + margin: -8px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #89b4fa; + background-color: #313244; + box-shadow: inset 0 0 0 2px #89b4fa; +} + +scale > trough > slider:hover { + box-shadow: inset 0 0 0 2px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale > trough > slider:active { + box-shadow: inset 0 0 0 4px #89b4fa, 0 0 0 8px rgba(239, 241, 245, 0.12); +} + +scale > trough > slider:disabled { + box-shadow: inset 0 0 0 2px rgba(239, 241, 245, 0.32); +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune > trough > slider { + margin: -7px; +} + +scale > marks, +scale > value { + color: rgba(239, 241, 245, 0.7); +} + +scale indicator { + background-color: rgba(239, 241, 245, 0.3); + color: transparent; +} + +scale.marks-before:not(.marks-after) > trough > slider, scale.marks-after:not(.marks-before) > trough > slider { + transform: rotate(45deg); + border-bottom-right-radius: 0; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal > trough > slider:dir(ltr), scale.color.horizontal > trough > slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) > trough > slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(239, 241, 245, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #89b4fa; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; + box-shadow: none; + margin: 0; + padding: 0; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #89b4fa; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #df8e1d; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #89b4fa; +} + +levelbar block.full { + background-color: #40a02b; +} + +levelbar block.empty { + background-color: rgba(239, 241, 245, 0.12); +} + +/**************** + * Print dialog * +*****************/ +window.dialog.print drawing { + color: #eff1f5; + background: none; + border: none; + padding: 0; +} + +window.dialog.print drawing paper { + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: #313244; + color: #eff1f5; +} + +window.dialog.print .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame, +.frame { + border: 1px solid rgba(239, 241, 245, 0.12); +} + +frame > list, +.frame > list { + border: none; +} + +frame.view, +.frame.view { + border-radius: 12px; +} + +frame.flat, +.frame.flat { + border-style: none; +} + +frame { + border-radius: 12px; +} + +frame > label { + margin: 4px; +} + +frame.flat > border, statusbar frame > border { + border: none; +} + +actionbar { + box-shadow: none; +} + +actionbar > revealer > box { + padding: 6px; + border-spacing: 6px; + box-shadow: none; + /* background-color: $base; */ + background-color: rgba(239, 241, 245, 0.04); + background-clip: border-box; + border: none; + color: #eff1f5; +} + +actionbar > revealer > box button, +actionbar > revealer > box entry, +actionbar > revealer > box menubutton, +actionbar > revealer > box menubutton > button, +actionbar > revealer > box splitbutton, +actionbar > revealer > box splitbutton > button, +actionbar > revealer > box spinbutton { + margin: 0; +} + +statusbar { + padding: 6px 18px; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +scrolledwindow > overshoot.top { + background-image: radial-gradient(farthest-side at top, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at top, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: top; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.bottom { + background-image: radial-gradient(farthest-side at bottom, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at bottom, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.left { + background-image: radial-gradient(farthest-side at left, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at left, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: left; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.right { + background-image: radial-gradient(farthest-side at right, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at right, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: right; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow.undershoot-top > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 0px 0px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +scrolledwindow > undershoot { + background-image: none; + box-shadow: none; + border: none; +} + +separator { + min-width: 1px; + min-height: 1px; + background-color: transparent; +} + +stacksidebar + separator.vertical, +stacksidebar separator.horizontal, button.font separator, button.file separator, separator.spacer, separator.sidebar { + min-width: 0; + min-height: 0; + background-color: transparent; + background-image: none; +} + +/********* + * Lists * + *********/ +list.content, +list.boxed-list { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); +} + +listview, +list { + border-color: rgba(239, 241, 245, 0.12); + background-color: rgba(239, 241, 245, 0.04); + background-clip: padding-box; +} + +listview > row, +list > row { + padding: 6px; + background-clip: padding-box; +} + +listview > row.expander, +list > row.expander { + padding: 0px; +} + +listview > row.expander .row-header, +list > row.expander .row-header { + padding: 2px; +} + +listview.horizontal row.separator:not(:last-child), listview.separators.horizontal > row:not(.separator):not(:last-child), +list.horizontal row.separator:not(:last-child), +list.separators.horizontal > row:not(.separator):not(:last-child) { + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +listview:not(.horizontal) row.separator:not(:last-child), listview.separators:not(.horizontal) > row:not(.separator):not(:last-child), +list:not(.horizontal) row.separator:not(:last-child), +list.separators:not(.horizontal) > row:not(.separator):not(:last-child) { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +list.frame { + border-radius: 12px; +} + +listview.view { + color: #eff1f5; + background-color: transparent; +} + +popover.menu listview.view { + padding: 0; + border-radius: 12px; +} + +popover.menu listview.view > row { + margin-left: 0; + margin-right: 0; + border-radius: 12px; +} + +row { + color: rgba(239, 241, 245, 0.7); + background-clip: padding-box; +} + +.nautilus-window .nautilus-grid-view child.activatable, +.nautilus-window .nautilus-list-view child.activatable, columnview.view > header > button, +treeview.view > header > button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), font-weight 0; + outline: none; + box-shadow: none; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.nautilus-window .nautilus-grid-view child.activatable:focus, +.nautilus-window .nautilus-list-view child.activatable:focus, columnview.view > header > button:focus, +treeview.view > header > button:focus, row.activatable:focus { + color: #eff1f5; + background-color: transparent; + box-shadow: none; + outline: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:hover, +.nautilus-window .nautilus-list-view child.activatable:hover, columnview.view > header > button:hover, +treeview.view > header > button:hover, .nautilus-window .nautilus-grid-view child.has-open-popup.activatable, +.nautilus-window .nautilus-list-view child.has-open-popup.activatable, columnview.view > header > button.has-open-popup, +treeview.view > header > button.has-open-popup, row.activatable:hover, row.activatable.has-open-popup { + color: #eff1f5; + background-color: alpha(currentColor, 0.05); + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:active, +.nautilus-window .nautilus-list-view child.activatable:active, columnview.view > header > button:active, +treeview.view > header > button:active, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, font-weight 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; + background-color: alpha(currentColor, 0.05); + color: #eff1f5; + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:selected, +.nautilus-window .nautilus-list-view child.activatable:selected, columnview.view > header > button:selected, +treeview.view > header > button:selected, row.activatable:selected { + background-color: alpha(currentColor, 0.06); +} + +.nautilus-window .nautilus-grid-view child.activatable:selected:hover, +.nautilus-window .nautilus-list-view child.activatable:selected:hover, columnview.view > header > button:selected:hover, +treeview.view > header > button:selected:hover, row.activatable:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +button row.activatable:focus, button row.activatable:hover, button row.activatable:active { + box-shadow: none; + background: none; +} + +button:checked row.activatable { + color: rgba(30, 30, 46, 0.87); +} + +row:selected { + background-color: alpha(currentColor, 0.06); + color: #eff1f5; + box-shadow: none; +} + +row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus, row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus:hover, row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.rich-list { + /* rich lists usually containing other widgets than just labels/text */ +} + +.rich-list > row { + padding: 9px 12px; + min-height: 32px; + /* should be tall even when only containing a label */ +} + +.rich-list > row:last-child { + border-bottom: none; +} + +.rich-list > row > box { + border-spacing: 12px; +} + +row label.subtitle { + font-size: smaller; +} + +row > box.header { + margin-left: 12px; + margin-right: 12px; + border-spacing: 6px; + min-height: 50px; +} + +row > box.header > .icon:disabled { + filter: opacity(0.45); +} + +row > box.header > box.title { + margin-top: 6px; + margin-bottom: 6px; + border-spacing: 3px; + padding: 0; +} + +row > box.header > box.title, +row > box.header > box.title > .title, +row > box.header > box.title > .subtitle { + padding: 0; + font-weight: inherit; +} + +row > box.header > .prefixes, +row > box.header > .suffixes { + border-spacing: 6px; +} + +row > box.header > .icon:dir(ltr), +row > box.header > .prefixes:dir(ltr) { + margin-right: 6px; +} + +row > box.header > .icon:dir(rtl), +row > box.header > .prefixes:dir(rtl) { + margin-left: 6px; +} + +row.property > box.header > box.title > .subtitle { + font-size: inherit; + opacity: 1; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry:disabled text { + opacity: 0.45; +} + +row.entry:disabled .dim-label, row.entry:disabled row.expander image.expander-row-arrow, row.expander row.entry:disabled image.expander-row-arrow, row.entry:disabled row.property > box.header > box.title > .title, +row.entry:disabled .subtitle { + opacity: 1; +} + +row.entry .edit-icon, +row.entry .indicator { + min-width: 24px; + min-height: 24px; + padding: 5px; +} + +row.entry .edit-icon:disabled { + opacity: 0.5; +} + +row.entry .indicator { + opacity: 0.65; +} + +row.entry.monospace { + font-family: inherit; +} + +row.entry.monospace text { + font-family: monospace; +} + +row.spin:not(:selected).activatable.focused:hover, row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.spin spinbutton { + background: none; + border-spacing: 6px; + box-shadow: none; +} + +row.spin spinbutton, row.spin spinbutton:focus { + outline: none; +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child { + min-width: 30px; + min-height: 30px; + margin: 10px 2px; + border: none; +} + +row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child:disabled { + filter: none; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active, +row.spin:not(:selected).activatable.focused:hover, +row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry.error text > selection:focus-within, +row.spin.error text > selection:focus-within { + background-color: alpha(#d20f39, 0.2); +} + +row.entry.error text > cursor-handle > contents, +row.spin.error text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.error .dim-label, row.entry.error row.expander image.expander-row-arrow, row.expander row.entry.error image.expander-row-arrow, row.entry.error row.property > box.header > box.title > .title, +row.entry.error .subtitle, +row.spin.error .dim-label, +row.spin.error row.expander image.expander-row-arrow, +row.expander row.spin.error image.expander-row-arrow, +row.spin.error row.property > box.header > box.title > .title, +row.spin.error .subtitle { + opacity: 1; +} + +row.entry.error .suggested-action, +row.spin.error .suggested-action { + background-color: #d20f39; + color: #eff1f5; +} + +row.entry.warning text > selection:focus-within, +row.spin.warning text > selection:focus-within { + background-color: alpha(#df8e1d, 0.2); +} + +row.entry.warning text > cursor-handle > contents, +row.spin.warning text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.warning .dim-label, row.entry.warning row.expander image.expander-row-arrow, row.expander row.entry.warning image.expander-row-arrow, row.entry.warning row.property > box.header > box.title > .title, +row.entry.warning .subtitle, +row.spin.warning .dim-label, +row.spin.warning row.expander image.expander-row-arrow, +row.expander row.spin.warning image.expander-row-arrow, +row.spin.warning row.property > box.header > box.title > .title, +row.spin.warning .subtitle { + opacity: 1; +} + +row.entry.warning .suggested-action, +row.spin.warning .suggested-action { + background-color: #df8e1d; + color: #eff1f5; +} + +row.entry.success text > selection:focus-within, +row.spin.success text > selection:focus-within { + background-color: alpha(#40a02b, 0.2); +} + +row.entry.success text > cursor-handle > contents, +row.spin.success text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.success .dim-label, row.entry.success row.expander image.expander-row-arrow, row.expander row.entry.success image.expander-row-arrow, row.entry.success row.property > box.header > box.title > .title, +row.entry.success .subtitle, +row.spin.success .dim-label, +row.spin.success row.expander image.expander-row-arrow, +row.expander row.spin.success image.expander-row-arrow, +row.spin.success row.property > box.header > box.title > .title, +row.spin.success .subtitle { + opacity: 1; +} + +row.entry.success .suggested-action, +row.spin.success .suggested-action { + background-color: #40a02b; + color: #eff1f5; +} + +row.combo image.dropdown-arrow:disabled { + filter: opacity(0.45); +} + +row.combo listview.inline { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +row.combo listview.inline, row.combo listview.inline:disabled { + background: none; + color: inherit; +} + +row.combo popover > contents { + min-width: 120px; +} + +row.combo popover > contents .combo-searchbar { + margin: 6px; +} + +row.combo popover > contents .combo-searchbar + scrolledwindow > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(239, 241, 245, 0.12), 0.75), transparent 4px); +} + +list.content > row, list.content > row.expander row.header, +list.boxed-list > row, +list.boxed-list > row.expander row.header, row.expander list.nested > row { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +list.content > row:not(:selected).activatable:hover, list.content > row.expander row.header:not(:selected).activatable:hover, +list.boxed-list > row:not(:selected).activatable:hover, +list.boxed-list > row.expander row.header:not(:selected).activatable:hover, row.expander list.nested > row:not(:selected).activatable:hover { + background-color: alpha(currentColor, 0.08); +} + +list.content > row:not(:selected).activatable:active, list.content > row.expander row.header:not(:selected).activatable:active, +list.boxed-list > row:not(:selected).activatable:active, +list.boxed-list > row.expander row.header:not(:selected).activatable:active, row.expander list.nested > row:not(:selected).activatable:active { + background-color: alpha(currentColor, 0.12); +} + +list.content > row:not(:selected).activatable.has-open-popup, list.content > row.expander row.header:not(:selected).activatable.has-open-popup, +list.boxed-list > row:not(:selected).activatable.has-open-popup, +list.boxed-list > row.expander row.header:not(:selected).activatable.has-open-popup, row.expander list.nested > row:not(:selected).activatable.has-open-popup { + background-color: alpha(currentColor, 0.03); +} + +row.expander { + background: none; + padding: 0px; +} + +row.expander > box > list { + background: none; + color: inherit; +} + +row.expander list.nested { + color: inherit; +} + +row.expander image.expander-row-arrow { + transition: -gtk-icon-transform 200ms cubic-bezier(0, 0, 0.2, 1); +} + +row.expander image.expander-row-arrow:dir(ltr) { + margin-left: 6px; +} + +row.expander image.expander-row-arrow:dir(rtl) { + margin-right: 6px; +} + +row.expander image.expander-row-arrow:dir(ltr) { + -gtk-icon-transform: rotate(0.5turn); +} + +row.expander image.expander-row-arrow:dir(rtl) { + -gtk-icon-transform: rotate(-0.5turn); +} + +row.expander image.expander-row-arrow:disabled { + filter: opacity(0.45); +} + +row.expander:checked image.expander-row-arrow { + -gtk-icon-transform: rotate(0turn); + opacity: 1; +} + +row.expander:checked image.expander-row-arrow:not(:disabled) { + color: #89b4fa; +} + +.osd row.expander:checked image.expander-row-arrow:not(:disabled) { + color: inherit; +} + +list.content > row.expander, +list.boxed-list > row.expander { + border: none; +} + +list.content > row:first-child, list.content > row:first-child.expander row.header, +list.boxed-list > row:first-child, +list.boxed-list > row:first-child.expander row.header { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +list.content > row:last-child, list.content > row:last-child.expander:not(:checked), list.content > row:last-child.expander:not(:checked) row.header, list.content > row:last-child.expander:checked list.nested, list.content > row:last-child.expander:checked list.nested > row:last-child, +list.boxed-list > row:last-child, +list.boxed-list > row:last-child.expander:not(:checked), +list.boxed-list > row:last-child.expander:not(:checked) row.header, +list.boxed-list > row:last-child.expander:checked list.nested, +list.boxed-list > row:last-child.expander:checked list.nested > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; + border-bottom-width: 0; +} + +columnview > listview > row { + padding: 0; +} + +columnview > listview > row > cell { + padding: 8px 6px; +} + +columnview > listview > row > cell:not(:first-child) { + border-left: 1px solid transparent; +} + +columnview.column-separators > listview > row > cell { + border-left-color: rgba(239, 241, 245, 0.12); +} + +columnview.data-table > listview > row > cell { + padding-top: 2px; + padding-bottom: 2px; +} + +treeexpander { + border-spacing: 6px; +} + +columnview row:not(:selected) cell editablelabel:not(.editing):focus-within { + outline: 2px solid alpha(currentColor, 0.06); +} + +columnview row:not(:selected) cell editablelabel.editing:focus-within { + outline: 2px solid #89b4fa; +} + +columnview row:not(:selected) cell editablelabel.editing text selection { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 6px; + border-spacing: 0; + padding: 0; + border: none; + background-image: none; +} + +.app-notification button.text-button:not(:disabled) { + color: #89b4fa; +} + +.app-notification > box > label { + margin-left: 9px; +} + +.app-notification.frame, +.app-notification border { + border: none; +} + +/************* + * Expanders * + *************/ +expander { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + color: rgba(239, 241, 245, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +expander:hover, expander:active { + color: #eff1f5; +} + +expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +expander:disabled { + color: rgba(239, 241, 245, 0.32); +} + +expander-widget > box > title { + border-radius: 12px; +} + +expander-widget > box > title:hover > expander { + color: rgba(239, 241, 245, 0.7); +} + +.navigation-sidebar:not(decoration):not(window):drop(active):focus, .navigation-sidebar:not(decoration):not(window):drop(active), +placessidebar:not(decoration):not(window):drop(active):focus, +placessidebar:not(decoration):not(window):drop(active), +stackswitcher:not(decoration):not(window):drop(active):focus, +stackswitcher:not(decoration):not(window):drop(active), +expander-widget:not(decoration):not(window):drop(active):focus, +expander-widget:not(decoration):not(window):drop(active) { + box-shadow: none; +} + +/************ + * Calendar * + ************/ +calendar { + padding: 0; + border: 1px solid rgba(239, 241, 245, 0.12); + border-radius: 12px; + color: #eff1f5; +} + +calendar:disabled { + color: rgba(239, 241, 245, 0.5); +} + +calendar:selected { + border-radius: 12px; +} + +calendar > header { + padding: 3px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +calendar > header > button { + min-height: 24px; +} + +calendar > grid { + margin: 3px; +} + +calendar > grid > label { + border-radius: 12px; + margin: 0; +} + +calendar > grid > label.today:selected { + box-shadow: none; +} + +calendar > grid > label:focus { + outline-style: none; +} + +calendar > grid > label.day-number { + padding: 6px; +} + +calendar > grid > label.day-number.other-month { + color: alpha(currentColor, 0.3); +} + +/*********** + * Dialogs * + ***********/ +window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button { + border-radius: 9px; + min-height: 28px; + padding: 6px 12px; + margin: 0; + border: none; +} + +window.dialog.message.background { + background-color: #1e1e2e; +} + +window.dialog.message box.dialog-vbox.vertical { + margin-top: 6px; +} + +window.dialog.message box.dialog-vbox.vertical > box > box > box > label.title { + font-weight: 800; + font-size: 15pt; +} + +window.dialog.message .titlebar { + min-height: 24px; + border-style: none; + /* box-shadow: inset 0 1px highlight($surface); */ + background-color: #1e1e2e; + color: #eff1f5; +} + +window.dialog.message .titlebar:backdrop { + background-color: #292c3c; + color: rgba(239, 241, 245, 0.7); +} + +window.dialog.message .dialog-action-area { + padding: 18px; + border-spacing: 18px; +} + +window.dialog.message .dialog-action-area > button { + background-color: rgba(239, 241, 245, 0.08); + border: 0 solid transparent; + outline: 0 solid transparent; +} + +window.dialog.message .dialog-action-area > button:not(:last-child):hover { + background-color: rgba(239, 241, 245, 0.1); +} + +window.dialog.message .dialog-action-area > button.suggested-action:not(:disabled) { + background-color: #0a52e0; + color: #eff1f5; +} + +window.dialog.message .dialog-action-area > button.destructive-action:not(:disabled) { + background-color: #a20c2c; + color: #eff1f5; +} + +window.aboutdialog.background.csd scrolledwindow.frame, +window.aboutdialog.background.csd scrolledwindow.frame > viewport.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view > text { + border-radius: 12px; +} + +/******************** + * AdwMessageDialog * + ********************/ +window.messagedialog { + background-color: #292c3c; + color: #eff1f5; + padding: 6px; +} + +window.messagedialog .message-area { + padding: 24px 30px; + border-spacing: 10px; +} + +window.messagedialog .response-area { + border-spacing: 6px; +} + +window.messagedialog .response-area button.suggested { + background-color: #0a52e0; + color: #eff1f5; + /* color: $primary; */ +} + +window.messagedialog .response-area button.destructive { + background-color: #a20c2c; + color: #eff1f5; + /* color: $destructive; */ +} + +window.messagedialog .response-area separator { + background: none; + margin: 3px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; + background-color: #313244; +} + +.sidebar listview.view, +.sidebar list { + background-color: transparent; + color: inherit; +} + +stacksidebar.sidebar:dir(ltr), stacksidebar.sidebar.left, stacksidebar.sidebar.left:dir(rtl) { + box-shadow: inset -1px 0 rgba(239, 241, 245, 0.12); +} + +stacksidebar.sidebar:dir(rtl), stacksidebar.sidebar.right, stacksidebar.sidebar.right:dir(ltr) { + box-shadow: inset 1px 0 rgba(239, 241, 245, 0.12); +} + +.sidebar-pane stacksidebar.sidebar, leaflet.unfolded > box > stacksidebar.sidebar { + box-shadow: none; +} + +stacksidebar list { + padding: 6px; + background-color: #313244; +} + +stacksidebar row { + min-height: 24px; + padding: 6px; + border-radius: 12px; +} + +stacksidebar row:selected { + font-weight: 500; +} + +stacksidebar row + row { + margin-top: 4px; +} + +stacksidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +separator.sidebar { + background-color: rgba(239, 241, 245, 0.12); + border-right: none; +} + +separator.sidebar.selection-mode, .selection-mode separator.sidebar { + background-color: rgba(255, 255, 255, 0.12); +} + +/********************** + * Navigation Sidebar * + **********************/ +.navigation-sidebar { + padding: 2px 4px; + border-right: none; +} + +.navigation-sidebar, .navigation-sidebar.view, .navigation-sidebar.background { + background-color: transparent; + color: inherit; +} + +.navigation-sidebar > separator { + background-color: rgba(239, 241, 245, 0.12); + margin: 10px 15px; +} + +.navigation-sidebar row.activatable label.dim-label { + color: rgba(239, 241, 245, 0.32); +} + +.navigation-sidebar > row { + min-height: 24px; + /* padding: 0 $space-size 0 $space-size; */ + padding: 0 6px; + margin: 0; + border-radius: 9px; +} + +.navigation-sidebar > row:hover, .navigation-sidebar > row:focus-visible:focus-within { + background-color: alpha(currentColor, 0.08); + color: #89b4fa; +} + +.navigation-sidebar > row:active { + background-color: alpha(currentColor, 0.12); +} + +.navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + box-shadow: none; +} + +.navigation-sidebar > row:selected label, +.navigation-sidebar > row:selected image { + color: #89b4fa; + font-weight: 700; +} + +.navigation-sidebar > row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +.navigation-sidebar > row:disabled { + color: rgba(239, 241, 245, 0.5); +} + +.navigation-sidebar > row:not(:first-child) { + margin-top: 3px; +} + +/**************** + * File chooser * + ****************/ +filechooser paned > separator { + background: rgba(239, 241, 245, 0.12); +} + +filechooser paned > box #pathbarbox.view, +filechooser paned > box stack.view, +filechooser paned > box columnview.view, +filechooser paned > box gridview.view { + background-color: transparent; + color: #eff1f5; +} + +filechooser .dialog-action-box { + border: none; +} + +filechooser #pathbarbox { + border: none; + background-color: transparent; +} + +filechooser stack.view frame > border { + border: none; +} + +filechooserbutton > button > box { + border-spacing: 6px; +} + +filechooserbutton:drop(active) { + box-shadow: none; + border-color: transparent; +} + +filechooser child.activatable filelistcell.dim-label { + color: rgba(239, 241, 245, 0.7); +} + +placessidebar { + background-color: transparent; +} + +placessidebar > viewport.frame { + border-style: none; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon { + color: inherit; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label { + color: inherit; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button { + /* @extend %button-on-indicator; */ +} + +placessidebar list.navigation-sidebar > row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row { + color: #89b4fa; +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row image.sidebar-icon { + color: #89b4fa; +} + +placessidebar list.navigation-sidebar > row:drop(active) { + background-color: alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + border-spacing: 6px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(#4a4b5a); + background-size: 1px 1px; + background-clip: content-box; + box-shadow: none; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #1e1e2e; + background-image: image(#4a4b5a), image(#4a4b5a); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************ + * GtkVideo * + ************/ +video { + background: black; + border-radius: 12px; +} + +video image.osd { + min-width: 64px; + min-height: 64px; + border-radius: 9999px; + border: none; +} + +/************** + * GtkInfoBar * + **************/ +infobar > revealer > box { + padding: 6px; + border-spacing: 12px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + box-shadow: none; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #313244; + color: #eff1f5; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #89b4fa; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action > revealer > box *:link, infobar.action:backdrop > revealer > box *:link, infobar.question > revealer > box *:link, infobar.question:backdrop > revealer > box *:link { + color: rgba(30, 30, 46, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #71a4f9; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #df8e1d; + color: #eff1f5; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.warning > revealer > box *:link, infobar.warning:backdrop > revealer > box *:link { + color: #eff1f5; +} + +infobar.warning:hover > revealer > box { + background-color: #c8801a; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #d20f39; + color: #eff1f5; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #eff1f5; +} + +infobar.error > revealer > box *:link, infobar.error:backdrop > revealer > box *:link { + color: #eff1f5; +} + +infobar.error:hover > revealer > box { + background-color: #ba0d33; +} + +/************ + * Tooltips * + ************/ +tooltip { + padding: 6px 12px; + box-shadow: none; + border: none; +} + +tooltip.background { + background-color: rgba(24, 24, 37, 0.9); + color: #eff1f5; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05); + border-radius: 12px; + margin: 2px 6px 8px 6px; +} + +tooltip > box { + border-spacing: 6px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #eff1f5; +} + +colorswatch.light { + color: rgba(30, 30, 46, 0.87); +} + +colorchooser colorswatch:hover { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 0 0 2px #89b4fa; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; + color: #eff1f5; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(239, 241, 245, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(239, 241, 245, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(239, 241, 245, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(239, 241, 245, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #1e1e2e; +} + +/********************** + * Window Decorations * + **********************/ +window { + border: none; +} + +window.csd { + border-radius: 12px; + margin: 0; + transition: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +window.csd:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #89b4fa, 0 0 36px transparent; +} + +window.csd.maximized, window.csd.fullscreen, window.csd.tiled, window.csd.tiled-top, window.csd.tiled-right, window.csd.tiled-bottom, window.csd.tiled-left { + border-radius: 0; + transition: none; +} + +window.csd.maximized, window.csd.fullscreen { + box-shadow: none; + outline: none; +} + +window.solid-csd { + margin: 0; + padding: 2px; + border-radius: 0; + background-color: #1e1e2e; + border: 1px solid #4a4b5a; +} + +window.solid-csd:backdrop { + background-color: #1e1e2e; +} + +window.ssd { + box-shadow: 0 0 0 1px rgba(239, 241, 245, 0.12); +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + padding: 9px 0; + margin-left: 0px; + margin-right: 0px; + /* min-height: 22px; */ + /* min-width: 22px; */ + /* padding: ($medium-size - 22px) / 2 0; */ + /* margin-left: $space-size - 7px; */ + /* margin-right: $space-size - 7px; */ +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + color: rgba(239, 241, 245, 0.7); +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + background: none; + box-shadow: none; +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:not(.suggested-action):not(.destructive-action) > image { + padding: 1px; + background-color: alpha(currentColor, 0.1); +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.15); +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.2); +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) > image { + background-color: #313244; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #eff1f5; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: rgba(239, 241, 245, 0.3); +} + +/* $window-space: if($window_button == 'mac', $space-size * 1.5, $space-size); */ +windowcontrols { + border-spacing: 6px; +} + +windowcontrols:not(.empty).start:dir(ltr), windowcontrols:not(.empty).end:dir(rtl) { + margin-right: 6px; + margin-left: 6px; +} + +windowcontrols:not(.empty).start:dir(rtl), windowcontrols:not(.empty).end:dir(ltr) { + margin-left: 6px; + margin-right: 6px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) > image { + border-radius: 100%; + padding: 0; +} + + +.view:selected, iconview:selected, gridview > child:selected, columnview.view:selected, +treeview.view:selected, calendar:selected, calendar > grid > label.day-number:selected { + background-color: alpha(currentColor, 0.06); +} + +flowbox > flowboxchild:selected, calendar > grid > label.today { + color: #89b4fa; + background-color: rgba(137, 180, 250, 0.2); +} + +textview text selection:focus, textview text selection, label > selection, +entry > text > selection, spinbutton > text > selection, +entry headerbar popover.background entry > text > selection, +headerbar popover.background entry entry > text > selection, calendar > grid > label.today:selected { + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #89b4fa; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; +} + +shortcuts-section { + margin: 20px; +} + +.shortcuts-search-results { + margin: 20px; + border-spacing: 24px; +} + +shortcut { + border-spacing: 6px; +} + +shortcut > .keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(239, 241, 245, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(239, 241, 245, 0.12); + background-color: #292c3c; + color: #eff1f5; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #89b4fa; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0 2px; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/************* + * App Icons * + *************/ +.lowres-icon { + -gtk-icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.icon-dropshadow { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 1px 6px rgba(0, 0, 0, 0.1); +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker > contents { + padding: 0; +} + +.emoji-searchbar { + padding: 6px; + border-spacing: 6px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); + background: none; +} + +.emoji-searchbar entry text { + background: none; + box-shadow: none; +} + +.emoji-toolbar { + padding: 0; + border-spacing: 3px; + border-top: 1px solid rgba(239, 241, 245, 0.12); + background: none; +} + +button.emoji-section { + margin: 0; + padding: 6px; + border-radius: 12px; +} + +button.emoji-section:checked { + color: #89b4fa; +} + +popover.emoji-picker emoji { + font-size: x-large; + padding: 6px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker emoji:focus, popover.emoji-picker emoji:hover { + background: alpha(currentColor, 0.08); +} + +emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +emoji-completion-row > box { + border-spacing: 6px; + padding: 2px 6px; +} + +emoji-completion-row:focus, emoji-completion-row:hover, +emoji-completion-row emoji:hover, +emoji-completion-row emoji:focus { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; +} + +popover.entry-completion > contents { + padding: 0; +} + +.nautilus-window.view { + background-color: #1e1e2e; +} + +.nautilus-window .sidebar-pane, +.nautilus-window .content-pane { + background-color: #1e1e2e; + color: #eff1f5; +} + +.nautilus-window .sidebar-pane:backdrop, +.nautilus-window .content-pane:backdrop { + background-color: #1e1e2e; + transition: none; +} + +.nautilus-window .sidebar-pane:dir(ltr), +.nautilus-window .sidebar-pane:dir(ltr) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(rtl), +.nautilus-window .sidebar-pane.end:dir(rtl) banner > revealer > widget { + box-shadow: none; + border-right: none; +} + +.nautilus-window .sidebar-pane:dir(rtl), +.nautilus-window .sidebar-pane:dir(rtl) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(ltr), +.nautilus-window .sidebar-pane.end:dir(ltr) banner > revealer > widget { + box-shadow: none; + border-left: none; +} + +.nautilus-window placesview label { + color: rgba(239, 241, 245, 0.7); +} + +.nautilus-window flap > separator { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view .view, +.nautilus-window .nautilus-list-view .view { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell { + padding: 0; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell > widget#NautilusViewCell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell > widget#NautilusViewCell { + padding: 3px 9px; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable:nth-child(odd):not(:disabled), +.nautilus-window .nautilus-list-view listview.view > row.activatable:nth-child(odd):not(:disabled) { + background-image: image(alpha(currentColor, 0.03)); +} + +.nautilus-window .nautilus-grid-view gridview.view, +.nautilus-window .nautilus-list-view gridview.view { + margin: 10px 5px; + padding: 10px 5px; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border-style: none; + border-radius: 9px; + background-color: rgba(49, 50, 68, 0.95); + color: #89b4fa; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(30, 30, 46, 0.87); +} + +.nautilus-window banner > revealer > widget { + background-color: rgba(49, 50, 68, 0.4); + color: #eff1f5; + border-radius: 9px; + margin: 9px; +} + +.nautilus-window banner > revealer > widget button { + background-color: rgba(137, 180, 250, 0.3); + color: rgba(30, 30, 46, 0.87); +} + +.nautilus-window banner > revealer > widget button:hover { + background-color: rgba(137, 180, 250, 0.6); +} + +#NautilusQueryEditor > menubutton > button.image-button { + min-width: 24px; + min-height: 24px; + padding: 3px; + margin-right: -5px; +} + +#NautilusQueryEditor > menubutton > button.image-button:checked image { + color: rgba(30, 30, 46, 0.87); +} + +#NautilusQueryEditor > text, +#NautilusQueryEditor > box, +#NautilusQueryEditor > menubutton { + margin: 3px 0; +} + +#NautilusQueryEditorTag { + background-color: rgba(239, 241, 245, 0.12); +} + +#NautilusQueryEditorTag > button.image-button { + margin: 0; + padding: 0; +} + +#NautilusPathBar { + /* background-color: if($variant == 'light', $grey-100, $titlebar-fill); */ + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +#NautilusPathButton { + margin: 0 3px; + border-radius: 12px; +} + +#NautilusPathButton.current-dir { + color: #89b4fa; +} + +#NautilusPathButton.current-dir:hover, #NautilusPathButton.current-dir:active { + background: none; + box-shadow: none; +} + +#NautilusPathButton:first-child { + margin-left: 0; +} + +#NautilusViewCell clamp box { + margin: 0; + border-spacing: 0; +} + +#NautilusFileChooser gridview.view { + background-color: transparent; + margin: 10px 5px; + padding: 10px 5px; +} + +#NautilusFileChooser columnview.view, +row.activatable > cell { + background-color: transparent; + padding: 1px 10px; +} + +#NautilusProgressIndicator popover label { + color: rgba(239, 241, 245, 0.7); +} + +#NautilusProgressIndicator popover image { + color: rgba(239, 241, 245, 0.7); +} + +/* Nautilus Progress Indicator */ +windowhandle box.vertical box.toolbar { + background-color: #1e1e2e; + border: none; + outline: none; +} + +windowhandle box.toolbar menubutton button.toggle { + background-color: #1e1e2e; + border: none; + outline: none; +} + +window.dialog > box > stack > box > box > notebook.frame { + border-width: 0 0 0 1px; + border-radius: 0; +} + +.display-container.card { + background-color: #313244; +} + +.small .display-container.card { + border-radius: 0; + box-shadow: none; + border-width: 0 0 1px 0; +} + +.display-container .history-view { + background-color: transparent; +} + +.display-container #displayitem { + padding: 0 12px 8px 0; + font-size: 1.4em; + border-top: 1px solid rgba(239, 241, 245, 0.12); +} + +.math-buttons button { + font-size: 1.1em; + padding: 2px 6px; +} + +.math-buttons button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +leaflet button.number-button { + background-color: rgba(239, 241, 245, 0.1); +} + +leaflet button.number-button:hover { + background-color: rgba(239, 241, 245, 0.2); +} + +leaflet button.number-button:active { + background-color: rgba(239, 241, 245, 0.3); +} + +label.primary-label, label.month-name, label.secondary-label { + font-size: 16pt; + font-weight: bold; + padding: 12px; +} + +label.primary-label, label.month-name { + color: #89b4fa; +} + +label.secondary-label { + color: rgba(239, 241, 245, 0.5); +} + +toastoverlay datechooser.view, +toastoverlay agenda-view.view, +toastoverlay agenda-view.view list, +toastoverlay stack.view { + background-color: transparent; +} + +calendar-view { + font-size: 10pt; +} + +calendar-view:selected { + color: #89b4fa; + font-weight: bold; +} + +calendar-view.header, +label.header { + font-size: 10pt; + font-weight: bold; + color: rgba(239, 241, 245, 0.5); +} + +calendar-view.current, +weekgrid.current { + background-color: alpha(#89b4fa, 0.3); +} + +popover.events { + background-color: #292c3c; + padding: 0; +} + +popover.events box { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +popover.events list { + background-color: #313244; + border-radius: 12px; +} + +popover.events scrolledwindow { + border-width: 0; +} + +popover.events button { + border-radius: 12px; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-style: solid none none; + box-shadow: none; +} + +event { + margin: 1px; + font-size: 0.9rem; +} + +event widget.content { + margin: 4px; +} + +event.timed, event:not(.slanted):not(.slanted-start):not(.slanted-end) { + border-radius: 12px; +} + +event.timed widget.edge { + border-radius: 6px; + min-width: 5px; +} + +event.slanted-start, event.slanted-end:dir(rtl) { + padding-left: 16px; + border-radius: 0 6px 6px 0; +} + +event.slanted-end, event.slanted-start:dir(rtl) { + padding-right: 16px; + border-radius: 6px 0 0 6px; +} + +event:not(.timed).color-dark { + color: white; + outline-color: rgba(0, 0, 0, 0.3); +} + +event.timed, event:not(.timed).color-light { + color: alpha(black, 0.75); + outline-color: rgba(255, 255, 255, 0.5); +} + +popover.event-popover, +popover.event-popover > contents { + padding: 0; +} + +.search-viewport { + background-color: #313244; +} + +.calendar-list { + background-color: transparent; +} + +.calendar-list > list { + border-radius: 4px; +} + +menubutton.flat.sources-button { + margin-top: 0; + margin-bottom: 0; + border-radius: 0; + border-top-style: none; + border-bottom-style: none; +} + +menubutton.flat.sources-button:hover:not(:backdrop) { + background-image: none; + text-shadow: none; +} + +menubutton.flat.sources-button > button { + border-radius: 0 0 12px 12px; +} + +.calendar-color-image { + -gtk-icon-filter: none; +} + +image.calendar-color-image, +button:active:not(:backdrop) .calendar-color-image, +button:checked:not(:backdrop) .calendar-color-image, +.calendars-list .calendar-color-image:not(:backdrop):not(:disabled), +.calendar-list .calendar-color-image:not(:backdrop):not(:disabled), +.sources-button:not(:backdrop):not(:disabled) .calendar-color-image { + -gtk-icon-shadow: 0 1px alpha(black, 0.1); +} + +datechooser { + padding: 6px; +} + +datechooser .current-week { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; + border-radius: 12px; +} + +datechooser navigator { + margin-right: 6px; + margin-left: 6px; + margin-bottom: 6px; +} + +datechooser navigator label { + font-weight: bold; +} + +datechooser navigator button.flat, +datechooser navigator button.image-button { + min-height: 34px; + min-width: 34px; + padding: 0; +} + +datechooser .weeknum, +datechooser .weekday { + color: rgba(239, 241, 245, 0.5); + font-size: smaller; +} + +datechooser button.day { + font-size: 10pt; + font-weight: normal; + margin: 3px; + padding: 0; + min-height: 34px; + min-width: 34px; + transition: none; +} + +datechooser button.day dot { + background-color: #eff1f5; + border-radius: 50%; + min-height: 3px; + min-width: 3px; +} + +datechooser button.day:selected, datechooser button.day.today:selected { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); + font-weight: bold; +} + +datechooser button.day:selected dot, datechooser button.day.today:selected dot { + background-color: rgba(30, 30, 46, 0.87); +} + +datechooser button.day.today { + color: #89b4fa; +} + +datechooser button.day.today dot { + background-color: #89b4fa; +} + +datechooser button.day.other-month:not(:hover), datechooser button.day.other-month:backdrop { + color: rgba(239, 241, 245, 0.32); +} + +datechooser button.day.other-month:not(:hover) dot, datechooser button.day.other-month:backdrop dot { + background-color: rgba(239, 241, 245, 0.32); +} + +datechooser button.day.other-month:hover:not(:backdrop) { + color: rgba(239, 241, 245, 0.5); +} + +datechooser button.day.other-month:hover:not(:backdrop) dot { + background-color: rgba(239, 241, 245, 0.5); +} + +.week-header { + padding: 0; +} + +.week-header > box:first-child { + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.week-header .week-number { + font-size: 16pt; + font-weight: bold; + padding: 12px 12px 18px 12px; + color: rgba(239, 241, 245, 0.3); +} + +.week-header.week-temperature { + font-size: 10pt; + font-weight: bold; + color: rgba(239, 241, 245, 0.5); +} + +.week-header.lines { + color: rgba(239, 241, 245, 0.12); +} + +weekhourbar > label { + font-size: 10pt; + padding: 4px 6px; +} + +.week-view .lines { + color: rgba(239, 241, 245, 0.12); +} + +weekgrid > widget.now-strip { + background-color: alpha(#89b4fa, 0.8); + margin: 0 0 0 1px; + min-height: 3px; +} + +weekgrid:selected, weekgrid.dnd, +.week-header:selected, +.week-header.dnd { + background-color: alpha(#89b4fa, 0.25); +} + +monthcell { + border: solid 1px rgba(239, 241, 245, 0.12); + border-width: 1px 0 0 1px; + background-color: transparent; + transition: background-color 200ms; +} + +monthcell:hover:not(.out-of-month):not(.today) { + background-color: #313244; + transition: background-color 200ms; + color: #eff1f5; +} + +monthcell:selected { + background-color: alpha(#89b4fa, 0.1); +} + +monthcell:selected:hover { + background-color: alpha(#89b4fa, 0.2); +} + +monthcell:selected label.day-label { + font-weight: bold; +} + +monthcell:nth-child(7n + 1) { + border-left-width: 0; +} + +monthcell.today { + background-color: alpha(#89b4fa, 0.2); +} + +monthcell.today:hover { + background-color: alpha(#89b4fa, 0.3); + color: #89b4fa; +} + +monthcell.today:selected { + background-color: alpha(#89b4fa, 0.25); +} + +monthcell.today:selected:hover { + background-color: alpha(#89b4fa, 0.35); +} + +monthcell label { + color: #eff1f5; + font-size: 0.9rem; +} + +monthcell label.day-label { + font-size: 1rem; +} + +monthcell.out-of-month { + background-color: rgba(239, 241, 245, 0.04); +} + +monthcell.out-of-month label { + color: rgba(239, 241, 245, 0.7); +} + +monthcell button { + padding: 0 6px; + border-radius: 0; + border-bottom: none; + border-right: none; +} + +monthpopover > box { + margin: 0; + padding: 0; + background-color: transparent; +} + +.notes-section box > textview { + border-radius: 12px; + padding: 6px; +} + +.notes-section box > textview > text { + background: none; +} + +agenda-view list.background > row { + padding: 2px 12px; +} + +agenda-view list.background > label { + padding: 6px 12px; +} + +label.no-events { + font-style: italic; +} + +searchbutton > popover > arrow { + background: none; + border: none; +} + +menubutton stack > box { + border-spacing: 6px; +} + +#TweakPreferencesPage.tweak-group label.subtitle { + color: rgba(239, 241, 245, 0.32); +} + +#TweakPreferencesPage label.dim-label { + color: rgba(239, 241, 245, 0.32); +} + +.sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow .dim-label, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row label.subtitle, row .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow label.subtitle, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.expander image.expander-row-arrow, row.expander .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow image.expander-row-arrow { + color: rgba(30, 30, 46, 0.38); +} + +.details-page { + margin: 24px 0px; +} + +.installed-overlay-box { + font-size: smaller; + background-color: #89b4fa; + border-radius: 0; + color: rgba(30, 30, 46, 0.87); + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); +} + +screenshot-carousel box.frame { + border-width: 1px 0; + border-radius: 0; +} + +screenshot-carousel button, +.featured-carousel button { + margin: 12px; +} + +carousel.card { + border: none; + background-color: rgba(239, 241, 245, 0.04); +} + +.smaller { + font-size: smaller; +} + +.screenshot-image-main .image1, +.screenshot-image-main .image2 { + margin-top: 6px; + margin-bottom: 12px; + margin-left: 6px; + margin-right: 6px; +} + +.app-tile-label { + font-size: 105%; +} + +gs-summary-tile image.loading-icon { + background-color: rgba(239, 241, 245, 0.12); + border-radius: 12px; +} + +.review-row > box { + margin: 12px; + border-spacing: 3px; +} + +.review-row textview { + background: none; +} + +.review-row .edit-icon { + min-width: 24px; + min-height: 24px; + padding: 6px; +} + +.review-textbox { + padding: 6px; +} + +.origin-rounded-box { + background-color: rgba(239, 241, 245, 0.12); + border-radius: 9999px; + padding: 4px; +} + +.origin-beta { + color: #df8e1d; +} + +.origin-button > button { + padding: 3px 9px; +} + +clamp.medium .category-tile:not(.category-tile-iconless) { + font-size: large; +} + +clamp.large .category-tile:not(.category-tile-iconless) { + font-size: larger; +} + +flowboxchild.card:not(.category-tile) { + padding: 0; + box-shadow: none; + border: none; + background-color: transparent; + background-image: none; +} + +.category-tile.card { + padding: 21px; + border: none; + border-radius: 12px; + min-width: 140px; + font-weight: 900; + font-size: larger; +} + +.category-tile.card:not(.category-tile-iconless), .category-tile.card:not(.category-tile-iconless):active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + animation: none; +} + +.category-tile.card.category-tile-iconless { + padding: 9px 15px; + min-width: 130px; + font-size: 105%; + font-weight: normal; +} + +.category-tile.card.category-create { + background: linear-gradient(180deg, #ce8cd7 0%, #2861c6 100%); + color: white; +} + +.category-tile.card.category-create:hover { + background: linear-gradient(180deg, shade(#ce8cd7, 1.07) 0%, shade(#2861c6, 1.1) 100%); + color: white; +} + +.category-tile.card.category-create:active { + background: linear-gradient(180deg, shade(#ce8cd7, 0.95) 0%, shade(#2861c6, 0.95) 100%); + color: white; +} + +.category-tile.card.category-develop { + background-color: #5e5c64; + color: white; +} + +.category-tile.card.category-develop:hover { + background-color: shade(#5e5c64, 1.2); + color: white; +} + +.category-tile.card.category-develop:active { + background-color: shade(#5e5c64, 0.95); + color: white; +} + +.category-tile.card.category-learn { + background: linear-gradient(180deg, #2ec27e 30%, #27a66c 100%); + color: white; +} + +.category-tile.card.category-learn:hover { + background: linear-gradient(180deg, shade(#2ec27e, 1.06) 30%, shade(#27a66c, 1.06) 100%); + color: white; +} + +.category-tile.card.category-learn:active { + background: linear-gradient(180deg, shade(#2ec27e, 0.95) 30%, shade(#27a66c, 0.95) 100%); + color: white; +} + +.category-tile.card.category-play { + background: linear-gradient(75deg, #f9e2a7 0%, #eb5ec3 50%, #6d53e0 100%); + color: #393484; +} + +.category-tile.card.category-play:hover { + background: linear-gradient(75deg, shade(#f9e2a7, 1.07) 0%, shade(#eb5ec3, 1.07) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-play:active { + background: linear-gradient(75deg, shade(#f9e2a7, 0.97) 0%, shade(#eb5ec3, 0.95) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-socialize { + background: linear-gradient(90deg, #ef4e9b 0%, #f77466 100%); + color: rgba(239, 241, 245, 0.7); +} + +.category-tile.card.category-socialize:hover { + background: linear-gradient(90deg, shade(#ef4e9b, 1.08) 0%, shade(#f77466, 1.08) 100%); +} + +.category-tile.card.category-socialize:active { + background: linear-gradient(90deg, shade(#ef4e9b, 0.95) 0%, shade(#f77466, 0.95) 100%); +} + +.category-tile.card.category-work { + padding: 1px; + /* FIXME: work around https://gitlab.gnome.org/GNOME/gtk/-/issues/4324 */ + color: #1c71d8; + background-color: #fdf8d7; + background-image: linear-gradient(rgba(239, 241, 245, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(239, 241, 245, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.category-tile.card.category-work:hover { + color: #1c71d8; + background-color: #fefcef; + background-image: linear-gradient(rgba(239, 241, 245, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(239, 241, 245, 0.12) 1px, transparent 1px); +} + +.category-tile.card.category-work:active { + color: #1c71d8; + background-color: #fcf4bf; + background-image: linear-gradient(rgba(239, 241, 245, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(239, 241, 245, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.featured-tile { + padding: 0; + box-shadow: none; + color: #eff1f5; +} + +.featured-tile label.title-1 { + margin-top: 6px; + margin-bottom: 6px; +} + +.featured-tile.narrow label.title-1 { + font-size: 16pt; +} + +.application-details-infobar, .application-details-infobar.info { + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; + border: 1px solid rgba(239, 241, 245, 0.12); +} + +.application-details-infobar.warning { + background-color: #df8e1d; + color: #eff1f5; + border: 1px solid rgba(239, 241, 245, 0.12); +} + +.card.info { + background-color: #1f1f2f; + color: #eff1f5; +} + +.card.warning { + background-color: #1f1f2e; + color: #eff1f5; +} + +.infobox { + border-spacing: 6px; + padding: 12px; +} + +@keyframes install-progress-unknown-move { + 0% { + background-position: 0%; + } + 50% { + background-position: 100%; + } + 100% { + background-position: 0%; + } +} + +.application-details-description .button { + padding-left: 24px; + padding-right: 24px; +} + +.install-progress { + background-image: linear-gradient(to top, #89b4fa 2px, alpha(#89b4fa, 0) 2px); + background-repeat: no-repeat; + background-position: 0 bottom; + background-size: 0; + transition: none; +} + +.install-progress:dir(rtl) { + background-position: 100% bottom; +} + +.review-row > * { + margin: 12px; +} + +.review-row button { + font-size: smaller; +} + +.review-row .vote-buttons button { + margin-right: -1px; +} + +.review-row .vote-buttons button:not(:first-child) { + border-image: linear-gradient(to top, rgba(239, 241, 245, 0.12), rgba(239, 241, 245, 0.12)) 0 0 0 1/5px 0 5px 1px; +} + +.review-row .vote-buttons button:hover, +.review-row .vote-buttons button:active, +.review-row .vote-buttons button:hover + button, +.review-row .vote-buttons button:active + button { + border-image: none; +} + +review-bar { + color: rgba(239, 241, 245, 0.5); + background-image: none; + background-color: rgba(239, 241, 245, 0.3); +} + +.review-histogram star-image { + color: rgba(239, 241, 245, 0.5); +} + +.version-arrow-label { + font-size: x-small; +} + +.overview-more-button { + font-size: smaller; + padding: 0 16px; +} + +.app-row-origin-text { + font-size: smaller; +} + +.app-listbox-header { + padding: 6px; + border-bottom: 1px solid rgba(239, 241, 245, 0.12); +} + +.image-list { + background-color: transparent; +} + +box.star { + background-color: transparent; + background-image: none; +} + +button.star { + outline-offset: 0; + background-color: transparent; + background-image: none; + border-image: none; + border-radius: 0; + border-width: 0; + padding: 0; + box-shadow: none; + outline-offset: -1px; +} + +flowboxchild { + padding: 0px; +} + +star-image > image.starred { + color: #f9e2af; + transition-duration: 200ms; +} + +star-image > image.starred:hover { + color: #df8e1d; +} + +star-image > image.non-starred { + opacity: 0.2; + transition-duration: 200ms; +} + +star-image > image.non-starred:hover { + color: #f9e2af; + opacity: 0.7; +} + +.dimmer-label { + opacity: 0.25; +} + +.update-failed-details { + font-family: Monospace; + font-size: smaller; + padding: 16px; +} + +.upgrade-banner { + padding: 0px; + border-radius: 12px; + border: none; +} + +.upgrade-banner-background { + background: linear-gradient(to bottom, #40a02b, #1e66f5); + color: white; +} + +.upgrade-buttons #button_upgrades_install, +.upgrade-buttons #button_upgrades_install_cancel { + padding-left: 16px; + padding-right: 16px; +} + +scrolledwindow.list-page > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +.update-preferences preferencesgroup > box > box { + margin-top: 18px; +} + +.section > label:not(:first-child) { + margin-top: 6px; +} + +.section > box:not(:first-child) { + margin-top: 12px; +} + +clamp.status-page { + margin: 36px 12px; +} + +clamp.status-page .iconbox { + min-height: 128px; + min-width: 128px; +} + +clamp.status-page .icon { + color: rgba(239, 241, 245, 0.5); + min-height: 32px; + min-width: 32px; +} + +clamp.status-page .icon:not(:last-child) { + margin-bottom: 36px; +} + +clamp.status-page .title:not(:last-child) { + margin-bottom: 12px; +} + +app-context-bar .context-tile { + border: 1px solid rgba(239, 241, 245, 0.12); + background-color: transparent; + border-radius: 0; + padding: 24px 12px 21px 12px; + outline-offset: 5px; + transition-property: outline, outline-offset, background-image; + border-bottom: none; + border-right: none; +} + +app-context-bar .context-tile:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); +} + +app-context-bar .context-tile.keyboard-activating, app-context-bar .context-tile:active { + background-color: alpha(currentColor, 0.12); +} + +app-context-bar .context-tile:focus:focus-visible { + outline-offset: -1px; +} + +app-context-bar.horizontal box:first-child .context-tile:first-child, app-context-bar.vertical .context-tile:first-child { + border-left: none; +} + +app-context-bar.horizontal .context-tile, app-context-bar.vertical box:first-child .context-tile { + border-top: none; +} + +app-context-bar > box:not(:first-child) > button.flat { + border-radius: 0; +} + +app-context-bar > box:not(:first-child) > button.flat:last-child { + border-radius: 0 12px 12px 0; +} + +app-context-bar > box:first-child > button.flat { + border-radius: 0; +} + +app-context-bar > box:first-child > button.flat:first-child { + border-radius: 12px 0 0 12px; +} + +app-context-bar > box > button.flat { + border-left-color: rgba(239, 241, 245, 0.12); +} + +.context-tile-lozenge { + min-height: 28px; + min-width: 28px; + padding: 6px; + font-size: 18px; + font-weight: bold; + border-radius: 9999px; +} + +.context-tile-lozenge.large { + font-size: 24px; + padding: 16px; + min-width: 24px; + /* 60px minus the left and right padding */ + min-height: 24px; + /* 60px minus the top and bottom padding */ +} + +.context-tile-lozenge.wide-image image { + margin-top: -28px; + margin-bottom: -28px; +} + +.context-tile-lozenge image { + -gtk-icon-style: symbolic; +} + +.context-tile-lozenge.grey { + color: #eff1f5; + background-color: rgba(239, 241, 245, 0.12); +} + +.context-tile-lozenge.green, .context-tile-lozenge.details-rating-0 { + color: #28641b; + background-color: rgba(64, 160, 43, 0.15); +} + +.context-tile-lozenge.blue, .context-tile-lozenge.details-rating-5 { + color: #1e66f5; + background-color: rgba(30, 102, 245, 0.15); +} + +.context-tile-lozenge.yellow, .context-tile-lozenge.details-rating-12 { + color: #9b6314; + background-color: rgba(223, 142, 29, 0.15); +} + +.context-tile-lozenge.details-rating-15 { + color: #fe640b; + background-color: rgba(254, 100, 11, 0.15); +} + +.context-tile-lozenge.red, .context-tile-lozenge.details-rating-18 { + color: #8b0a26; + background-color: rgba(210, 15, 57, 0.15); +} + +.eol-red { + font-weight: bold; + color: #d20f39; +} + +window.narrow .app-title { + font-size: 16pt; +} + +window.narrow .app-developer { + font-size: small; +} + +.install-progress-label { + font-size: smaller; + font-feature-settings: 'tnum'; +} + +scrolledwindow.fake-adw-status-page > viewport > box { + margin: 36px 12px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp:not(:last-child) +> box { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .icon:not(:last-child) { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .title:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.icon-dropshadow image.icon { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 -1px rgba(0, 0, 0, 0.05), 1px 0 rgba(0, 0, 0, 0.1), 0 1px rgba(0, 0, 0, 0.3), -1px 0 rgba(0, 0, 0, 0.1); +} + +window.info scrollbar.vertical { + margin-top: 48px; + background: none; + box-shadow: none; +} + +window.info scrollbar.vertical trough { + margin-top: 0; +} + +row.app > box.header { + margin-left: 12px; + margin-right: 12px; +} + +row.app > box.header { + border-spacing: 12px; +} + +row.app > box.header > image { + margin-top: 12px; + margin-bottom: 12px; +} + +row.app label.warning { + color: #d20f39; +} + +@keyframes pre-delay { + from { + opacity: 0; + } + to { + opacity: 0; + } +} + +@keyframes fade-in { + from { + filter: opacity(0%); + } +} + +/* Give a fade-in animation to spinners. */ +spinner.fade-in:checked { + animation: pre-delay 0.5s linear 1, fade-in 1s linear 1, spin 1s linear infinite; + animation-delay: 0s, 0.5s, 0.5s; +} + +window > contents > leaflet > box > stack.background { + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, transparent 46px, #1e1e2e 46px, #1e1e2e); +} + +@define-color weather_temp_chart_fill_color rgba(223, 142, 29, 0.5); +@define-color weather_temp_chart_stroke_color #b27117; +@define-color weather_thermometer_warm_color #df8e1d; +@define-color weather_thermometer_cold_color #1e66f5; +#places-label { + font-weight: bold; +} + +#temperature-label { + font-size: 32pt; + font-weight: 900; + margin-left: 9px; +} + +#conditions-grid *:backdrop { + color: rgba(239, 241, 245, 0.7); +} + +.content-view.cell { + font-weight: bold; +} + +#locationEntry { + margin: 6px; +} + +.weather-popover { + margin-top: 6px; +} + +.forecast-card { + transition: border-radius 100ms ease-out; + border-radius: 12px; +} + +.forecast-card separator { + background-color: #1e1e2e; +} + +#daily-forecast-box > separator:last-child { + background-color: transparent; + min-width: 0; +} + +#conditions-grid, +#attributionGrid { + margin-left: 18px; + margin-right: 18px; +} + +#weather-page .small .forecast-card { + margin-left: 0; + margin-right: 0; + border-radius: 0; + border-width: 1px 0; +} + +.forecast-temperature-label { + font-weight: bold; + color: #ae7b03; +} + +WeatherThermometer { + margin-bottom: 12px; +} + +WeatherThermometer > label.high { + font-weight: bold; + color: #df8e1d; +} + +WeatherThermometer > label.low { + font-weight: bold; + color: #1e66f5; +} + +.forecast-button { + margin: 0 12px; +} + +.forecast-graphic { + margin: 18px; +} + +button.osd.circular { + border-radius: 9999px; + min-width: 24px; + min-height: 24px; +} + +button.osd.circular > image { + padding: 0; +} + +scrolledwindow.inline list, +scrolledwindow.inline listview { + background: none; + color: inherit; +} + +scrolledwindow.inline undershoot.top { + box-shadow: inset 0 1px rgba(239, 241, 245, 0.12); +} + +.search-view { + background-color: #89b4fa; + color: rgba(30, 30, 46, 0.87); +} + +.search-view menubutton button:focus:focus-visible { + outline-color: rgba(255, 255, 255, 0.3); +} + +image.circular { + min-width: 34px; + min-height: 34px; + padding: 0; + border-radius: 9999px; +} + +#gnome-system-monitor.background.csd { + background-color: #1e1e2e; +} + +.large-button { + padding: 6px; +} + +.alarm-time { + font-size: 2.5em; + font-weight: 300; +} + +.clocks-ampm-toggle-button, +.clocks-secondary-standalone-label { + font-size: 18pt; +} + +.clocks-standalone-label, +.clocks-ringing-label { + font-size: 6em; + font-weight: 300; +} + +.clocks-ringing-title { + font-size: 1.5em; + font-weight: bold; +} + +.clocks-alarm-setup-time { + font-size: 32pt; +} + +.clocks-timer-label, +.clocks-spinbutton { + font-size: 48pt; +} + +.timer-panel .timer-header { + font-size: 20pt; + font-weight: 300; +} + +.timer-countdown { + font-size: 40pt; + font-weight: 300; +} + +/* Stopwatch Panel */ +.lap-time { + font-weight: bold; +} + +.stopped-stopwatch label, +.running-stopwatch label, +.paused-stopwatch label { + font-size: 70px; + font-weight: lighter; +} + +.stopped-stopwatch .seconds-label { + font-weight: 300; +} + +.running-stopwatch .seconds-label, +.running-stopwatch .miliseconds-label { + color: #89b4fa; +} + +.stopped-stopwatch .miliseconds-label, +.running-stopwatch .miliseconds-label, +.paused-stopwatch .miliseconds-label { + font-size: 50px; +} + +.running-stopwatch .seconds-label, +.paused-stopwatch .seconds-label { + font-weight: 300; +} + +.clock-location { + font-weight: bolder; +} + +.hidden { + opacity: 0; +} + +.clock-time { + font-size: 2em; + padding: 0.2em 0.5em; + border-radius: 1em; +} + +.none .clock-time { + background: alpha(currentColor, 0.2); +} + +.night .clock-time { + color: #89b4fa; + background-color: alpha(#1e66f5, 0.25); +} + +.naut .clock-time, +.astro .clock-time { + color: #fab387; + background-color: alpha(#fe640b, 0.25); +} + +.civil .clock-time, +.day .clock-time { + color: #f9e2af; + background: alpha(#df8e1d, 0.25); +} + +headerbar splitbutton notification button { + margin: 0; + min-height: 24px; + min-width: 24px; + padding: 0; +} + +popover.background.global-search > arrow, +popover.background.global-search > contents { + padding: 0; +} + +panelframeswitcher { + padding: 3px; +} + +.frameheader.header { + min-height: 24px; + background-color: #313244; +} + +.frameheader.header > button { + border: none; + margin: 0; + padding: 3px; +} + +.frameheader.header tabbar.inline > revealer > box { + min-height: 24px; +} + +.frameheader.header tabbar.inline > revealer > box .start-action { + padding: 0; + border: none; +} + +.frameheader.header tabbar.inline > revealer > box .end-action { + padding: 0; + border-left: 1px solid rgba(239, 241, 245, 0.12); +} + +.frameheader.header tabbar.inline > revealer > box tabbox { + border: none; + background: none; +} + +panelstatusbar > menubutton > button, +panelstatusbar > paneltogglebutton button { + border-radius: 0; +} + +.style-variant { + padding: 0 12px; +} + +.style-variant button.toggle { + padding: 0; +} + +.style-variant button.toggle, .style-variant button.toggle:hover, .style-variant button.toggle:focus, .style-variant button.toggle:active, .style-variant button.toggle:checked { + background: none; + outline: none; + border: none; + box-shadow: none; +} + +.style-variant button.toggle > stylevariantpreview > .wallpaper { + border-radius: 12px; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; + box-shadow: none; +} + +.style-variant button.toggle:hover > stylevariantpreview > .wallpaper { + outline-color: rgba(239, 241, 245, 0.04); +} + +.style-variant button.toggle:active > stylevariantpreview > .wallpaper { + outline-color: rgba(239, 241, 245, 0.3); +} + +.style-variant button.toggle:checked > stylevariantpreview > .wallpaper { + outline-color: #89b4fa; +} + +playlistview scrollbar.overlay-indicator.dragging, playlistview scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +playlistview queuerow picture.cover, +playlistview queuerow image.card { + border: none; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list { + border: none; + border-radius: 0; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:first-child, window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:last-child { + border-radius: 0; +} + +/* Tagger */ +list.music-list { + margin: -40px 0; + background-color: transparent; +} + +/* Nicotine+ */ +notebook scrolledwindow treeview.treeview-spacing { + background-color: #1e1e2e; +} + +.account-switcher-row label { + color: #eff1f5; +} + +.account-switcher-row label.dim-label { + color: rgba(239, 241, 245, 0.7); +} + +window.background.chromium { + background-color: rgba(239, 241, 245, 0.04); +} + +window.background.chromium headerbar.header-bar.titlebar { + padding: 0 12px; + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px 0 rgba(239, 241, 245, 0.1); +} + +window.background.chromium headerbar.header-bar.titlebar:backdrop { + background-color: #1e1e2e; + color: rgba(239, 241, 245, 0.5); +} + +window.background.chromium headerbar.header-bar.titlebar button.titlebutton { + margin: 0 0px; +} + +.nautilus-window placessidebar > scrolledwindow { + background-color: #1e1e2e; + color: #eff1f5; + border-radius: 0; + /* margin: 0 6px 0 0; */ +} + +.nautilus-window placessidebar > scrolledwindow .dim-label, .nautilus-window placessidebar > scrolledwindow row label.subtitle, row .nautilus-window placessidebar > scrolledwindow label.subtitle, .nautilus-window placessidebar > scrolledwindow row.property > box.header > box.title > .title, .nautilus-window placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander .nautilus-window placessidebar > scrolledwindow image.expander-row-arrow { + color: rgba(30, 30, 46, 0.38); +} + +.nautilus-window .nautilus-grid-view, +.nautilus-window .nautilus-list-view { + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px; + margin: 0 6px 6px 6px; +} + +calendar-view { + margin: 6px; +} + +.sidebar-pane .sidebar > scrolledwindow, +.sidebar-pane toolbarview > scrolledwindow, +.sidebar-pane navigation-view-page stack > scrolledwindow, .sidebar-pane, filechooser paned > box, placessidebar > scrolledwindow, agenda-view list.background, .tweak-titlebar-left, .tweak-titlebar-left:backdrop, leaflet.unfolded > box > scrolledwindow, leaflet.unfolded .contacts-contact-list > scrolledwindow, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow { + background-color: #181825; + color: #eff1f5; + border-radius: 0; + margin: 0; +} + +.sidebar-pane .sidebar > scrolledwindow .dim-label, +.sidebar-pane toolbarview > scrolledwindow .dim-label, +.sidebar-pane navigation-view-page stack > scrolledwindow .dim-label, .sidebar-pane .dim-label, filechooser paned > box .dim-label, placessidebar > scrolledwindow .dim-label, agenda-view list.background .dim-label, .tweak-titlebar-left .dim-label, leaflet.unfolded > box > scrolledwindow .dim-label, leaflet.unfolded .contacts-contact-list > scrolledwindow .dim-label, .sidebar-pane row label.subtitle, row .sidebar-pane label.subtitle, filechooser paned > box row label.subtitle, row filechooser paned > box label.subtitle, placessidebar > scrolledwindow row label.subtitle, row placessidebar > scrolledwindow label.subtitle, agenda-view list.background row label.subtitle, row agenda-view list.background label.subtitle, .tweak-titlebar-left row label.subtitle, row .tweak-titlebar-left label.subtitle, leaflet.unfolded > box > scrolledwindow row label.subtitle, row leaflet.unfolded > box > scrolledwindow label.subtitle, leaflet.unfolded .contacts-contact-list > scrolledwindow row label.subtitle, row leaflet.unfolded .contacts-contact-list > scrolledwindow label.subtitle, .sidebar-pane row.property > box.header > box.title > .title, placessidebar > scrolledwindow row.property > box.header > box.title > .title, agenda-view list.background row.property > box.header > box.title > .title, .tweak-titlebar-left row.property > box.header > box.title > .title, leaflet.unfolded > box > scrolledwindow row.property > box.header > box.title > .title, leaflet.unfolded .contacts-contact-list > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane row.expander image.expander-row-arrow, row.expander .sidebar-pane image.expander-row-arrow, filechooser paned > box row.expander image.expander-row-arrow, row.expander filechooser paned > box image.expander-row-arrow, placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander placessidebar > scrolledwindow image.expander-row-arrow, agenda-view list.background row.expander image.expander-row-arrow, row.expander agenda-view list.background image.expander-row-arrow, .tweak-titlebar-left row.expander image.expander-row-arrow, row.expander .tweak-titlebar-left image.expander-row-arrow, leaflet.unfolded > box > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded > box > scrolledwindow image.expander-row-arrow, leaflet.unfolded .contacts-contact-list > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded .contacts-contact-list > scrolledwindow image.expander-row-arrow { + color: rgba(30, 30, 46, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider, placessidebar > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar > range > trough > slider { + background-color: rgba(239, 241, 245, 0.5); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:hover, placessidebar > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:hover { + background-color: rgba(239, 241, 245, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:active, placessidebar > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:active { + background-color: rgba(239, 241, 245, 0.7); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:disabled, placessidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:disabled { + background-color: rgba(239, 241, 245, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(30, 30, 46, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(30, 30, 46, 0.3); +} + +placessidebar list.navigation-sidebar, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar { + padding: 6px 0 6px 6px; + background: none; + color: rgba(239, 241, 245, 0.7); +} + +placessidebar list.navigation-sidebar > separator, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > separator, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > separator { + background-color: rgba(239, 241, 245, 0.12); + margin: 10px 15px; +} + +placessidebar list.navigation-sidebar > row, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row { + color: rgba(30, 30, 46, 0.6); + border-radius: 9px; + color: #eff1f5; + padding: 6px 0; +} + +placessidebar list.navigation-sidebar > row:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:hover, placessidebar list.navigation-sidebar > row:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:active, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:active, placessidebar list.navigation-sidebar > row:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:focus { + color: #d2e3fd; +} + +placessidebar list.navigation-sidebar > row:selected, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + color: #89b4fa; + font-weight: 500; +} + +placessidebar list.navigation-sidebar > row:selected:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:hover, placessidebar list.navigation-sidebar > row:selected:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:focus { + color: #bad3fc; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.top, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.top, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.top, filechooser paned > box scrolledwindow scrollbar.top, placessidebar > scrolledwindow > scrollbar.top, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.top, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.top, leaflet.unfolded > box > scrolledwindow > scrollbar.top, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.top, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.top { + border-bottom: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.bottom, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.bottom, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.bottom, filechooser paned > box scrolledwindow scrollbar.bottom, placessidebar > scrolledwindow > scrollbar.bottom, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.bottom, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.bottom, leaflet.unfolded > box > scrolledwindow > scrollbar.bottom, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.bottom, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.bottom { + border-top: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.left, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.left, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.left, filechooser paned > box scrolledwindow scrollbar.left, placessidebar > scrolledwindow > scrollbar.left, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.left, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.left, leaflet.unfolded > box > scrolledwindow > scrollbar.left, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.left, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.left { + border-right: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.right, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.right, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.right, filechooser paned > box scrolledwindow scrollbar.right, placessidebar > scrolledwindow > scrollbar.right, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.right, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.right, leaflet.unfolded > box > scrolledwindow > scrollbar.right, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.right, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.right { + border-left: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.dragging, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.dragging, placessidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.dragging, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.dragging, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.dragging, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.hovering, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.hovering, placessidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.hovering, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.hovering, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.hovering, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.hovering, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-top > undershoot.top, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-top > undershoot.top { + border-radius: 12px 12px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-bottom > undershoot.bottom, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 12px 12px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.75), transparent 4px); +} + +avatar { + border-radius: 9999px; + font-weight: bold; +} + +avatar.color1 { + background-image: linear-gradient(#83b6ec, #337fdc); + color: #cfe1f5; +} + +avatar.color2 { + background-image: linear-gradient(#7ad9f1, #0f9ac8); + color: #caeaf2; +} + +avatar.color3 { + background-image: linear-gradient(#8de6b1, #29ae74); + color: #cef8d8; +} + +avatar.color4 { + background-image: linear-gradient(#b5e98a, #6ab85b); + color: #e6f9d7; +} + +avatar.color5 { + background-image: linear-gradient(#f8e359, #d29d09); + color: #f9f4e1; +} + +avatar.color6 { + background-image: linear-gradient(#ffcb62, #d68400); + color: #ffead1; +} + +avatar.color7 { + background-image: linear-gradient(#ffa95a, #ed5b00); + color: #ffe5c5; +} + +avatar.color8 { + background-image: linear-gradient(#f78773, #e62d42); + color: #f8d2ce; +} + +avatar.color9 { + background-image: linear-gradient(#e973ab, #e33b6a); + color: #fac7de; +} + +avatar.color10 { + background-image: linear-gradient(#cb78d4, #9945b5); + color: #e7c2e8; +} + +avatar.color11 { + background-image: linear-gradient(#9e91e8, #7a59ca); + color: #d5d2f5; +} + +avatar.color12 { + background-image: linear-gradient(#e3cf9c, #b08952); + color: #f2eade; +} + +avatar.color13 { + background-image: linear-gradient(#be916d, #785336); + color: #e5d6ca; +} + +avatar.color14 { + background-image: linear-gradient(#c0bfbc, #6e6d71); + color: #d8d7d3; +} + +avatar.contrasted { + color: #eff1f5; +} + +avatar.image { + background: none; +} + +.card { + border-radius: 12px; + border: 1px solid rgba(239, 241, 245, 0.12); + background-clip: border-box; + color: rgba(239, 241, 245, 0.7); + box-shadow: none; + outline: none; + background-color: rgba(239, 241, 245, 0.04); + color: #eff1f5; +} + +.card.activatable { + background-color: rgba(239, 241, 245, 0.08); + color: #eff1f5; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(239, 241, 245, 0.04); +} + +.card.activatable:hover { + background-color: alpha(currentColor, 0.08); + color: #eff1f5; + outline: 0 solid transparent; +} + +.card.activatable:active { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +toast { + margin: 12px; + margin-bottom: 24px; + border-radius: 9999px; + border-spacing: 6px; + padding: 6px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1), inset 0 1px rgba(239, 241, 245, 0.1); + background-color: #292c3c; + color: #eff1f5; + border: none; +} + +toast:dir(ltr) { + padding-left: 12px; +} + +toast:dir(rtl) { + padding-right: 12px; +} + +toast > label { + margin: 0 6px; +} + +viewswitcher { + min-height: 0; + padding: 3px; + margin: 6px 0; + border-radius: 12px; + background-color: rgba(239, 241, 245, 0.04); + border: none; +} + +viewswitcher.wide { + margin-top: 6px; + margin-bottom: 6px; +} + +viewswitcher.wide button.toggle { + margin: 0; + border-radius: 9px; +} + +viewswitcher.narrow button.toggle { + border-radius: 0; + margin: 0; +} + +viewswitcher.narrow button.toggle:focus-within, viewswitcher.narrow button.toggle:focus { + box-shadow: none; +} + +viewswitcher button.toggle { + font-weight: bold; + padding: 0; +} + +viewswitcher button.toggle > stack > box.narrow { + font-size: 0.75rem; + padding-top: 6px; + padding-bottom: 4px; + border-spacing: 4px; +} + +viewswitcher button.toggle > stack > box.narrow > stack > label { + padding-left: 6px; + padding-right: 6px; +} + +viewswitcher button.toggle > stack > box.wide { + padding: 2px 12px; + border-spacing: 6px; +} + +viewswitcherbar actionbar > revealer > box { + padding: 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle { + border-radius: 12px; + margin: 3px 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 5px; + padding-bottom: 1px; + border-spacing: 0; +} + +viewswitchertitle { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher { + margin-left: 12px; + margin-right: 12px; +} + +viewswitchertitle viewswitcher.narrow { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 0; + padding-bottom: 0; + border-spacing: 0; +} + +viewswitchertitle viewswitcher.wide { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle windowtitle { + margin-top: 0; + margin-bottom: 0; +} + +indicatorbin > indicator, +indicatorbin > mask { + min-width: 6px; + min-height: 6px; + border-radius: 9999px; +} + +indicatorbin > indicator { + margin: 1px; + background-color: alpha(currentColor, 0.4); +} + +indicatorbin > indicator > label { + font-size: 0.6rem; + font-weight: bold; + padding: 1px 4px; + color: #eff1f5; +} + +indicatorbin > mask { + padding: 1px; + background: black; +} + +indicatorbin.needs-attention > indicator { + background-color: #89b4fa; +} + +indicatorbin.needs-attention > indicator > label { + color: rgba(30, 30, 46, 0.87); +} + +preferencespage > scrolledwindow > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +preferencesgroup > box background-preview widget.sidebar, +preferencesgroup > box widget.header-bar:not(.editable-area) { + background-color: #11111b; +} + +preferencesgroup > box, +preferencesgroup > box .labels { + border-spacing: 6px; +} + +preferencesgroup > box > box.header:not(.single-line) { + margin-bottom: 6px; +} + +preferencesgroup > box > box.single-line { + min-height: 34px; +} + +preferencesgroup > box button.background-preview-button.toggle { + padding: 0; + background: none; + box-shadow: none; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; +} + +preferencesgroup > box button.background-preview-button.toggle, +preferencesgroup > box button.background-preview-button.toggle > background-preview { + border-radius: 12px; +} + +preferencesgroup > box button.background-preview-button.toggle:hover { + outline-color: rgba(239, 241, 245, 0.04); +} + +preferencesgroup > box button.background-preview-button.toggle:active { + outline-color: rgba(239, 241, 245, 0.3); +} + +preferencesgroup > box button.background-preview-button.toggle:checked { + outline-color: #89b4fa; +} + +preferencesgroup > box .cutout-button { + background-color: #313244; +} + +preferencesgroup > box button.accent-button { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; + background: var(--accent-bg-color); + outline: none; + background-clip: content-box; + box-shadow: none; +} + +preferencesgroup > box button.accent-button:hover { + box-shadow: 0 0 0 3px alpha(currentColor, 0.08); +} + +preferencesgroup > box button.accent-button:checked { + box-shadow: 0 0 0 3px #89b4fa; +} + +preferencesgroup > box button.accent-button.blue, preferencesgroup > box button.accent-button.teal, preferencesgroup > box button.accent-button.green, preferencesgroup > box button.accent-button.yellow, preferencesgroup > box button.accent-button.orange, preferencesgroup > box button.accent-button.red, preferencesgroup > box button.accent-button.pink, preferencesgroup > box button.accent-button.purple, preferencesgroup > box button.accent-button.slate { + --accent-color: oklab( + from var(--accent-bg-color) var(--standalone-color-oklab) + ); +} + +preferencesgroup > box button.accent-button.blue { + --accent-bg-color: var(--accent-blue); +} + +preferencesgroup > box button.accent-button.teal { + --accent-bg-color: var(--accent-teal); +} + +preferencesgroup > box button.accent-button.green { + --accent-bg-color: var(--accent-green); +} + +preferencesgroup > box button.accent-button.yellow { + --accent-bg-color: var(--accent-yellow); +} + +preferencesgroup > box button.accent-button.orange { + --accent-bg-color: var(--accent-orange); +} + +preferencesgroup > box button.accent-button.red { + --accent-bg-color: var(--accent-red); +} + +preferencesgroup > box button.accent-button.pink { + --accent-bg-color: var(--accent-pink); +} + +preferencesgroup > box button.accent-button.purple { + --accent-bg-color: var(--accent-purple); +} + +preferencesgroup > box button.accent-button.slate { + --accent-bg-color: var(--accent-slate); +} + +preferencesgroup > box box > list.boxed-list-separate { + background-color: transparent; + border-radius: 12px; + border: 1px solid rgba(239, 241, 245, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row { + color: rgba(239, 241, 245, 0.7); + background-color: rgba(239, 241, 245, 0.04); + border-radius: 12px 12px 0 0; + margin-top: 0px; + margin-bottom: 0px; +} + +preferencesgroup > box box > list.boxed-list-separate row:first-child { + border-radius: 12px 12px 0 0; + box-shadow: 0 1px rgba(239, 241, 245, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row:last-child { + border-radius: 0 0 12px 12px; +} + +preferencesgroup > box box > list.boxed-list-separate row:hover, preferencesgroup > box box > list.boxed-list-separate row:focus { + color: #eff1f5; + background-color: alpha(currentColor, 0.12); +} + +window.about .main-page > viewport > clamp > box { + margin: 12px; + border-spacing: 6px; +} + +window.about .main-page > viewport > clamp > box > box { + margin-top: 18px; + border-spacing: 18px; + margin-bottom: 6px; +} + +window.about .main-page .app-version { + padding: 3px 18px; + color: #89b4fa; + border-radius: 12px; + margin-top: 3px; +} + +window.about .subpage > viewport > clamp > box { + margin: 18px 12px; + border-spacing: 18px; +} + +window.about .subpage > clamp > textview { + background: none; + color: inherit; +} + +statuspage > scrolledwindow > viewport > box { + margin: 36px 12px; + border-spacing: 36px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box { + border-spacing: 12px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 128px; + color: alpha(currentColor, 0.55); +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:disabled { + opacity: 0.35; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box { + margin: 24px 12px; + border-spacing: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 96px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .title { + font-size: 18pt; +} + +flap > dimming, +leaflet > dimming, +navigation-view > dimming, +overlay-split-view > dimming { + background-color: rgba(30, 30, 46, 0.2); + background-image: none; +} + +flap > border, +leaflet > border, +navigation-view > border, +overlay-split-view > border { + background-color: transparent; + background-image: none; +} + +flap > shadow, +leaflet > shadow, +navigation-view > shadow, +overlay-split-view > shadow { + min-width: 56px; + min-height: 56px; +} + +flap > shadow.left, +leaflet > shadow.left, +navigation-view > shadow.left, +overlay-split-view > shadow.left { + background-image: linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to right, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +flap > shadow.right, +leaflet > shadow.right, +navigation-view > shadow.right, +overlay-split-view > shadow.right { + background-image: linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to left, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +flap > shadow.up, +leaflet > shadow.up, +navigation-view > shadow.up, +overlay-split-view > shadow.up { + background-image: linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to bottom, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +flap > shadow.down, +leaflet > shadow.down, +navigation-view > shadow.down, +overlay-split-view > shadow.down { + background-image: linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.7), alpha(rgba(30, 30, 46, 0.2), 0.14) 40px, alpha(rgba(30, 30, 46, 0.2), 0) 56px), linear-gradient(to top, alpha(rgba(30, 30, 46, 0.2), 0.4), alpha(rgba(30, 30, 46, 0.2), 0.14) 7px, alpha(rgba(30, 30, 46, 0.2), 0) 24px); +} + +.sidebar-pane { + color: #eff1f5; + border-top-left-radius: 12px; +} + +.sidebar-pane .sidebar-pane { + background-color: transparent; + color: inherit; +} + +.sidebar-pane headerbar, +.sidebar-pane .navigation-sidebar, +.sidebar-pane searchbar > revealer > box { + background-color: transparent; + box-shadow: none; + border: none; +} + +.sidebar-pane .navigation-sidebar { + padding: 2px 4px; + background: none; + color: rgba(239, 241, 245, 0.7); +} + +.sidebar-pane:dir(ltr), +.sidebar-pane:dir(ltr) banner > revealer > widget, .sidebar-pane.end:dir(rtl), +.sidebar-pane.end:dir(rtl) banner > revealer > widget { + /* box-shadow: inset 0 1px highlight($base-alt); */ + border-right: 1px solid rgba(239, 241, 245, 0.12); +} + +/* Middle pane in three-pane setups */ +.content-pane .sidebar-pane, +.sidebar-pane .content-pane { + background-color: transparent; + color: #eff1f5; +} + +.content-pane .sidebar-pane:backdrop, +.sidebar-pane .content-pane:backdrop { + background-color: transparent; + transition: none; +} + +.content-pane { + background-color: #1e1e2e; + color: #eff1f5; + border-top-right-radius: 12px; + /* box-shadow: inset 0 1px highlight($background); */ +} + +.content-pane headerbar, .content-pane headerbar:backdrop { + background-color: transparent; + box-shadow: none; + border: none; +} + +.maximized .content-pane, .fullscreen .content-pane, .tiled .content-pane, .tiled-top .content-pane, .tiled-right .content-pane, .tiled-bottom .content-pane, .tiled-left .content-pane { + border-radius: 0; + box-shadow: inset 0 1px rgba(239, 241, 245, 0.1); +} + +.top-bar { + box-shadow: none; + background: none; + border: none; +} + +.top-bar headerbar, .top-bar headerbar:backdrop { + background-color: transparent; + box-shadow: none; +} + +.top-bar .collapse-spacing { + padding: 0; +} + +themeselector, +panelthemeselector { + margin: 9px; +} + +themeselector checkbutton, +panelthemeselector checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.12); +} + +themeselector checkbutton.follow:checked, themeselector checkbutton.light:checked, themeselector checkbutton.dark:checked, +panelthemeselector checkbutton.follow:checked, +panelthemeselector checkbutton.light:checked, +panelthemeselector checkbutton.dark:checked { + box-shadow: inset 0 0 0 2px #89b4fa; +} + +themeselector checkbutton.follow, +panelthemeselector checkbutton.follow { + background-image: linear-gradient(to bottom right, #eff1f5 50%, #292c3c 50%); +} + +themeselector checkbutton.light, +panelthemeselector checkbutton.light { + background-color: #eff1f5; +} + +themeselector checkbutton.dark, +panelthemeselector checkbutton.dark { + background-color: #292c3c; +} + +themeselector checkbutton.theme-selector radio, +panelthemeselector checkbutton.theme-selector radio { + -gtk-icon-source: none; + border: none; + background: none; + box-shadow: none; + min-height: 20px; + min-width: 20px; + padding: 0; +} + +themeselector checkbutton.theme-selector radio:hover, themeselector checkbutton.theme-selector radio:active, themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:hover, +panelthemeselector checkbutton.theme-selector radio:active, +panelthemeselector checkbutton.theme-selector radio:checked { + background-color: transparent; +} + +themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked { + -gtk-icon-size: 20px; + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +themeselector checkbutton.theme-selector radio:checked, themeselector checkbutton.theme-selector radio:checked:hover, themeselector checkbutton.theme-selector radio:checked:active, +panelthemeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked:hover, +panelthemeselector checkbutton.theme-selector radio:checked:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher { + padding: 6px; +} + +themeswitcher .check { + min-height: 20px; + min-width: 20px; + background: none; + padding: 0; + margin: 0; + border-radius: 9999px; + color: rgba(30, 30, 46, 0.87); + background-color: #89b4fa; +} + +themeswitcher .check, themeswitcher .check:hover, themeswitcher .check:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(239, 241, 245, 0.12); +} + +themeswitcher checkbutton:checked { + box-shadow: inset 0 0 0 2px #89b4fa; +} + +themeswitcher checkbutton radio, themeswitcher checkbutton radio:hover, themeswitcher checkbutton radio:active, themeswitcher checkbutton radio:checked, themeswitcher checkbutton radio:checked:hover, themeswitcher checkbutton radio:checked:active { + background-color: transparent; + border: none; + background: none; + box-shadow: none; + color: transparent; + -gtk-icon-source: none; + -gtk-icon-size: 0; +} + +themeswitcher checkbutton.system { + background: linear-gradient(-45deg, #1e1e2e 50%, #eff1f5 50%); +} + +themeswitcher checkbutton.light { + color: alpha(black, 0.8); + background-color: #eff1f5; +} + +themeswitcher checkbutton.dark { + color: #eff1f5; + background-color: #1e1e2e; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #eff1f5; +/* text color for entries, views and content in general */ +@define-color theme_text_color #eff1f5; +/* widget base background color */ +@define-color theme_bg_color #1e1e2e; +/* text widgets and the like base background color */ +@define-color theme_base_color #313244; +/* base background color of selections */ +@define-color theme_selected_bg_color #89b4fa; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(30, 30, 46, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #1e1e2e; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(239, 241, 245, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #313244; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #eff1f5; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #eff1f5; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #1e1e2e; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #313244; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #89b4fa; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(30, 30, 46, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(239, 241, 245, 0.5); +/* widgets main borders color */ +@define-color borders rgba(239, 241, 245, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(239, 241, 245, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #df8e1d; +@define-color error_color #d20f39; +@define-color success_color #40a02b; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #eff1f5; +@define-color wm_unfocused_title rgba(239, 241, 245, 0.7); +@define-color wm_highlight rgba(239, 241, 245, 0.1); +@define-color wm_border #0a0a0e; +@define-color wm_focused_bg #1e1e2e; +@define-color wm_unfocused_bg #1e1e2e; +@define-color wm_button_icon #eff1f5; +@define-color wm_button_focused_bg #2b2b3a; +@define-color wm_button_unfocused_bg #2b2b3a; +@define-color wm_button_hover_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_active_fg rgba(30, 30, 46, 0.87); +@define-color wm_button_hover_bg #e6e9ef; +@define-color wm_button_active_bg #e7eaf0; +/* FIXME this is really an API */ +@define-color content_view_bg #313244; +@define-color placeholder_text_color #b6b8c0; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #313244; +@define-color budgie_tasklist_indicator_color rgba(121, 122, 133, 0.7); +@define-color budgie_tasklist_indicator_color_active #89b4fa; +@define-color budgie_tasklist_indicator_color_active_window rgba(108, 140, 195, 0.816); +@define-color budgie_tasklist_indicator_color_attention #df8e1d; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; +@define-color blue_1 #99c1f1; +@define-color blue_2 #62a0ea; +@define-color blue_3 #3584e4; +@define-color blue_4 #1c71d8; +@define-color blue_5 #1a5fb4; +@define-color green_1 #8ff0a4; +@define-color green_2 #57e389; +@define-color green_3 #33d17a; +@define-color green_4 #2ec27e; +@define-color green_5 #26a269; +@define-color yellow_1 #f9f06b; +@define-color yellow_2 #f8e45c; +@define-color yellow_3 #f6d32d; +@define-color yellow_4 #f5c211; +@define-color yellow_5 #e5a50a; +@define-color orange_1 #ffbe6f; +@define-color orange_2 #ffa348; +@define-color orange_3 #ff7800; +@define-color orange_4 #e66100; +@define-color orange_5 #c64600; +@define-color red_1 #f66151; +@define-color red_2 #ed333b; +@define-color red_3 #e01b24; +@define-color red_4 #c01c28; +@define-color red_5 #a51d2d; +@define-color purple_1 #dc8add; +@define-color purple_2 #c061cb; +@define-color purple_3 #9141ac; +@define-color purple_4 #813d9c; +@define-color purple_5 #613583; +@define-color brown_1 #cdab8f; +@define-color brown_2 #b5835a; +@define-color brown_3 #986a44; +@define-color brown_4 #865e3c; +@define-color brown_5 #63452c; +@define-color light_1 #ffffff; +@define-color light_2 #f6f5f4; +@define-color light_3 #deddda; +@define-color light_4 #c0bfbc; +@define-color light_5 #9a9996; +@define-color dark_1 #77767b; +@define-color dark_2 #5e5c64; +@define-color dark_3 #3d3846; +@define-color dark_4 #241f31; +@define-color dark_5 #000000; +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +@define-color accent_bg_color #89b4fa; +@define-color accent_fg_color rgba(30, 30, 46, 0.87); +@define-color accent_color #89b4fa; +@define-color destructive_bg_color #d20f39; +@define-color destructive_fg_color #eff1f5; +@define-color destructive_color #d20f39; +@define-color success_bg_color #40a02b; +@define-color success_fg_color #eff1f5; +@define-color success_color #40a02b; +@define-color warning_bg_color #df8e1d; +@define-color warning_fg_color #eff1f5; +@define-color warning_color #df8e1d; +@define-color error_bg_color #d20f39; +@define-color error_fg_color #eff1f5; +@define-color error_color #d20f39; +@define-color window_bg_color #1e1e2e; +@define-color window_fg_color #eff1f5; +@define-color view_bg_color #313244; +@define-color view_fg_color #eff1f5; +@define-color headerbar_bg_color #1e1e2e; +@define-color headerbar_fg_color #eff1f5; +@define-color headerbar_border_color rgba(239, 241, 245, 0.12); +@define-color headerbar_backdrop_color #1e1e2e; +@define-color headerbar_shade_color rgba(239, 241, 245, 0.12); +@define-color card_bg_color #313244; +@define-color card_fg_color #eff1f5; +@define-color card_shade_color rgba(239, 241, 245, 0.12); +@define-color dialog_bg_color #313244; +@define-color dialog_fg_color #eff1f5; +@define-color popover_bg_color #292c3c; +@define-color popover_fg_color #eff1f5; +@define-color shade_color rgba(239, 241, 245, 0.12); +@define-color scrollbar_outline_color rgba(239, 241, 245, 0.12); diff --git a/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/thumbnail.png b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/thumbnail.png new file mode 100755 index 0000000..3cd7c7c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/gtk-4.0/thumbnail.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/index.theme b/local/share/themes/Catppuccin-B-LB-Dark/index.theme new file mode 100755 index 0000000..33734ce --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/index.theme @@ -0,0 +1,12 @@ +Type=X-GNOME-Metatheme +[Desktop Entry] +Name=Catppuccin-B-LB-Dark +Comment=An Flat Gtk+ theme based on Elegant Design +Encoding=UTF-8 + +[X-GNOME-Metatheme] +GtkTheme=Catppuccin-B-LB-Dark +MetacityTheme=Catppuccin-B-LB-Dark +IconTheme=Tela-circle-Dark +CursorTheme=Catppuccin-B-LB-cursors +ButtonLayout=close,minimize,maximize:menu diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/button.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/button.svg new file mode 100755 index 0000000..c2a738d --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/button.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/close.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/close.svg new file mode 100755 index 0000000..fb798d7 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/close.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/maximize.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/maximize.svg new file mode 100755 index 0000000..0c2f170 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/maximize.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/menu.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/menu.svg new file mode 100755 index 0000000..179ff4c --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/menu.svg @@ -0,0 +1,40 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/minimize.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/minimize.svg new file mode 100755 index 0000000..76fe7cb --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/minimize.svg @@ -0,0 +1,47 @@ + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/shade.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/shade.svg new file mode 100755 index 0000000..8213b03 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/shade.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unmaximize.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unmaximize.svg new file mode 100755 index 0000000..8d60a57 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unmaximize.svg @@ -0,0 +1,67 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unshade.svg b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unshade.svg new file mode 100755 index 0000000..a161564 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/assets/unshade.svg @@ -0,0 +1,38 @@ + + + + + + diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-1.xml b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-1.xml new file mode 120000 index 0000000..562ac74 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-1.xml @@ -0,0 +1 @@ +metacity-theme-3.xml \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-2.xml b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-2.xml new file mode 120000 index 0000000..562ac74 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-2.xml @@ -0,0 +1 @@ +metacity-theme-3.xml \ No newline at end of file diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-3.xml b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-3.xml new file mode 100755 index 0000000..250a8fa --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/metacity-theme-3.xml @@ -0,0 +1,820 @@ + + + + Tokyonight + vinceliucie | mod: fkorpsvart + GPL + 2024 + Tokyonight Metacity theme + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <title version=">= 3.1" + x="(0 `max` ((frame_x_center - title_width / 2) `min` (width - title_width)))" + y="(0 `max` ((height - title_height) / 2))" + ellipsize_width="width" + color="C_title_focused"/> +</draw_ops> + +<draw_ops name="title_unfocused"> + <title version="< 3.1" + x="(0 `max` ((width - title_width) / 2))" + y="(0 `max` ((height - title_height) / 2))" + color="C_title_unfocused"/> + <title version=">= 3.1" + x="(0 `max` ((frame_x_center - title_width / 2) `min` (width - title_width)))" + y="(0 `max` ((height - title_height) / 2))" + ellipsize_width="width" + color="C_title_unfocused"/> +</draw_ops> + +<!-- window decorations --> + +<draw_ops name="entire_background_focused"> + <rectangle color="C_titlebar_focused" x="0" y="0" width="width" height="height" filled="true"/> +</draw_ops> + +<draw_ops name="entire_background_unfocused"> + <rectangle color="C_titlebar_unfocused" x="0" y="0" width="width" height="height" filled="true"/> +</draw_ops> + +<draw_ops name="titlebar_focused"> + <include name="entire_background_focused"/> +</draw_ops> + +<draw_ops name="titlebar_unfocused"> + <include name="entire_background_unfocused"/> +</draw_ops> + +<draw_ops name="rounded_border_focused"> + <line color="C_border_focused" x1="12" y1="0" x2="width-13" y2="0" /> + <line color="C_border_focused" x1="0" y1="height-1" x2="width-1" y2="height-1" /> + <line color="C_border_focused" x1="0" y1="12" x2="0" y2="height-2" /> + <line color="C_border_focused" x1="width-1" y1="12" x2="width-1" y2="height-2" /> + <arc color="C_border_focused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_focused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <!-- double arcs for darker borders --> + <arc color="C_border_focused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_focused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <line color="C_highlight_focused" x1="13" y1="1" x2="width - 14" y2="1"/> + <arc color="C_highlight_focused" x="0" y="1" width="25" height="25" start_angle="270" extent_angle="90"/> + <arc color="C_highlight_focused" x="width - 26" y="1" width="25" height="25" start_angle="0" extent_angle="90"/> +</draw_ops> + +<draw_ops name="rounded_border_unfocused"> + <line color="C_border_unfocused" x1="12" y1="0" x2="width-13" y2="0" /> + <line color="C_border_unfocused" x1="0" y1="height-1" x2="width-1" y2="height-1" /> + <line color="C_border_unfocused" x1="0" y1="12" x2="0" y2="height-2" /> + <line color="C_border_unfocused" x1="width-1" y1="12" x2="width-1" y2="height-2" /> + <arc color="C_border_unfocused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_unfocused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <!-- double arcs for darker borders --> + <arc color="C_border_unfocused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_unfocused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <line color="C_highlight_unfocused" x1="13" y1="1" x2="width - 14" y2="1"/> + <arc color="C_highlight_unfocused" x="0" y="1" width="25" height="25" start_angle="270" extent_angle="90"/> + <arc color="C_highlight_unfocused" x="width - 26" y="1" width="25" height="25" start_angle="0" extent_angle="90"/> +</draw_ops> + +<!-- button icons --> + +<draw_ops name="windows_button_focused"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.1" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_focused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.15" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_focused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.2" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_unfocused"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.06" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_unfocused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.1" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_unfocused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.15" colorize="C_title_focused"/> +</draw_ops> + +<!-- close --> + +<draw_ops name="windows_close_icon_focused"> + <image filename="assets/close.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_close_icon_unfocused"> + <image filename="assets/close.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="close_focused"> + <include name="windows_close_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="close_focused_prelight"> + <include name="windows_close_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="close_focused_pressed"> + <include name="windows_close_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="close_unfocused"> + <include name="windows_close_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="close_unfocused_prelight"> + <include name="windows_close_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="close_unfocused_pressed"> + <include name="windows_close_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- maximize --> + +<draw_ops name="windows_maximize_icon_focused"> + <image filename="assets/maximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_maximize_icon_unfocused"> + <image filename="assets/maximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="maximize_focused"> + <include name="windows_maximize_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="maximize_focused_prelight"> + <include name="windows_maximize_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="maximize_focused_pressed"> + <include name="windows_maximize_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="maximize_unfocused"> + <include name="windows_maximize_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="maximize_unfocused_prelight"> + <include name="windows_maximize_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="maximize_unfocused_pressed"> + <include name="windows_maximize_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- unmaximize --> + +<draw_ops name="windows_unmaximize_icon_focused"> + <image filename="assets/unmaximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_unmaximize_icon_unfocused"> + <image filename="assets/unmaximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="unmaximize_focused"> + <include name="windows_unmaximize_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="unmaximize_focused_prelight"> + <include name="windows_unmaximize_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="unmaximize_focused_pressed"> + <include name="windows_unmaximize_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="unmaximize_unfocused"> + <include name="windows_unmaximize_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="unmaximize_unfocused_prelight"> + <include name="windows_unmaximize_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="unmaximize_unfocused_pressed"> + <include name="windows_unmaximize_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- minimize --> + +<draw_ops name="windows_minimize_icon_focused"> + <image filename="assets/minimize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_minimize_icon_unfocused"> + <image filename="assets/minimize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="minimize_focused"> + <include name="windows_minimize_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="minimize_focused_prelight"> + <include name="windows_minimize_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="minimize_focused_pressed"> + <include name="windows_minimize_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="minimize_unfocused"> + <include name="windows_minimize_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="minimize_unfocused_prelight"> + <include name="windows_minimize_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="minimize_unfocused_pressed"> + <include name="windows_minimize_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- menu --> + +<draw_ops name="menu_focused"> + <image filename="assets/menu.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="menu_focused_prelight"> + <include name="menu_focused"/> +</draw_ops> + +<draw_ops name="menu_focused_pressed"> + <include name="menu_focused"/> +</draw_ops> + +<draw_ops name="menu_unfocused"> + <image filename="assets/menu.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="menu_unfocused_prelight"> + <include name="menu_unfocused"/> +</draw_ops> + +<draw_ops name="menu_unfocused_pressed"> + <include name="menu_unfocused"/> +</draw_ops> + +<!-- shade --> + +<draw_ops name="shade_focused"> + <image filename="assets/shade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="shade_focused_prelight"> + <include name="shade_focused"/> +</draw_ops> + +<draw_ops name="shade_focused_pressed"> + <include name="shade_focused"/> +</draw_ops> + +<draw_ops name="shade_unfocused"> + <image filename="assets/shade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="shade_unfocused_prelight"> + <include name="shade_unfocused"/> +</draw_ops> + +<draw_ops name="shade_unfocused_pressed"> + <include name="shade_unfocused"/> +</draw_ops> + +<!-- unshade --> + +<draw_ops name="unshade_focused"> + <image filename="assets/unshade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="unshade_focused_prelight"> + <include name="unshade_focused"/> +</draw_ops> + +<draw_ops name="unshade_focused_pressed"> + <include name="unshade_focused"/> +</draw_ops> + +<draw_ops name="unshade_unfocused"> + <image filename="assets/unshade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="unshade_unfocused_prelight"> + <include name="unshade_unfocused"/> +</draw_ops> + +<draw_ops name="unshade_unfocused_pressed"> + <include name="unshade_unfocused"/> +</draw_ops> + +<!-- appmenu --> + +<constant name="D_appmenu_icon_size" value="16"/> + +<draw_ops name="appmenu_focused"> + <icon + x="(width - D_appmenu_icon_size) / 2" y="(height - D_appmenu_icon_size) / 2" + width="D_appmenu_icon_size" height="D_appmenu_icon_size"/> +</draw_ops> + +<draw_ops name="appmenu_focused_prelight"> + <include name="appmenu_focused"/> +</draw_ops> + +<draw_ops name="appmenu_focused_pressed"> + <include name="appmenu_focused"/> +</draw_ops> + +<draw_ops name="appmenu_unfocused"> + <icon + x="(width - D_appmenu_icon_size) / 2" y="(height - D_appmenu_icon_size) / 2" + width="D_appmenu_icon_size" height="D_appmenu_icon_size" + alpha="0.7"/> +</draw_ops> + +<draw_ops name="appmenu_unfocused_prelight"> + <include name="appmenu_unfocused"/> +</draw_ops> + +<draw_ops name="appmenu_unfocused_pressed"> + <include name="appmenu_unfocused"/> +</draw_ops> + +<!-- button backgrounds --> + +<draw_ops name="button_focused"> +</draw_ops> + +<draw_ops name="button_focused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.08" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="button_focused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.2" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="button_unfocused"> +</draw_ops> + +<draw_ops name="button_unfocused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.08" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="button_unfocused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.2" colorize="C_title_unfocused"/> +</draw_ops> + +<!-- frame styles --> + +<frame_style name="normal_focused" geometry="normal"> + <piece position="entire_background" draw_ops="entire_background_focused"/> + <piece position="titlebar" draw_ops="titlebar_focused"/> + <piece position="title" draw_ops="title_focused"/> + <piece position="overlay" draw_ops="rounded_border_focused"/> + <button function="close" state="normal" draw_ops="close_focused"/> + <button function="close" state="prelight" draw_ops="close_focused_prelight"/> + <button function="close" state="pressed" draw_ops="close_focused_pressed"/> + <button function="maximize" state="normal" draw_ops="maximize_focused"/> + <button function="maximize" state="prelight" draw_ops="maximize_focused_prelight"/> + <button function="maximize" state="pressed" draw_ops="maximize_focused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_focused"/> + <button function="minimize" state="prelight" draw_ops="minimize_focused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_focused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_focused"/> + <button function="menu" state="prelight" draw_ops="menu_focused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_focused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_focused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_focused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_focused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_focused"/> + <button function="shade" state="prelight" draw_ops="shade_focused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_focused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_focused"/> + <button function="unshade" state="prelight" draw_ops="unshade_focused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_focused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_focused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_focused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="normal_unfocused" geometry="normal"> + <piece position="entire_background" draw_ops="entire_background_unfocused"/> + <piece position="titlebar" draw_ops="titlebar_unfocused"/> + <piece position="title" draw_ops="title_unfocused"/> + <piece position="overlay" draw_ops="rounded_border_unfocused"/> + <button function="close" state="normal" draw_ops="close_unfocused"/> + <button function="close" state="prelight" draw_ops="close_unfocused_prelight"/> + <button function="close" state="pressed" draw_ops="close_unfocused_pressed"/> + <button function="maximize" state="normal" draw_ops="maximize_unfocused"/> + <button function="maximize" state="prelight" draw_ops="maximize_unfocused_prelight"/> + <button function="maximize" state="pressed" draw_ops="maximize_unfocused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_unfocused"/> + <button function="minimize" state="prelight" draw_ops="minimize_unfocused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_unfocused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_unfocused"/> + <button function="menu" state="prelight" draw_ops="menu_unfocused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_unfocused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_unfocused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_unfocused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_unfocused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_unfocused"/> + <button function="shade" state="prelight" draw_ops="shade_unfocused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_unfocused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_unfocused"/> + <button function="unshade" state="prelight" draw_ops="unshade_unfocused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_unfocused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="normal_max_focused" geometry="max"> + <piece position="entire_background" draw_ops="entire_background_focused"/> + <piece position="titlebar" draw_ops="titlebar_focused"/> + <piece position="title" draw_ops="title_focused"/> + <button function="close" state="normal" draw_ops="close_focused"/> + <button function="close" state="prelight" draw_ops="close_focused_prelight"/> + <button function="close" state="pressed" draw_ops="close_focused_pressed"/> + <button function="maximize" state="normal" draw_ops="unmaximize_focused"/> + <button function="maximize" state="prelight" draw_ops="unmaximize_focused_prelight"/> + <button function="maximize" state="pressed" draw_ops="unmaximize_focused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_focused"/> + <button function="minimize" state="prelight" draw_ops="minimize_focused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_focused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_focused"/> + <button function="menu" state="prelight" draw_ops="menu_focused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_focused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_focused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_focused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_focused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_focused"/> + <button function="shade" state="prelight" draw_ops="shade_focused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_focused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_focused"/> + <button function="unshade" state="prelight" draw_ops="unshade_focused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_focused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_focused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_focused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="normal_max_unfocused" geometry="max"> + <piece position="entire_background" draw_ops="entire_background_unfocused"/> + <piece position="titlebar" draw_ops="titlebar_unfocused"/> + <piece position="title" draw_ops="title_unfocused"/> + <button function="close" state="normal" draw_ops="close_unfocused"/> + <button function="close" state="prelight" draw_ops="close_unfocused_prelight"/> + <button function="close" state="pressed" draw_ops="close_unfocused_pressed"/> + <button function="maximize" state="normal" draw_ops="unmaximize_unfocused"/> + <button function="maximize" state="prelight" draw_ops="unmaximize_unfocused_prelight"/> + <button function="maximize" state="pressed" draw_ops="unmaximize_unfocused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_unfocused"/> + <button function="minimize" state="prelight" draw_ops="minimize_unfocused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_unfocused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_unfocused"/> + <button function="menu" state="prelight" draw_ops="menu_unfocused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_unfocused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_unfocused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_unfocused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_unfocused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_unfocused"/> + <button function="shade" state="prelight" draw_ops="shade_unfocused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_unfocused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_unfocused"/> + <button function="unshade" state="prelight" draw_ops="unshade_unfocused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_unfocused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="tiled_left_focused" geometry="tiled_left" parent="normal_max_focused"> + <piece position="titlebar" draw_ops="entire_background_focused"/> +</frame_style> + +<frame_style name="tiled_left_unfocused" geometry="tiled_left" parent="normal_max_unfocused"> + <piece position="titlebar" draw_ops="entire_background_unfocused"/> +</frame_style> + +<frame_style name="tiled_right_focused" geometry="tiled_right" parent="normal_max_focused"> + <piece position="titlebar" draw_ops="entire_background_focused"/> +</frame_style> + +<frame_style name="tiled_right_unfocused" geometry="tiled_right" parent="normal_max_unfocused"> + <piece position="titlebar" draw_ops="entire_background_unfocused"/> +</frame_style> + +<frame_style name="dialog_focused" geometry="modal" parent="normal_focused"> +</frame_style> + +<frame_style name="dialog_unfocused" geometry="modal" parent="normal_unfocused"> +</frame_style> + +<frame_style name="modal_dialog_focused" geometry="modal" parent="normal_focused"> +</frame_style> + +<frame_style name="modal_dialog_unfocused" geometry="modal" parent="normal_unfocused"> +</frame_style> + +<frame_style name="utility_focused" geometry="small" parent="normal_focused"> +</frame_style> + +<frame_style name="utility_unfocused" geometry="small" parent="normal_unfocused"> +</frame_style> + +<frame_style name="border_focused" geometry="border" parent="normal_focused"> +</frame_style> + +<frame_style name="border_unfocused" geometry="border" parent="normal_unfocused"> +</frame_style> + +<frame_style name="borderless_focused" geometry="borderless" parent="normal_focused"> +</frame_style> + +<frame_style name="borderless_unfocused" geometry="borderless" parent="normal_unfocused"> +</frame_style> + +<frame_style name="attached_focused" geometry="attached" parent="modal_dialog_focused"> +</frame_style> + +<frame_style name="attached_unfocused" geometry="attached" parent="modal_dialog_unfocused"> +</frame_style> + +<!-- placeholder for unimplementated styles--> + +<frame_style name="blank" geometry="normal"> + <button function="close" state="normal"><draw_ops></draw_ops></button> + <button function="close" state="pressed"><draw_ops></draw_ops></button> + <button function="maximize" state="normal"><draw_ops></draw_ops></button> + <button function="maximize" state="pressed"><draw_ops></draw_ops></button> + <button function="minimize" state="normal"><draw_ops></draw_ops></button> + <button function="minimize" state="pressed"><draw_ops></draw_ops></button> + <button function="menu" state="normal"><draw_ops></draw_ops></button> + <button function="menu" state="pressed"><draw_ops></draw_ops></button> + <button version=">= 3.5" function="appmenu" state="normal"><draw_ops></draw_ops></button> + <button version=">= 3.5" function="appmenu" state="pressed"><draw_ops></draw_ops></button> + <button function="shade" state="normal"><draw_ops></draw_ops></button> + <button function="shade" state="pressed"><draw_ops></draw_ops></button> + <button function="unshade" state="normal"><draw_ops></draw_ops></button> + <button function="unshade" state="pressed"><draw_ops></draw_ops></button> + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<!-- frame style sets --> + +<frame_style_set name="normal_style_set"> + <frame focus="yes" state="normal" resize="both" style="normal_focused"/> + <frame focus="no" state="normal" resize="both" style="normal_unfocused"/> + <frame focus="yes" state="maximized" style="normal_max_focused"/> + <frame focus="no" state="maximized" style="normal_max_unfocused"/> + <frame focus="yes" state="shaded" style="normal_focused"/> + <frame focus="no" state="shaded" style="normal_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="normal_max_focused"/> + <frame focus="no" state="maximized_and_shaded" style="normal_max_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_left" style="tiled_left_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_left" style="tiled_left_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_right" style="tiled_right_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_right" style="tiled_right_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_left_and_shaded" style="tiled_left_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_left_and_shaded" style="tiled_left_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_right_and_shaded" style="tiled_right_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_right_and_shaded" style="tiled_right_unfocused"/> +</frame_style_set> + +<frame_style_set name="dialog_style_set"> + <frame focus="yes" state="normal" resize="both" style="dialog_focused"/> + <frame focus="no" state="normal" resize="both" style="dialog_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="dialog_focused"/> + <frame focus="no" state="shaded" style="dialog_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="modal_dialog_style_set"> + <frame focus="yes" state="normal" resize="both" style="modal_dialog_focused"/> + <frame focus="no" state="normal" resize="both" style="modal_dialog_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="modal_dialog_focused"/> + <frame focus="no" state="shaded" style="modal_dialog_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="utility_style_set"> + <frame focus="yes" state="normal" resize="both" style="utility_focused"/> + <frame focus="no" state="normal" resize="both" style="utility_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="utility_focused"/> + <frame focus="no" state="shaded" style="utility_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="border_style_set"> + <frame focus="yes" state="normal" resize="both" style="border_focused"/> + <frame focus="no" state="normal" resize="both" style="border_unfocused"/> + <frame focus="yes" state="maximized" style="borderless_focused"/> + <frame focus="no" state="maximized" style="borderless_unfocused"/> + <frame focus="yes" state="shaded" style="blank"/> + <frame focus="no" state="shaded" style="blank"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="attached_style_set"> + <frame focus="yes" state="normal" resize="both" style="attached_focused"/> + <frame focus="no" state="normal" resize="both" style="attached_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="blank"/> + <frame focus="no" state="shaded" style="blank"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<!-- windows --> + +<window type="normal" style_set="normal_style_set"/> +<window type="dialog" style_set="dialog_style_set"/> +<window type="modal_dialog" style_set="modal_dialog_style_set"/> +<window type="menu" style_set="utility_style_set"/> +<window type="utility" style_set="utility_style_set"/> +<window type="border" style_set="border_style_set"/> +<window version=">= 3.2" type="attached" style_set="attached_style_set"/> + +</metacity_theme> diff --git a/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/thumbnail.png b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/thumbnail.png new file mode 100755 index 0000000..6d1abe6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/metacity-1/thumbnail.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/plank/dock.theme b/local/share/themes/Catppuccin-B-LB-Dark/plank/dock.theme new file mode 100755 index 0000000..b080f12 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/plank/dock.theme @@ -0,0 +1,64 @@ +#This file based on: +#https://git.launchpad.net/plank/tree/data/themes/Default/dock.theme + +[PlankTheme] +#The roundness of the top corners. +TopRoundness=15 +#The roundness of the bottom corners. +BottomRoundness=15 +#The thickness (in pixels) of lines drawn. +LineWidth=1 +#The color (RGBA) of the outer stroke. +OuterStrokeColor=166;;173;;200;;50 +#The starting color (RGBA) of the fill gradient. +FillStartColor=30;;30;;46;;200 +#The ending color (RGBA) of the fill gradient. +FillEndColor=30;;30;;46;;200 +#The color (RGBA) of the inner stroke. +InnerStrokeColor=30;;30;;46;;100 + +[PlankDockTheme] +#The padding on the left/right dock edges, in tenths of a percent of IconSize. +HorizPadding=2 +#The padding on the top dock edge, in tenths of a percent of IconSize. +TopPadding=2 +#The padding on the bottom dock edge, in tenths of a percent of IconSize. +BottomPadding=1 +#The padding between items on the dock, in tenths of a percent of IconSize. +ItemPadding=2 +#The size of item indicators, in tenths of a percent of IconSize. +IndicatorSize=5 +#The size of the icon-shadow behind every item, in tenths of a percent of IconSize. +IconShadowSize=0 +#The height (in percent of IconSize) to bounce an icon when the application sets urgent. +UrgentBounceHeight=1.6666666666666667 +#The height (in percent of IconSize) to bounce an icon when launching an application. +LaunchBounceHeight=0.625 +#The opacity value (0 to 1) to fade the dock to when hiding it. +FadeOpacity=1 +#The amount of time (in ms) for click animations. +ClickTime=0 +#The amount of time (in ms) to bounce an urgent icon. +UrgentBounceTime=600 +#The amount of time (in ms) to bounce an icon when launching an application. +LaunchBounceTime=600 +#The amount of time (in ms) for active window indicator animations. +ActiveTime=150 +#The amount of time (in ms) to slide icons into/out of the dock. +SlideTime=300 +#The time (in ms) to fade the dock in/out on a hide (if FadeOpacity is < 1). +FadeTime=250 +#The time (in ms) to slide the dock in/out on a hide (if FadeOpacity is 1). +HideTime=250 +#The size of the urgent glow (shown when dock is hidden), in tenths of a percent of IconSize. +GlowSize=30 +#The total time (in ms) to show the hidden-dock urgent glow. +GlowTime=10000 +#The time (in ms) of each pulse of the hidden-dock urgent glow. +GlowPulseTime=2000 +#The hue-shift (-180 to 180) of the urgent indicator color. +UrgentHueShift=150 +#The time (in ms) to move an item to its new position or its addition/removal to/from the dock. +ItemMoveTime=450 +#Whether background and icons will unhide/hide with different speeds. The top-border of both will leave/hit the screen-edge at the same time. +CascadeHide=true diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-active.png new file mode 100755 index 0000000..6325e7c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-inactive.png new file mode 100755 index 0000000..04469cb Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-active.png new file mode 100755 index 0000000..c4cdbc5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-inactive.png new file mode 100755 index 0000000..b57db90 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-left-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-active.png new file mode 100755 index 0000000..8e149b5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-inactive.png new file mode 100755 index 0000000..15e720d Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/bottom-right-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-active.png new file mode 100755 index 0000000..dec36d7 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-inactive.png new file mode 100755 index 0000000..7cf1754 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-prelight.png new file mode 100755 index 0000000..cd27068 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-pressed.png new file mode 100755 index 0000000..7d5ff1d Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/close-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-active.png new file mode 100755 index 0000000..220debb Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-inactive.png new file mode 100755 index 0000000..6068159 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-prelight.png new file mode 100755 index 0000000..dc0b11f Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-pressed.png new file mode 100755 index 0000000..e1c90d9 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/hide-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-active.png new file mode 100755 index 0000000..52a83fd Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-inactive.png new file mode 100755 index 0000000..64c26e3 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/left-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-active.png new file mode 100755 index 0000000..a637c12 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-inactive.png new file mode 100755 index 0000000..334788a Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-prelight.png new file mode 100755 index 0000000..98e1e63 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-pressed.png new file mode 100755 index 0000000..0c6348e Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-active.png new file mode 100755 index 0000000..2f8ec07 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-inactive.png new file mode 100755 index 0000000..ef3755d Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-prelight.png new file mode 100755 index 0000000..cd01e4d Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-pressed.png new file mode 100755 index 0000000..a9332f6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/maximize-toggled-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-active.png new file mode 100755 index 0000000..b101bc6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-inactive.png new file mode 100755 index 0000000..65901d3 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-prelight.png new file mode 100755 index 0000000..aa31796 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-pressed.png new file mode 100755 index 0000000..8489ec6 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/menu-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-active.png new file mode 100755 index 0000000..c908af8 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-inactive.png new file mode 100755 index 0000000..64c26e3 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/right-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-active.png new file mode 100755 index 0000000..f84ebc7 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-inactive.png new file mode 100755 index 0000000..b611edf Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-prelight.png new file mode 100755 index 0000000..673ed11 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-pressed.png new file mode 100755 index 0000000..a79898d Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-active.png new file mode 100755 index 0000000..0587c93 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-inactive.png new file mode 100755 index 0000000..99382e2 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-prelight.png new file mode 100755 index 0000000..de2bb88 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-pressed.png new file mode 100755 index 0000000..fbf4c53 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/shade-toggled-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-active.png new file mode 100755 index 0000000..1d7267a Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-inactive.png new file mode 100755 index 0000000..4e52d12 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-prelight.png new file mode 100755 index 0000000..0a54e2a Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-pressed.png new file mode 100755 index 0000000..6c3cfc5 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-active.png new file mode 100755 index 0000000..ee34b3b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-inactive.png new file mode 100755 index 0000000..7ae318c Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-prelight.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-prelight.png new file mode 100755 index 0000000..5febc8a Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-prelight.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-pressed.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-pressed.png new file mode 100755 index 0000000..0545cc1 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/stick-toggled-pressed.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/themerc b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/themerc new file mode 100755 index 0000000..22732f3 --- /dev/null +++ b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/themerc @@ -0,0 +1,23 @@ +button_offset=6 +button_spacing=0 + +show_app_icon=false + +full_width_title=true + +title_shadow_active=false +title_shadow_inactive=false + +title_horizontal_offset=3 + +active_text_color=#f0f7fe +active_text_shadow_color=#222426 + +inactive_text_color=#999da3 +inactive_text_shadow_color=#222426 + +shadow_delta_height=2 +shadow_delta_width=0 +shadow_delta_x=0 +shadow_delta_y=-5 +shadow_opacity=40 diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-active.png new file mode 100755 index 0000000..596f8e4 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-inactive.png new file mode 100755 index 0000000..290ae0b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-1-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-active.png new file mode 100755 index 0000000..596f8e4 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-inactive.png new file mode 100755 index 0000000..290ae0b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-2-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-active.png new file mode 100755 index 0000000..596f8e4 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-inactive.png new file mode 100755 index 0000000..290ae0b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-3-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-active.png new file mode 100755 index 0000000..596f8e4 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-inactive.png new file mode 100755 index 0000000..290ae0b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-4-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-active.png new file mode 100755 index 0000000..596f8e4 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-inactive.png new file mode 100755 index 0000000..290ae0b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/title-5-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-active.png new file mode 100755 index 0000000..a2b8acc Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-inactive.png new file mode 100755 index 0000000..c6c0653 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-left-inactive.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-active.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-active.png new file mode 100755 index 0000000..56c423b Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-active.png differ diff --git a/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-inactive.png b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-inactive.png new file mode 100755 index 0000000..285a147 Binary files /dev/null and b/local/share/themes/Catppuccin-B-LB-Dark/xfwm4/top-right-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-active.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-active.svg new file mode 100755 index 0000000..e80140c --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-active.svg @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="35" + height="200" + version="1.1" + id="svg8" + sodipodi:docname="add-workspace-active.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs12"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1168" + x="-0.102608" + y="-0.040503159" + width="1.205216" + height="1.0810063"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="3.2065" + id="feGaussianBlur1170" /> + </filter> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1174" + x="-0.147" + y="-0.147" + width="1.294" + height="1.294"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.98" + id="feGaussianBlur1176" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview10" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="3.337544" + inkscape:cx="19.175777" + inkscape:cy="88.088726" + inkscape:window-width="1835" + inkscape:window-height="977" + inkscape:window-x="102" + inkscape:window-y="102" + inkscape:window-maximized="0" + inkscape:current-layer="svg8"> + <inkscape:grid + type="xygrid" + id="grid340" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <rect + id="rect612" + width="75" + height="190" + x="5" + y="6" + rx="8" + ry="8" + style="fill:#000000;fill-opacity:1;filter:url(#filter1168);opacity:0.25" /> + <rect + id="rect342" + width="75" + height="190" + x="5" + y="5" + rx="8" + ry="8" + style="fill:#45707a;fill-opacity:1" /> + <path + d="m 18,95 c -0.554,0 -1,0.446 -1,1 v 4 h -4 c -0.554,0 -1,0.446 -1,1 0,0.554 0.446,1 1,1 h 4 v 4 c 0,0.554 0.446,1 1,1 0.554,0 1,-0.446 1,-1 v -4 h 4 c 0.554,0 1,-0.446 1,-1 0,-0.554 -0.446,-1 -1,-1 h -4 v -4 c 0,-0.554 -0.446,-1 -1,-1 z m 8,6 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" + color="#000000" + color-rendering="auto" + fill="#ffffff" + image-rendering="auto" + solid-color="#000000" + style="isolation:auto;mix-blend-mode:normal;shape-rendering:auto;fill:#000000;filter:url(#filter1174);opacity:0.15" + id="path1172" /> + <path + d="m 18,94 c -0.554,0 -1,0.446 -1,1 v 4 h -4 c -0.554,0 -1,0.446 -1,1 0,0.554 0.446,1 1,1 h 4 v 4 c 0,0.554 0.446,1 1,1 0.554,0 1,-0.446 1,-1 v -4 h 4 c 0.554,0 1,-0.446 1,-1 0,-0.554 -0.446,-1 -1,-1 h -4 v -4 c 0,-0.554 -0.446,-1 -1,-1 z m 8,6 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" + color="#000000" + color-rendering="auto" + fill="#ffffff" + image-rendering="auto" + solid-color="#000000" + style="isolation:auto;mix-blend-mode:normal;shape-rendering:auto" + id="path4" /> + <path + id="rect607" + style="fill:#ffffff;fill-opacity:1;opacity:0.1" + d="M 13 5 C 8.5680044 5 5 8.5680044 5 13 L 5 14 C 5 9.5680044 8.5680044 6 13 6 L 72 6 C 76.431996 6 80 9.5680044 80 14 L 80 13 C 80 8.5680044 76.431996 5 72 5 L 13 5 z " /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-hover.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-hover.svg new file mode 100755 index 0000000..8a1d351 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace-hover.svg @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="35" + height="200" + id="svg2" + version="1.1" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" + sodipodi:docname="add-workspace-hover.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="4" + inkscape:cx="-81.038405" + inkscape:cy="108.58132" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1366" + inkscape:window-height="709" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + showguides="false" + inkscape:guide-bbox="true" + inkscape:snap-bbox="true" + inkscape:bbox-paths="true" + inkscape:snap-bbox-edge-midpoints="true" + inkscape:bbox-nodes="true"> + <inkscape:grid + type="xygrid" + id="grid3040" + empspacing="5" + visible="true" + enabled="true" + snapvisiblegridlinesonly="true" /> + <sodipodi:guide + orientation="0,1" + position="20,100" + id="guide3893" + inkscape:locked="false" /> + <sodipodi:guide + orientation="1,0" + position="18,190" + id="guide3895" + inkscape:locked="false" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + <cc:license + rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#Notice" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#Attribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#ShareAlike" /> + </cc:License> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-852.36218)"> + <path + id="rect4694" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.5;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 7,857.36218 28,0 0,190.00002 -28,0 c -1.108,0 -2,-0.892 -2,-2 L 5,859.36218 c 0,-1.108 0.892,-2 2,-2 z" + inkscape:connector-curvature="0" + sodipodi:nodetypes="sccssss" /> + <g + transform="translate(0,-0.9999969)" + id="g3917-7" + style="fill:#eceff1;fill-opacity:1;opacity:0.5;stroke:none;stroke-opacity:1" /> + <path + id="rect4804" + transform="translate(0,852.36218)" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 18,94 c -0.554,0 -1,0.446 -1,1 l 0,4 -4,0 c -0.554,0 -1,0.446 -1,1 0,0.554 0.446,1 1,1 l 4,0 0,4 c 0,0.554 0.446,1 1,1 0.554,0 1,-0.446 1,-1 l 0,-4 4,0 c 0.554,0 1,-0.446 1,-1 0,-0.554 -0.446,-1 -1,-1 l -4,0 0,-4 c 0,-0.554 -0.446,-1 -1,-1 z m 8,6 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" /> + </g> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace.svg new file mode 100755 index 0000000..8dba5df --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/add-workspace.svg @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="35" + height="200" + id="svg2" + version="1.1" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" + sodipodi:docname="add-workspace.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="4" + inkscape:cx="-28.526103" + inkscape:cy="75.41215" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1366" + inkscape:window-height="709" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + showguides="false" + inkscape:guide-bbox="true" + inkscape:snap-bbox="true" + inkscape:bbox-paths="true" + inkscape:snap-bbox-edge-midpoints="true" + inkscape:bbox-nodes="true" + inkscape:document-rotation="0"> + <inkscape:grid + type="xygrid" + id="grid3040" + empspacing="5" + visible="true" + enabled="true" + snapvisiblegridlinesonly="true" /> + <sodipodi:guide + orientation="0,1" + position="20,100" + id="guide3893" + inkscape:locked="false" /> + <sodipodi:guide + orientation="1,0" + position="18,190" + id="guide3895" + inkscape:locked="false" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + <cc:license + rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#Notice" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#Attribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#ShareAlike" /> + </cc:License> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-852.36218)"> + <path + id="rect4694" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.35;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 7,857.36218 28,0 0,190.00002 -28,0 c -1.108,0 -2,-0.892 -2,-2 L 5,859.36218 c 0,-1.108 0.892,-2 2,-2 z" + inkscape:connector-curvature="0" + sodipodi:nodetypes="sccssss" /> + <g + transform="translate(0,-0.9999969)" + id="g3917-7" + style="fill:#eceff1;fill-opacity:1;opacity:0.5;stroke:none;stroke-opacity:1" /> + <path + id="rect4804" + transform="translate(0,852.36218)" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.87;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 18,94 c -0.554,0 -1,0.446 -1,1 l 0,4 -4,0 c -0.554,0 -1,0.446 -1,1 0,0.554 0.446,1 1,1 l 4,0 0,4 c 0,0.554 0.446,1 1,1 0.554,0 1,-0.446 1,-1 l 0,-4 4,0 c 0.554,0 1,-0.446 1,-1 0,-0.554 -0.446,-1 -1,-1 l -4,0 0,-4 c 0,-0.554 -0.446,-1 -1,-1 z m 8,6 a 8,8 0 0 1 -8,8 8,8 0 0 1 -8,-8 8,8 0 0 1 8,-8 8,8 0 0 1 8,8 z" /> + </g> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-left.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-left.svg new file mode 100755 index 0000000..dcf8298 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-left.svg @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + id="svg4" + sodipodi:docname="calendar-arrow-left.svg" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="704" + id="namedview6" + showgrid="false" + inkscape:zoom="29.5" + inkscape:cx="13.680381" + inkscape:cy="6.1418434" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <path + d="M10 3v10L5 8z" + fill="#000000" + opacity="0.54" + id="path2" + style="fill:#e6e6e6" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-right.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-right.svg new file mode 100755 index 0000000..ed66559 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/calendar-arrow-right.svg @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + id="svg4" + sodipodi:docname="calendar-arrow-right.svg" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="704" + id="namedview6" + showgrid="false" + inkscape:zoom="14.75" + inkscape:cx="8" + inkscape:cy="8" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <path + d="M6 3v10l5-5z" + fill="#000000" + opacity="0.54" + id="path2" + style="fill:#e6e6e6" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-dark.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-dark.svg new file mode 100755 index 0000000..567b007 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-dark.svg @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg1516" + sodipodi:docname="checkbox-dark.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs1520"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1446" + x="-0.05808" + y="-0.05808" + width="1.11616" + height="1.11616"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.484" + id="feGaussianBlur1448" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview1518" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="19.666667" + inkscape:cx="15.177966" + inkscape:cy="13.677966" + inkscape:window-width="1835" + inkscape:window-height="977" + inkscape:window-x="102" + inkscape:window-y="102" + inkscape:window-maximized="0" + inkscape:current-layer="svg1516" /> + <rect + style="opacity:0.25;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter1446)" + id="rect890" + width="20" + height="20" + x="2" + y="3" + rx="4" + ry="4" /> + <rect + style="fill:#7daea3;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + id="rect616" + width="20" + height="20" + x="2" + y="2" + rx="4" + ry="4" /> + <path + id="rect340" + d="m 18.36396,7.7576861 c -0.391736,-0.3917365 -1.022477,-0.3917368 -1.414214,0 L 10.585785,14.121648 7.0502516,10.586113 c -0.3917367,-0.391737 -1.0224771,-0.391736 -1.4142135,0 -0.3917365,0.391736 -0.3917368,1.022477 0,1.414214 l 4.2426409,4.242641 c 0.02448,0.02448 0.04973,0.04625 0.07596,0.06767 0.393511,0.321347 0.971002,0.299581 1.338255,-0.06767 l 7.071068,-7.0710684 c 0.391737,-0.3917367 0.391736,-1.0224771 0,-1.4142135 z" + style="fill:#1d2021;fill-opacity:1" /> + <path + id="rect885" + style="opacity:0.1;fill:#ffffff;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + d="M 6,2 C 3.7840022,2 2,3.7840022 2,6 V 7 C 2,4.7840022 3.7840022,3 6,3 h 12 c 2.215998,0 4,1.7840022 4,4 V 6 C 22,3.7840022 20.215998,2 18,2 Z" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-off.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-off.svg new file mode 100755 index 0000000..b00efa6 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox-off.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" r="10" fill="#ffffff" opacity=".12"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox.svg new file mode 100755 index 0000000..9f5a5a7 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/checkbox.svg @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg439" + sodipodi:docname="checkbox.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs443"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1446" + x="-0.05808" + y="-0.05808" + width="1.11616" + height="1.11616"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.484" + id="feGaussianBlur1448" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview441" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="13.906433" + inkscape:cx="17.509881" + inkscape:cy="10.067283" + inkscape:window-width="1835" + inkscape:window-height="977" + inkscape:window-x="102" + inkscape:window-y="102" + inkscape:window-maximized="0" + inkscape:current-layer="svg439"> + <inkscape:grid + type="xygrid" + id="grid562" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <rect + style="opacity:0.25;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter1446)" + id="rect890" + width="20" + height="20" + x="2" + y="3" + rx="4" + ry="4" /> + <rect + style="opacity:1;fill:#45707a;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + id="rect616" + width="20" + height="20" + x="2" + y="2" + rx="4" + ry="4" /> + <path + id="rect340" + d="m 18.36396,7.7576861 c -0.391736,-0.3917365 -1.022477,-0.3917368 -1.414214,0 L 10.585785,14.121648 7.0502516,10.586113 c -0.3917367,-0.391737 -1.0224771,-0.391736 -1.4142135,0 -0.3917365,0.391736 -0.3917368,1.022477 0,1.414214 l 4.2426409,4.242641 c 0.02448,0.02448 0.04973,0.04625 0.07596,0.06767 0.393511,0.321347 0.971002,0.299581 1.338255,-0.06767 l 7.071068,-7.0710684 c 0.391737,-0.3917367 0.391736,-1.0224771 0,-1.4142135 z" + style="fill:#ffffff" /> + <path + id="rect885" + style="opacity:0.1;fill:#ffffff;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + d="M 6 2 C 3.7840022 2 2 3.7840022 2 6 L 2 7 C 2 4.7840022 3.7840022 3 6 3 L 18 3 C 20.215998 3 22 4.7840022 22 7 L 22 6 C 22 3.7840022 20.215998 2 18 2 L 6 2 z " /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-active.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-active.svg new file mode 100755 index 0000000..815d943 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-active.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + id="Foreground" + width="26" + height="26" + enable-background="new 0 0 16 16" + version="1.0" + viewBox="0 0 18.909 18.909" + sodipodi:docname="close-active.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview2" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="28.730769" + inkscape:cx="13" + inkscape:cy="12.982597" + inkscape:window-width="1867" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="Foreground" /> + <defs + id="defs1"> + <filter + id="filter839" + x="-0.047999999" + y="-0.047999999" + width="1.096" + height="1.096" + color-interpolation-filters="sRGB"> + <feGaussianBlur + stdDeviation="0.32" + id="feGaussianBlur1" /> + </filter> + </defs> + <circle + cx="9.4545" + cy="10.182" + r="8" + fill="#000000" + filter="url(#filter839)" + opacity=".1" + stroke-width="0" + id="circle1" /> + <circle + cx="9.4545" + cy="9.4545" + r="8" + fill="#d8354a" + stroke-width="0" + id="circle2" + style="fill:#ea6962;fill-opacity:1" /> + <path + d="m6.1115 5.7478c-0.092952 1e-7 -0.18588 0.035309-0.2571 0.10653-0.14245 0.14245-0.14245 0.37175 0 0.5142l3.0852 3.0866-3.0852 3.0852c-0.14245 0.14245-0.14245 0.37175 0 0.5142 0.14245 0.14245 0.37317 0.14245 0.51562 0l3.0852-3.0852 3.0852 3.0852c0.14245 0.14245 0.37175 0.14245 0.5142 0 0.14245-0.14245 0.14245-0.37175 0-0.5142l-3.0852-3.0852 3.0852-3.0866c0.14245-0.14245 0.14245-0.37175 0-0.5142-0.14245-0.14245-0.37175-0.14245-0.5142 0l-3.0852 3.0852-3.0852-3.0852c-0.071224-0.071224-0.16557-0.10653-0.25852-0.10653z" + fill="#ffffff" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="1.3606" + style="paint-order:markers stroke fill" + id="path2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-hover.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-hover.svg new file mode 100755 index 0000000..fbebd4a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close-hover.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + id="Foreground" + width="26" + height="26" + enable-background="new 0 0 16 16" + version="1.0" + viewBox="0 0 18.909 18.909" + sodipodi:docname="close-hover.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview2" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="28.730769" + inkscape:cx="13" + inkscape:cy="12.982597" + inkscape:window-width="1867" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="Foreground" /> + <defs + id="defs1"> + <filter + id="filter839" + x="-0.047999999" + y="-0.047999999" + width="1.096" + height="1.096" + color-interpolation-filters="sRGB"> + <feGaussianBlur + stdDeviation="0.32" + id="feGaussianBlur1" /> + </filter> + </defs> + <circle + cx="9.4545" + cy="10.182" + r="8" + fill="#000000" + filter="url(#filter839)" + opacity=".1" + stroke-width="0" + id="circle1" /> + <circle + cx="9.4545" + cy="9.4545" + r="8" + fill="#ff7a80" + stroke-width="0" + id="circle2" + style="fill:#c14a4a;fill-opacity:1" /> + <path + d="m6.1115 5.7478c-0.092952 1e-7 -0.18588 0.035309-0.2571 0.10653-0.14245 0.14245-0.14245 0.37175 0 0.5142l3.0852 3.0866-3.0852 3.0852c-0.14245 0.14245-0.14245 0.37175 0 0.5142 0.14245 0.14245 0.37317 0.14245 0.51562 0l3.0852-3.0852 3.0852 3.0852c0.14245 0.14245 0.37175 0.14245 0.5142 0 0.14245-0.14245 0.14245-0.37175 0-0.5142l-3.0852-3.0852 3.0852-3.0866c0.14245-0.14245 0.14245-0.37175 0-0.5142-0.14245-0.14245-0.37175-0.14245-0.5142 0l-3.0852 3.0852-3.0852-3.0852c-0.071224-0.071224-0.16557-0.10653-0.25852-0.10653z" + fill="#ffffff" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="1.3606" + style="paint-order:markers stroke fill" + id="path2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close.svg new file mode 100755 index 0000000..dce612d --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/close.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + id="Foreground" + width="26" + height="26" + enable-background="new 0 0 16 16" + version="1.0" + viewBox="0 0 18.909 18.909" + sodipodi:docname="close.svg" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview2" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="28.730769" + inkscape:cx="13" + inkscape:cy="13" + inkscape:window-width="1920" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="Foreground" /> + <defs + id="defs1"> + <filter + id="filter879" + x="-0.047999999" + y="-0.047999999" + width="1.096" + height="1.096" + color-interpolation-filters="sRGB"> + <feGaussianBlur + stdDeviation="0.32" + id="feGaussianBlur1" /> + </filter> + </defs> + <circle + cx="9.4545" + cy="10.182" + r="8" + fill="#000000" + filter="url(#filter879)" + opacity=".1" + stroke-width="0" + id="circle1" /> + <circle + cx="9.4545" + cy="9.4545" + r="8" + fill="#f75a61" + stroke-width="0" + id="circle2" + style="fill:#ea6962;fill-opacity:1" /> + <path + d="m6.1115 5.7478c-0.092952 1e-7 -0.18588 0.035309-0.2571 0.10653-0.14245 0.14245-0.14245 0.37175 0 0.5142l3.0852 3.0866-3.0852 3.0852c-0.14245 0.14245-0.14245 0.37175 0 0.5142 0.14245 0.14245 0.37317 0.14245 0.51562 0l3.0852-3.0852 3.0852 3.0852c0.14245 0.14245 0.37175 0.14245 0.5142 0 0.14245-0.14245 0.14245-0.37175 0-0.5142l-3.0852-3.0852 3.0852-3.0866c0.14245-0.14245 0.14245-0.37175 0-0.5142-0.14245-0.14245-0.37175-0.14245-0.5142 0l-3.0852 3.0852-3.0852-3.0852c-0.071224-0.071224-0.16557-0.10653-0.25852-0.10653z" + fill="#ffffff" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="1.3606" + style="paint-order:markers stroke fill" + id="path2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/corner-ripple.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/corner-ripple.svg new file mode 100755 index 0000000..db72e9a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/corner-ripple.svg @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="104" + height="104" + version="1.1" + id="svg1" + sodipodi:docname="corner-ripple.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs1" /> + <sodipodi:namedview + id="namedview1" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="7.5769231" + inkscape:cx="52.197969" + inkscape:cy="52.13198" + inkscape:window-width="1867" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg1" /> + <g + transform="translate(0 -948.36)" + id="g1" + style="fill:#45707a;fill-opacity:1"> + <circle + id="corner-ripple" + cx="52" + cy="1000.4" + r="48" + fill="#009688" + opacity=".25" + style="fill:#45707a;fill-opacity:1" /> + </g> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-dark.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-dark.svg new file mode 100755 index 0000000..3984396 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-dark.svg @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg1780" + sodipodi:docname="radiobutton-dark.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs1784"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1250" + x="-0.05808" + y="-0.05808" + width="1.11616" + height="1.11616"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.484" + id="feGaussianBlur1252" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview1782" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="27.812867" + inkscape:cx="16.197539" + inkscape:cy="14.273969" + inkscape:window-width="1867" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg1780" /> + <circle + id="circle694" + cx="12" + cy="13" + r="10" + style="opacity:0.25;fill:#000000;fill-opacity:1;filter:url(#filter1250)" /> + <circle + id="path291" + cx="12" + cy="12" + r="10" + style="fill:#7daea3;fill-opacity:1" /> + <circle + id="path675" + cx="12" + cy="12" + r="3" + style="fill:#1d2021;stroke-width:1.2;fill-opacity:1" /> + <path + id="circle689" + style="opacity:0.1;fill:#ffffff;fill-opacity:1" + d="M 12,2 A 10,10 0 0 0 2,12 10,10 0 0 0 2.0351562,12.5 10,10 0 0 1 12,3 10,10 0 0 1 21.976562,12.341797 10,10 0 0 0 22,12 10,10 0 0 0 12,2 Z" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-off.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-off.svg new file mode 100755 index 0000000..b00efa6 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton-off.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" r="10" fill="#ffffff" opacity=".12"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton.svg new file mode 100755 index 0000000..433c89c --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/radiobutton.svg @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg4" + sodipodi:docname="radiobutton.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1250" + x="-0.05808" + y="-0.05808" + width="1.11616" + height="1.11616"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.484" + id="feGaussianBlur1252" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="27.812867" + inkscape:cx="12.062762" + inkscape:cy="11.865012" + inkscape:window-width="1867" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4"> + <inkscape:grid + type="xygrid" + id="grid237" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <circle + id="circle694" + cx="12" + cy="13" + r="10" + style="fill:#000000;fill-opacity:1;filter:url(#filter1250);opacity:0.25" /> + <circle + id="path291" + cx="12" + cy="12" + r="10" + style="fill:#45707a;fill-opacity:1" /> + <circle + id="path675" + cx="12" + cy="12" + r="3" + style="fill:#ffffff;stroke-width:1.2" /> + <path + id="circle689" + style="fill:#ffffff;fill-opacity:1;opacity:0.1" + d="M 12 2 A 10 10 0 0 0 2 12 A 10 10 0 0 0 2.0351562 12.5 A 10 10 0 0 1 12 3 A 10 10 0 0 1 21.976562 12.341797 A 10 10 0 0 0 22 12 A 10 10 0 0 0 12 2 z " /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-off.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-off.svg new file mode 100755 index 0000000..8522010 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-off.svg @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="46" + height="24" + version="1.1" + id="svg1878" + sodipodi:docname="toggle-off.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs1882"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1830" + x="-0.108" + y="-0.108" + width="1.216" + height="1.216"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.81" + id="feGaussianBlur1832" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview1880" + pagecolor="#4d4d4d" + bordercolor="#666666" + borderopacity="1.0" + inkscape:showpageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#6b6b6b" + showgrid="false" + inkscape:zoom="4.17193" + inkscape:cx="-13.662741" + inkscape:cy="-9.2283427" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg1878" /> + <rect + x="0" + y="0" + width="46" + height="24" + rx="12" + ry="12" + id="rect2" + style="opacity:0.45;fill:#ffffff" /> + <circle + cx="12" + cy="13" + r="9" + id="circle1465" + style="opacity:0.1;fill:#000000;filter:url(#filter1830)" /> + <circle + cx="12" + cy="12.089559" + r="9" + id="circle4" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on-dark.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on-dark.svg new file mode 100755 index 0000000..e509eff --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on-dark.svg @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="24" + version="1.1" + id="svg939" + sodipodi:docname="toggle-on-dark.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs943"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter863" + x="-0.14699999" + y="-0.14699999" + width="1.294" + height="1.294"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="1.1025" + id="feGaussianBlur865" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview941" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="11.8" + inkscape:cx="29.533898" + inkscape:cy="15.762712" + inkscape:window-width="1867" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg939"> + <inkscape:grid + type="xygrid" + id="grid1663" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <rect + transform="scale(-1,1)" + x="-48" + y="-0.019988" + width="48" + height="24" + rx="12" + ry="12" + fill="#009688" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#7daea3;fill-opacity:1" + id="rect2" /> + <circle + cx="36" + cy="13" + r="9" + fill="#ffffff" + stroke-width="0" + style="opacity:0.35;fill:#000000;paint-order:stroke fill markers;filter:url(#filter863)" + id="circle307" /> + <circle + cx="36" + cy="12" + r="9" + fill="#ffffff" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#1d2021;fill-opacity:1" + id="circle4" /> + <path + id="rect876" + style="opacity:0.1;fill:#ffffff;paint-order:stroke fill markers" + d="m 12,-0.01953125 c -6.6479934,0 -12,5.35200665 -12,12.00000025 0,0.171056 0.00665429,0.340494 0.01367188,0.509765 C 0.27938822,6.080891 5.523063,1 12,1 H 36 C 42.476937,1 47.720612,6.080891 47.986328,12.490234 47.993346,12.320963 48,12.151525 48,11.980469 48,5.3324754 42.647993,-0.01953125 36,-0.01953125 Z" /> + <path + id="circle1665" + style="paint-order:stroke fill markers;fill:#ffffff;fill-opacity:1;opacity:0.1" + d="M 36 3 A 9 9 0 0 0 27 12 A 9 9 0 0 0 27.035156 12.5 A 9 9 0 0 1 36 4 A 9 9 0 0 1 44.974609 12.359375 A 9 9 0 0 0 45 12 A 9 9 0 0 0 36 3 z " /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on.svg new file mode 100755 index 0000000..6477902 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/toggle-on.svg @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="24" + version="1.1" + id="svg6" + sodipodi:docname="toggle-on.svg" + inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs10"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter863" + x="-0.14699999" + y="-0.14699999" + width="1.294" + height="1.294"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="1.1025" + id="feGaussianBlur865" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview8" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="16.68772" + inkscape:cx="22.921046" + inkscape:cy="13.183347" + inkscape:window-width="1835" + inkscape:window-height="977" + inkscape:window-x="102" + inkscape:window-y="102" + inkscape:window-maximized="0" + inkscape:current-layer="svg6"> + <inkscape:grid + type="xygrid" + id="grid293" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <rect + transform="scale(-1,1)" + x="-48" + y="-0.019988" + width="48" + height="24" + rx="12" + ry="12" + fill="#009688" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#45707a;fill-opacity:1" + id="rect2" /> + <circle + cx="36" + cy="13" + r="9" + fill="#ffffff" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#000000;filter:url(#filter863);opacity:0.35" + id="circle307" /> + <circle + cx="36" + cy="12" + r="9" + fill="#ffffff" + stroke-width="0" + style="paint-order:stroke fill markers" + id="circle4" /> + <path + id="rect876" + style="paint-order:stroke fill markers;fill:#ffffff;opacity:0.1" + d="M -12 -0.01953125 C -5.3520066 -0.01953125 0 5.3324754 0 11.980469 C 0 12.151525 -0.0066542885 12.320963 -0.013671875 12.490234 C -0.27938822 6.080891 -5.523063 1 -12 1 L -36 1 C -42.476937 1 -47.720612 6.080891 -47.986328 12.490234 C -47.993346 12.320963 -48 12.151525 -48 11.980469 C -48 5.3324754 -42.647993 -0.01953125 -36 -0.01953125 L -12 -0.01953125 z " + transform="scale(-1,1)" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/trash-icon.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/trash-icon.svg new file mode 100755 index 0000000..d78a123 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/assets/trash-icon.svg @@ -0,0 +1,6 @@ +<svg width="400" height="120" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <g transform="translate(0 -932.36)"> + <rect x="10" y="942.36" width="380" height="160" rx="18" ry="18" fill="#4d4d4d" stroke-width="0"/> + <path class="ColorScheme-Text" d="m200 964.36c-4.4183 0-8 3.5817-8 8h-16v4h48v-4h-16c0-4.4183-3.5817-8-8-8zm0 4c2.2091 1e-5 4 1.7909 4 4h-8c1e-5 -2.2091 1.7909-4 4-4zm-20 12v32c0 4.4321 3.5679 8.0001 8 8.0001h24c4.4321 0 8-3.568 8-8.0001v-32h-38zm4 4h32v28c0 2.2161-1.7839 4.0001-4 4.0001h-24c-2.2161 0-4-1.784-4-4.0001z" fill="#ececec"/> + </g> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/cinnamon.css b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/cinnamon.css new file mode 100755 index 0000000..fc1eca3 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/cinnamon.css @@ -0,0 +1,2594 @@ +/* General Typography */ +.dialog .confirm-dialog-title, +.modal-dialog .confirm-dialog-title { + font-weight: 800; + font-size: 15ptpt; +} + +.workspace-switch-osd, .media-keys-osd { + font-weight: 700; + font-size: 13ptpt; +} + +.polkit-dialog-user-combo { + font-weight: 700; + font-size: 11ptpt; +} + +.prompt-dialog-error-label, .prompt-dialog-info-label, .prompt-dialog-null-label { + font-weight: 400; + font-size: 9ptpt; +} + +stage { + color: #fbf1c7; +} + +.label-shadow { + color: rgba(0, 0, 0, 0); +} + +.sound-button, .dialog .dialog-button, +.modal-dialog .dialog-button { + min-height: 24px; + padding: 5px 32px; + transition-duration: 100ms; + border-radius: 12px; + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.04); +} + +.sound-button:focus, .dialog .dialog-button:focus, +.modal-dialog .dialog-button:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.sound-button:hover, .dialog .dialog-button:hover, +.modal-dialog .dialog-button:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + border-radius: 12px; + color: #7daea3; +} + +.sound-button:hover:focus, .dialog .dialog-button:hover:focus, +.modal-dialog .dialog-button:hover:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.3); + border-radius: 12px; +} + +.sound-button:active, .dialog .dialog-button:active, +.modal-dialog .dialog-button:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.3); + border-radius: 12px; +} + +.sound-button:insensitive, .dialog .dialog-button:insensitive, +.modal-dialog .dialog-button:insensitive { + color: rgba(251, 241, 199, 0.5); + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; +} + +.polkit-dialog-user-combo, .dialog .dialog-button:destructive-action, +.modal-dialog .dialog-button:destructive-action, .dialog .dialog-button:default, +.modal-dialog .dialog-button:default, .notification-button, .notification-icon-button, .menu #notification .notification-button, +.menu #notification .notification-icon-button, .popup-menu #notification .notification-button, +.popup-menu #notification .notification-icon-button, #notification .notification-button, +#notification .notification-icon-button, .calendar-today-home-button, +.calendar-today-home-button-enabled { + border-radius: 12px; + color: rgba(251, 241, 199, 0.7); + background-color: transparent; +} + +.polkit-dialog-user-combo:hover, .dialog .dialog-button:hover:destructive-action, +.modal-dialog .dialog-button:hover:destructive-action, .dialog .dialog-button:hover:default, +.modal-dialog .dialog-button:hover:default, .notification-button:hover, .notification-icon-button:hover, #notification .notification-button:hover, +#notification .notification-icon-button:hover, .calendar-today-home-button:hover, +.calendar-today-home-button-enabled:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.polkit-dialog-user-combo:active, .dialog .dialog-button:active:destructive-action, +.modal-dialog .dialog-button:active:destructive-action, .dialog .dialog-button:active:default, +.modal-dialog .dialog-button:active:default, .notification-button:active, .notification-icon-button:active, #notification .notification-button:active, +#notification .notification-icon-button:active, .calendar-today-home-button:active, +.calendar-today-home-button-enabled:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.3); + border-radius: 12px; +} + +.polkit-dialog-user-combo:insensitive, .dialog .dialog-button:insensitive:destructive-action, +.modal-dialog .dialog-button:insensitive:destructive-action, .dialog .dialog-button:insensitive:default, +.modal-dialog .dialog-button:insensitive:default, .notification-button:insensitive, .notification-icon-button:insensitive, #notification .notification-button:insensitive, +#notification .notification-icon-button:insensitive, .calendar-today-home-button:insensitive, +.calendar-today-home-button-enabled:insensitive { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; + border-radius: 12px; +} + +.dialog-button-box .modal-dialog-button, +.modal-dialog-button-box .modal-dialog-button { + min-height: 24px; + padding: 6px 30px; + transition-duration: 100ms; + border-radius: 12px; + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.04); +} + +.dialog-button-box .modal-dialog-button:hover, +.modal-dialog-button-box .modal-dialog-button:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.dialog-button-box .modal-dialog-button:focus, +.modal-dialog-button-box .modal-dialog-button:focus { + color: #7daea3; +} + +.dialog-button-box .modal-dialog-button:active, +.modal-dialog-button-box .modal-dialog-button:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.3); +} + +.dialog-button-box .modal-dialog-button:insensitive, +.modal-dialog-button-box .modal-dialog-button:insensitive { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +#menu-search-entry, .prompt-dialog-password-entry, .notification StEntry, .menu #notification StEntry, .popup-menu #notification StEntry, #notification StEntry { + padding: 3px 12px; + min-height: 24px; + caret-size: 1px; + selection-background-color: #7daea3; + selected-color: rgba(40, 40, 40, 0.87); + transition-duration: 300ms; + border-radius: 12px; + color: #fbf1c7; + border: 2px solid transparent; + background-color: rgba(251, 241, 199, 0.04); +} + +#menu-search-entry:focus, .prompt-dialog-password-entry:focus, .notification StEntry:focus, .menu #notification StEntry:focus, .popup-menu #notification StEntry:focus, #notification StEntry:focus, #menu-search-entry:hover, .prompt-dialog-password-entry:hover, .notification StEntry:hover, .menu #notification StEntry:hover, .popup-menu #notification StEntry:hover, #notification StEntry:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + border: 2px solid #7daea3; +} + +#menu-search-entry:insensitive, .prompt-dialog-password-entry:insensitive, .notification StEntry:insensitive, .menu #notification StEntry:insensitive, .popup-menu #notification StEntry:insensitive, #notification StEntry:insensitive { + border: 2px solid transparent; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +#menu-search-entry StIcon.capslock-warning, .prompt-dialog-password-entry StIcon.capslock-warning, .notification StEntry StIcon.capslock-warning, .menu #notification StEntry StIcon.capslock-warning, .popup-menu #notification StEntry StIcon.capslock-warning, #notification StEntry StIcon.capslock-warning { + icon-size: 16px; + warning-color: #b47109; + padding: 0 6px; +} + +StScrollView.vfade { + -st-vfade-offset: 0px; +} + +StScrollView.hfade { + -st-hfade-offset: 0px; +} + +StScrollBar { + padding: 8px; +} + +StScrollView StScrollBar { + min-width: 5px; + min-height: 5px; +} + +StScrollBar StBin#trough { + background-color: rgba(40, 37, 36, 0.1); + border-radius: 9999px; +} + +StScrollBar StButton#vhandle, +StScrollBar StButton#hhandle { + border-radius: 9999px; + background-color: #7c7868; + border: 0px solid; + margin: 0px; +} + +StScrollBar StButton#vhandle:hover, +StScrollBar StButton#hhandle:hover { + background-color: #676458; +} + +StScrollBar StButton#vhandle:active, +StScrollBar StButton#hhandle:active { + background-color: #7daea3; +} + +.separator { + -gradient-height: 1px; + -gradient-start: rgba(0, 0, 0, 0); + -gradient-end: rgba(0, 0, 0, 0); + -margin-horizontal: 1.5em; + height: 1em; +} + +.popup-slider-menu-item, +.slider { + -slider-height: 4px; + -slider-background-color: rgba(251, 241, 199, 0.12); + -slider-border-color: transparent; + -slider-active-background-color: #7daea3; + -slider-active-border-color: transparent; + -slider-border-width: 0; + -slider-handle-radius: 4px; + height: 18px; + min-width: 15em; + border: 0 solid transparent; + border-right-width: 1px; + border-left-width: 5px; + color: transparent; +} + +.check-box CinnamonGenericContainer { + spacing: 0.2em; + min-height: 30px; + padding-top: 2px; +} + +.check-box StLabel { + font-weight: normal; +} + +.check-box StBin { + width: 24px; + height: 24px; +} + +.check-box StBin, .check-box:focus StBin { + background-image: url("assets/checkbox-off.svg"); +} + +.check-box:checked StBin, .check-box:focus:checked StBin { + background-image: url("assets/checkbox-dark.svg"); +} + +.radiobutton CinnamonGenericContainer { + spacing: 0.2em; + min-height: 30px; + padding-top: 2px; +} + +.radiobutton StLabel { + padding-top: 4px; + font-size: 0.9em; + box-shadow: none; +} + +.radiobutton StBin { + width: 24px; + height: 24px; +} + +.radiobutton StBin, .radiobutton:focus StBin { + background-image: url("assets/radiobutton-off.svg"); +} + +.radiobutton:checked StBin, .radiobutton:focus:checked StBin { + background-image: url("assets/radiobutton-dark.svg"); +} + +.toggle-switch { + width: 46px; + height: 24px; + background-size: contain; +} + +.toggle-switch, .popup-menu-item:active .toggle-switch { + background-image: url("assets/toggle-off.svg"); +} + +.toggle-switch:checked, .popup-menu-item:active .toggle-switch:checked { + background-image: url("assets/toggle-on-dark.svg"); +} + +.cinnamon-link { + color: #83b193; + text-decoration: underline; +} + +.cinnamon-link:hover { + color: #a2c5ae; +} + +#Tooltip { + border-radius: 9999px; + padding: 6px 12px; + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; + margin: 6px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12); + font-size: 1em; + font-weight: normal; + text-align: center; +} + +.menu, +.popup-menu, +.popup-combo-menu { + padding: 0; + color: #fbf1c7; + border-radius: 12px; + margin: 6px; + box-shadow: none; + /* @if $outline == 'true' { + border: 2px solid $primary; + } */ +} + +.menu-arrow, +.popup-menu-arrow { + icon-size: 16px; +} + +.menu .popup-sub-menu, +.popup-menu .popup-sub-menu, +.popup-combo-menu .popup-sub-menu { + border-radius: 12px; + background-gradient-direction: none; + box-shadow: none; + background-color: #3a3731; + color: rgba(251, 241, 199, 0.7); +} + +.menu .popup-sub-menu .popup-menu-item:active, +.popup-menu .popup-sub-menu .popup-menu-item:active, +.popup-combo-menu .popup-sub-menu .popup-menu-item:active { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.menu .popup-sub-menu StScrollBar, +.popup-menu .popup-sub-menu StScrollBar, +.popup-combo-menu .popup-sub-menu StScrollBar { + padding: 4px; +} + +.menu .popup-sub-menu StScrollBar StBin#trough, +.menu .popup-sub-menu StScrollBar StBin#vhandle, +.popup-menu .popup-sub-menu StScrollBar StBin#trough, +.popup-menu .popup-sub-menu StScrollBar StBin#vhandle, +.popup-combo-menu .popup-sub-menu StScrollBar StBin#trough, +.popup-combo-menu .popup-sub-menu StScrollBar StBin#vhandle { + border-width: 0; +} + +.menu .popup-menu-content, +.popup-menu .popup-menu-content, +.popup-combo-menu .popup-menu-content { + padding: 6px; + border-radius: 12px; + background-color: #242220; + box-shadow: 0 5px 12px rgba(0, 0, 0, 0.35); + border: 2px solid #7daea3; + background-clip: border-box; +} + +.menu .popup-menu-item, +.popup-menu .popup-menu-item, +.popup-combo-menu .popup-menu-item { + padding: 6px 12px; + spacing: 12px; + border-radius: 12px; +} + +.menu .popup-menu-item:hover, .menu .popup-menu-item:active, +.popup-menu .popup-menu-item:hover, +.popup-menu .popup-menu-item:active, +.popup-combo-menu .popup-menu-item:hover, +.popup-combo-menu .popup-menu-item:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.menu .popup-menu-item:insensitive, +.popup-menu .popup-menu-item:insensitive, +.popup-combo-menu .popup-menu-item:insensitive { + color: rgba(251, 241, 199, 0.5); + background: none; +} + +.menu .popup-inactive-menu-item, +.popup-menu .popup-inactive-menu-item, +.popup-combo-menu .popup-inactive-menu-item { + color: rgba(251, 241, 199, 0.5); +} + +.menu .popup-inactive-menu-item:insensitive, +.popup-menu .popup-inactive-menu-item:insensitive, +.popup-combo-menu .popup-inactive-menu-item:insensitive { + color: rgba(251, 241, 199, 0.12); +} + +.menu .popup-menu-item:active .popup-inactive-menu-item, +.popup-menu .popup-menu-item:active .popup-inactive-menu-item, +.popup-combo-menu .popup-menu-item:active .popup-inactive-menu-item { + color: rgba(251, 241, 199, 0.5); +} + +.menu-icon, +.popup-menu-icon { + icon-size: 16px; +} + +.popup-menu-boxpointer { + -arrow-border-radius: 12px; + -arrow-background-color: rgba(0, 0, 0, 0); + -arrow-border-width: 0; + -arrow-border-color: rgba(0, 0, 0, 0); + -arrow-base: 0; + -arrow-rise: 0; +} + +.popup-combo-menu { + padding: 6px; + border: 2px solid #7daea3; +} + +.popup-combobox-item { + spacing: 1em; +} + +.popup-separator-menu-item { + -gradient-height: 0; + -gradient-start: transparent; + -gradient-end: transparent; + -margin-horizontal: 1.5em; + height: 0; + margin: 0; + padding: 0; + border-color: rgba(251, 241, 199, 0.12); + border-bottom-width: 0; + border-bottom-style: solid; + background-color: transparent; +} + +.popup-alternating-menu-item:alternate { + font-weight: normal; +} + +.popup-device-menu-item { + spacing: 0.5em; +} + +.popup-subtitle-menu-item { + font-weight: normal; +} + +.nm-menu-item-icons { + spacing: 0.5em; +} + +#panel { + font-weight: bold; + height: 34px; + width: 40px; +} + +#panel:highlight { + border-image: none; + background-color: rgba(193, 74, 74, 0.5); +} + +#panelLeft { + spacing: 4px; +} + +#panelLeft:dnd { + background-gradient-direction: vertical; + background-gradient-start: rgba(193, 74, 74, 0.35); + background-gradient-end: rgba(193, 74, 74, 0.35); +} + +#panelLeft:ltr { + padding-right: 4px; +} + +#panelLeft:rtl { + padding-left: 4px; +} + +#panelLeft.vertical { + padding: 0; +} + +#panelLeft.vertical:ltr { + padding-right: 0px; +} + +#panelLeft.vertical:rtl { + padding-left: 0px; +} + +#panelRight:dnd { + background-gradient-direction: vertical; + background-gradient-start: rgba(69, 112, 122, 0.35); + background-gradient-end: rgba(69, 112, 122, 0.35); +} + +#panelRight:ltr { + padding-left: 6px; + spacing: 0px; +} + +#panelRight:rtl { + padding-right: 6px; + spacing: 0px; +} + +#panelRight.vertical { + padding: 0; +} + +#panelRight.vertical:ltr { + padding-right: 0px; +} + +#panelRight.vertical:rtl { + padding-left: 0px; +} + +#panelCenter { + spacing: 4px; +} + +#panelCenter:dnd { + background-gradient-direction: vertical; + background-gradient-start: rgba(108, 120, 46, 0.35); + background-gradient-end: rgba(108, 120, 46, 0.35); +} + +.panel-top, .panel-bottom, .panel-left, .panel-right { + color: rgba(251, 241, 199, 0.7); + font-size: 1em; + padding: 0px; + background-color: rgba(40, 40, 40, 0.75); + box-shadow: 0 0 5px rgba(0, 0, 0, 0.5), 0 0 16px rgba(0, 0, 0, 0.24); +} + +.panel-top .panel-button:hover, +.panel-top .panel-status-button:hover, .panel-bottom .panel-button:hover, +.panel-bottom .panel-status-button:hover, .panel-left .panel-button:hover, +.panel-left .panel-status-button:hover, .panel-right .panel-button:hover, +.panel-right .panel-status-button:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); +} + +.panel-top .panel-button:active, +.panel-top .panel-status-button:active, .panel-bottom .panel-button:active, +.panel-bottom .panel-status-button:active, .panel-left .panel-button:active, +.panel-left .panel-status-button:active, .panel-right .panel-button:active, +.panel-right .panel-status-button:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.panel-dummy { + background-color: rgba(193, 74, 74, 0.5); +} + +.panel-dummy:entered { + background-color: rgba(193, 74, 74, 0.6); +} + +.panel-status-button { + border-width: 0; + -natural-hpadding: 3px; + -minimum-hpadding: 3px; + font-weight: bold; + height: 22px; + color: rgba(251, 241, 199, 0.7); +} + +.panel-button { + -natural-hpadding: 6px; + -minimum-hpadding: 2px; + font-weight: bold; + transition-duration: 100ms; + color: rgba(251, 241, 199, 0.7); +} + +.system-status-icon { + icon-size: 16px; + padding: 0 1px; +} + +#overview { + spacing: 12px; +} + +.window-caption { + background-color: rgba(32, 32, 32, 0.9); + border: 1px solid rgba(32, 32, 32, 0.9); + color: #fbf1c7; + spacing: 25px; + border-radius: 12px; + font-size: 9pt; + padding: 5px 8px; + -cinnamon-caption-spacing: 4px; +} + +.window-caption#selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + border: 1px solid #7daea3; + spacing: 25px; +} + +.expo-workspaces-name-entry, +.expo-workspaces-name-entry#selected { + height: 15px; + border-radius: 12px; + font-size: 9pt; + padding: 5px 8px; + -cinnamon-caption-spacing: 4px; + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + border: 2px solid transparent; +} + +.expo-workspaces-name-entry:focus, +.expo-workspaces-name-entry#selected:focus { + border: 1px solid #7daea3; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + font-style: italic; + transition-duration: 300; + selection-background-color: rgba(40, 40, 40, 0.87); + selected-color: #7daea3; +} + +.expo-workspace-thumbnail-frame { + border: 4px solid rgba(255, 255, 255, 0); + background-color: rgba(255, 255, 255, 0); + border-radius: 0; +} + +.expo-workspace-thumbnail-frame#active { + border: 4px solid #7daea3; + background-color: black; + border-radius: 0; +} + +.expo-background { + background-color: #202020; +} + +.workspace-thumbnails { + spacing: 26px; +} + +.workspace-thumbnails-background, .workspace-thumbnails-background:rtl { + padding: 8px; +} + +.workspace-add-button { + background-image: url("assets/add-workspace.svg"); + height: 200px; + width: 35px; + transition-duration: 100; +} + +.workspace-add-button:hover { + background-image: url("assets/add-workspace-hover.svg"); + transition-duration: 100; +} + +.workspace-add-button:active { + background-image: url("assets/add-workspace-active.svg"); + transition-duration: 100; +} + +.workspace-overview-background-shade { + background-color: rgba(0, 0, 0, 0.5); +} + +.workspace-close-button, +.window-close { + background-image: url("assets/close.svg"); + background-size: 26px; + height: 26px; + width: 26px; + -cinnamon-close-overlap: 13px; +} + +.workspace-close-button:hover, +.window-close:hover { + background-image: url("assets/close-hover.svg"); + background-size: 26px; + height: 26px; + width: 26px; +} + +.workspace-close-button:active, +.window-close:active { + background-image: url("assets/close-active.svg"); + background-size: 26px; + height: 26px; + width: 26px; +} + +.workspace-thumbnail-indicator { + outline: 2px solid red; + border: 1px solid green; +} + +.window-close:rtl { + -st-background-image-shadow: 2px 2px 6px rgba(0, 0, 0, 0.5); +} + +.window-close-area { + background-image: url("assets/trash-icon.svg"); + height: 120px; + width: 400px; +} + +.about-content { + width: 550px; + height: 250px; + spacing: 8px; + padding-bottom: 10px; +} + +.about-title { + font-size: 2em; + font-weight: bold; +} + +.about-uuid { + font-size: 10px; + color: #888; +} + +.about-icon { + padding-right: 20px; + padding-bottom: 14px; +} + +.about-scrollBox { + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 12px; + background-color: #282524; + padding: 4px; + padding-right: 0; + border-radius: 0; +} + +.about-scrollBox-innerBox { + padding: 1.2em; + spacing: 1.2em; +} + +.about-description { + padding-top: 4px; + padding-bottom: 16px; +} + +.about-version { + padding-left: 7px; + font-size: 10px; + color: #888; +} + +#LookingGlassDialog { + background-color: #282524; + spacing: 6px; + padding: 6px; + margin: 32px; + border-radius: 12px; + color: #fbf1c7; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); + border: none; +} + +.calendar-main-box { + margin: 0 0.8em; +} + +.calendar { + spacing-rows: 0px; + spacing-columns: 0px; +} + +.calendar-today-home-button, +.calendar-today-home-button-enabled { + margin: 6px 0; + padding: 6px; +} + +.calendar-today-day-label { + font-size: 1.75em; + color: rgba(251, 241, 199, 0.7); + font-weight: bold; + text-align: center; + padding-bottom: 0.1em; +} + +.calendar-today-date-label { + font-size: 1.1em; + color: rgba(251, 241, 199, 0.5); + font-weight: bold; + text-align: center; +} + +.calendar-month-label { + color: #fbf1c7; + font-weight: bold; + padding-bottom: 8px; + padding-top: 8px; +} + +.calendar-change-month-back, +.calendar-change-month-forward { + width: 2.4em; + height: 2.4em; + margin: 2px 0; + padding: 0; + border-radius: 9999px; +} + +.calendar-change-month-back:focus, .calendar-change-month-back:hover, +.calendar-change-month-forward:focus, +.calendar-change-month-forward:hover { + background-color: rgba(251, 241, 199, 0.1); +} + +.calendar-change-month-back:active, +.calendar-change-month-forward:active { + background-color: rgba(251, 241, 199, 0.25); +} + +.calendar-change-month-back { + background-image: url("assets/calendar-arrow-left.svg"); +} + +.calendar-change-month-back:rtl { + background-image: url("assets/calendar-arrow-right.svg"); +} + +.calendar-change-month-forward { + background-image: url("assets/calendar-arrow-right.svg"); +} + +.calendar-change-month-forward:rtl { + background-image: url("assets/calendar-arrow-left.svg"); +} + +.datemenu-date-label { + padding: 0.4em 1.75em; + font-weight: normal; + text-align: center; + font-size: 14px; + color: #fbf1c7; + border-radius: 12px; +} + +.calendar-day-base { + text-align: center; + width: 2.4em; + height: 2.4em; + padding: 0; + margin: 2px; + border-radius: 9999px; +} + +.calendar-day-base:hover { + background-color: rgba(251, 241, 199, 0.04); +} + +.calendar-day-base:active { + background-color: rgba(251, 241, 199, 0.12); +} + +.calendar-day-heading { + color: rgba(251, 241, 199, 0.7); + margin-top: 1em; +} + +.calendar-day { + border-width: 0; + color: rgba(251, 241, 199, 0.7); +} + +.calendar-day-top { + border-top-width: 0; +} + +.calendar-day-left { + border-left-width: 0; +} + +.calendar-nonwork-day { + color: #fbf1c7; + background-color: transparent; + font-weight: bold; +} + +.calendar-today, +.calendar-today:active, +.calendar-today:focus, +.calendar-today:hover { + font-weight: bold; + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; + border-width: 0; +} + +.calendar-other-month-day { + color: rgba(251, 241, 199, 0.7); + opacity: 1; +} + +.calendar-week-number { + width: 2.4em; + height: 2.4em; + margin: 0; + color: rgba(251, 241, 199, 0.3); + font-weight: bold; + background-color: transparent; + border-radius: 9999px; +} + +.calendar-week-number StLabel { + padding: 0; + margin-top: 3px; +} + +.calendar-events-main-box { + height: 300px; + margin: 8px 0.8em 0 0; + padding: 8px; + min-width: 350px; + border: none; + border-radius: 12px; + background-gradient-direction: vertical; + background-gradient-start: rgba(251, 241, 199, 0.04); + background-gradient-end: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.7); +} + +.calendar-events-no-events-button { + margin: 6px 0; + padding: 6px; + border-radius: 12px; +} + +.calendar-events-no-events-button:hover { + background-gradient-direction: vertical; + background-gradient-start: rgba(251, 241, 199, 0.04); + background-gradient-end: rgba(251, 241, 199, 0.04); + box-shadow: none; +} + +.calendar-events-no-events-icon { + color: rgba(251, 241, 199, 0.5); +} + +.calendar-events-no-events-label { + font-size: 1.1em; + color: rgba(251, 241, 199, 0.5); + font-weight: bold; + text-align: center; + margin-top: 9px; +} + +.calendar-events-date-label { + padding: 3px 0 12px 3px; + font-size: 1.1em; + color: rgba(251, 241, 199, 0.7); + font-weight: bold; + text-align: center; +} + +.calendar-events-event-container { + padding: 2px; +} + +.calendar-events-main-box .separator { + -margin-horizontal: 1em; + -gradient-height: 1px; + -gradient-start: rgba(251, 241, 199, 0.12); + -gradient-end: rgba(251, 241, 199, 0.12); +} + +.calendar-event-button { + margin: 6px 0 6px 0; + border-radius: 12px; +} + +.calendar-event-button:hover { + background-gradient-direction: vertical; + background-gradient-start: rgba(251, 241, 199, 0.04); + background-gradient-end: rgba(251, 241, 199, 0.04); + box-shadow: none; +} + +.calendar-event-color-strip { + width: 4px; + border-radius: 4px 0 0 4px; +} + +.calendar-event-row-content { + margin: 6px; +} + +.calendar-event-time-past { + color: rgba(251, 241, 199, 0.32); + font-weight: bold; + text-align: left; + margin-bottom: 0.6em; +} + +.calendar-event-time-present { + font-weight: bold; + text-align: left; + margin-bottom: 0.6em; +} + +.calendar-event-time-present:all-day { + color: rgba(108, 120, 46, 0.6); +} + +.calendar-event-time-future { + text-align: left; + margin-bottom: 0.6em; +} + +.calendar-event-countdown { + color: rgba(251, 241, 199, 0.5); + font-weight: bold; + text-align: right; + margin-bottom: 0.6em; +} + +.calendar-event-countdown:soon { + color: #fbf1c7; +} + +.calendar-event-countdown:imminent { + color: rgba(180, 113, 9, 0.6); +} + +.calendar-event-countdown:current { + color: rgba(108, 120, 46, 0.6); +} + +.calendar-event-summary { + color: rgba(251, 241, 199, 0.5); + text-align: left; + width: 200px; +} + +#notification { + border-radius: 12px; + padding: 12px; + spacing-rows: 9px; + spacing-columns: 9px; + margin-from-right-edge-of-screen: 18px; + width: 28em; + color: #fbf1c7; + background-color: rgba(40, 37, 36, 0.8); + box-shadow: 0 5px 12px rgba(0, 0, 0, 0.35); + margin: 7px 12px 17px 12px; +} + +#notification .notification-button, +#notification .notification-icon-button { + padding: 6px; +} + +.menu #notification, .popup-menu #notification { + border: none; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.05); + box-shadow: none; + margin: 0; +} + +.menu #notification:hover, .popup-menu #notification:hover { + background-color: rgba(251, 241, 199, 0.1); + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15); +} + +.menu #notification, .menu #notification.multi-line-notification, .popup-menu #notification, .popup-menu #notification.multi-line-notification { + color: #fbf1c7; +} + +.menu #notification .notification-button, +.menu #notification .notification-icon-button, .popup-menu #notification .notification-button, +.popup-menu #notification .notification-icon-button { + padding: 6px; +} + +#notification.multi-line-notification { + padding-bottom: 12px; + color: #fbf1c7; +} + +#notification-scrollview { + max-height: 10em; +} + +#notification-scrollview > .top-shadow, +#notification-scrollview > .bottom-shadow { + height: 1em; +} + +#notification-scrollview:ltr > StScrollBar { + padding-left: 6px; +} + +#notification-scrollview:rtl > StScrollBar { + padding-right: 6px; +} + +#notification-body { + spacing: 6px; +} + +#notification-actions { + spacing: 9px; +} + +.notification-with-image { + min-height: 159px; + color: #fbf1c7; +} + +.notification-button, .notification-icon-button { + padding: 6px; +} + +.notification-icon-button > StIcon { + icon-size: 36px; +} + +#altTabPopup { + padding: 8px; + spacing: 16px; +} + +.switcher-list { + color: #fbf1c7; + background-color: #242220; + border: none; + border-radius: 12px; + padding: 20px; +} + +.switcher-list > StBoxLayout { + padding: 4px; +} + +.switcher-list-item-container { + spacing: 8px; +} + +.switcher-list .item-box { + padding: 8px; + border-radius: 12px; +} + +.switcher-list .item-box:outlined { + padding: 8px; + border: 1px solid #7daea3; +} + +.switcher-list .item-box:selected { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; + border: 0px solid #7daea3; +} + +.switcher-list .thumbnail { + width: 256px; +} + +.switcher-list .thumbnail-box { + padding: 2px; + spacing: 4px; +} + +.switcher-list .separator { + width: 1px; + background: rgba(255, 255, 255, 0.2); +} + +.switcher-arrow { + border-color: rgba(0, 0, 0, 0); + color: #fbf1c7; +} + +.switcher-arrow:highlighted { + border-color: rgba(0, 0, 0, 0); + color: rgba(251, 241, 199, 0.7); +} + +.thumbnail-scroll-gradient-left { + background-color: rgba(0, 0, 0, 0); + border-radius: 24px; + border-radius-topright: 0px; + border-radius-bottomright: 0px; + width: 60px; +} + +.thumbnail-scroll-gradient-right { + background-color: rgba(0, 0, 0, 0); + border-radius: 24px; + border-radius-topleft: 0px; + border-radius-bottomleft: 0px; + width: 60px; +} + +.ripple-box { + width: 104px; + height: 104px; + background-image: url("assets/corner-ripple.svg"); + background-size: contain; +} + +.lightbox { + background-color: rgba(0, 0, 0, 0.4); +} + +.flashspot { + background-color: #fbf1c7; +} + +.dialog, +.modal-dialog { + color: #fbf1c7; + background-color: rgba(40, 40, 40, 0.95); + padding: 6px; + border-radius: 12px; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.75), 0 5px 18px rgba(0, 0, 0, 0.55); + /* border: 1px solid $divider; */ + border: 2px solid #7daea3; +} + +.dialog > StBoxLayout:first-child, +.modal-dialog > StBoxLayout:first-child { + padding: 20px 10px 10px 10px; +} + +.dialog-button-box, +.modal-dialog-button-box { + spacing: 0; + margin: 0; + padding: 14px 10px; + background-color: transparent; + border: none; +} + +.dialog-button-box .modal-dialog-button, +.modal-dialog-button-box .modal-dialog-button { + padding-top: 0; + padding-bottom: 0; + height: 30px; +} + +.dialog .dialog-content-box, +.modal-dialog .dialog-content-box { + margin-top: 6px; + margin-bottom: 6px; + spacing: 6px; + max-width: 18em; +} + +.dialog .dialog-button:default:hover, +.modal-dialog .dialog-button:default:hover { + background-color: #cb6868 !important; + color: #fbf1c7 !important; +} + +.dialog .dialog-button:destructive-action, +.modal-dialog .dialog-button:destructive-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +.dialog .confirm-dialog-title, +.modal-dialog .confirm-dialog-title { + text-align: center; +} + +.dialog .end-session-dialog, +.modal-dialog .end-session-dialog { + min-width: 40em; +} + +.dialog .end-session-dialog .dialog-content-box, +.modal-dialog .end-session-dialog .dialog-content-box { + spacing: 0; +} + +.dialog .end-session-dialog .dialog-list, +.modal-dialog .end-session-dialog .dialog-list { + spacing: 0; +} + +.dialog .end-session-dialog .dialog-list .dialog-list-title, +.modal-dialog .end-session-dialog .dialog-list .dialog-list-title { + color: #b47109; + background-color: tranparentize(#b47109, 0.9); + padding: 9px; + border-radius: 12px; + margin: 6px 0; +} + +.run-dialog { + padding: 6px 12px; + background-color: rgba(32, 32, 32, 0.9); + border-radius: 12px; + color: #fbf1c7; +} + +.run-dialog > * { + padding: 0; +} + +.run-dialog-label { + font-size: 0; + font-weight: bold; + color: #fbf1c7; + padding-bottom: 0; +} + +.run-dialog-error-label { + color: #c14a4a; +} + +.run-dialog-error-box { + padding-top: 15px; + spacing: 5px; +} + +.run-dialog-completion-box { + padding-left: 15px; + font-size: 10px; +} + +.run-dialog-entry { + width: 21em; + padding: 3px 12px; + border-radius: 12px; + caret-color: #fbf1c7; + selected-color: rgba(40, 40, 40, 0.87); + selection-background-color: #7daea3; + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + border: 2px solid transparent; +} + +.run-dialog-entry:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + border: 2px solid #7daea3; +} + +.run-dialog .modal-dialog-button-box { + border: none; + box-shadow: none; + background: none; + background-gradient-direction: none; +} + +.prompt-dialog { + width: 26em; +} + +.prompt-dialog .dialog-content-box { + spacing: 24px; + margin-bottom: 18px; +} + +.prompt-dialog-password-entry { + width: 20em; +} + +.prompt-dialog-password-layout { + spacing: 12px; +} + +.prompt-dialog-error-label, .prompt-dialog-info-label, .prompt-dialog-null-label { + text-align: center; +} + +.prompt-dialog-error-label { + color: #c14a4a; +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 2px; +} + +.polkit-dialog-user-combo { + border-radius: 9px; + padding: 6px 36px; +} + +.polkit-dialog-user-combo:insensitive { + color: #fbf1c7; +} + +/* CinnamonMountOperation Dialogs */ +.cinnamon-mount-operation-icon { + icon-size: 48px; +} + +.mount-password-reask { + color: #b47109; +} + +.show-processes-dialog, +.mount-question-dialog { + spacing: 24px; +} + +.show-processes-dialog-subject, +.mount-question-dialog-subject { + padding-top: 10px; + padding-left: 17px; + padding-bottom: 6px; +} + +.show-processes-dialog-subject:rtl, +.mount-question-dialog-subject:rtl { + padding-left: 0px; + padding-right: 17px; +} + +.show-processes-dialog-description, +.mount-question-dialog-description { + padding-left: 17px; + width: 28em; +} + +.show-processes-dialog-description:rtl, +.mount-question-dialog-description:rtl { + padding-right: 17px; +} + +.show-processes-dialog-app-list { + max-height: 200px; + padding-top: 24px; + padding-left: 49px; + padding-right: 32px; +} + +.show-processes-dialog-app-list:rtl { + padding-right: 49px; + padding-left: 32px; +} + +.show-processes-dialog-app-list-item { + color: #ccc; +} + +.show-processes-dialog-app-list-item:hover { + color: #fbf1c7; +} + +.show-processes-dialog-app-list-item:ltr { + padding-right: 1em; +} + +.show-processes-dialog-app-list-item:rtl { + padding-left: 1em; +} + +.show-processes-dialog-app-list-item-icon:ltr { + padding-right: 17px; +} + +.show-processes-dialog-app-list-item-icon:rtl { + padding-left: 17px; +} + +.show-processes-dialog-app-list-item-name { + font-size: 1.1em; +} + +.magnifier-zoom-region { + border: 2px solid maroon; +} + +.magnifier-zoom-region .full-screen { + border-width: 0px; +} + +#keyboard { + background-color: rgba(32, 32, 32, 0.9); + border-width: 0; + border-top-width: 1px; + border-color: rgba(0, 0, 0, 0.4); +} + +.keyboard-layout { + spacing: 10px; + padding: 10px; +} + +.keyboard-row { + spacing: 15px; +} + +.keyboard-key { + min-height: 2em; + min-width: 2em; + font-size: 14pt; + font-weight: bold; + border-radius: 12px; + box-shadow: none; + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.04); +} + +.keyboard-key:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.keyboard-key:active, .keyboard-key:checked { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.3); +} + +.keyboard-key:grayed { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +.keyboard-subkeys { + color: #fbf1c7; + padding: 5px; + -arrow-border-radius: 12px; + -arrow-background-color: rgba(32, 32, 32, 0.9); + -arrow-border-width: 1px; + -arrow-border-color: rgba(0, 0, 0, 0.4); + -arrow-base: 20px; + -arrow-rise: 10px; + -boxpointer-gap: 5px; +} + +.menu-favorites-box { + margin: auto; + margin-bottom: 6px; + padding: 6px; + transition-duration: 300; + background-color: rgba(251, 241, 199, 0.05); + border: none; + border-radius: 12px; +} + +.menu-favorites-button { + padding: 9px; + border: none; + border-radius: 6px; +} + +.menu-favorites-button:hover { + background-color: rgba(251, 241, 199, 0.1); +} + +.menu-places-box { + margin: auto; + padding: 9px; + border: 1px solid rgba(0, 0, 0, 0); +} + +.menu-places-button { + padding: 9px; +} + +.menu-categories-box { + padding: 9px 30px; +} + +.menu-applications-inner-box, .menu-applications-outer-box { + padding: 9px 9px 0 9px; +} + +.menu-application-button { + padding: 6px; + border-radius: 12px; + border: none; +} + +.menu-application-button:highlighted { + font-weight: bold; +} + +.menu-application-button-selected { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + padding: 6px; + border-radius: 12px; + border: none; +} + +.menu-application-button-selected:highlighted { + font-weight: bold; +} + +.menu-application-button-label:ltr { + padding-left: 6px; +} + +.menu-application-button-label:rtl { + padding-right: 6px; +} + +.menu StScrollView.menu-application-button { + padding: 3px 0; + border-radius: 12px; + background-color: #3a3731; + color: #fbf1c7; +} + +.menu StScrollView.menu-application-button .popup-menu-item { + padding: 0; + spacing: 0; + margin: 0 3px; + border-radius: 12px; + color: #fbf1c7; +} + +.menu StScrollView.menu-application-button .popup-menu-item:ltr { + padding-left: 6px; +} + +.menu StScrollView.menu-application-button .popup-menu-item:rtl { + padding-right: 6px; +} + +.menu StScrollView.menu-application-button .popup-menu-item:active { + border-image: none; + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.menu StScrollView.menu-application-button .popup-menu-item StIcon { + min-width: 22px; +} + +.menu StScrollView.menu-application-button .popup-menu-item StLabel:ltr { + padding: 6px 0 6px 6px; +} + +.menu StScrollView.menu-application-button .popup-menu-item StLabel:rtl { + padding: 6px 6px 6px 0; +} + +.menu-category-button { + padding: 6px; + border-radius: 12px; +} + +.menu-category-button-selected { + padding: 6px; +} + +.menu-category-button-hover, .menu-category-button-selected { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.menu-category-button-greyed { + padding: 6px; + color: rgba(251, 241, 199, 0.5); +} + +.menu-category-button-label:ltr { + padding-left: 6px; +} + +.menu-category-button-label:rtl { + padding-right: 6px; +} + +.menu-selected-app-box { + padding-right: 30px; + padding-left: 28px; + text-align: right; + height: 30px; +} + +.menu-selected-app-box:rtl { + padding-top: 10px; + height: 30px; +} + +.menu-selected-app-title { + font-weight: bold; +} + +.menu-selected-app-description { + max-width: 150px; + margin-bottom: 6px; +} + +.menu-search-box:ltr { + padding-left: 30px; +} + +.menu-search-box-rtl { + padding-right: 30px; +} + +#menu-search-entry { + width: 250px; + height: 15px; + font-weight: normal; + caret-color: #fbf1c7; + border-radius: 12px; +} + +.menu-search-entry-icon { + icon-size: 1em; + color: #fbf1c7; +} + +.media-keys-osd { + color: #fbf1c7; + background-color: rgba(40, 40, 40, 0.99); + border: 1px solid rgba(251, 241, 199, 0.11); + border-radius: 12px; + text-align: center; + padding: 24px; +} + +.media-keys-osd { + margin-bottom: 1em; + border-radius: 9999px; + font-weight: bold; + spacing: 12px; + padding: 12px 24px; +} + +.media-keys-osd > * { + spacing: 12px; +} + +.media-keys-osd StIcon { + icon-size: 32px; +} + +.media-keys-osd StLabel:ltr { + margin-right: 6px; +} + +.media-keys-osd StLabel:rtl { + margin-left: 6px; +} + +.media-keys-osd .level { + min-width: 160px; + -barlevel-height: 6px; + -barlevel-background-color: #282524; + -barlevel-active-background-color: #fbf1c7; + -barlevel-amplify-color: #b47109; + -barlevel-amplify-separator-width: 3px; +} + +.media-keys-osd .level:ltr { + margin-right: 6px; +} + +.media-keys-osd .level:rtl { + margin-left: 6px; +} + +.media-keys-osd .level-bar { + border-radius: 12px; + background-color: #fbf1c7; +} + +.info-osd { + text-align: center; + font-weight: bold; + spacing: 1em; + padding: 16px; + color: rgba(251, 241, 199, 0.7); + background-color: rgba(40, 40, 40, 0.75); +} + +.osd-window { + text-align: center; + font-weight: bold; + spacing: 1em; + padding: 20px; + min-width: 64px; + min-height: 64px; + color: rgba(251, 241, 199, 0.7); + border-radius: 0; + background-color: rgba(40, 40, 40, 0.75); + border: none; +} + +.osd-window .osd-monitor-label { + font-size: 3em; +} + +.osd-window .level { + padding: 0; + height: 4px; + background-color: rgba(0, 0, 0, 0.35); + border-radius: 12px; + color: #7daea3; +} + +.osd-window .level-bar { + border-radius: 12px; + background-color: #7daea3; +} + +.workspace-switch-osd { + color: #7daea3; + background-color: rgba(40, 40, 40, 0.99); + /* border: 1px solid transparentize($divider, 0.01); */ + border: 2px solid #7daea3; + border-radius: 9px; + text-align: center; + padding: 24px; + min-width: 140px; + margin-bottom: 1em; + border-radius: 9999px; + font-weight: bold; + padding: 12px 36px 0 36px; +} + +.workspace-switch-osd-indicator-box { + spacing: 12px; +} + +.workspace-switch-osd-indicator { + background-color: rgba(251, 241, 199, 0.5); + padding: 2.6666666667px; + margin: 13.3333333333px; + border-radius: 32px; +} + +.workspace-switch-osd-indicator:active { + background-color: #7daea3; + padding: 5.3333333333px; + margin: 10.6666666667px; +} + +.window-list-box { + spacing: 2px; +} + +.panel-bottom .window-list-box:ltr, .panel-top .window-list-box:ltr { + padding: 0 0 0 8px; +} + +.panel-bottom .window-list-box:rtl, .panel-top .window-list-box:rtl { + padding: 0 8px 0 0; +} + +.window-list-box.vertical { + padding: 6px 0 0 0; +} + +.window-list-box.vertical #appMenuIcon { + padding-top: 2px; +} + +.window-list-box:highlight { + background-color: rgba(193, 74, 74, 0.5); +} + +.window-list-item-label { + font-weight: normal; + width: 15em; + min-width: 5px; +} + +.window-list-item-box { + font-weight: normal; + background-image: none; + transition-duration: 100ms; + color: rgba(251, 241, 199, 0.9); + border-radius: 0; +} + +.panel-bottom .window-list-item-box StLabel { + padding-left: 6px; +} + +.panel-top .window-list-item-box StLabel { + padding-left: 6px; +} + +.panel-left .window-list-item-box StLabel { + padding-top: 6px; +} + +.panel-right .window-list-item-box StLabel { + padding-top: 6px; +} + +.panel-top .window-list-item-box { + border-top: 2px solid transparent; +} + +.panel-top .window-list-item-box StIcon, +.panel-top .window-list-item-box StBin, +.panel-top .window-list-item-box #appMenuIcon { + padding: 2px; + padding-top: 0; +} + +.panel-bottom .window-list-item-box { + border-bottom: 2px solid transparent; +} + +.panel-bottom .window-list-item-box StIcon, +.panel-bottom .window-list-item-box StBin, +.panel-bottom .window-list-item-box #appMenuIcon { + padding: 2px; + padding-bottom: 0; +} + +.panel-left .window-list-item-box { + border-left: 2px solid transparent; +} + +.panel-left .window-list-item-box StIcon, +.panel-left .window-list-item-box StBin, +.panel-left .window-list-item-box #appMenuIcon { + padding: 2px; + padding-left: 0; +} + +.panel-right .window-list-item-box { + border-right: 2px solid transparent; +} + +.panel-right .window-list-item-box StIcon, +.panel-right .window-list-item-box StBin, +.panel-right .window-list-item-box #appMenuIcon { + padding: 2px; + padding-right: 0; +} + +.window-list-item-box:hover { + color: rgba(251, 241, 199, 0.7); + background-gradient-direction: none; + background-color: rgba(251, 241, 199, 0.15); +} + +.window-list-item-box:active, .window-list-item-box:checked, .window-list-item-box:running { + color: rgba(251, 241, 199, 0.7); + background-gradient-direction: none; + background-color: rgba(251, 241, 199, 0.25); + border-color: rgba(251, 241, 199, 0.3); +} + +.window-list-item-box:active:hover, .window-list-item-box:checked:hover, .window-list-item-box:running:hover { + background-color: rgba(251, 241, 199, 0.3); +} + +.window-list-item-box:focus { + color: rgba(251, 241, 199, 0.7); + background-gradient-direction: none; + background-image: radial-gradient(5px 5px 45deg, circle cover, rgba(251, 241, 199, 0.7) 0%, rgba(251, 241, 199, 0.7) 100%); + border-color: #7daea3; + background-color: rgba(251, 241, 199, 0.2); +} + +.window-list-item-box:focus:hover { + background-color: rgba(251, 241, 199, 0.3); +} + +.panel-top .window-list-item-box:focus { + background-position: top center; +} + +.panel-bottom .window-list-item-box:focus { + background-position: bottom center; +} + +.panel-left .window-list-item-box:focus { + background-position: left center; +} + +.panel-right .window-list-item-box:focus { + background-position: right center; +} + +.window-list-item-box.right, .window-list-item-box.left { + padding-left: 0px; + padding-right: 0px; +} + +.window-list-item-box .progress { + background-gradient-direction: vertical; + background-gradient-start: #6c782e; + background-gradient-end: #6c782e; + border-radius: 12px; + box-shadow: none; +} + +.window-list-item-demands-attention { + background-gradient-start: #b47109; + background-gradient-end: #b47109; +} + +.window-list-preview { + padding: 6px; + spacing: 6px; + border: none; + background-color: #282524; + border-radius: 12px; + color: #fbf1c7; + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.35), 0 3px 12px rgba(0, 0, 0, 0.16); +} + +.grouped-window-list-thumbnail-label { + padding-left: 4px; +} + +.grouped-window-list-thumbnail-alert { + background-color: rgba(193, 74, 74, 0.5); +} + +.grouped-window-list-thumbnail-menu { + padding: 6px; + margin: 6px; + background-color: #242220; + border-radius: 12px; + background-clip: border-box; + box-shadow: 0 5px 12px rgba(0, 0, 0, 0.35); + border: 2px solid #7daea3; +} + +.grouped-window-list-thumbnail-menu .item-box { + padding: 6px; + border-radius: 12px; + spacing: 6px; + margin: 1px; +} + +.grouped-window-list-thumbnail-menu .item-box:outlined { + background-color: rgba(251, 241, 199, 0.1); +} + +.grouped-window-list-thumbnail-menu .item-box:hover { + background-color: rgba(251, 241, 199, 0.15); +} + +.grouped-window-list-thumbnail-menu .thumbnail { + width: 256px; +} + +.grouped-window-list-thumbnail-menu .separator { + width: 1px; + background-color: rgba(251, 241, 199, 0.12); +} + +.grouped-window-list-number-label { + z-index: 120; + text-shadow: none; + color: rgba(40, 40, 40, 0.87); + padding: 0; +} + +.grouped-window-list-button-label { + padding-left: 2px; +} + +.grouped-window-list-badge { + border-radius: 256px; + background-color: #7daea3; +} + +.grouped-window-list-item-box { + font-weight: normal; + transition-duration: 100ms; + border: none; + margin: 0; + color: rgba(251, 241, 199, 0.6); + border-radius: 0; + spacing: 6px; + border-bottom: 2px solid transparent; +} + +.grouped-window-list-item-box.top, .grouped-window-list-item-box.bottom { + padding: 0 2px; +} + +.grouped-window-list-item-box:hover { + color: rgba(251, 241, 199, 0.7); + background-gradient-direction: none; + background-color: rgba(251, 241, 199, 0.15); +} + +.grouped-window-list-item-box:active { + color: rgba(251, 241, 199, 0.7); + background-gradient-direction: none; + background-color: transparent; + border-color: rgba(251, 241, 199, 0.3); +} + +.grouped-window-list-item-box:active:hover { + background-color: rgba(251, 241, 199, 0.15); +} + +.grouped-window-list-item-box:focus { + color: rgba(251, 241, 199, 0.7); + background-gradient-direction: none; + background-color: rgba(251, 241, 199, 0.2); + border-color: #7daea3; +} + +.grouped-window-list-item-box:focus:hover { + background-color: rgba(251, 241, 199, 0.3); +} + +.grouped-window-list-item-box .progress { + background-gradient-direction: vertical; + background-gradient-start: #6c782e; + background-gradient-end: #6c782e; + border-radius: 12px; + box-shadow: none; +} + +.grouped-window-list-item-demands-attention { + background-gradient-start: #b47109; + background-gradient-end: #b47109; +} + +.sound-button { + width: 22px; + height: 13px; + padding: 8px; +} + +.sound-button-container { + padding-right: 3px; + padding-left: 3px; +} + +.sound-button StIcon { + icon-size: 1.4em; +} + +.sound-track-infos { + padding: 5px; +} + +.sound-track-info { + padding-top: 2px; + padding-bottom: 2px; +} + +.sound-track-info StIcon { + icon-size: 16px; +} + +.sound-track-info StLabel { + padding-left: 5px; + padding-right: 5px; +} + +.sound-track-box { + padding-left: 15px; + padding-right: 15px; + max-width: 220px; +} + +.sound-seek-box { + padding-left: 15px; +} + +.sound-seek-box StLabel { + padding-top: 2px; +} + +.sound-seek-box StIcon { + icon-size: 16px; +} + +.sound-seek-slider { + width: 140px; +} + +.sound-volume-menu-item { + padding: 0.4em 1.75em; +} + +.sound-volume-menu-item StIcon { + icon-size: 1.14em; + padding-left: 8px; + padding-right: 8px; +} + +.sound-playback-control { + padding: 5px 10px 10px 10px; +} + +.sound-player { + padding: 0 0; + margin-top: 6px; + border-radius: 12px; + background-color: #3a3731; + color: #fbf1c7; +} + +.sound-player > StBoxLayout:first-child { + padding: 5px 10px 10px 10px; + spacing: 0.5em; +} + +.sound-player > StBoxLayout:first-child StButton:small { + width: 24px; + height: 24px; + border-radius: 9999px; +} + +.sound-player > StBoxLayout:first-child StButton:small:hover { + background-color: rgba(251, 241, 199, 0.12); +} + +.sound-player > StBoxLayout:first-child StButton:small:active { + background-color: rgba(251, 241, 199, 0.3); +} + +.sound-player > StBoxLayout:first-child StButton:small StIcon { + icon-size: 16px; +} + +.sound-player-generic-coverart { + background: rgba(0, 0, 0, 0.2); +} + +.sound-player-overlay { + width: 290px; + height: 80px; + padding: 12px 18px; + spacing: 6px; + background-color: rgba(0, 0, 0, 0.45); + border: none; + border-radius: 0 0 12px 12px; + color: #fbf1c7; + text-shadow: none; +} + +.sound-player-overlay StButton { + width: 16px; + height: 16px; + padding: 8px; + margin: 0 6px 6px; + color: #fbf1c7; + border-radius: 9999px; + border: none; + text-shadow: none; +} + +.sound-player-overlay StButton StIcon { + icon-size: 16px; +} + +.sound-player-overlay StButton:hover { + background-color: rgba(251, 241, 199, 0.12); +} + +.sound-player-overlay StButton:active { + background-color: rgba(251, 241, 199, 0.3); +} + +.sound-player-overlay StButton:insensitive { + opacty: 0.35; + color: rgba(251, 241, 199, 0.5); +} + +.sound-player-overlay StLabel { + padding: 0 6px; +} + +.sound-player-overlay StBoxLayout { + padding-top: 2px; +} + +.sound-player .slider { + height: 0.5em; + padding: 0; + border: 0px solid rgba(12, 12, 12, 0.9); + border-bottom: 1px; + -slider-height: 0.5em; + -slider-background-color: #1b1b1b; + -slider-border-color: rgba(0, 0, 0, 0); + -slider-active-background-color: #7daea3; + -slider-active-border-color: rgba(0, 0, 0, 0); + -slider-border-width: 0px; + -slider-handle-radius: 0px; +} + +#workspaceSwitcher { + spacing: 0px; + padding: 3px; +} + +/* Controls the styling when using the "Simple buttons" option */ +.workspace-switcher { + padding-left: 3px; + padding-right: 3px; +} + +.workspace-button { + width: 20px; + height: 10px; + color: rgba(251, 241, 199, 0.7); + padding: 3px; + padding-top: 4px; + transition-duration: 300; +} + +.workspace-button:outlined, .workspace-button:outlined:hover { + color: #7daea3; +} + +.workspace-button:hover { + color: #9cc2b9; +} + +/* Controls the style when using the "Visual representation" option */ +.workspace-graph { + padding: 3px; + spacing: 3px; +} + +.workspace-graph .workspace { + border: 1px solid rgba(0, 0, 0, 0.4); + background-gradient-direction: none; + background-color: rgba(0, 0, 0, 0.2); +} + +.workspace-graph .workspace:active { + border: 1px solid #7daea3; + background-gradient-direction: none; +} + +.workspace-graph .workspace .windows { + -active-window-background: rgba(78, 78, 78, 0.75); + -active-window-border: rgba(0, 0, 0, 0.8); + -inactive-window-background: rgba(78, 78, 78, 0.75); + -inactive-window-border: rgba(0, 0, 0, 0.8); +} + +.workspace-graph .workspace:active .windows { + -active-window-background: rgba(91, 91, 91, 0.75); + -active-window-border: rgba(0, 0, 0, 0.8); + -inactive-window-background: rgba(53, 53, 53, 0.75); + -inactive-window-border: rgba(0, 0, 0, 0.8); +} + +#panel-launchers-box { + padding: 0 6px; +} + +#panel-launchers-box.vertical { + padding: 3px 0; +} + +.panel-launcher { + padding: 2px; + transition-duration: 200ms; + border-radius: 0; +} + +.panel-launcher:hover { + background-gradient-direction: none; + background-color: rgba(251, 241, 199, 0.1); +} + +.panel-launcher:active { + background-color: rgba(251, 241, 199, 0.2); +} + +.launcher { + padding: 2px; + spacing: 2px; + transition-duration: 0.2s; + border-radius: 0; +} + +.launcher:hover { + background-gradient-direction: none; + background-color: rgba(251, 241, 199, 0.1); +} + +.launcher:active { + background-color: rgba(251, 241, 199, 0.2); +} + +.launcher .icon-box { + padding: 2px; +} + +.applet-separator { + padding: 1px 3px; +} + +.applet-separator-line { + width: 1px; + background: rgba(251, 241, 199, 0.12); +} + +.applet-box { + padding: 0 6px; + color: rgba(251, 241, 199, 0.7); + text-shadow: none; + transition-duration: 100ms; + border-radius: 0; +} + +.applet-box.vertical { + padding: 6px 0; +} + +.applet-box:hover { + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.04); +} + +.applet-box:checked, .applet-box:checked:hover { + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.12); +} + +.applet-box:highlight { + background-image: none; + border-image: none; + background-color: rgba(193, 74, 74, 0.5); +} + +.applet-label { + font-weight: bold; + color: rgba(251, 241, 199, 0.7); +} + +.applet-box:checked .applet-label { + color: rgba(251, 241, 199, 0.7); + text-shadow: none; +} + +.applet-icon { + color: rgba(251, 241, 199, 0.7); + icon-size: 16px; +} + +.applet-box:checked .applet-icon { + color: rgba(251, 241, 199, 0.7); + text-shadow: none; +} + +.user-icon { + width: 32px; + height: 32px; + background-color: transparent; + border: none; + border-radius: 0; +} + +.user-label { + color: #fbf1c7; + font-size: 1em; + font-weight: bold; + margin: 0px; +} + +.desklet { + color: #fbf1c7; +} + +.desklet:highlight { + background-color: rgba(193, 74, 74, 0.5); +} + +.desklet-with-borders { + color: #fbf1c7; + background-color: rgba(32, 32, 32, 0.9); + padding: 12px; + padding-bottom: 16px; +} + +.desklet-with-borders:highlight { + background-color: rgba(193, 74, 74, 0.5); +} + +.desklet-with-borders-and-header { + color: #fbf1c7; + background-color: rgba(32, 32, 32, 0.9); + border-radius: 6px; + border-radius-topleft: 0; + border-radius-topright: 0; + padding: 12px; + padding-bottom: 17px; +} + +.desklet-with-borders-and-header:highlight { + background-color: rgba(193, 74, 74, 0.5); +} + +.desklet-header { + color: #fbf1c7; + background-color: rgba(32, 32, 32, 0.9); + border-radius: 0; + border-radius-topleft: 6px; + border-radius-topright: 6px; + font-size: 1em; + padding: 12px; + padding-bottom: 6px; +} + +.desklet-drag-placeholder { + border: 2px solid #7daea3; + background-color: rgba(125, 174, 163, 0.3); +} + +.photoframe-box { + color: #fbf1c7; + background-color: rgba(32, 32, 32, 0.9); + padding: 12px; + padding-bottom: 16px; +} + +.workspace-osd { + text-shadow: black 5px 5px 5px; + font-weight: bold; + font-size: 48pt; +} + +.notification-applet-padding { + padding: 0.5em 1em; +} + +.notification-applet-container { + max-height: 9999px; +} + +.tile-preview, +.tile-preview.snap, +.tile-hud, +.tile-hud.snap { + background-color: rgba(125, 174, 163, 0.3); + border: 1px solid #7daea3; +} + +.xkcd-box { + padding: 6px; + border: 0px; + background-color: rgba(0, 0, 0, 0); + border-radius: 0px; +} diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/thumbnail.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/thumbnail.png new file mode 100755 index 0000000..0bfc66d Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/cinnamon/thumbnail.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-left.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-left.svg new file mode 100755 index 0000000..ec8b478 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-left.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#FFFFFF" opacity="0.7"> + <path d="m10 3v10l-5-5z"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-right.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-right.svg new file mode 100755 index 0000000..6fc5556 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-arrow-right.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#FFFFFF" opacity="0.7"> + <path d="m6 3v10l5-5z"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-today.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-today.svg new file mode 100755 index 0000000..fc3fdf7 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/calendar-today.svg @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="48" + version="1.1" + id="svg6" + sodipodi:docname="calendar-today.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs10" /> + <sodipodi:namedview + id="namedview8" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="6.9532167" + inkscape:cx="-13.087468" + inkscape:cy="15.676198" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg6"> + <inkscape:grid + type="xygrid" + id="grid293" /> + </sodipodi:namedview> + <g + transform="matrix(2,0,0,2,-939.14001,-1079.92)" + id="g4" + style="fill:#ffffff"> + <circle + cx="481.57001" + cy="559.46002" + r="1.5" + color="#000000" + color-rendering="auto" + fill-opacity="0.2" + image-rendering="auto" + shape-rendering="auto" + solid-color="#000000" + style="isolation:auto;mix-blend-mode:normal;paint-order:normal;fill:#ffffff" + id="circle2" /> + </g> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-dark.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-dark.svg new file mode 100755 index 0000000..d8e58fd --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-dark.svg @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg1516" + sodipodi:docname="checkbox-dark.svg" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs1520"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1446" + x="-0.05808" + y="-0.05808" + width="1.11616" + height="1.11616"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.484" + id="feGaussianBlur1448" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview1518" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="4.9166667" + inkscape:cx="2.338983" + inkscape:cy="9.2542372" + inkscape:window-width="1920" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg1516" /> + <rect + style="opacity:0.25;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter1446)" + id="rect890" + width="20" + height="20" + x="2" + y="3" + rx="4" + ry="4" /> + <rect + style="fill:#80aa9e;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + id="rect616" + width="20" + height="20" + x="2" + y="2" + rx="4" + ry="4" /> + <path + id="rect340" + d="m 18.36396,7.7576861 c -0.391736,-0.3917365 -1.022477,-0.3917368 -1.414214,0 L 10.585785,14.121648 7.0502516,10.586113 c -0.3917367,-0.391737 -1.0224771,-0.391736 -1.4142135,0 -0.3917365,0.391736 -0.3917368,1.022477 0,1.414214 l 4.2426409,4.242641 c 0.02448,0.02448 0.04973,0.04625 0.07596,0.06767 0.393511,0.321347 0.971002,0.299581 1.338255,-0.06767 l 7.071068,-7.0710684 c 0.391737,-0.3917367 0.391736,-1.0224771 0,-1.4142135 z" + style="fill:#1a1b26;fill-opacity:1" /> + <path + id="rect885" + style="opacity:0.1;fill:#ffffff;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + d="M 6,2 C 3.7840022,2 2,3.7840022 2,6 V 7 C 2,4.7840022 3.7840022,3 6,3 h 12 c 2.215998,0 4,1.7840022 4,4 V 6 C 22,3.7840022 20.215998,2 18,2 Z" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-active.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-active.svg new file mode 100755 index 0000000..9cfdefd --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-active.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" r="10" fill="#ffffff" opacity=".25"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-hover.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-hover.svg new file mode 100755 index 0000000..ef5123a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off-hover.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" r="10" fill="#ffffff" opacity=".2"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off.svg new file mode 100755 index 0000000..b00efa6 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox-off.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" r="10" fill="#ffffff" opacity=".12"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox.svg new file mode 100755 index 0000000..0c79c35 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/checkbox.svg @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg439" + sodipodi:docname="checkbox.svg" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs443"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter1446" + x="-0.05808" + y="-0.05808" + width="1.11616" + height="1.11616"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.484" + id="feGaussianBlur1448" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview441" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="6.9532167" + inkscape:cx="-3.955004" + inkscape:cy="14.309924" + inkscape:window-width="1920" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg439"> + <inkscape:grid + type="xygrid" + id="grid562" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <rect + style="opacity:0.25;fill:#000000;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;filter:url(#filter1446)" + id="rect890" + width="20" + height="20" + x="2" + y="3" + rx="4" + ry="4" /> + <rect + style="opacity:1;fill:#266b79;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + id="rect616" + width="20" + height="20" + x="2" + y="2" + rx="4" + ry="4" /> + <path + id="rect340" + d="m 18.36396,7.7576861 c -0.391736,-0.3917365 -1.022477,-0.3917368 -1.414214,0 L 10.585785,14.121648 7.0502516,10.586113 c -0.3917367,-0.391737 -1.0224771,-0.391736 -1.4142135,0 -0.3917365,0.391736 -0.3917368,1.022477 0,1.414214 l 4.2426409,4.242641 c 0.02448,0.02448 0.04973,0.04625 0.07596,0.06767 0.393511,0.321347 0.971002,0.299581 1.338255,-0.06767 l 7.071068,-7.0710684 c 0.391737,-0.3917367 0.391736,-1.0224771 0,-1.4142135 z" + style="fill:#e9e9ed;fill-opacity:1" /> + <path + id="rect885" + style="opacity:0.1;fill:#ffffff;fill-opacity:1;stroke-width:2;stroke-linecap:round;stroke-linejoin:round" + d="M 6 2 C 3.7840022 2 2 3.7840022 2 6 L 2 7 C 2 4.7840022 3.7840022 3 6 3 L 18 3 C 20.215998 3 22 4.7840022 22 7 L 22 6 C 22 3.7840022 20.215998 2 18 2 L 6 2 z " /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/dash-placeholder.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/dash-placeholder.svg new file mode 100755 index 0000000..172156a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/dash-placeholder.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"> + <circle cx="12" cy="12" r="12" opacity="0.3"/> + <circle cx="12" cy="12" r="4"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-events.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-events.svg new file mode 100755 index 0000000..239177d --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-events.svg @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="48" + height="48" + viewBox="0 0 48 48" + id="svg2" + version="1.1" + inkscape:version="0.92.3 (2405546, 2018-03-11)" + sodipodi:docname="no-events.svg"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + <cc:license + rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#Notice" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#Attribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + <cc:requires + rdf:resource="http://creativecommons.org/ns#ShareAlike" /> + </cc:License> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1413" + inkscape:window-height="955" + id="namedview8" + showgrid="true" + inkscape:zoom="4.9166667" + inkscape:cx="-16.677966" + inkscape:cy="15.864407" + inkscape:window-x="46" + inkscape:window-y="71" + inkscape:window-maximized="0" + inkscape:current-layer="svg2"> + <inkscape:grid + type="xygrid" + id="grid4134" /> + </sodipodi:namedview> + <path + d="M0 0h48v48H0z" + fill="none" + id="path4" /> + <path + d="m 38,6 -2,0 0,-4 -4,0 0,4 -16,0 0,-4 -4,0 0,4 -2,0 C 7.79,6 6.02,7.79 6.02,10 L 6,38 c 0,2.21 1.79,4 4,4 l 28,0 c 2.21,0 4,-1.79 4,-4 L 42,10 C 42,7.79 40.21,6 38,6 Z m 0,32 -28,0 0,-22 28,0 z" + id="path6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="sccccccccsccsssssccccc" + style="fill:#f5f5f5;fill-opacity:1;opacity:0.54" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-notifications.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-notifications.svg new file mode 100755 index 0000000..ae09f92 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/no-notifications.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="#FFFFFF" opacity="0.5"> + <path d="M24 44c2.21 0 4-1.79 4-4h-8c0 2.21 1.79 4 4 4zm12-12V22c0-6.15-3.27-11.28-9-12.64V8c0-1.66-1.34-3-3-3s-3 1.34-3 3v1.36c-5.73 1.36-9 6.49-9 12.64v10l-4 4v2h32v-2l-4-4zm-4 2H16V22c0-4.97 3.03-9 8-9s8 4.03 8 9v12z"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/noise-texture.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/noise-texture.svg new file mode 100755 index 0000000..484f6c8 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/noise-texture.svg @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="1600" + height="900" + viewBox="0 0 1600 900" + version="1.1" + id="svg13" + sodipodi:docname="noise-texture.svg" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"> + <metadata + id="metadata17"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="698" + id="namedview15" + showgrid="false" + inkscape:zoom="0.26222222" + inkscape:cx="647.80786" + inkscape:cy="422.79535" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg13" /> + <defs + id="defs9"> + <radialGradient + id="a" + gradientTransform="matrix(1 1 -1 1 0.5 -0.5)"> + <stop + stop-color="#455A64" + stop-opacity="0" + offset="0.25" + id="stop2" + style="stop-color:#444444;stop-opacity:0" /> + <stop + stop-color="#455A64" + stop-opacity="0.5" + offset="0.75" + id="stop4" + style="stop-color:#444444;stop-opacity:0.50196081" /> + <stop + stop-color="#455A64" + stop-opacity="1" + offset="1" + id="stop6" + style="stop-color:#444444;stop-opacity:1" /> + </radialGradient> + </defs> + <rect + width="1600" + height="900" + fill="url(#a)" + id="rect11" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/process-working.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/process-working.svg new file mode 100755 index 0000000..0f311b0 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/process-working.svg @@ -0,0 +1,72 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="32" viewBox="0 0 512 32"> + <defs> + <g id="g" fill="#FFFFFF" opacity="0.7"> + <circle cx="8" cy="8" r="8" fill="none"/> + <path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7h-3a4 4 0 0 1 -4 4 4 4 0 0 1 -4 -4 4 4 0 0 1 4 -4v-3z"/> + </g> + </defs> + <use xlink:href="#g" transform="translate(0) rotate(0 8 8)"/> + <use xlink:href="#g" transform="translate(16) rotate(5.625 8 8)"/> + <use xlink:href="#g" transform="translate(32) rotate(11.25 8 8)"/> + <use xlink:href="#g" transform="translate(48) rotate(16.875 8 8)"/> + <use xlink:href="#g" transform="translate(64) rotate(22.5 8 8)"/> + <use xlink:href="#g" transform="translate(80) rotate(28.125 8 8)"/> + <use xlink:href="#g" transform="translate(96) rotate(33.75 8 8)"/> + <use xlink:href="#g" transform="translate(112) rotate(39.375 8 8)"/> + <use xlink:href="#g" transform="translate(128) rotate(45 8 8)"/> + <use xlink:href="#g" transform="translate(144) rotate(50.625 8 8)"/> + <use xlink:href="#g" transform="translate(160) rotate(56.25 8 8)"/> + <use xlink:href="#g" transform="translate(176) rotate(61.875 8 8)"/> + <use xlink:href="#g" transform="translate(192) rotate(67.5 8 8)"/> + <use xlink:href="#g" transform="translate(208) rotate(73.125 8 8)"/> + <use xlink:href="#g" transform="translate(224) rotate(78.75 8 8)"/> + <use xlink:href="#g" transform="translate(240) rotate(84.375 8 8)"/> + <use xlink:href="#g" transform="translate(256) rotate(90 8 8)"/> + <use xlink:href="#g" transform="translate(272) rotate(95.625 8 8)"/> + <use xlink:href="#g" transform="translate(288) rotate(101.25 8 8)"/> + <use xlink:href="#g" transform="translate(304) rotate(106.875 8 8)"/> + <use xlink:href="#g" transform="translate(320) rotate(112.5 8 8)"/> + <use xlink:href="#g" transform="translate(336) rotate(118.125 8 8)"/> + <use xlink:href="#g" transform="translate(352) rotate(123.75 8 8)"/> + <use xlink:href="#g" transform="translate(368) rotate(129.375 8 8)"/> + <use xlink:href="#g" transform="translate(384) rotate(135 8 8)"/> + <use xlink:href="#g" transform="translate(400) rotate(140.625 8 8)"/> + <use xlink:href="#g" transform="translate(416) rotate(146.25 8 8)"/> + <use xlink:href="#g" transform="translate(432) rotate(151.875 8 8)"/> + <use xlink:href="#g" transform="translate(448) rotate(157.5 8 8)"/> + <use xlink:href="#g" transform="translate(464) rotate(163.125 8 8)"/> + <use xlink:href="#g" transform="translate(480) rotate(168.75 8 8)"/> + <use xlink:href="#g" transform="translate(496) rotate(174.375 8 8)"/> + <use xlink:href="#g" transform="translate(0 16) rotate(180 8 8)"/> + <use xlink:href="#g" transform="translate(16 16) rotate(185.625 8 8)"/> + <use xlink:href="#g" transform="translate(32 16) rotate(191.25 8 8)"/> + <use xlink:href="#g" transform="translate(48 16) rotate(196.875 8 8)"/> + <use xlink:href="#g" transform="translate(64 16) rotate(202.5 8 8)"/> + <use xlink:href="#g" transform="translate(80 16) rotate(208.125 8 8)"/> + <use xlink:href="#g" transform="translate(96 16) rotate(213.75 8 8)"/> + <use xlink:href="#g" transform="translate(112 16) rotate(219.375 8 8)"/> + <use xlink:href="#g" transform="translate(128 16) rotate(225 8 8)"/> + <use xlink:href="#g" transform="translate(144 16) rotate(230.625 8 8)"/> + <use xlink:href="#g" transform="translate(160 16) rotate(236.25 8 8)"/> + <use xlink:href="#g" transform="translate(176 16) rotate(241.875 8 8)"/> + <use xlink:href="#g" transform="translate(192 16) rotate(247.5 8 8)"/> + <use xlink:href="#g" transform="translate(208 16) rotate(253.125 8 8)"/> + <use xlink:href="#g" transform="translate(224 16) rotate(258.75 8 8)"/> + <use xlink:href="#g" transform="translate(240 16) rotate(264.375 8 8)"/> + <use xlink:href="#g" transform="translate(256 16) rotate(270 8 8)"/> + <use xlink:href="#g" transform="translate(272 16) rotate(275.625 8 8)"/> + <use xlink:href="#g" transform="translate(288 16) rotate(281.25 8 8)"/> + <use xlink:href="#g" transform="translate(304 16) rotate(286.875 8 8)"/> + <use xlink:href="#g" transform="translate(320 16) rotate(292.5 8 8)"/> + <use xlink:href="#g" transform="translate(336 16) rotate(298.125 8 8)"/> + <use xlink:href="#g" transform="translate(352 16) rotate(303.75 8 8)"/> + <use xlink:href="#g" transform="translate(368 16) rotate(309.375 8 8)"/> + <use xlink:href="#g" transform="translate(384 16) rotate(315 8 8)"/> + <use xlink:href="#g" transform="translate(400 16) rotate(320.625 8 8)"/> + <use xlink:href="#g" transform="translate(416 16) rotate(326.25 8 8)"/> + <use xlink:href="#g" transform="translate(432 16) rotate(331.875 8 8)"/> + <use xlink:href="#g" transform="translate(448 16) rotate(337.5 8 8)"/> + <use xlink:href="#g" transform="translate(464 16) rotate(343.125 8 8)"/> + <use xlink:href="#g" transform="translate(480 16) rotate(348.75 8 8)"/> + <use xlink:href="#g" transform="translate(496 16) rotate(354.375 8 8)"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-off.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-off.svg new file mode 100755 index 0000000..6cd17d8 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-off.svg @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="24" + version="1.1" + id="svg3299" + sodipodi:docname="toggle-off.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs3303" /> + <sodipodi:namedview + id="namedview3301" + pagecolor="#474747" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="5.9" + inkscape:cx="5.4237288" + inkscape:cy="12.542373" + inkscape:window-width="1368" + inkscape:window-height="700" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg3299"> + <inkscape:grid + type="xygrid" + id="grid3422" /> + </sodipodi:namedview> + <rect + transform="scale(-1,1)" + x="-48" + y="-0.019988" + width="48" + height="24" + rx="12" + ry="12" + fill="#ffffff" + opacity="0.45" + stroke-width="0" + style="paint-order:stroke fill markers" + id="rect3295" /> + <circle + cx="12" + cy="12" + r="9" + fill="#ffffff" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#242424;fill-opacity:1" + id="circle3297" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on-dark.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on-dark.svg new file mode 100755 index 0000000..11512bf --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on-dark.svg @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="24" + version="1.1" + id="svg939" + sodipodi:docname="toggle-on-dark.svg" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs943"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter863" + x="-0.14699999" + y="-0.14699999" + width="1.294" + height="1.294"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="1.1025" + id="feGaussianBlur865" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview941" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="2.95" + inkscape:cx="74.067797" + inkscape:cy="14.40678" + inkscape:window-width="1920" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg939"> + <inkscape:grid + type="xygrid" + id="grid1663" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <rect + transform="scale(-1,1)" + x="-48" + y="-0.019988" + width="48" + height="24" + rx="12" + ry="12" + fill="#009688" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#80aa9e;fill-opacity:1" + id="rect2" /> + <circle + cx="36" + cy="13" + r="9" + fill="#ffffff" + stroke-width="0" + style="opacity:0.35;fill:#000000;paint-order:stroke fill markers;filter:url(#filter863)" + id="circle307" /> + <circle + cx="36" + cy="12" + r="9" + fill="#ffffff" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#1a1b26;fill-opacity:1" + id="circle4" /> + <path + id="rect876" + style="opacity:0.1;fill:#ffffff;paint-order:stroke fill markers" + d="m 12,-0.01953125 c -6.6479934,0 -12,5.35200665 -12,12.00000025 0,0.171056 0.00665429,0.340494 0.01367188,0.509765 C 0.27938822,6.080891 5.523063,1 12,1 H 36 C 42.476937,1 47.720612,6.080891 47.986328,12.490234 47.993346,12.320963 48,12.151525 48,11.980469 48,5.3324754 42.647993,-0.01953125 36,-0.01953125 Z" /> + <path + id="circle1665" + style="paint-order:stroke fill markers;fill:#ffffff;fill-opacity:1;opacity:0.1" + d="M 36 3 A 9 9 0 0 0 27 12 A 9 9 0 0 0 27.035156 12.5 A 9 9 0 0 1 36 4 A 9 9 0 0 1 44.974609 12.359375 A 9 9 0 0 0 45 12 A 9 9 0 0 0 36 3 z " /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on.svg new file mode 100755 index 0000000..3a729d4 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/assets/toggle-on.svg @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="24" + version="1.1" + id="svg6" + sodipodi:docname="toggle-on.svg" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs10"> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter863" + x="-0.14699999" + y="-0.14699999" + width="1.294" + height="1.294"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="1.1025" + id="feGaussianBlur865" /> + </filter> + </defs> + <sodipodi:namedview + id="namedview8" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="true" + inkscape:zoom="4.17193" + inkscape:cx="17.138351" + inkscape:cy="19.295626" + inkscape:window-width="1920" + inkscape:window-height="1009" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg6"> + <inkscape:grid + type="xygrid" + id="grid293" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" + visible="true" /> + </sodipodi:namedview> + <rect + transform="scale(-1,1)" + x="-48" + y="-0.019988" + width="48" + height="24" + rx="12" + ry="12" + fill="#009688" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#266b79;fill-opacity:1" + id="rect2" /> + <circle + cx="36" + cy="13" + r="9" + fill="#ffffff" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#000000;filter:url(#filter863);opacity:0.35" + id="circle307" /> + <circle + cx="36" + cy="12" + r="9" + fill="#ffffff" + stroke-width="0" + style="paint-order:stroke fill markers;fill:#e9e9ed;fill-opacity:1" + id="circle4" /> + <path + id="rect876" + style="paint-order:stroke fill markers;fill:#ffffff;opacity:0.1" + d="M -12 -0.01953125 C -5.3520066 -0.01953125 0 5.3324754 0 11.980469 C 0 12.151525 -0.0066542885 12.320963 -0.013671875 12.490234 C -0.27938822 6.080891 -5.523063 1 -12 1 L -36 1 C -42.476937 1 -47.720612 6.080891 -47.986328 12.490234 C -47.993346 12.320963 -48 12.151525 -48 11.980469 C -48 5.3324754 -42.647993 -0.01953125 -36 -0.01953125 L -12 -0.01953125 z " + transform="scale(-1,1)" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/gnome-shell.css b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/gnome-shell.css new file mode 100755 index 0000000..37a4fa1 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/gnome-shell.css @@ -0,0 +1,6084 @@ +/* This stylesheet is generated, DO NOT EDIT */ +/* Copyright 2009, 2015 Red Hat, Inc. + * + * Portions adapted from Mx's data/style/default.css + * Copyright 2009 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* General Typography */ +.search-statustext, .app-folder-dialog .folder-name-container .folder-name-label, +.app-folder-dialog .folder-name-container .folder-name-entry { + font-weight: 800; + font-size: 20pt; +} + +.message-notification-group .message-group-header .message-group-title, .message-list .message-list-placeholder, .message-dialog-content .message-dialog-title, .lg-debug-flags-header { + font-weight: 800; + font-size: 15pt; +} + +.quick-toggle-menu .header .title { + font-weight: 700; + font-size: 15pt; +} + +.bt-menu-placeholder.popup-menu-item, .restart-message, .polkit-dialog-user-layout .polkit-dialog-user-label, +.polkit-dialog-user-layout .polkit-dialog-user-root-label, .message-dialog-content .message-dialog-title.lightweight { + font-weight: 700; + font-size: 13pt; +} + +.background-app-item .title, .message-list-controls, .dialog-list .dialog-list-title, .world-clocks-button .world-clocks-header, .calendar .calendar-month-label, .lg-extension-name { + font-weight: 700; + font-size: 11pt; +} + +.quick-toggle-menu .header .subtitle, .app-menu .popup-inactive-menu-item:first-child > StLabel { + font-weight: 700; + font-size: 9pt; +} + +.icon-label-button-container, .background-app-item .subtitle, .message .message-header .message-header-content .event-time, .prompt-dialog .prompt-dialog-error-label, +.prompt-dialog .prompt-dialog-info-label, +.prompt-dialog .prompt-dialog-null-label, .run-dialog .run-dialog-description, .dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + font-weight: 400; + font-size: 9pt; +} + +.calendar .calendar-week-number, .calendar .calendar-day-heading { + font-weight: 400; + font-size: 8pt; +} + +.calendar .calendar-day-heading { + font-feature-settings: 'tnum'; +} + +.ripple-pointer-location { + width: 48px; + height: 48px; + border-radius: 24px; + background-color: rgba(219, 233, 230, 0.3); + box-shadow: 0 0 2px 2px #bcd5cf; +} + +.pie-timer { + width: 60px; + height: 60px; + -pie-border-width: 3px; + -pie-border-color: #7daea3; + -pie-background-color: rgba(251, 252, 252, 0.3); +} + +.magnifier-zoom-region { + border: 2px solid #7daea3; +} + +.magnifier-zoom-region.full-screen { + border-width: 0; +} + +.shell-link { + border-radius: 12px; + color: #83b193; +} + +.shell-link:hover { + color: #83b193; + background-color: rgba(131, 177, 147, 0.15); +} + +.shell-link:active { + color: #83b193; + background-color: rgba(131, 177, 147, 0.25); +} + +.lowres-icon { + icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); +} + +.icon-dropshadow { + icon-shadow: 0 3px 6px rgba(0, 0, 0, 0.2); +} + +/* Buttons */ +.quick-settings-system-item .icon-button, .quick-settings-system-item .background-app-item .close-button, .background-app-item .quick-settings-system-item .close-button, .quick-settings-system-item .message .message-header .message-expand-button, .message .message-header .quick-settings-system-item .message-expand-button, +.quick-settings-system-item .message .message-header .message-close-button, +.message .message-header .quick-settings-system-item .message-close-button, .quick-settings-system-item .message-notification-group .message-collapse-button, .message-notification-group .quick-settings-system-item .message-collapse-button, .hotplug-notification-item, .button { + color: #fbf1c7; + background-color: #282524; + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:focus, .quick-settings-system-item .background-app-item .close-button:focus, .background-app-item .quick-settings-system-item .close-button:focus, .quick-settings-system-item .message .message-header .message-expand-button:focus, .message .message-header .quick-settings-system-item .message-expand-button:focus, +.quick-settings-system-item .message .message-header .message-close-button:focus, +.message .message-header .quick-settings-system-item .message-close-button:focus, .quick-settings-system-item .message-notification-group .message-collapse-button:focus, .message-notification-group .quick-settings-system-item .message-collapse-button:focus, .hotplug-notification-item:focus, .button:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:hover, .quick-settings-system-item .background-app-item .close-button:hover, .background-app-item .quick-settings-system-item .close-button:hover, .quick-settings-system-item .message .message-header .message-expand-button:hover, .message .message-header .quick-settings-system-item .message-expand-button:hover, +.quick-settings-system-item .message .message-header .message-close-button:hover, +.message .message-header .quick-settings-system-item .message-close-button:hover, .quick-settings-system-item .message-notification-group .message-collapse-button:hover, .message-notification-group .quick-settings-system-item .message-collapse-button:hover, .hotplug-notification-item:hover, .button:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:active, .quick-settings-system-item .background-app-item .close-button:active, .background-app-item .quick-settings-system-item .close-button:active, .quick-settings-system-item .message .message-header .message-expand-button:active, .message .message-header .quick-settings-system-item .message-expand-button:active, +.quick-settings-system-item .message .message-header .message-close-button:active, +.message .message-header .quick-settings-system-item .message-close-button:active, .quick-settings-system-item .message-notification-group .message-collapse-button:active, .message-notification-group .quick-settings-system-item .message-collapse-button:active, .hotplug-notification-item:active, .button:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.quick-settings-system-item .icon-button:insensitive, .quick-settings-system-item .background-app-item .close-button:insensitive, .background-app-item .quick-settings-system-item .close-button:insensitive, .quick-settings-system-item .message .message-header .message-expand-button:insensitive, .message .message-header .quick-settings-system-item .message-expand-button:insensitive, +.quick-settings-system-item .message .message-header .message-close-button:insensitive, +.message .message-header .quick-settings-system-item .message-close-button:insensitive, .quick-settings-system-item .message-notification-group .message-collapse-button:insensitive, .message-notification-group .quick-settings-system-item .message-collapse-button:insensitive, .hotplug-notification-item:insensitive, .button:insensitive { + color: rgba(251, 241, 199, 0.35); + background-color: #282524; + box-shadow: none !important; +} + +.modal-dialog-button, .lg-obj-inspector-button, .candidate-page-button, .modal-dialog-linked-button, .icon-button.flat, .background-app-item .flat.close-button, .message-notification-group .flat.message-collapse-button, .message .message-header .flat.message-expand-button, +.message .message-header .flat.message-close-button, .button.flat, .popup-menu .button { + color: #fbf1c7; + background-color: transparent; + box-shadow: none !important; +} + +.modal-dialog-button:focus, .lg-obj-inspector-button:focus, .candidate-page-button:focus, .modal-dialog-linked-button:focus, .icon-button.flat:focus, .background-app-item .flat.close-button:focus, .message-notification-group .flat.message-collapse-button:focus, .message .message-header .flat.message-expand-button:focus, +.message .message-header .flat.message-close-button:focus, .button.flat:focus, .popup-menu .button:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.modal-dialog-button:hover, .lg-obj-inspector-button:hover, .candidate-page-button:hover, .modal-dialog-linked-button:hover, .icon-button.flat:hover, .background-app-item .flat.close-button:hover, .message-notification-group .flat.message-collapse-button:hover, .message .message-header .flat.message-expand-button:hover, +.message .message-header .flat.message-close-button:hover, .button.flat:hover, .popup-menu .button:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.modal-dialog-button:active, .lg-obj-inspector-button:active, .candidate-page-button:active, .modal-dialog-linked-button:active, .icon-button.flat:active, .background-app-item .flat.close-button:active, .message-notification-group .flat.message-collapse-button:active, .message .message-header .flat.message-expand-button:active, +.message .message-header .flat.message-close-button:active, .button.flat:active, .popup-menu .button:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.modal-dialog-button:insensitive, .lg-obj-inspector-button:insensitive, .candidate-page-button:insensitive, .modal-dialog-linked-button:insensitive, .icon-button.flat:insensitive, .background-app-item .flat.close-button:insensitive, .message-notification-group .flat.message-collapse-button:insensitive, .message .message-header .flat.message-expand-button:insensitive, +.message .message-header .flat.message-close-button:insensitive, .button.flat:insensitive, .popup-menu .button:insensitive { + background-color: transparent; + color: rgba(251, 241, 199, 0.35); + box-shadow: none !important; +} + +.icon-button.default, .background-app-item .default.close-button, .message-notification-group .default.message-collapse-button, .message .message-header .default.message-expand-button, +.message .message-header .default.message-close-button, .button.default { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; + box-shadow: none !important; +} + +.icon-button.default:focus, .background-app-item .default.close-button:focus, .message-notification-group .default.message-collapse-button:focus, .message .message-header .default.message-expand-button:focus, +.message .message-header .default.message-close-button:focus, .button.default:focus { + color: rgba(40, 40, 40, 0.87); + background-color: rgba(40, 40, 40, 0.08); + box-shadow: none !important; +} + +.icon-button.default:hover, .background-app-item .default.close-button:hover, .message-notification-group .default.message-collapse-button:hover, .message .message-header .default.message-expand-button:hover, +.message .message-header .default.message-close-button:hover, .button.default:hover { + color: rgba(40, 40, 40, 0.87); + background-color: rgba(40, 40, 40, 0.12); + box-shadow: none !important; +} + +.icon-button.default:insensitive, .background-app-item .default.close-button:insensitive, .message-notification-group .default.message-collapse-button:insensitive, .message .message-header .default.message-expand-button:insensitive, +.message .message-header .default.message-close-button:insensitive, .button.default:insensitive { + color: rgba(40, 40, 40, 0.35); + background-color: #7daea3; + box-shadow: none !important; +} + +.icon-button.default:active, .background-app-item .default.close-button:active, .message-notification-group .default.message-collapse-button:active, .message .message-header .default.message-expand-button:active, +.message .message-header .default.message-close-button:active, .button.default:active { + color: rgba(40, 40, 40, 0.87); + background-color: rgba(40, 40, 40, 0.2); + box-shadow: none !important; +} + +.button { + min-height: 20px; + padding: 6px 12px; + border-radius: 12px; + border: none; +} + +.icon-button, .background-app-item .close-button, .message-notification-group .message-collapse-button, .message .message-header .message-expand-button, +.message .message-header .message-close-button { + border-radius: 9999px; + padding: 6px; + min-height: 1.091em; +} + +.icon-button StIcon, .background-app-item .close-button StIcon, .message-notification-group .message-collapse-button StIcon, .message .message-header .message-expand-button StIcon, +.message .message-header .message-close-button StIcon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.screenshot-ui-show-pointer-button, .screenshot-ui-type-button { + color: #fbf1c7; + background-color: transparent; + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:insensitive, .screenshot-ui-type-button:insensitive { + color: rgba(251, 241, 199, 0.35); + background-color: #282828; + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:focus, .screenshot-ui-type-button:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:hover, .screenshot-ui-type-button:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:active, .screenshot-ui-type-button:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.screenshot-ui-show-pointer-button:outlined, .screenshot-ui-type-button:outlined, .screenshot-ui-show-pointer-button:checked, .screenshot-ui-type-button:checked { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; + box-shadow: none !important; +} + +/* Check Boxes */ +.check-box StBoxLayout { + spacing: 0.8em; +} + +.check-box StBin { + width: 24px; + height: 24px; + padding: 3px; +} + +.check-box StBin, .check-box:focus StBin { + background-image: url("assets/checkbox-off.svg"); +} + +.check-box:hover StBin { + background-image: url("assets/checkbox-off-hover.svg"); +} + +.check-box:active StBin { + background-image: url("assets/checkbox-off-active.svg"); +} + +.check-box:checked StBin, .check-box:focus:checked StBin { + background-image: url("assets/checkbox-dark.svg"); +} + +/* Activities Ripple */ +.ripple-box { + background-color: rgba(125, 174, 163, 0.35); + box-shadow: 0 0 2px 2px #bcd5cf; + width: 52px; + height: 52px; + border-radius: 0 0 52px 0; +} + +.ripple-box:rtl { + border-radius: 0 0 0 52px; +} + +/* Modal Dialogs */ +.candidate-popup-content, .modal-dialog { + background-color: #242220; + border-radius: 21px; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.35); + border: 2px solid #fbf1c7; +} + +.modal-dialog-button:last-child, .modal-dialog-linked-button:last-child { + color: #282828; + background-color: #7daea3; +} + +.modal-dialog-button:hover:last-child, .modal-dialog-linked-button:hover:last-child { + color: #282828; + background-color: #99c0b7; +} + +.modal-dialog-button:active:last-child, .modal-dialog-linked-button:active:last-child { + color: #282828; + background-color: #6da498; +} + +.modal-dialog-button:insensitive:last-child, .modal-dialog-linked-button:insensitive:last-child { + color: #282828; + background-color: rgba(125, 174, 163, 0.05); +} + +.headline { + font-size: 12ptpt; +} + +.modal-dialog { + color: rgba(251, 241, 199, 0.7); + padding: 0 6px 6px 6px; +} + +.modal-dialog-linked-button { + min-height: 32px !important; + padding: 6px !important; + margin: 3px !important; + border: none !important; + border-radius: 12px; +} + +.modal-dialog-linked-button:first-child { + background-color: rgba(251, 241, 199, 0.04); +} + +.modal-dialog-linked-button:first-child:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.modal-dialog-linked-button:first-child:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.modal-dialog-linked-button:first-child:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.modal-dialog .modal-dialog-content-box { + margin: 30px 42px; + spacing: 30px; + max-width: 28em; +} + +.end-session-dialog { + width: 30em; +} + +.end-session-dialog .end-session-dialog-battery-warning, +.end-session-dialog .dialog-list-title { + color: #b47109; +} + +.message-dialog-content { + spacing: 18px; +} + +.message-dialog-content .message-dialog-title { + text-align: center; + font-size: 18pt; + font-weight: 800; +} + +.message-dialog-content .message-dialog-title.lightweight { + font-size: 13pt; + font-weight: 800; +} + +.message-dialog-content .message-dialog-description { + text-align: center; +} + +.dialog-list { + spacing: 18px; +} + +.dialog-list .dialog-list-title { + text-align: center; + font-weight: bold; +} + +.dialog-list .dialog-list-scrollview { + max-height: 200px; +} + +.dialog-list .dialog-list-box { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-title { + font-weight: bold; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + color: rgba(251, 241, 199, 0.7); + font-size: 10ptpt; +} + +.run-dialog .modal-dialog-content-box { + margin-top: 24px; + margin-bottom: 12px; +} + +.run-dialog .run-dialog-entry { + width: 20em; +} + +.run-dialog .run-dialog-description { + text-align: center; + color: rgba(251, 241, 199, 0.7); + font-size: 10ptpt; +} + +.prompt-dialog { + width: 28em; +} + +.prompt-dialog .modal-dialog-content-box { + margin-bottom: 24px; +} + +.prompt-dialog-password-grid { + spacing-rows: 8px; + spacing-columns: 4px; +} + +.prompt-dialog-password-grid .prompt-dialog-password-entry { + width: auto; +} + +.prompt-dialog-password-grid .prompt-dialog-password-entry:ltr { + margin-left: 20px; +} + +.prompt-dialog-password-grid .prompt-dialog-password-entry:rtl { + margin-right: 20px; +} + +.prompt-dialog-password-layout { + spacing: 8px; +} + +.prompt-dialog-password-entry { + width: 20em; +} + +.prompt-dialog-error-label, +.prompt-dialog-info-label, +.prompt-dialog-null-label { + text-align: center; + font-size: 10ptpt; + margin: 6px; +} + +.prompt-dialog-error-label { + color: #c14a4a; +} + +.prompt-dialog-info-label, +.prompt-dialog-null-label { + color: rgba(251, 241, 199, 0.5); +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 8px; + margin-bottom: 6px; +} + +.polkit-dialog-user-layout .polkit-dialog-user-root-label { + color: #b47109; +} + +.audio-device-selection-dialog .modal-dialog-content-box { + margin-bottom: 28px; +} + +.audio-device-selection-dialog .audio-selection-box { + spacing: 20px; +} + +.audio-selection-device { + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.audio-selection-device:hover, .audio-selection-device:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.audio-selection-device:active { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.audio-selection-device-box { + padding: 18px; + spacing: 18px; +} + +.audio-selection-device-icon { + icon-size: 64px; +} + +.welcome-dialog-image { + background-image: url("resource:///org/gnome/shell/theme/gnome-shell-start.svg"); + background-size: contain; + height: 300px; + width: 300px; +} + +/* Entries */ +StEntry, +.popup-menu .search-entry { + min-height: 20px; + padding: 6px 12px; + margin: 2px; + border-radius: 12px; + color: #fbf1c7; + caret-color: #fbf1c7; + selection-background-color: #7daea3; + selected-color: rgba(40, 40, 40, 0.87); + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + border: 2px solid transparent !important; + box-shadow: none !important; +} + +StEntry:hover, +.popup-menu .search-entry:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + border: 2px solid rgba(251, 241, 199, 0.3) !important; + box-shadow: none !important; +} + +StEntry:focus, +.popup-menu .search-entry:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + border: 2px solid #7daea3 !important; + box-shadow: none !important; +} + +StEntry:insensitive, +.popup-menu .search-entry:insensitive { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.35); + box-shadow: none !important; +} + +StEntry StIcon.capslock-warning, +.popup-menu .search-entry StIcon.capslock-warning { + icon-size: 16px; + warning-color: #b47109; + padding: 0; +} + +StEntry StIcon.peek-password, +.popup-menu .search-entry StIcon.peek-password { + icon-size: 16px; + padding: 0 4px; +} + +StEntry StLabel.hint-text, +.popup-menu .search-entry StLabel.hint-text { + margin-left: 2px; + color: rgba(251, 241, 199, 0.5); +} + +.hotplug-notification-item { + padding: 12px; + border-style: solid; + border-width: 0; + border-left-width: 0; + border-bottom-width: 0; +} + +.hotplug-notification-item:first-child { + border-radius: 0 0 0 12px; +} + +.hotplug-notification-item:last-child { + border-right-width: 0; + border-radius: 0 0 12px 0; +} + +.hotplug-notification-item:first-child:last-child { + border-radius: 0 0 12px 12px; +} + +.hotplug-notification-item-icon { + icon-size: 24px; + padding: 0 4px; +} + +.candidate-popup-boxpointer { + -arrow-border-radius: 2px; + -arrow-background-color: transparent; + -arrow-border-width: 0; + -arrow-border-color: transparent; + -arrow-base: 64px; + -arrow-rise: 12px; +} + +.candidate-popup-content { + color: rgba(251, 241, 199, 0.7); + box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.15); + border: none; + margin: 3px 8px; + padding: 6px; + spacing: 6px; + border-radius: 12px; +} + +.candidate-index { + padding: 0 0.5em 0 0; + color: rgba(251, 241, 199, 0.7); +} + +.candidate-box:selected .candidate-index { + color: rgba(40, 40, 40, 0.6); +} + +.candidate-box { + padding: 0.3em 0.5em 0.3em 0.5em; + margin-right: 2px; + border-radius: 6px; + color: rgba(251, 241, 199, 0.7); +} + +.candidate-box:hover { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.candidate-box:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +.candidate-box:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.candidate-box:last-child { + margin-right: 0; +} + +.candidate-page-button-box { + height: 2em; +} + +.vertical .candidate-page-button-box { + padding-top: 0.5em; +} + +.horizontal .candidate-page-button-box { + padding-left: 0.5em; +} + +.candidate-page-button { + padding: 4px 8px; + border-radius: 6px; +} + +.candidate-page-button-previous, +.candidate-page-button-next { + border-radius: 6px; +} + +.candidate-page-button-icon { + icon-size: 1em; +} + +/* On-screen Keyboard */ +#keyboard { + background-color: #1d1d1d; + box-shadow: none; +} + +#keyboard .page-indicator { + padding: 6px; +} + +#keyboard .page-indicator .page-indicator-icon { + width: 8px; + height: 8px; +} + +.key-container, +.keyboard-layout { + padding: 4px; + spacing: 4px; +} + +.keyboard-key { + font-size: 16ptpt; + font-weight: bold; + min-height: 1.2em; + min-width: 1.2em; + padding: 0 !important; + border-radius: 15px; + border: none; + color: rgba(251, 241, 199, 0.7); + background-color: #707070; + box-shadow: inset 0 -1px rgba(0, 0, 0, 0.85); +} + +.keyboard-key:focus, .keyboard-key:hover { + color: #fbf1c7; + background-color: #656565; +} + +.keyboard-key:checked, .keyboard-key:active { + color: #fbf1c7; + background-color: #717171; +} + +.keyboard-key:grayed { + background-color: #4b4b4b; + color: rgba(251, 241, 199, 0.7); +} + +.keyboard-key.default-key { + background-color: #4b4b4b; + box-shadow: inset 0 -1px rgba(0, 0, 0, 0.85); +} + +.keyboard-key.default-key:focus, .keyboard-key.default-key:hover { + color: #fbf1c7; + background-color: #585858; +} + +.keyboard-key.default-key:checked, .keyboard-key.default-key:active { + color: #fbf1c7; + background-color: #6a6a6a; +} + +.keyboard-key.enter-key { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +.keyboard-key.enter-key:focus, .keyboard-key.enter-key:hover { + color: rgba(40, 40, 40, 0.87); + background-color: #8db8ae; +} + +.keyboard-key.enter-key:checked, .keyboard-key.enter-key:active { + color: rgba(40, 40, 40, 0.87); + background-color: #5f998c; +} + +.keyboard-key.shift-key-uppercase, .keyboard-key.shift-key-uppercase:focus, .keyboard-key.shift-key-uppercase:hover, .keyboard-key.shift-key-uppercase:checked, .keyboard-key.shift-key-uppercase:active { + color: #7daea3; +} + +.keyboard-key StIcon { + icon-size: 1.125em; +} + +.keyboard-subkeys { + color: inherit; + -arrow-border-radius: 18px; + -arrow-background-color: #33322e; + -arrow-border-width: 0; + -arrow-border-color: transparent; + -arrow-base: 20px; + -arrow-rise: 10px; + -boxpointer-gap: 6px; + box-shadow: inset 0 -1px rgba(0, 0, 0, 0.85); +} + +.emoji-page .keyboard-key { + background-color: transparent; + border: none; + color: initial; +} + +.emoji-panel .keyboard-key:latched { + border: none; + background-color: #7daea3; +} + +.word-suggestions { + font-size: 14pt; + spacing: 12px; + min-height: 20pt; +} + +/* Login Dialog */ +#lockDialogGroup { + background-color: #282828; +} + +.login-dialog-banner-view { + padding-top: 24px; + max-width: 23em; +} + +.login-dialog, +.unlock-dialog { + border: none; + background-color: transparent; +} + +.login-dialog StEntry, +.unlock-dialog StEntry { + selection-background-color: #7daea3; + selected-color: rgba(40, 40, 40, 0.87); + padding: 4px 8px; + min-height: 26px; + border-radius: 9999px; + caret-color: rgba(40, 40, 40, 0.87); + background-color: rgba(251, 241, 199, 0.04); + border-radius: 0; + border: none !important; + box-shadow: inset 0 -1px rgba(40, 40, 40, 0.15) !important; + color: rgba(40, 40, 40, 0.87); +} + +.login-dialog StEntry:focus, +.unlock-dialog StEntry:focus { + border: none !important; + background-color: rgba(251, 241, 199, 0.04); + box-shadow: inset 0 -2px #7daea3 !important; + color: rgba(40, 40, 40, 0.87); +} + +.login-dialog StEntry:insensitive, +.unlock-dialog StEntry:insensitive { + border: none !important; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(40, 40, 40, 0.35); +} + +.login-dialog StEntry StLabel.hint-text, +.unlock-dialog StEntry StLabel.hint-text { + color: rgba(40, 40, 40, 0.38); +} + +.login-dialog .modal-dialog-button-box, +.unlock-dialog .modal-dialog-button-box { + spacing: 3px; +} + +.login-dialog .modal-dialog-button, +.unlock-dialog .modal-dialog-button { + padding: 0 16px; + border: none; + color: rgba(40, 40, 40, 0.87); + background-color: transparent; + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:hover, .login-dialog .modal-dialog-button:focus, +.unlock-dialog .modal-dialog-button:hover, +.unlock-dialog .modal-dialog-button:focus { + color: rgba(40, 40, 40, 0.87); + background-color: rgba(251, 241, 199, 0.12); +} + +.login-dialog .modal-dialog-button:active, +.unlock-dialog .modal-dialog-button:active { + color: rgba(40, 40, 40, 0.87); + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:insensitive, +.unlock-dialog .modal-dialog-button:insensitive { + background-color: transparent; + color: rgba(40, 40, 40, 0.35); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default, +.unlock-dialog .modal-dialog-button:default { + color: rgba(40, 40, 40, 0.87); + background-color: #282524; + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default:hover, .login-dialog .modal-dialog-button:default:focus, +.unlock-dialog .modal-dialog-button:default:hover, +.unlock-dialog .modal-dialog-button:default:focus { + color: rgba(40, 40, 40, 0.87); + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default:active, +.unlock-dialog .modal-dialog-button:default:active { + color: rgba(40, 40, 40, 0.87); + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.login-dialog .modal-dialog-button:default:insensitive, +.unlock-dialog .modal-dialog-button:default:insensitive { + color: rgba(40, 40, 40, 0.35); + background-color: #282524; + box-shadow: none !important; +} + +.login-dialog .cancel-button, +.login-dialog .switch-user-button, +.login-dialog .login-dialog-session-list-button, +.unlock-dialog .cancel-button, +.unlock-dialog .switch-user-button, +.unlock-dialog .login-dialog-session-list-button { + padding: 0; + border-radius: 100px; + width: 32px; + height: 32px; + border: none; + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.login-dialog .cancel-button StIcon, +.login-dialog .switch-user-button StIcon, +.login-dialog .login-dialog-session-list-button StIcon, +.unlock-dialog .cancel-button StIcon, +.unlock-dialog .switch-user-button StIcon, +.unlock-dialog .login-dialog-session-list-button StIcon { + icon-size: 16px; +} + +.login-dialog .login-dialog-message-warning, +.unlock-dialog .login-dialog-message-warning { + color: rgba(251, 241, 199, 0.7); +} + +.login-dialog-logo-bin { + padding: 24px 0px; +} + +.login-dialog-banner { + color: rgba(251, 241, 199, 0.7); +} + +.login-dialog-button-box { + spacing: 5px; +} + +.login-dialog-message { + text-align: center; +} + +.login-dialog-message-warning { + color: #b47109; +} + +.login-dialog-message-hint { + padding-top: 0; + padding-bottom: 20px; +} + +.login-dialog-user-selection-box { + padding: 100px 0px; +} + +.login-dialog-not-listed-label { + padding-left: 2px; +} + +.login-dialog-not-listed-button:focus .login-dialog-not-listed-label, .login-dialog-not-listed-button:hover .login-dialog-not-listed-label { + color: #fbf1c7; +} + +.login-dialog-not-listed-label { + font-size: 1em; + font-weight: bold; + color: rgba(251, 241, 199, 0.7); + padding-top: 1em; +} + +.login-dialog-not-listed-label:hover { + color: rgba(251, 241, 199, 0.7); +} + +.login-dialog-not-listed-label:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.login-dialog-user-list-view { + -st-vfade-offset: 1em; +} + +.login-dialog-user-list { + spacing: 12px; + padding: 0.2em; + width: 23em; +} + +.login-dialog-user-list:expanded .login-dialog-user-list-item:selected, .login-dialog-user-list:expanded .login-dialog-user-list-item:hover, .login-dialog-user-list:expanded .login-dialog-user-list-item:active { + background-color: rgba(251, 241, 199, 0.3); + color: rgba(251, 241, 199, 0.7); +} + +.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in { + border-right: 2px solid #7daea3; +} + +.login-dialog-user-list-item { + border-radius: 18px; + padding: 6px; + color: rgba(251, 241, 199, 0.7); +} + +.login-dialog-user-list-item:ltr .user-widget { + padding-right: 1em; +} + +.login-dialog-user-list-item:rtl .user-widget { + padding-left: 1em; +} + +.login-dialog-user-list-item:focus { + background-color: rgba(251, 241, 199, 0.04) !important; +} + +.login-dialog-user-list-item:hover, .login-dialog-user-list-item:focus:hover { + background-color: rgba(251, 241, 199, 0.12) !important; + color: rgba(251, 241, 199, 0.7); +} + +.login-dialog-user-list-item:active, .login-dialog-user-list-item:focus:active { + background-color: rgba(251, 241, 199, 0.3) !important; + color: rgba(251, 241, 199, 0.7); +} + +.login-dialog-user-list-item .login-dialog-timed-login-indicator { + height: 2px; + margin: 6px 0 0 0; + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.user-widget-label { + color: rgba(251, 241, 199, 0.7); +} + +.user-widget.horizontal .user-widget-label { + font-size: 13ptpt; + font-weight: bold; + padding-left: 15px; +} + +.user-widget.horizontal .user-widget-label:ltr { + padding-left: 14px; + text-align: left; +} + +.user-widget.horizontal .user-widget-label:rtl { + padding-right: 14px; + text-align: right; +} + +.user-widget.vertical .user-widget-label { + font-size: 16ptpt; + text-align: center; + font-weight: normal; + padding-top: 16px; +} + +.login-dialog-prompt-layout { + padding-top: 24px; + padding-bottom: 12px; + spacing: 12px; + width: 23em; +} + +.login-dialog-prompt-entry { + height: 1.5em; +} + +.login-dialog-prompt-label { + color: rgba(251, 241, 199, 0.7); + font-size: 12ptpt; + padding-top: 1em; +} + +/* Looking Glass */ +#LookingGlassDialog { + background-color: #282524; + padding: 0; + spacing: 6px; + margin: 6px; + border-radius: 20px; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.25); + color: #fbf1c7; + border: 2px solid #fbf1c7; +} + +#LookingGlassDialog > #Toolbar { + padding: 0 6px; + border: none; + border-radius: 20px 20px 0 0; + background-color: rgba(251, 241, 199, 0.04); + box-shadow: inset 0 -1px 0 rgba(251, 241, 199, 0.12); + spacing: 6px; +} + +#LookingGlassDialog .labels { + spacing: 6px; +} + +#LookingGlassDialog .notebook-tab { + -natural-hpadding: 12px; + -minimum-hpadding: 12px; + font-weight: bold; + color: rgba(251, 241, 199, 0.5); + padding-left: 16px; + padding-right: 16px; + min-height: 32px; + padding: 3px 30px; + transition-duration: 100ms; + border: none; + background-color: transparent; + border-radius: 0; +} + +#LookingGlassDialog .notebook-tab:hover { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; + text-shadow: none; +} + +#LookingGlassDialog .notebook-tab:selected { + border-color: transparent; + background-color: rgba(251, 241, 199, 0.12); + box-shadow: inset 0 -2px 0px #fbf1c7; + color: #fbf1c7; + text-shadow: none; +} + +#LookingGlassDialog StBoxLayout#EvalBox { + padding: 4px; + spacing: 6px; + padding: 6px; +} + +#LookingGlassDialog StBoxLayout#ResultsArea { + spacing: 6px; + padding: 6px; +} + +.lg-dialog StEntry { + min-height: 22px; + selection-background-color: #7daea3; + selected-color: rgba(40, 40, 40, 0.87); +} + +.lg-dialog .shell-link { + color: #83b193; +} + +.lg-dialog .shell-link:hover { + color: #a2c5ae; +} + +.lg-dialog .shell-link:active { + color: #649d78; +} + +.lg-dialog .actor-link { + color: rgba(251, 241, 199, 0.5); +} + +.lg-dialog .actor-link:hover { + color: #fbf1c7; +} + +.lg-dialog .actor-link:active { + color: rgba(251, 241, 199, 0.7); +} + +.lg-dialog .actor-link StIcon { + icon-size: 12px; +} + +.lg-completions-text { + font-size: 0.9em; + font-style: italic; + color: rgba(251, 241, 199, 0.7); +} + +.lg-obj-inspector-title { + spacing: 6px; + color: rgba(251, 241, 199, 0.7); +} + +.lg-obj-inspector-button { + padding: 0 16px; + border: none; + border-radius: 12px; +} + +.lg-obj-inspector-button:hover { + border: none; +} + +#lookingGlassExtensions { + padding: 6px; + color: rgba(251, 241, 199, 0.7); +} + +.lg-extensions-list { + padding: 6px; + spacing: 6px; + color: rgba(251, 241, 199, 0.7); +} + +.lg-extension { + border: none; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.7); + padding: 12px; +} + +.lg-extension:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.lg-extension:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.3); +} + +.lg-extension-meta { + spacing: 6px; + color: rgba(251, 241, 199, 0.7); +} + +#LookingGlassPropertyInspector { + color: rgba(251, 241, 199, 0.7); + background: #282524; + border: none; + border-radius: 12px; + padding: 6px; + margin: 5px 8px 11px; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.25); +} + +.lg-debug-flag-button { + color: rgba(251, 241, 199, 0.7); +} + +.lg-debug-flag-button StLabel { + padding: 6px, 12px; +} + +.lg-debug-flag-button:hover { + color: #fbf1c7; +} + +.lg-debug-flag-button:active { + color: #fbf1c7; +} + +.lg-debug-flags-header { + padding-top: 12px; + padding: 6px; +} + +.select-area-rubberband { + background-color: rgba(125, 174, 163, 0.3); + border: 1px solid #7daea3; + border-radius: 12px; +} + +.user-icon { + background-size: contain; + color: rgba(251, 241, 199, 0.7); + border-radius: 9999px; + border: none; + box-shadow: none; + icon-size: 64px; +} + +.modal-dialog .user-icon { + box-shadow: none; +} + +.user-icon:hover { + color: #fbf1c7; +} + +.user-icon StIcon { + background-color: #fbf1c7; + border-radius: 9999px; + padding: 12px; + width: 40px; + height: 40px; +} + +.user-icon.user-avatar { + border: 2px solid #7daea3; +} + +.user-widget.vertical .user-icon { + icon-size: 96px; +} + +.user-widget.vertical .user-icon StIcon { + padding: 20px; + padding-top: 18px; + padding-bottom: 22px; + width: 88px; + height: 88px; +} + +.lightbox { + background-color: black; +} + +.flashspot { + background-color: white; +} + +.hidden { + color: rgba(0, 0, 0, 0); +} + +.caps-lock-warning-label { + text-align: center; + padding-bottom: 8px; + font-size: 10ptpt; + color: #b47109; +} + +/* Network Dialogs */ +.nm-dialog { + max-height: 34em; + min-height: 31em; + min-width: 32em; +} + +.nm-dialog-content { + spacing: 20px; + padding: 24px; +} + +.nm-dialog-header-hbox { + spacing: 10px; +} + +.nm-dialog-airplane-box { + spacing: 12px; +} + +.nm-dialog-airplane-headline { + font-weight: bold; + text-align: center; +} + +.nm-dialog-airplane-text { + color: #fbf1c7; +} + +.nm-dialog-header { + font-weight: bold; +} + +.nm-dialog-header-icon { + icon-size: 32px; +} + +.nm-dialog-header-hbox { + spacing: 10px; +} + +.nm-dialog-scroll-view { + border: none; + padding: 0; + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; +} + +.nm-dialog-item { + font-size: 11ptpt; + border-bottom: none; + padding: 12px; + spacing: 0px; +} + +.nm-dialog-item:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.nm-dialog-item:hover, .nm-dialog-item:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.nm-dialog-item:active { + background-color: rgba(251, 241, 199, 0.3); +} + +.nm-dialog-icon { + icon-size: 16px; +} + +.nm-dialog-icons { + spacing: 12px; +} + +.no-networks-label { + color: rgba(251, 241, 199, 0.5); +} + +.no-networks-box { + spacing: 6px; +} + +/* OSD */ +.screenshot-ui-panel, .workspace-switcher-container, .switcher-list, .resize-popup, .osd-window { + color: rgba(251, 241, 199, 0.7); + background-color: #282828; + border: none; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.25); + margin: 5px 8px 11px; + border-radius: 18px; + padding: 12px; +} + +.osd-window { + text-align: center; + font-weight: bold; +} + +.osd-window .osd-monitor-label { + font-size: 3em; +} + +.osd-window .level { + height: 2px; + border-radius: 2px; + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; + -barlevel-height: 2px; + -barlevel-background-color: rgba(251, 241, 199, 0.12); + -barlevel-active-background-color: #7daea3; + -barlevel-overdrive-color: #c14a4a; + -barlevel-overdrive-separator-width: 2px; + -barlevel-border-width: 0; + -barlevel-border-color: rgba(251, 241, 199, 0.12); +} + +.osd-window .level-bar { + background-color: white; + border-radius: 2px; +} + +.pad-osd-window { + padding: 32px; + background-color: #282828; +} + +.pad-osd-window .pad-osd-title-box { + spacing: 12px; +} + +.pad-osd-window .pad-osd-title-menu-box { + spacing: 6px; +} + +.combo-box-label { + width: 15em; +} + +#overview StScrollBar StBin#trough { + background-color: rgba(251, 241, 199, 0.12); +} + +#overview StScrollBar StButton#vhandle, +#overview StScrollBar StButton#hhandle { + background-color: rgba(251, 241, 199, 0.5); +} + +#overview StScrollBar StButton#vhandle:hover, +#overview StScrollBar StButton#hhandle:hover { + background-color: rgba(251, 241, 199, 0.7); +} + +#overview StScrollBar StButton#vhandle:active, +#overview StScrollBar StButton#hhandle:active { + background-color: #fbf1c7; +} + +#overview { + spacing: 24px; +} + +.overview-controls { + padding-bottom: 30px; +} + +/* Top Bar */ +#panel { + color: rgba(251, 241, 199, 0.7); + font-weight: bold; + font-feature-settings: 'tnum'; + font-size: 11ptpt; + transition-duration: 250ms; + box-shadow: none; + border: none; + height: 35px; + background-color: rgba(40, 40, 40, 0.85); + margin: 5px 10px 1px; + border: 2px solid #7daea3; + border-radius: 9999px; +} + +#panel .panel-corner { + -panel-corner-radius: 0; + -panel-corner-background-color: rgba(40, 40, 40, 0.6); + -panel-corner-border-width: 2px; + -panel-corner-border-color: transparent; + -panel-corner-opacity: 1; + transition-duration: 250ms; +} + +#panel .panel-button { + -natural-hpadding: 12px; + -minimum-hpadding: 12px; + font-weight: bold; + color: rgba(251, 241, 199, 0.7); + transition-duration: 150ms; + border-radius: 12px; + text-shadow: none; + box-shadow: none; + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button.clock-display { + box-shadow: none; +} + +#panel .panel-button.clock-display .clock { + transition-duration: 150ms; + border-radius: 12px; + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button:hover { + color: #7daea3; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(67, 66, 61, 0.624); + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button:hover.clock-display { + box-shadow: none; + color: rgba(251, 241, 199, 0.7); +} + +#panel .panel-button:hover.clock-display .clock { + color: #7daea3; + box-shadow: inset 0 0 0 1000px rgba(67, 66, 61, 0.624); + border: 4px solid transparent; + border-radius: 9999px; +} + +#panel .panel-button:active, #panel .panel-button:active:hover, #panel .panel-button:overview, #panel .panel-button:overview:hover, #panel .panel-button:focus, #panel .panel-button:focus:hover, #panel .panel-button:checked, #panel .panel-button:checked:hover { + color: #7daea3; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(91, 89, 78, 0.648); +} + +#panel .panel-button:active.clock-display, #panel .panel-button:overview.clock-display, #panel .panel-button:focus.clock-display, #panel .panel-button:checked.clock-display { + box-shadow: none; + color: rgba(251, 241, 199, 0.7); +} + +#panel .panel-button:active.clock-display .clock, #panel .panel-button:overview.clock-display .clock, #panel .panel-button:focus.clock-display .clock, #panel .panel-button:checked.clock-display .clock { + color: #7daea3; + box-shadow: inset 0 0 0 1000px rgba(91, 89, 78, 0.648); +} + +.unlock-screen #panel .panel-button, .login-screen #panel .panel-button, .lock-screen #panel .panel-button { + color: #fbf1c7; +} + +.unlock-screen #panel .panel-button:focus, .unlock-screen #panel .panel-button:hover, .unlock-screen #panel .panel-button:active, .login-screen #panel .panel-button:focus, .login-screen #panel .panel-button:hover, .login-screen #panel .panel-button:active, .lock-screen #panel .panel-button:focus, .lock-screen #panel .panel-button:hover, .lock-screen #panel .panel-button:active { + color: #fbf1c7; +} + +#panel .panel-button .system-status-icon { + icon-size: 16px; + padding: 6px; + margin: 0; + -st-icon-style: symbolic; +} + +#panel .panel-button .appindicator-trayicons-box { + margin: 0 6px; +} + +#panel .panel-button .app-menu-icon { + -st-icon-style: symbolic; +} + +#panel .panel-button#panelActivities { + -natural-hpadding: 18px; +} + +#panel .panel-button#panelActivities StBoxLayout { + padding: 0 3px; + spacing: 6px; +} + +#panel .panel-button#panelActivities .workspace-dot { + border-radius: 9999px; + min-width: 8px; + min-height: 8px; + background-color: #fbf1c7; +} + +#panel:overview, #panel.unlock-screen, #panel.login-screen, #panel.lock-screen { + background-color: transparent; + box-shadow: none; + border: 2px solid transparent; +} + +#panel:overview StLabel, +#panel:overview StIcon, #panel.unlock-screen StLabel, +#panel.unlock-screen StIcon, #panel.login-screen StLabel, +#panel.login-screen StIcon, #panel.lock-screen StLabel, +#panel.lock-screen StIcon { + color: rgba(251, 241, 199, 0.7); +} + +#panel:overview .panel-button:hover, #panel.unlock-screen .panel-button:hover, #panel.login-screen .panel-button:hover, #panel.lock-screen .panel-button:hover { + color: #fbf1c7; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(251, 241, 199, 0.12); +} + +#panel:overview .panel-button:hover.clock-display, #panel.unlock-screen .panel-button:hover.clock-display, #panel.login-screen .panel-button:hover.clock-display, #panel.lock-screen .panel-button:hover.clock-display { + box-shadow: none; + color: #fbf1c7; +} + +#panel:overview .panel-button:hover.clock-display .clock, #panel.unlock-screen .panel-button:hover.clock-display .clock, #panel.login-screen .panel-button:hover.clock-display .clock, #panel.lock-screen .panel-button:hover.clock-display .clock { + color: #fbf1c7; + box-shadow: inset 0 0 0 1000px rgba(251, 241, 199, 0.12); +} + +#panel:overview .panel-button:active, #panel:overview .panel-button:overview, #panel:overview .panel-button:focus, #panel:overview .panel-button:checked, #panel.unlock-screen .panel-button:active, #panel.unlock-screen .panel-button:overview, #panel.unlock-screen .panel-button:focus, #panel.unlock-screen .panel-button:checked, #panel.login-screen .panel-button:active, #panel.login-screen .panel-button:overview, #panel.login-screen .panel-button:focus, #panel.login-screen .panel-button:checked, #panel.lock-screen .panel-button:active, #panel.lock-screen .panel-button:overview, #panel.lock-screen .panel-button:focus, #panel.lock-screen .panel-button:checked { + color: #fbf1c7; + background-color: transparent; + box-shadow: inset 0 0 0 1000px rgba(251, 241, 199, 0.2); +} + +#panel:overview .panel-button:active.clock-display, #panel:overview .panel-button:overview.clock-display, #panel:overview .panel-button:focus.clock-display, #panel:overview .panel-button:checked.clock-display, #panel.unlock-screen .panel-button:active.clock-display, #panel.unlock-screen .panel-button:overview.clock-display, #panel.unlock-screen .panel-button:focus.clock-display, #panel.unlock-screen .panel-button:checked.clock-display, #panel.login-screen .panel-button:active.clock-display, #panel.login-screen .panel-button:overview.clock-display, #panel.login-screen .panel-button:focus.clock-display, #panel.login-screen .panel-button:checked.clock-display, #panel.lock-screen .panel-button:active.clock-display, #panel.lock-screen .panel-button:overview.clock-display, #panel.lock-screen .panel-button:focus.clock-display, #panel.lock-screen .panel-button:checked.clock-display { + box-shadow: none; + color: #fbf1c7; +} + +#panel:overview .panel-button:active.clock-display .clock, #panel:overview .panel-button:overview.clock-display .clock, #panel:overview .panel-button:focus.clock-display .clock, #panel:overview .panel-button:checked.clock-display .clock, #panel.unlock-screen .panel-button:active.clock-display .clock, #panel.unlock-screen .panel-button:overview.clock-display .clock, #panel.unlock-screen .panel-button:focus.clock-display .clock, #panel.unlock-screen .panel-button:checked.clock-display .clock, #panel.login-screen .panel-button:active.clock-display .clock, #panel.login-screen .panel-button:overview.clock-display .clock, #panel.login-screen .panel-button:focus.clock-display .clock, #panel.login-screen .panel-button:checked.clock-display .clock, #panel.lock-screen .panel-button:active.clock-display .clock, #panel.lock-screen .panel-button:overview.clock-display .clock, #panel.lock-screen .panel-button:focus.clock-display .clock, #panel.lock-screen .panel-button:checked.clock-display .clock { + box-shadow: inset 0 0 0 1000px rgba(251, 241, 199, 0.2); + color: #fbf1c7; +} + +#panel:overview .panel-button#panelActivities .workspace-dot, #panel.unlock-screen .panel-button#panelActivities .workspace-dot, #panel.login-screen .panel-button#panelActivities .workspace-dot, #panel.lock-screen .panel-button#panelActivities .workspace-dot { + background-color: #fbf1c7; +} + +#panel:overview .panel-corner, #panel.unlock-screen .panel-corner, #panel.login-screen .panel-corner, #panel.lock-screen .panel-corner { + -panel-corner-radius: 0; + -panel-corner-background-color: transparent; + -panel-corner-border-color: transparent; +} + +#panel Gjs_status_keyboard_InputSourceIndicator.panel-button, +#panel Gjs_appindicatorsupport_rgcjonas_gmail_com_indicatorStatusIcon_IndicatorStatusIcon.panel-button, +#panel Gjs_appindicatorsupport_rgcjonas_gmail_com_indicatorStatusIcon_AppIndicatorsIndicatorStatusIcon.panel-button { + -natural-hpadding: 18px !important; + -minimum-hpadding: 18px !important; +} + +#panel .screencast-indicator, +#panel .remote-access-indicator { + color: #b47109; +} + +/* Popovers/Menus */ +.popup-menu-boxpointer { + -arrow-border-radius: 18px; + -arrow-background-color: transparent; + -arrow-border-width: 0; + -arrow-border-color: transparent; + -arrow-base: 12px; + -arrow-rise: 0; + -arrow-box-shadow: none; + background: transparent; +} + +.popup-menu { + min-width: 12em; + color: rgba(251, 241, 199, 0.7) !important; + padding: 0; + border-radius: 30px; + box-shadow: 0 3px 5px -2px rgba(0, 0, 0, 0.18); + margin: 6px 6px 8px; +} + +.popup-menu .popup-menu-content { + padding: 6px; + background-color: #282828; + border-radius: 12px; + margin: 0; + border: 2px solid #7daea3; +} + +.popup-menu .popup-menu-item { + spacing: 6px; + color: rgba(251, 241, 199, 0.7) !important; + text-shadow: none; + border-radius: 12px; + margin: 0; + transition-duration: 100ms; + background-color: transparent; +} + +.popup-menu .popup-menu-item:checked { + border: none; + box-shadow: none; + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.12) !important; + border-radius: 12px 12px 0 0 !important; +} + +.popup-menu .popup-menu-item:checked:focus, .popup-menu .popup-menu-item:checked:hover, .popup-menu .popup-menu-item:checked.selected { + color: #fbf1c7 !important; + background-color: alpha(currentColor, 0.08) !important; +} + +.popup-menu .popup-menu-item:checked:active { + color: #fbf1c7 !important; + background-color: alpha(currentColor, 0.12) !important; +} + +.popup-menu .popup-menu-item:checked:insensitive { + color: rgba(251, 241, 199, 0.32) !important; +} + +.popup-menu .popup-menu-item:focus, .popup-menu .popup-menu-item:hover, .popup-menu .popup-menu-item.selected { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.12) !important; + transition-duration: 0; +} + +.popup-menu .popup-menu-item:active, .popup-menu .popup-menu-item.selected:active { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.3) !important; +} + +.popup-menu .popup-menu-item:insensitive { + color: rgba(251, 241, 199, 0.32) !important; +} + +.popup-menu .popup-sub-menu { + background-color: rgba(251, 241, 199, 0.12) !important; + color: rgba(251, 241, 199, 0.7) !important; + border: none; + box-shadow: none; + margin: 0; + border-radius: 0 0 12px 12px !important; +} + +.popup-menu .popup-sub-menu .popup-menu-item { + margin: 0; +} + +.popup-menu .popup-sub-menu .popup-menu-item:focus, .popup-menu .popup-sub-menu .popup-menu-item:hover, .popup-menu .popup-sub-menu .popup-menu-item.selected { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.popup-menu .popup-sub-menu .popup-menu-item:active, .popup-menu .popup-sub-menu .popup-menu-item.selected:active { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.3) !important; +} + +.popup-menu .popup-sub-menu .popup-menu-item:insensitive { + color: rgba(251, 241, 199, 0.32) !important; +} + +.popup-menu .popup-inactive-menu-item { + color: rgba(251, 241, 199, 0.7) !important; +} + +.popup-menu .popup-inactive-menu-item:insensitive { + color: rgba(251, 241, 199, 0.32) !important; +} + +.popup-menu.panel-menu { + -boxpointer-gap: 4px; + margin-bottom: 1.75em; +} + +.popup-menu-arrow, +.popup-menu-icon { + icon-size: 16px; +} + +.popup-menu-ornament { + width: 1.2em; +} + +.popup-menu-ornament:ltr { + text-align: right; +} + +.popup-menu-ornament:rtl { + text-align: left; +} + +.background-menu { + -boxpointer-gap: 4px; + -arrow-rise: 0px; +} + +.aggregate-menu { + min-width: 20em; +} + +.aggregate-menu .popup-menu-icon { + padding: 0; + margin: 0 3px; + -st-icon-style: symbolic; +} + +.app-menu { + max-width: 27.25em; +} + +.app-menu .popup-menu-ornament { + width: 0 !important; +} + +.app-menu .popup-inactive-menu-item:first-child > StLabel:ltr { + margin-right: 8px; +} + +.app-menu .popup-inactive-menu-item:first-child > StLabel:rtl { + margin-left: 8px; +} + +/* Screen Shield */ +.unlock-dialog-clock { + color: white; + font-weight: 300; + text-align: center; + spacing: 24px; + padding-bottom: 2.5em; +} + +.unlock-dialog-clock-time { + font-size: 64pt; + padding-top: 42px; + font-feature-settings: 'tnum'; +} + +.unlock-dialog-clock-date { + font-size: 16pt; + font-weight: normal; +} + +.unlock-dialog-clock-hint { + font-weight: normal; + padding-top: 48px; +} + +.unlock-dialog-notifications-container { + margin: 12px 0; + spacing: 6px; + width: 23em; + background-color: transparent; +} + +.unlock-dialog-notifications-container .summary-notification-stack-scrollview { + padding-top: 0; + padding-bottom: 0; +} + +.unlock-dialog-notifications-container .notification, +.unlock-dialog-notifications-container .unlock-dialog-notification-source { + padding: 12px 6px; + border: none; + background-color: #282828; + color: #fbf1c7; + border-radius: 18px; +} + +.unlock-dialog-notifications-container .notification.critical, +.unlock-dialog-notifications-container .unlock-dialog-notification-source.critical { + background-color: #3c3c3c; +} + +.unlock-dialog-notification-label { + padding: 0px 0px 0px 12px; +} + +.unlock-dialog-notification-count-text { + weight: bold; + padding: 0 6px; + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; + border-radius: 9999px; + margin-right: 12px; +} + +.screen-shield-background { + background: black; + box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.15); +} + +#unlockDialogNotifications StButton#vhandle, +#unlockDialogNotifications StButton#hhandle { + background-color: rgba(40, 40, 40, 0.3); +} + +#unlockDialogNotifications StButton#vhandle:hover, #unlockDialogNotifications StButton#vhandle:focus, +#unlockDialogNotifications StButton#hhandle:hover, +#unlockDialogNotifications StButton#hhandle:focus { + background-color: rgba(40, 40, 40, 0.5); +} + +#unlockDialogNotifications StButton#vhandle:active, +#unlockDialogNotifications StButton#hhandle:active { + background-color: rgba(125, 174, 163, 0.5); +} + +/* Scrollbars */ +StScrollView.vfade { + -st-vfade-offset: 32px; +} + +StScrollView.hfade { + -st-hfade-offset: 32px; +} + +StScrollBar { + padding: 0; +} + +StScrollView StScrollBar { + min-width: 12px; + min-height: 12px; +} + +StScrollBar StBin#trough { + border-radius: 9999px; + background-color: rgba(251, 241, 199, 0.12); + margin: 3px; +} + +StScrollBar StButton#vhandle, +StScrollBar StButton#hhandle { + border-radius: 9999px; + background-color: rgba(251, 241, 199, 0.5); + border: 3px solid transparent; + margin: 3px; +} + +StScrollBar StButton#vhandle:hover, +StScrollBar StButton#hhandle:hover { + background-color: rgba(251, 241, 199, 0.7); +} + +StScrollBar StButton#vhandle:active, +StScrollBar StButton#hhandle:active { + background-color: #fbf1c7; +} + + +.search-entry { + width: 320px; + min-height: 32px; + padding: 0 12px; + color: rgba(251, 241, 199, 0.7); + transition-duration: 150ms; + border-radius: 12px; + caret-color: #fbf1c7; + selection-background-color: rgba(251, 241, 199, 0.12); + selected-color: rgba(40, 40, 40, 0.87) !important; + color: #fbf1c7; + background-color: #282524; + border: 2px solid transparent !important; + box-shadow: none !important; +} + + +.search-entry:hover { + color: #fbf1c7; + background-color: #282524; + border: 2px solid rgba(251, 241, 199, 0.3) !important; + box-shadow: none !important; +} + + +.search-entry:focus { + color: #fbf1c7; + background-color: #282524; + border: 2px solid #7daea3 !important; + box-shadow: none !important; +} + + +.search-entry .search-entry-icon { + icon-size: 16px; + padding: 0; + color: rgba(251, 241, 199, 0.32); +} + + +.search-entry:hover .search-entry-icon, +.search-entry:focus .search-entry-icon { + color: rgba(251, 241, 199, 0.7); +} + + +.search-entry:insensitive { + border: none; + color: rgba(251, 241, 199, 0.32); +} + + +.search-entry StLabel.hint-text { + color: rgba(251, 241, 199, 0.5); +} + +/* Slider */ +.slider { + height: 20px; + color: #282524; + -slider-height: 2px; + -slider-background-color: rgba(251, 241, 199, 0.3); + -slider-border-color: #7daea3; + -slider-active-background-color: #7daea3; + -slider-active-border-color: #7daea3; + -slider-border-width: 2px; + -slider-handle-radius: 7px; + -slider-handle-border-width: 2px; + -slider-handle-border-color: #7daea3; + -barlevel-height: 15px; + -barlevel-background-color: rgba(251, 241, 199, 0.3); + -barlevel-border-color: transparent; + -barlevel-active-background-color: #7daea3; + -barlevel-active-border-color: transparent; + -barlevel-overdrive-color: #c14a4a; + -barlevel-overdrive-border-color: transparent; + -barlevel-overdrive-separator-width: 2px; + -barlevel-border-width: 0; +} + +/* App Switcher */ +.switcher-popup { + padding: 8px; + spacing: 24px; +} + +.switcher-list .item-box { + padding: 8px; + border-radius: 12px; + border: 1px solid transparent; + background-color: transparent; +} + +.switcher-list .item-box:outlined { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.switcher-list .item-box:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.switcher-list .thumbnail-box { + padding: 2px; + spacing: 6px; +} + +.switcher-list .thumbnail { + width: 256px; +} + +.switcher-list .separator { + width: 1px; + background: rgba(251, 241, 199, 0.12); +} + +.switcher-list .switcher-list-item-container { + spacing: 12px; +} + +.switcher-arrow { + border-color: rgba(0, 0, 0, 0); + color: rgba(251, 241, 199, 0.5); +} + +.switcher-arrow:highlighted { + color: #fbf1c7; +} + +.input-source-switcher-symbol { + font-size: 34pt; + width: 96px; + height: 96px; +} + +.cycler-highlight { + border: 5px solid #7daea3; +} + +/* Switches */ +.toggle-switch { + width: 46px; + height: 24px; + background-size: contain; +} + +.toggle-switch, .popup-sub-menu .toggle-switch { + background-image: url("assets/toggle-off.svg"); +} + +.toggle-switch:checked, .popup-sub-menu .toggle-switch:checked { + background-image: url("assets/toggle-on-dark.svg"); +} + +/* Tiled window previews */ +.tile-preview { + background-color: rgba(125, 174, 163, 0.3); + border: 1px solid #7daea3; +} + +.tile-preview-left.on-primary { + border-radius: 13px 0 0 0; +} + +.tile-preview-right.on-primary { + border-radius: 0 13px 0 0; +} + +.tile-preview-left.tile-preview-right.on-primary { + border-radius: 13px 13px 0 0; +} + +/* Workspace Switcher */ +.workspace-switcher-group { + padding: 12px; +} + +.workspace-switcher { + background: transparent; + border: none; + border-radius: 0; + padding: 0; + spacing: 12px; +} + +.ws-switcher-box { + background: transparent; + height: 50px; + background-size: 32px; + background: rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.ws-switcher-active-up, +.ws-switcher-active-down, +.ws-switcher-active-left, +.ws-switcher-active-right { + height: 52px; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + border-radius: 15px; + border: none; +} + +/* App Icons */ +.icon-grid { + row-spacing: 12px; + column-spacing: 12px; + max-row-spacing: 36px; + max-column-spacing: 36px; + page-padding-top: 24px; + page-padding-bottom: 24px; + page-padding-left: 18px; + page-padding-right: 18px; +} + +.overview-tile, .grid-search-result { + color: rgba(251, 241, 199, 0.7); + border-radius: 30px; + padding: 6px; + border: none; + transition-duration: 100ms; + text-align: center; + background-color: transparent; +} + +.overview-tile:hover, .grid-search-result:hover, .overview-tile:focus, .grid-search-result:focus, .overview-tile:selected, .grid-search-result:selected { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + border-image: none; + background-image: none; +} + +.overview-tile:active, .grid-search-result:active, .overview-tile:checked, .grid-search-result:checked { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.3); + box-shadow: none; +} + +.app-folder { + background-color: rgba(251, 241, 199, 0.12); + border-radius: 30px; + color: rgba(251, 241, 199, 0.7); +} + +.app-folder .overview-icon { + background-color: transparent; + border-radius: 30px; +} + +.app-folder:hover { + background-color: rgba(251, 241, 199, 0.2); + color: #fbf1c7; +} + +.app-folder:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +.app-grid-running-dot { + width: 6px; + height: 3px; + border-radius: 2px; + background-color: rgba(251, 241, 199, 0.3); + margin-bottom: 0; +} + +StWidget.focused .app-grid-running-dot { + width: 24px; + background-color: #fbf1c7 !important; +} + +.app-folder-dialog-container { + padding-top: 32px; +} + +.app-folder-dialog { + width: 720px; + height: 720px; + border-radius: 54px; + padding: 12px; + background-color: #282828; + border: 1px solid black; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.1); +} + +.app-folder-dialog .folder-name-container { + padding: 24px 36px; + padding-bottom: 0; +} + +.app-folder-dialog .folder-name-container .folder-name-entry { + width: 12em; + border: none; + caret-color: #fbf1c7; +} + +.app-folder-dialog .folder-name-container .folder-name-entry:focus { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.app-folder-dialog .icon-button, .app-folder-dialog .background-app-item .close-button, .background-app-item .app-folder-dialog .close-button, .app-folder-dialog .message-notification-group .message-collapse-button, .message-notification-group .app-folder-dialog .message-collapse-button, .app-folder-dialog .message .message-header .message-expand-button, .message .message-header .app-folder-dialog .message-expand-button, +.app-folder-dialog .message .message-header .message-close-button, +.message .message-header .app-folder-dialog .message-close-button { + background-color: rgba(251, 241, 199, 0.06); + color: rgba(251, 241, 199, 0.7); + border: none; + padding: 0; + width: 36px; + height: 36px; + border-radius: 9999px; +} + +.app-folder-dialog .icon-button > StIcon, .app-folder-dialog .background-app-item .close-button > StIcon, .background-app-item .app-folder-dialog .close-button > StIcon, .app-folder-dialog .message-notification-group .message-collapse-button > StIcon, .message-notification-group .app-folder-dialog .message-collapse-button > StIcon, .app-folder-dialog .message .message-header .message-expand-button > StIcon, .message .message-header .app-folder-dialog .message-expand-button > StIcon, +.app-folder-dialog .message .message-header .message-close-button > StIcon, +.message .message-header .app-folder-dialog .message-close-button > StIcon { + icon-size: 16px; +} + +.app-folder-dialog .icon-button:hover, .app-folder-dialog .background-app-item .close-button:hover, .background-app-item .app-folder-dialog .close-button:hover, .app-folder-dialog .message-notification-group .message-collapse-button:hover, .message-notification-group .app-folder-dialog .message-collapse-button:hover, .app-folder-dialog .message .message-header .message-expand-button:hover, .message .message-header .app-folder-dialog .message-expand-button:hover, +.app-folder-dialog .message .message-header .message-close-button:hover, +.message .message-header .app-folder-dialog .message-close-button:hover { + background-color: rgba(251, 241, 199, 0.12); +} + +.app-folder-dialog .icon-button:checked, .app-folder-dialog .background-app-item .close-button:checked, .background-app-item .app-folder-dialog .close-button:checked, .app-folder-dialog .message-notification-group .message-collapse-button:checked, .message-notification-group .app-folder-dialog .message-collapse-button:checked, .app-folder-dialog .message .message-header .message-expand-button:checked, .message .message-header .app-folder-dialog .message-expand-button:checked, +.app-folder-dialog .message .message-header .message-close-button:checked, +.message .message-header .app-folder-dialog .message-close-button:checked, .app-folder-dialog .icon-button:active, .app-folder-dialog .background-app-item .close-button:active, .background-app-item .app-folder-dialog .close-button:active, .app-folder-dialog .message-notification-group .message-collapse-button:active, .message-notification-group .app-folder-dialog .message-collapse-button:active, .app-folder-dialog .message .message-header .message-expand-button:active, .message .message-header .app-folder-dialog .message-expand-button:active, +.app-folder-dialog .message .message-header .message-close-button:active, +.message .message-header .app-folder-dialog .message-close-button:active { + background-color: #fbf1c7; + color: rgba(40, 40, 40, 0.87); +} + +.app-folder-dialog .page-indicators { + margin-bottom: 18px; +} + +.rename-folder-popup .rename-folder-popup-item { + spacing: 6px; +} + +.rename-folder-popup .rename-folder-popup-item:ltr, .rename-folder-popup .rename-folder-popup-item:rtl { + padding: 0 12px; +} + +.system-action-icon { + box-shadow: 0 4px 4px rgba(0, 0, 0, 0.2); + background-color: #282828; + color: #fbf1c7; + border-radius: 9999px; + icon-size: 48px; +} + +.page-navigation-hint.dnd { + background: rgba(255, 255, 255, 0.1); +} + +.page-navigation-hint.next:ltr, .page-navigation-hint.previous:rtl { + background-gradient-start: rgba(255, 255, 255, 0.05); + background-gradient-end: transparent; + background-gradient-direction: horizontal; + border-radius: 27px 0px 0px 27px; +} + +.page-navigation-hint.previous:ltr, .page-navigation-hint.next:rtl { + background-gradient-start: transparent; + background-gradient-end: rgba(255, 255, 255, 0.05); + background-gradient-direction: horizontal; + border-radius: 0px 27px 27px 0px; +} + +.page-navigation-arrow { + margin: 6px; + padding: 18px; + width: 24px; + height: 24px; + border-radius: 9999px; + transition-duration: 100ms; + color: rgba(251, 241, 199, 0.7); + background-color: transparent; +} + +.page-navigation-arrow > StIcon { + color: #fbf1c7; +} + +.page-navigation-arrow:insensitive { + background-color: transparent; + color: rgba(251, 241, 199, 0.5); +} + +.page-navigation-arrow:hover { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.page-navigation-arrow:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +/* Date/Time Menu */ +.popup-menu .message, .world-clocks-button, +.weather-button, +.events-button { + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + border: none; + box-shadow: none; + text-shadow: none; +} + +.popup-menu .message:hover, .world-clocks-button:hover, +.weather-button:hover, +.events-button:hover, .popup-menu .message:focus, .world-clocks-button:focus, +.weather-button:focus, +.events-button:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none; +} + +.popup-menu .message:active, .world-clocks-button:active, +.weather-button:active, +.events-button:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none; +} + +#calendarArea { + padding: 0; +} + +.datemenu-calendar-column { + spacing: 6px; + border: none; + padding: 0 !important; + margin: 0 !important; +} + +.datemenu-calendar-column:ltr { + margin-right: 0; + border-left-width: 0; +} + +.datemenu-calendar-column:rtl { + margin-left: 0; + border-right-width: 0; +} + +.datemenu-calendar-column .datemenu-displays-section { + padding-bottom: 0; +} + +.datemenu-calendar-column .datemenu-displays-box { + spacing: 6px; +} + +.world-clocks-header, +.weather-header, +.events-section-title { + color: rgba(251, 241, 199, 0.7); + font-weight: bold; +} + +.datemenu-today-button, +.datemenu-displays-box { + margin: 4px 6px; +} + +/* today button (the date) */ +.datemenu-today-button { + border: none; + box-shadow: none; + background: none; + padding: 6px 12px; + margin: 0; + text-shadow: none; + color: rgba(251, 241, 199, 0.7); + border-radius: 12px; + margin: 4px; +} + +.datemenu-today-button:ltr { + margin-left: 4px; +} + +.datemenu-today-button:rtl { + margin-right: 4px; +} + +.datemenu-today-button:hover, .datemenu-today-button:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.datemenu-today-button:active { + background-color: rgba(251, 241, 199, 0.2); +} + +.datemenu-today-button .day-label { + font-size: 12ptpt; + font-weight: bold; +} + +.datemenu-today-button .date-label { + font-size: 18ptpt; + font-weight: normal; +} + +/* Calendar */ +.calendar { + border: none; + box-shadow: none; + background-color: transparent; + padding: 6px !important; + margin: 4px !important; + text-shadow: none; + border-radius: 18px; + color: rgba(251, 241, 199, 0.7); +} + +.calendar .calendar-month-label { + padding: 6px 0; + color: rgba(251, 241, 199, 0.7) !important; + font-weight: bold; + text-align: center; + text-shadow: none; + background-color: transparent; +} + +.calendar .calendar-change-month-back, +.calendar .calendar-change-month-forward { + padding: 0 !important; + margin: 3px 0 !important; +} + +.calendar .calendar-change-month-back StIcon, +.calendar .calendar-change-month-forward StIcon { + icon-size: 16px; +} + +.calendar .pager-button { + width: 32px !important; + height: 32px !important; + margin: 2px !important; + border-radius: 9999px; + background-color: transparent; + color: #fbf1c7; + box-shadow: none !important; +} + +.calendar .pager-button:hover, .calendar .pager-button:focus { + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none !important; +} + +.calendar .pager-button:active { + background-color: rgba(251, 241, 199, 0.3); + box-shadow: none !important; +} + +.calendar .calendar-day { + font-size: 10ptpt; + text-align: center; + width: 34px !important; + height: 34px !important; + padding: 0 !important; + margin: 2px !important; + border-radius: 9999px; + color: rgba(251, 241, 199, 0.7) !important; + border: none; + font-feature-settings: 'tnum'; + background-color: transparent; +} + +.calendar .calendar-day:hover, .calendar .calendar-day:focus { + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none !important; + outline: none !important; +} + +.calendar .calendar-day:active, .calendar .calendar-day:selected { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.3); + border-color: transparent !important; + box-shadow: none !important; + outline: none !important; +} + +.calendar .calendar-day.calendar-weekend { + color: rgba(251, 241, 199, 0.5) !important; +} + +.calendar .calendar-day { + border-width: 0; +} + +.calendar .calendar-day-top { + border-top-width: 0; +} + +.calendar .calendar-day-left { + border-left-width: 0; +} + +.calendar .calendar-nonwork-day { + color: #fbf1c7; +} + +.calendar .calendar-today { + font-weight: bold; + color: rgba(251, 241, 199, 0.7) !important; + background-color: rgba(251, 241, 199, 0.06); + border: none; +} + +.calendar .calendar-today:hover, .calendar .calendar-today:focus { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7 !important; +} + +.calendar .calendar-today:active { + background-color: #6da498; + color: rgba(40, 40, 40, 0.87) !important; +} + +.calendar .calendar-today:selected { + background-color: #7daea3; + color: #282828 !important; +} + +.calendar .calendar-today:selected:hover, .calendar .calendar-today:selected:focus { + background-color: #96beb5; + color: #282828 !important; +} + +.calendar .calendar-day-with-events { + color: rgba(251, 241, 199, 0.7); + background-image: url("assets/calendar-today.svg"); +} + +.calendar .calendar-day-with-events.calendar-work-day { + color: rgba(251, 241, 199, 0.7); + font-weight: bold; +} + +.calendar .calendar-other-month { + color: rgba(251, 241, 199, 0.32) !important; + font-weight: normal; +} + +.calendar .calendar-other-month.calendar-weekend { + color: rgba(251, 241, 199, 0.32) !important; +} + +.calendar .calendar-day-heading { + font-weight: bold; + text-align: center; + margin: 4px; + padding: 3px 6px; + border-radius: 12px; + background-color: transparent; + color: #fbf1c7; +} + +.calendar .calendar-week-number { + width: 26px; + height: 20px; + margin: 6px 2px !important; + padding: 0; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + font-weight: bold; + font-feature-settings: 'tnum'; + text-align: center; +} + +.world-clocks-button, +.weather-button, +.events-button { + padding: 12px !important; + margin: 4px 0 0 !important; +} + +.events-button .events-box { + spacing: 6px; +} + +.events-button .events-list { + spacing: 12px; + text-shadow: none; + color: rgba(251, 241, 199, 0.7); +} + +.events-button .events-title { + font-weight: bold; + text-shadow: none; + color: rgba(251, 241, 199, 0.5); +} + +.events-button .event-time { + font-feature-settings: 'tnum'; + font-size: 10ptpt; + color: rgba(251, 241, 199, 0.5); +} + +.world-clocks-button .world-clocks-grid { + spacing-rows: 6px; + spacing-columns: 12px; +} + +.world-clocks-button .world-clocks-header { + color: rgba(251, 241, 199, 0.5); +} + +.world-clocks-button .world-clocks-city { + font-weight: bold; + font-size: 11ptpt; + color: rgba(251, 241, 199, 0.7); +} + +.world-clocks-button .world-clocks-time { + font-feature-settings: 'tnum'; + font-size: 11ptpt; + color: #fbf1c7; +} + +.world-clocks-button .world-clocks-time:ltr { + text-align: right; +} + +.world-clocks-button .world-clocks-time:rtl { + text-align: left; +} + +.world-clocks-button .world-clocks-timezone { + font-feature-settings: 'tnum'; + font-size: 10ptpt; + color: rgba(251, 241, 199, 0.5); +} + +.world-clocks-grid, +.weather-grid { + spacing-rows: 0.4em; + spacing-columns: 0.8em; +} + +.weather-button .weather-box { + spacing: 10px; +} + +.weather-button .weather-header-box { + spacing: 6px; +} + +.weather-button .weather-header { + font-weight: bold; + color: rgba(251, 241, 199, 0.7); +} + +.weather-button .weather-header.location { + font-weight: normal; + font-size: 10ptpt; + color: rgba(251, 241, 199, 0.5); +} + +.weather-button .weather-grid { + spacing-rows: 6px; + spacing-columns: 12px; +} + +.weather-button .weather-forecast-time { + font-feature-settings: 'tnum'; + font-size: 9ptpt; + font-weight: normal; + padding-top: 0.2em; + padding-bottom: 0.4em; + color: rgba(251, 241, 199, 0.7); +} + +.weather-button .weather-forecast-icon { + icon-size: 32px; +} + +.weather-button .weather-forecast-temp { + font-weight: bold; +} + +/* Check Boxes */ +.check-box StBoxLayout { + spacing: 0.8em; +} + +.check-box StBin { + width: 24px; + height: 24px; + padding: 3px; + border-radius: 9999px; +} + +.check-box StIcon { + icon-size: 0; + padding: 0; + color: transparent !important; + border: none !important; + background-color: transparent !important; +} + +.check-box StBin, .check-box:focus StBin { + background-image: url("assets/checkbox-off.svg"); + background-color: tranparent; + box-shadow: none; +} + +.check-box:hover StBin { + background-image: url("assets/checkbox-off-hover.svg"); + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.04); +} + +.check-box:active StBin { + background-image: url("assets/checkbox-off-active.svg"); +} + +.check-box:checked StBin, .check-box:focus:checked StBin { + background-image: url("assets/checkbox.svg"); +} + +/* Dash */ +#dash { + margin-top: 16px; +} + +#dash .dash-background { + background-color: rgba(40, 37, 36, 0.65); + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.12); + border: none; + /* remove black border on ubuntu */ + padding: 4px 3px; + border-radius: 23px; +} + +#dash .dash-item-container .placeholder { + background-image: none; + background-size: contain; + height: 32px; +} + +#dash .dash-item-container .empty-dash-drop-target { + width: 32px; + height: 32px; +} + +#dash .dash-item-container .show-apps, +#dash .dash-item-container .overview-tile, +#dash .dash-item-container .grid-search-result { + background: none; + box-shadow: none; + border: none; + border-radius: 0; + padding: 0; + margin: 0 2px; + padding-bottom: 16px; +} + +#dash .dash-item-container .show-apps .overview-icon, +#dash .dash-item-container .overview-tile .overview-icon, +#dash .dash-item-container .grid-search-result .overview-icon { + border-radius: 16px; + padding: 4px; + spacing: 4px; + text-align: center; + transition-duration: 100ms; + background-color: transparent; + color: #fbf1c7; +} + +#dash .dash-item-container .show-apps:focus .overview-icon, +#dash .dash-item-container .overview-tile:focus .overview-icon, +#dash .dash-item-container .grid-search-result:focus .overview-icon { + background-color: rgba(251, 241, 199, 0.12); +} + +#dash .dash-item-container .show-apps:hover .overview-icon, +#dash .dash-item-container .overview-tile:hover .overview-icon, +#dash .dash-item-container .grid-search-result:hover .overview-icon { + background-color: rgba(251, 241, 199, 0.15); + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.15); +} + +#dash .dash-item-container .show-apps:active .overview-icon, +#dash .dash-item-container .overview-tile:active .overview-icon, +#dash .dash-item-container .grid-search-result:active .overview-icon { + background-color: rgba(251, 241, 199, 0.3); +} + +#dash .dash-item-container .show-apps:checked .overview-icon, +#dash .dash-item-container .overview-tile:checked .overview-icon, +#dash .dash-item-container .grid-search-result:checked .overview-icon { + background-color: rgba(251, 241, 199, 0.12); +} + +#dash .dash-item-container .app-well-app-running-dot, +#dash .dash-item-container .app-grid-running-dot { + margin-bottom: 12px; + offset-y: 8px; + width: 6px; + height: 6px; + border-radius: 9999px; + background-color: #fbf1c7; +} + +#dash .dash-separator { + width: 1px; + margin-left: 4px; + margin-right: 4px; + background-color: rgba(251, 241, 199, 0.25); +} + +#dash .dash-separator, +#dash .dash-background { + margin-bottom: 16px; +} + +.dash-label { + background-color: #0f0e0e; + color: #928374; + border-radius: 12px; + padding: 6px 12px; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.12); + border: none; + text-align: center; + -y-offset: 12px; + -x-offset: 8px; +} + +/* Modal Dialogs */ +.modal-dialog, .candidate-popup-content { + background-color: #242220; + border-radius: 18px; + border: none; + box-shadow: inset 0 0.5px rgba(251, 241, 199, 0.1); + border: 2px solid #7daea3; +} + +.modal-dialog-button:last-child, .modal-dialog-linked-button:last-child { + background-color: #7daea3; + color: #282828; +} + +.modal-dialog-button:hover:last-child, .modal-dialog-linked-button:hover:last-child { + background-color: #99c0b7; + color: #282828; +} + +.modal-dialog-button:active:last-child, .modal-dialog-linked-button:active:last-child { + background-color: #6da498; + color: #282828; +} + +.modal-dialog-button:insensitive:last-child, .modal-dialog-linked-button:insensitive:last-child { + background-color: rgba(125, 174, 163, 0.05); + color: rgba(125, 174, 163, 0.35); +} + +.headline { + font-size: 12ptpt; +} + +.modal-dialog { + color: rgba(251, 241, 199, 0.7); + padding: 12px; + margin: 0; +} + +.modal-dialog-button, .modal-dialog-linked-button { + min-height: 32px !important; + padding: 6px !important; + margin: 0 !important; + border: none !important; + border-radius: 12px; +} + +.modal-dialog-button:first-child, .modal-dialog-linked-button:first-child { + background-color: rgba(251, 241, 199, 0.04); +} + +.modal-dialog-button:first-child:focus, .modal-dialog-linked-button:first-child:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.modal-dialog-button:first-child:hover, .modal-dialog-linked-button:first-child:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.modal-dialog-button:first-child:active, .modal-dialog-linked-button:first-child:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.modal-dialog .modal-dialog-button-box { + padding-top: 6px; +} + +.modal-dialog .modal-dialog-content-box { + margin: 6px; + spacing: 6px; + max-width: 28em; +} + +.end-session-dialog { + width: 26em; +} + +.end-session-dialog .end-session-dialog-battery-warning, +.end-session-dialog .dialog-list-title { + color: #b47109; + background-color: rgba(180, 113, 9, 0.1); + padding: 9px; + border-radius: 12px; + margin: 4px 0; +} + +.message-dialog-content { + spacing: 18px; +} + +.message-dialog-content .message-dialog-title { + text-align: center; +} + +.message-dialog-content .message-dialog-description { + text-align: center; +} + +.dialog-list { + spacing: 18px; +} + +.dialog-list .dialog-list-title { + text-align: center; +} + +.dialog-list .dialog-list-scrollview { + max-height: 200px; +} + +.dialog-list .dialog-list-box { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-title { + font-weight: bold; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + color: rgba(251, 241, 199, 0.7); +} + +.run-dialog { + width: 26em; + padding-bottom: 6px; +} + +.run-dialog .run-dialog-entry { + padding: 12px 9px; +} + +.run-dialog .run-dialog-description { + text-align: center; + color: rgba(251, 241, 199, 0.7); +} + +.prompt-dialog { + width: 28em; +} + +.prompt-dialog .prompt-dialog-password-grid { + spacing-rows: 8px; + spacing-columns: 4px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry { + width: auto; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:ltr { + margin-left: 20px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:rtl { + margin-right: 20px; +} + +.prompt-dialog .prompt-dialog-password-layout { + spacing: 8px; +} + +.prompt-dialog .prompt-dialog-password-entry { + width: 20em; + padding: 12px 9px; +} + +.prompt-dialog .prompt-dialog-error-label, +.prompt-dialog .prompt-dialog-info-label, +.prompt-dialog .prompt-dialog-null-label { + text-align: center; +} + +.prompt-dialog .prompt-dialog-error-label { + color: #b47109; +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 8px; + margin-bottom: 6px; +} + +.polkit-dialog-user-layout .polkit-dialog-user-root-label { + color: #b47109; +} + +.audio-device-selection-dialog { + min-width: 24em; +} + +.audio-device-selection-dialog .audio-selection-box { + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device { + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:hover, .audio-device-selection-dialog .audio-selection-box .audio-selection-device:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:active { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-box { + padding: 12px; + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-icon { + icon-size: 64px; +} + +.welcome-dialog-image { + background-image: url("resource:///org/gnome/shell/theme/gnome-shell-start.svg"); + background-size: contain; + height: 300px; + width: 300px; +} + +/* Access portal dialog */ +.access-dialog { + text-align: center; +} + +/* Modal Dialogs */ +.modal-dialog, .candidate-popup-content { + background-color: #242220; + border-radius: 18px; + border: none; + box-shadow: inset 0 0.5px rgba(251, 241, 199, 0.1); + border: 2px solid #7daea3; +} + +.modal-dialog-linked-button:last-child, .modal-dialog-button:last-child { + background-color: #7daea3; + color: #282828; +} + +.modal-dialog-linked-button:hover:last-child, .modal-dialog-button:hover:last-child { + background-color: #99c0b7; + color: #282828; +} + +.modal-dialog-linked-button:active:last-child, .modal-dialog-button:active:last-child { + background-color: #6da498; + color: #282828; +} + +.modal-dialog-linked-button:insensitive:last-child, .modal-dialog-button:insensitive:last-child { + background-color: rgba(125, 174, 163, 0.05); + color: rgba(125, 174, 163, 0.35); +} + +.headline { + font-size: 12ptpt; +} + +.modal-dialog { + color: rgba(251, 241, 199, 0.7); + padding: 12px; + margin: 0; +} + +.modal-dialog-button, .modal-dialog-linked-button { + min-height: 32px !important; + padding: 6px !important; + margin: 0 !important; + border: none !important; + border-radius: 12px; +} + +.modal-dialog-button:first-child, .modal-dialog-linked-button:first-child { + background-color: rgba(251, 241, 199, 0.04); +} + +.modal-dialog-button:first-child:focus, .modal-dialog-linked-button:first-child:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.modal-dialog-button:first-child:hover, .modal-dialog-linked-button:first-child:hover { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.modal-dialog-button:first-child:active, .modal-dialog-linked-button:first-child:active { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + box-shadow: none !important; +} + +.modal-dialog .modal-dialog-button-box { + padding-top: 6px; +} + +.modal-dialog .modal-dialog-content-box { + margin: 6px; + spacing: 6px; + max-width: 28em; +} + +.end-session-dialog { + width: 26em; +} + +.end-session-dialog .end-session-dialog-battery-warning, +.end-session-dialog .dialog-list-title { + color: #b47109; + background-color: rgba(180, 113, 9, 0.1); + padding: 9px; + border-radius: 12px; + margin: 4px 0; +} + +.message-dialog-content { + spacing: 18px; +} + +.message-dialog-content .message-dialog-title { + text-align: center; +} + +.message-dialog-content .message-dialog-description { + text-align: center; +} + +.dialog-list { + spacing: 18px; +} + +.dialog-list .dialog-list-title { + text-align: center; +} + +.dialog-list .dialog-list-scrollview { + max-height: 200px; +} + +.dialog-list .dialog-list-box { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item { + spacing: 1em; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-title { + font-weight: bold; +} + +.dialog-list .dialog-list-box .dialog-list-item .dialog-list-item-description { + color: rgba(251, 241, 199, 0.7); +} + +.run-dialog { + width: 26em; + padding-bottom: 6px; +} + +.run-dialog .run-dialog-entry { + padding: 12px 9px; +} + +.run-dialog .run-dialog-description { + text-align: center; + color: rgba(251, 241, 199, 0.7); +} + +.prompt-dialog { + width: 28em; +} + +.prompt-dialog .prompt-dialog-password-grid { + spacing-rows: 8px; + spacing-columns: 4px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry { + width: auto; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:ltr { + margin-left: 20px; +} + +.prompt-dialog .prompt-dialog-password-grid .prompt-dialog-password-entry:rtl { + margin-right: 20px; +} + +.prompt-dialog .prompt-dialog-password-layout { + spacing: 8px; +} + +.prompt-dialog .prompt-dialog-password-entry { + width: 20em; + padding: 12px 9px; +} + +.prompt-dialog .prompt-dialog-error-label, +.prompt-dialog .prompt-dialog-info-label, +.prompt-dialog .prompt-dialog-null-label { + text-align: center; +} + +.prompt-dialog .prompt-dialog-error-label { + color: #b47109; +} + +.polkit-dialog-user-layout { + text-align: center; + spacing: 8px; + margin-bottom: 6px; +} + +.polkit-dialog-user-layout .polkit-dialog-user-root-label { + color: #b47109; +} + +.audio-device-selection-dialog { + min-width: 24em; +} + +.audio-device-selection-dialog .audio-selection-box { + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device { + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:hover, .audio-device-selection-dialog .audio-selection-box .audio-selection-device:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device:active { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-box { + padding: 12px; + spacing: 12px; +} + +.audio-device-selection-dialog .audio-selection-box .audio-selection-device .audio-selection-device-icon { + icon-size: 64px; +} + +.welcome-dialog-image { + background-image: url("resource:///org/gnome/shell/theme/gnome-shell-start.svg"); + background-size: contain; + height: 300px; + width: 300px; +} + +/* Access portal dialog */ +.access-dialog { + text-align: center; +} + +/* Message List */ +.message-list { + width: 29em; + text-shadow: none; + border: solid rgba(251, 241, 199, 0.12); + padding: 0; +} + +.message-list:ltr { + margin-left: 0; + margin-right: 8px; + padding-right: 10px; + border-right-width: 0; +} + +.message-list:rtl { + margin-right: 0; + margin-left: 8px; + padding-left: 10px; + border-left-width: 0; +} + +.message-list .message-list-placeholder { + spacing: 12px; + color: rgba(251, 241, 199, 0.32); +} + +.message-list .message-list-placeholder > StIcon { + icon-size: 96px; + margin-bottom: 12px; + -st-icon-style: symbolic; +} + +.message-list-sections { + margin: 0; + padding-bottom: 6px; +} + +.message-list-sections:ltr { + margin-right: 0; +} + +.message-list-sections:rtl { + margin-left: 0; +} + +.message-list-section, +.message-list-sections, +.message-list-section-list { + spacing: 6px; +} + +.message-list-controls { + margin: 8px 16px 0; + padding: 6px; + spacing: 6px; +} + +.message-list-controls .dnd-button { + border-width: 2px; + border-color: transparent; + border-radius: 32px; + border-style: solid; +} + +.message-list-controls .dnd-button:focus { + border-color: rgba(125, 174, 163, 0.6); +} + +.message { + padding: 0; + margin: 3px; + border-radius: 20px; +} + +.popup-menu .message { + border-radius: 12px; +} + +.popup-menu .message .notification-button:first-child:ltr { + border-radius: 0 0 0 12px; +} + +.popup-menu .message .notification-button:last-child:ltr { + border-radius: 0 0 12px; +} + +.popup-menu .message .notification-button:first-child:rtl { + border-radius: 0 0 12px; +} + +.popup-menu .message .notification-button:last-child:rtl { + border-radius: 0 0 0 12px; +} + +.popup-menu .message .notification-button:first-child:last-child { + border-radius: 0 0 12px 12px; +} + +.message .message-header { + padding: 0 0.409em; + margin: 6px; + margin-bottom: 0; + spacing: 6px; + color: rgba(251, 241, 199, 0.5); +} + +.message .message-header .message-source-icon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.message .message-header .message-header-content { + spacing: 6px; + min-height: 1.637em; + padding-bottom: 6px; +} + +.message .message-header .message-header-content .message-source-title { + font-weight: bold; +} + +.message .message-header .message-header-content .event-time { + padding-bottom: 0.068em; + color: rgba(251, 241, 199, 0.5); +} + +.message .message-header .message-header-content .event-time:ltr { + text-align: right; +} + +.message .message-header .message-header-content .event-time:rtl { + text-align: left; +} + +.message .message-header .message-expand-button, +.message .message-header .message-close-button { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button, .message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:active, +.message .message-header .message-close-button, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:active { + color: #fbf1c7; +} + +.message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:focus, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.message .message-header .message-expand-button:active, .message .message-header .message-expand-button:active:hover, +.message .message-header .message-close-button:active, +.message .message-header .message-close-button:active:hover { + background-color: rgba(251, 241, 199, 0.3); +} + +.message .message-header .message-expand-button:insensitive, +.message .message-header .message-close-button:insensitive { + background-color: rgba(251, 241, 199, 0.04); +} + +.message .message-header .message-expand-button { + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button:ltr { + margin-right: 6px; +} + +.message .message-header .message-expand-button:rtl { + margin-left: 6px; +} + +.message .message-box { + padding: 6px; + margin: 6px; + margin-top: 0; + spacing: 6px; +} + +.message .message-box .message-icon { + icon-size: 48px; + -st-icon-style: symbolic; +} + +.message .message-box .message-icon:ltr { + margin-right: 6px; +} + +.message .message-box .message-icon:rtl { + margin-left: 6px; +} + +.message .message-box .message-icon.message-themed-icon { + border-radius: 9999px; + icon-size: 16px; + min-width: 48px; + min-height: 48px; + color: rgba(251, 241, 199, 0.5); + background-color: rgba(251, 241, 199, 0.12); +} + +.message .message-box:first-child { + margin-top: 12px; +} + +.message .message-box .message-content { + spacing: 4px; +} + +.message .message-box .message-content .message-title { + font-weight: bold; +} + +.url-highlighter { + link-color: #83b193; +} + +.message-media-control { + margin: 4px 6px; + padding: 12px; + border-radius: 9999px; + border: none; + color: rgba(251, 241, 199, 0.7); +} + +.message-media-control:hover, .message-media-control:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.message-media-control:active { + background-color: rgba(251, 241, 199, 0.3); +} + +.message-media-control:hover, .message-media-control:focus, .message-media-control:active { + color: #fbf1c7; +} + +.message-media-control:insensitive { + color: rgba(251, 241, 199, 0.5); +} + +.message-media-control StIcon { + icon-size: 16px; +} + +.media-message .message-icon { + border-radius: 6px !important; +} + +.media-message .message-icon.message-themed-icon { + icon-size: 32px !important; +} + +/* Message List */ +.message-list { + width: 29em; + text-shadow: none; + border: solid rgba(251, 241, 199, 0.12); + padding: 0; +} + +.message-list:ltr { + margin-left: 2px; + margin-right: 8px; + padding-right: 10px; + border-right-width: 0; +} + +.message-list:rtl { + margin-right: 0; + margin-left: 8px; + padding-left: 10px; + border-left-width: 0; +} + +.message-list .message-list-placeholder { + spacing: 12px; + color: rgba(251, 241, 199, 0.32); +} + +.message-list .message-list-placeholder > StIcon { + icon-size: 96px; + margin-bottom: 12px; + -st-icon-style: symbolic; +} + +.message-view { + -st-vfade-offset: 24px; +} + +.message-view:ltr { + margin-right: 12px; +} + +.message-view:rtl { + margin-left: 12px; +} + +.message-view .message { + margin-bottom: 12px !important; +} + +.message-list-controls { + margin: 8px 16px 0; + padding: 6px; + spacing: 6px; +} + +.message-list-controls .dnd-button { + border-width: 2px; + border-color: transparent; + border-radius: 32px; + border-style: solid; +} + +.message-list-controls .dnd-button:focus { + border-color: rgba(125, 174, 163, 0.6); +} + +.message-notification-group { + spacing: 12px; +} + +.message-notification-group .message-group-header { + padding: 6px; +} + +.message-notification-group .message-group-header .message-group-title { + margin: 0 4px; +} + +.message-notification-group .message-collapse-button { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + padding: 4px !important; + border: 4px transparent solid; +} + +.message-notification-group .message-collapse-button:hover { + background-color: rgba(251, 241, 199, 0.3); +} + +.message-notification-group .message-collapse-button:active { + background-color: rgba(251, 241, 199, 0.2); +} + +.message { + padding: 0; + margin: 3px; + border-radius: 20px; +} + +.popup-menu .message { + border-radius: 12px; + color: rgba(251, 241, 199, 0.5); + background-color: #323232; + border: 1px solid rgba(40, 40, 40, 0.75); + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.1); + /* &:insensitive { + color: $text-disabled; + background-color: lighten($background, 4%); + box-shadow: none !important; + } */ +} + +.popup-menu .message:hover, .popup-menu .message:focus { + color: rgba(125, 174, 163, 0.5); + background-color: #353535; +} + +.popup-menu .message:active { + color: #fbf1c7; + background-color: #323232; + box-shadow: none !important; +} + +.message:second-in-stack { + background-color: #373737; +} + +.message:lower-in-stack { + background-color: #3c3c3c; + border: 1px solid rgba(251, 241, 199, 0); +} + +.message .message-header { + padding: 0 0.409em; + margin: 6px; + margin-bottom: 0; + spacing: 6px; + color: rgba(251, 241, 199, 0.5); + /* .message-close-button { + margin-left: $base_padding * 0.5; + padding: 4px; + } */ +} + +.message .message-header:ltr { + padding-right: 0; +} + +.message .message-header:rtl { + padding-left: 0; +} + +.message .message-header .message-source-icon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.message .message-header .message-header-content { + spacing: 6px; + min-height: 1.637em; + padding-bottom: 6px; +} + +.message .message-header .message-header-content .message-source-title { + font-weight: bold; +} + +.message .message-header .message-header-content .event-time { + padding-bottom: 0.068em; + color: rgba(251, 241, 199, 0.5); +} + +.message .message-header .message-header-content .event-time:ltr { + text-align: right; +} + +.message .message-header .message-header-content .event-time:rtl { + text-align: left; +} + +.message .message-header .message-expand-button, +.message .message-header .message-close-button { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button, .message .message-header .message-expand-button:hover, +.message .message-header .message-close-button, +.message .message-header .message-close-button:hover { + color: #fbf1c7; +} + +.message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:focus, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.message .message-header .message-expand-button:active, .message .message-header .message-expand-button:active:hover, +.message .message-header .message-close-button:active, +.message .message-header .message-close-button:active:hover { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.message .message-header .message-expand-button:insensitive, +.message .message-header .message-close-button:insensitive { + background-color: rgba(251, 241, 199, 0.04); +} + +.message .message-header .message-expand-button { + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button:ltr { + margin-right: 6px; +} + +.message .message-header .message-expand-button:rtl { + margin-left: 6px; +} + +.message .message-box { + padding: 6px; + margin: 6px; + margin-top: 0; + spacing: 6px; +} + +.message .message-box .message-icon { + icon-size: 48px; + -st-icon-style: symbolic; +} + +.message .message-box .message-icon:ltr { + margin-right: 6px; +} + +.message .message-box .message-icon:rtl { + margin-left: 6px; +} + +.message .message-box .message-icon.message-themed-icon { + border-radius: 9999px; + icon-size: 16px; + min-width: 48px; + min-height: 48px; + color: rgba(251, 241, 199, 0.5); + background-color: rgba(251, 241, 199, 0.12); +} + +.message .message-box:first-child { + margin-top: 12px; +} + +.message .message-box .message-content { + spacing: 4px; +} + +.message .message-box .message-content .message-title { + font-weight: bold; +} + +.url-highlighter { + link-color: #83b193; +} + +.message-media-control { + margin: 4px 6px; + padding: 12px; + border-radius: 9999px; + border: none; + color: rgba(251, 241, 199, 0.7); +} + +.message-media-control:hover, .message-media-control:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.message-media-control:active { + background-color: rgba(251, 241, 199, 0.3); +} + +.message-media-control:hover, .message-media-control:focus, .message-media-control:active { + color: #fbf1c7; +} + +.message-media-control:insensitive { + color: rgba(251, 241, 199, 0.5); +} + +.message-media-control StIcon { + icon-size: 16px; +} + +.media-message .message-icon { + border-radius: 6px !important; +} + +.media-message .message-icon.message-themed-icon { + icon-size: 32px !important; +} + +/* Message List */ +.message-list { + width: 29em; + text-shadow: none; + border: solid rgba(251, 241, 199, 0.12); + padding: 0; +} + +.message-list:ltr { + margin-left: 2px; + margin-right: 8px; + padding-right: 10px; + border-right-width: 0; +} + +.message-list:rtl { + margin-right: 0; + margin-left: 8px; + padding-left: 10px; + border-left-width: 0; +} + +.message-list .message-list-placeholder { + spacing: 12px; + color: rgba(251, 241, 199, 0.32); +} + +.message-list .message-list-placeholder > StIcon { + icon-size: 96px; + margin-bottom: 12px; + -st-icon-style: symbolic; +} + +.message-view { + -st-vfade-offset: 24px; +} + +.message-view:ltr { + margin-right: 12px; +} + +.message-view:rtl { + margin-left: 12px; +} + +.message-view .message { + margin-bottom: 12px !important; +} + +.message-list-controls { + margin: 8px 16px 0; + padding: 6px; + spacing: 6px; +} + +.message-list-controls .dnd-button { + border-width: 2px; + border-color: transparent; + border-radius: 32px; + border-style: solid; +} + +.message-list-controls .dnd-button:focus { + border-color: rgba(125, 174, 163, 0.6); +} + +.message-notification-group { + spacing: 12px; +} + +.message-notification-group .message-group-header { + padding: 6px; +} + +.message-notification-group .message-group-header .message-group-title { + margin: 0 4px; +} + +.message-notification-group .message-collapse-button { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.2); + padding: 4px !important; + border: 4px transparent solid; +} + +.message-notification-group .message-collapse-button:hover { + background-color: rgba(251, 241, 199, 0.3); +} + +.message-notification-group .message-collapse-button:active { + background-color: rgba(251, 241, 199, 0.2); +} + +.message { + padding: 0; + margin: 3px; + border-radius: 20px; +} + +.popup-menu .message { + border-radius: 12px; + color: rgba(251, 241, 199, 0.5); + background-color: #323232; + border: 1px solid rgba(40, 40, 40, 0.75); + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.1); + /* &:insensitive { + color: $text-disabled; + background-color: lighten($background, 4%); + box-shadow: none !important; + } */ +} + +.popup-menu .message:hover, .popup-menu .message:focus { + color: rgba(125, 174, 163, 0.5); + background-color: #353535; +} + +.popup-menu .message:active { + color: #fbf1c7; + background-color: #323232; + box-shadow: none !important; +} + +.message:second-in-stack { + background-color: #373737; +} + +.message:lower-in-stack { + background-color: #3c3c3c; + border: 1px solid rgba(251, 241, 199, 0); +} + +.message .message-header { + padding: 0 0.409em; + margin: 6px; + margin-bottom: 0; + spacing: 6px; + color: rgba(251, 241, 199, 0.5); + /* .message-close-button { + margin-left: $base_padding * 0.5; + padding: 4px; + } */ +} + +.message .message-header:ltr { + padding-right: 0; +} + +.message .message-header:rtl { + padding-left: 0; +} + +.message .message-header .message-source-icon { + icon-size: 1.091em; + -st-icon-style: symbolic; +} + +.message .message-header .message-header-content { + spacing: 6px; + min-height: 1.637em; + padding-bottom: 6px; +} + +.message .message-header .message-header-content .message-source-title { + font-weight: bold; +} + +.message .message-header .message-header-content .event-time { + padding-bottom: 0.068em; + color: rgba(251, 241, 199, 0.5); +} + +.message .message-header .message-header-content .event-time:ltr { + text-align: right; +} + +.message .message-header .message-header-content .event-time:rtl { + text-align: left; +} + +.message .message-header .message-expand-button, +.message .message-header .message-close-button { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button, .message .message-header .message-expand-button:hover, +.message .message-header .message-close-button, +.message .message-header .message-close-button:hover { + color: #fbf1c7; +} + +.message .message-header .message-expand-button:hover, .message .message-header .message-expand-button:focus, +.message .message-header .message-close-button:hover, +.message .message-header .message-close-button:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.message .message-header .message-expand-button:active, .message .message-header .message-expand-button:active:hover, +.message .message-header .message-close-button:active, +.message .message-header .message-close-button:active:hover { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.message .message-header .message-expand-button:insensitive, +.message .message-header .message-close-button:insensitive { + background-color: rgba(251, 241, 199, 0.04); +} + +.message .message-header .message-expand-button { + padding: 4px; + border: none; +} + +.message .message-header .message-expand-button:ltr { + margin-right: 6px; +} + +.message .message-header .message-expand-button:rtl { + margin-left: 6px; +} + +.message .message-box { + padding: 6px; + margin: 6px; + margin-top: 0; + spacing: 6px; +} + +.message .message-box .message-icon { + icon-size: 48px; + -st-icon-style: symbolic; +} + +.message .message-box .message-icon:ltr { + margin-right: 6px; +} + +.message .message-box .message-icon:rtl { + margin-left: 6px; +} + +.message .message-box .message-icon.message-themed-icon { + border-radius: 9999px; + icon-size: 16px; + min-width: 48px; + min-height: 48px; + color: rgba(251, 241, 199, 0.5); + background-color: rgba(251, 241, 199, 0.12); +} + +.message .message-box:first-child { + margin-top: 12px; +} + +.message .message-box .message-content { + spacing: 4px; +} + +.message .message-box .message-content .message-title { + font-weight: bold; +} + +.url-highlighter { + link-color: #83b193; +} + +.message-media-control { + margin: 4px 6px; + padding: 12px; + border-radius: 9999px; + border: none; + color: rgba(251, 241, 199, 0.7); +} + +.message-media-control:hover, .message-media-control:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.message-media-control:active { + background-color: rgba(251, 241, 199, 0.3); +} + +.message-media-control:hover, .message-media-control:focus, .message-media-control:active { + color: #fbf1c7; +} + +.message-media-control:insensitive { + color: rgba(251, 241, 199, 0.5); +} + +.message-media-control StIcon { + icon-size: 16px; +} + +.media-message .message-icon { + border-radius: 6px !important; +} + +.media-message .message-icon.message-themed-icon { + icon-size: 32px !important; +} + +.workspace-animation { + background-color: #282828; +} + +.calendar .calendar-change-month-back, +.calendar .calendar-change-month-forward { + padding: 0 2px; +} + +/* Notifications & Message Tray */ +.notification-banner { + min-height: 64px; + width: 34em; + margin: 20px; + border-radius: 12px; + color: rgba(251, 241, 199, 0.7); + background-color: #242220; + border: none; + text-shadow: none; + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.25); + border-radius: 18px; + border: 2px solid #7daea3; +} + +.notification-banner:hover, .notification-banner:active { + color: #fbf1c7; + background-color: #242220; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.25); + margin: 20px; +} + +.notification-banner:focus { + color: #fbf1c7; + background-color: #242220; +} + +.notification-buttons-bin { + background-color: transparent; + padding-top: 0; + border: none; + border-top: 1px solid rgba(251, 241, 199, 0.12); + spacing: 0; +} + +.notification-button { + min-height: 44px; + padding: 0 18px; + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + font-weight: 500; + border: none; +} + +.notification-button:focus { + background-color: transparent; + color: #fbf1c7; + box-shadow: inset 0 0 0 2px rgba(251, 241, 199, 0.12); +} + +.notification-button:hover, .notification-button:focus:hover { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; + box-shadow: none; +} + +.notification-button:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +.notification-button:first-child:ltr { + border-radius: 0 0 0 18px; +} + +.notification-button:last-child:ltr { + border-radius: 0 0 18px; + margin-right: 0 !important; +} + +.notification-button:first-child:rtl { + border-radius: 0 0 18px; +} + +.notification-button:last-child:rtl { + border-radius: 0 0 0 18px; + margin-left: 0 !important; +} + +.notification-button:first-child:last-child { + border-radius: 0 0 18px 18px; + margin-left: 0 !important; + margin-right: 0 !important; +} + +/* Notifications & Message Tray */ +.notification-banner { + min-height: 64px; + width: 34em; + padding: 0; + margin: 12px 8px 8px; + color: rgba(251, 241, 199, 0.7); + background-color: #141617; + text-shadow: none; + border-radius: 18px; + border: none; + border: 2px solid #7daea3; +} + +.notification-banner:hover, .notification-banner:active, .notification-banner:focus { + color: #7daea3; + background-color: #202325; + border: 1px solid rgba(40, 40, 40, 0.75); + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.1); +} + +.notification-buttons-bin { + spacing: 0; +} + +.notification-button { + min-height: 6px; + padding: 12px 0; + margin: 0; + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + font-weight: 500; + border: none; + border-radius: 12px; +} + +.notification-button:focus { + background-color: transparent; + color: #fbf1c7; + box-shadow: inset 0 0 0 2px rgba(251, 241, 199, 0.12); +} + +.notification-button:hover, .notification-button:focus:hover { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; + box-shadow: none; +} + +.notification-button:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +/* Notifications & Message Tray */ +.notification-banner { + min-height: 64px; + width: 34em; + padding: 0; + margin: 12px 8px 8px; + color: rgba(251, 241, 199, 0.7); + background-color: #141617; + text-shadow: none; + border-radius: 18px; + border: none; + border: 2px solid #7daea3; +} + +.notification-banner:hover, .notification-banner:active, .notification-banner:focus { + color: #7daea3; + background-color: #202325; + border: 1px solid rgba(40, 40, 40, 0.75); + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.1); +} + +.notification-buttons-bin { + spacing: 0; +} + +.notification-button { + min-height: 6px; + padding: 12px 0; + margin: 0; + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + font-weight: 500; + border: none; + border-radius: 12px; +} + +.notification-button:focus { + background-color: transparent; + color: #fbf1c7; + box-shadow: inset 0 0 0 2px rgba(251, 241, 199, 0.12); +} + +.notification-button:hover, .notification-button:focus:hover { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; + box-shadow: none; +} + +.notification-button:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +.controls-manager, +.secondary-monitor-workspaces { + spacing: 12px; +} + +#overviewGroup { + background-color: #0d0907; +} + +.osd-window { + spacing: 12px; + padding: 12px 18px; + margin-bottom: 4em; +} + +.osd-window > * { + spacing: 8px; +} + +.osd-window StIcon { + icon-size: 32px; +} + +.osd-window StLabel:ltr { + margin-right: 6px; +} + +.osd-window StLabel:rtl { + margin-left: 6px; +} + +#appMenu { + spacing: 6px; +} + +#appMenu .label-shadow { + color: transparent; +} + +#appMenu .panel-status-menu-box { + padding: 0 6px; + spacing: 6px; +} + +.popup-menu .popup-menu-item { + padding: 9px 12px; +} + +.popup-separator-menu-item { + padding: 3px 0 !important; +} + +.popup-separator-menu-item .popup-menu-ornament { + width: 0 !important; +} + +.popup-separator-menu-item .popup-separator-menu-item-separator { + height: 1px; + background-color: rgba(251, 241, 199, 0.12); + margin: 6px 32px; + padding: 0 !important; +} + +.popup-sub-menu .popup-separator-menu-item .popup-separator-menu-item-separator { + padding: 0 !important; + margin: 0 32px 0 0; + height: 1px; +} + +.popup-menu-ornament { + icon-size: 16px !important; + width: 16px; +} + +/* Quick Settings */ +.quick-settings { + padding: 18px !important; + border-radius: 24px !important; + margin-top: 6px !important; +} + +.quick-settings .icon-button, .quick-settings .background-app-item .close-button, .background-app-item .quick-settings .close-button, .quick-settings .message .message-header .message-expand-button, .message .message-header .quick-settings .message-expand-button, +.quick-settings .message .message-header .message-close-button, +.message .message-header .quick-settings .message-close-button, .quick-settings .message-notification-group .message-collapse-button, .message-notification-group .quick-settings .message-collapse-button, +.quick-settings .button { + padding: 10.5px; +} + +.quick-settings .icon-button > StIcon, .quick-settings .background-app-item .close-button > StIcon, .background-app-item .quick-settings .close-button > StIcon, .quick-settings .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings .message-expand-button > StIcon, +.quick-settings .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings .message-close-button > StIcon, .quick-settings .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings .message-collapse-button > StIcon, +.quick-settings .button > StIcon { + icon-size: 16px; +} + +.quick-settings-grid { + spacing-rows: 12px; + spacing-columns: 12px; +} + +.quick-toggle, +.quick-menu-toggle { + border-radius: 12px; + min-width: 12em; + max-width: 12em; + min-height: 44px; + border: none; + margin: 1px; +} + +.quick-toggle { + background-color: rgba(251, 241, 199, 0.08) !important; + /* Move padding into the box; this is to allow menu arrows + to extend to the border */ +} + +.quick-toggle:hover { + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.quick-toggle:active { + background-color: rgba(251, 241, 199, 0.15) !important; +} + +.quick-toggle:checked { + background-color: rgba(125, 174, 163, 0.95) !important; + color: #282828; +} + +.quick-toggle:checked:hover { + background-color: #afc9b1 !important; + color: #282828; +} + +.quick-toggle:checked:active { + background-color: #96bbaa !important; + color: #282828; +} + +.quick-toggle > StBoxLayout { + spacing: 6px; +} + +.quick-toggle.button { + padding: 0; +} + +.quick-toggle > StBoxLayout { + padding: 0 12px; +} + +.quick-toggle:ltr > StBoxLayout { + padding-left: 15px; +} + +.quick-toggle:rtl > StBoxLayout { + padding-right: 15px; +} + +.quick-toggle .quick-toggle-title { + font-weight: bold; +} + +.quick-toggle StBoxLayout > .quick-toggle-subtitle { + font-weight: normal; + font-size: 12px; +} + +.quick-toggle .quick-toggle-icon { + icon-size: 16px; +} + +.quick-menu-toggle .quick-toggle { + min-width: auto; + max-width: auto; +} + +.quick-menu-toggle .quick-toggle:ltr { + border-radius: 12px 0 0 12px; +} + +.quick-menu-toggle .quick-toggle:ltr > StBoxLayout { + padding-right: 9px; +} + +.quick-menu-toggle .quick-toggle:rtl { + border-radius: 0 12px 12px 0; +} + +.quick-menu-toggle .quick-toggle:rtr > StBoxLayout { + padding-left: 9px; +} + +.quick-menu-toggle .quick-toggle:ltr:last-child { + border-radius: 12px; +} + +.quick-menu-toggle .quick-toggle:rtl:last-child { + border-radius: 12px; +} + +.quick-menu-toggle .quick-toggle-arrow { + background-color: rgba(251, 241, 199, 0.08) !important; + padding: 6px 10.5px; + border: none !important; + color: #fbf1c7; + margin: 1px; +} + +.quick-menu-toggle .quick-toggle-arrow:hover { + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.quick-menu-toggle .quick-toggle-arrow:active { + background-color: rgba(251, 241, 199, 0.15) !important; +} + +.quick-menu-toggle .quick-toggle-arrow:checked { + background-color: rgba(125, 174, 163, 0.75) !important; + color: #282828; +} + +.quick-menu-toggle .quick-toggle-arrow:checked:hover { + background-color: #afc9b1 !important; + color: #282828; +} + +.quick-menu-toggle .quick-toggle-arrow:checked:active { + background-color: #96bbaa !important; + color: #282828; +} + +.quick-menu-toggle .quick-toggle-arrow:ltr { + border-radius: 0 12px 12px 0; +} + +.quick-menu-toggle .quick-toggle-arrow:rtl { + border-radius: 12px 0 0 12px; +} + +.quick-slider > StBoxLayout { + spacing: 6px; +} + +.quick-slider .slider-bin { + min-height: 16px; + padding: 6px; + border-radius: 9999px; +} + +.quick-slider .slider-bin:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.quick-slider .quick-toggle-icon { + icon-size: 16px; +} + +.quick-slider .icon-button, .quick-slider .background-app-item .close-button, .background-app-item .quick-slider .close-button, .quick-slider .message .message-header .message-expand-button, .message .message-header .quick-slider .message-expand-button, +.quick-slider .message .message-header .message-close-button, +.message .message-header .quick-slider .message-close-button, .quick-slider .message-notification-group .message-collapse-button, .message-notification-group .quick-slider .message-collapse-button { + background-color: rgba(251, 241, 199, 0.08) !important; + color: #7daea3 !important; + border-radius: 12px; + padding: 9px; +} + +.quick-slider .icon-button:hover, .quick-slider .background-app-item .close-button:hover, .background-app-item .quick-slider .close-button:hover, .quick-slider .message .message-header .message-expand-button:hover, .message .message-header .quick-slider .message-expand-button:hover, +.quick-slider .message .message-header .message-close-button:hover, +.message .message-header .quick-slider .message-close-button:hover, .quick-slider .message-notification-group .message-collapse-button:hover, .message-notification-group .quick-slider .message-collapse-button:hover { + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.quick-slider .icon-button:active, .quick-slider .background-app-item .close-button:active, .background-app-item .quick-slider .close-button:active, .quick-slider .message .message-header .message-expand-button:active, .message .message-header .quick-slider .message-expand-button:active, +.quick-slider .message .message-header .message-close-button:active, +.message .message-header .quick-slider .message-close-button:active, .quick-slider .message-notification-group .message-collapse-button:active, .message-notification-group .quick-slider .message-collapse-button:active { + background-color: rgba(251, 241, 199, 0.04); +} + +.quick-toggle-menu { + background-color: #242220 !important; + color: #fbf1c7 !important; + border-radius: 24px !important; + padding: 12px; + margin: 12px 18px 0; +} + +.quick-toggle-menu .popup-menu-item { + border-radius: 12px !important; +} + +.quick-toggle-menu .popup-menu-item:focus, .quick-toggle-menu .popup-menu-item:hover, .quick-toggle-menu .popup-menu-item.selected { + color: #7daea3 !important; + background-color: rgba(251, 241, 199, 0.1) !important; +} + +.quick-toggle-menu .popup-menu-item:active { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.2) !important; +} + +.quick-toggle-menu .popup-menu-item > StIcon { + -st-icon-style: symbolic; +} + +.quick-toggle-menu .header { + spacing-rows: 3px; + spacing-columns: 12px; + padding-bottom: 12px; +} + +.quick-toggle-menu .header .icon { + icon-size: 24px; + border-radius: 12px; + padding: 9px; + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.quick-toggle-menu .header .icon.active { + background-color: #7daea3 !important; + color: rgba(40, 40, 40, 0.87); +} + +.quick-settings-system-item > StBoxLayout { + spacing: 12px; +} + +.quick-settings-system-item .icon-button, .quick-settings-system-item .background-app-item .close-button, .background-app-item .quick-settings-system-item .close-button, .quick-settings-system-item .message .message-header .message-expand-button, .message .message-header .quick-settings-system-item .message-expand-button, +.quick-settings-system-item .message .message-header .message-close-button, +.message .message-header .quick-settings-system-item .message-close-button, .quick-settings-system-item .message-notification-group .message-collapse-button, .message-notification-group .quick-settings-system-item .message-collapse-button { + background-color: rgba(251, 241, 199, 0.08); + color: #7daea3 !important; + border-radius: 12px; +} + +.quick-settings-system-item .icon-button > StIcon, .quick-settings-system-item .background-app-item .close-button > StIcon, .background-app-item .quick-settings-system-item .close-button > StIcon, .quick-settings-system-item .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings-system-item .message-expand-button > StIcon, +.quick-settings-system-item .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings-system-item .message-close-button > StIcon, .quick-settings-system-item .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings-system-item .message-collapse-button > StIcon { + -st-icon-style: symbolic; + icon-size: 16px; +} + +.quick-settings-system-item .power-item { + color: #7daea3 !important; + min-height: 0; + min-width: 0; +} + +.quick-settings-system-item .power-item:insensitive { + color: #fbf1c7; + background-color: #282524; + box-shadow: none !important; + background-color: transparent; +} + +.nm-network-item .wireless-secure-icon { + icon-size: 8px; +} + +.bt-device-item .popup-menu-icon { + -st-icon-style: symbolic; +} + +.bt-menu-placeholder.popup-menu-item { + text-align: center; + padding: 2em 4em; +} + +.device-subtitle { + color: rgba(251, 241, 199, 0.5); +} + +.background-apps-quick-toggle { + min-height: 40px; + background-color: transparent; +} + +.background-apps-quick-toggle StIcon { + icon-size: 16px !important; +} + +.background-app-item .popup-menu-icon { + icon-size: 32px !important; + -st-icon-style: regular !important; +} + +.background-app-item .close-button { + padding: 6px; +} + +.background-app-item.popup-inactive-menu-item { + color: #fbf1c7; +} + +/* Quick Settings */ +.quick-settings { + padding: 18px !important; + border-radius: 24px !important; + margin-top: 6px !important; +} + +.quick-settings .icon-button, .quick-settings .message .message-header .message-expand-button, .message .message-header .quick-settings .message-expand-button, +.quick-settings .message .message-header .message-close-button, +.message .message-header .quick-settings .message-close-button, .quick-settings .message-notification-group .message-collapse-button, .message-notification-group .quick-settings .message-collapse-button, .quick-settings .background-app-item .close-button, .background-app-item .quick-settings .close-button, +.quick-settings .button { + padding: 10.5px; +} + +.quick-settings .icon-button > StIcon, .quick-settings .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings .message-expand-button > StIcon, +.quick-settings .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings .message-close-button > StIcon, .quick-settings .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings .message-collapse-button > StIcon, .quick-settings .background-app-item .close-button > StIcon, .background-app-item .quick-settings .close-button > StIcon, +.quick-settings .button > StIcon { + icon-size: 16px; +} + +.quick-settings-grid { + spacing-rows: 12px; + spacing-columns: 12px; +} + +.quick-toggle, +.quick-toggle-has-menu { + border-radius: 12px; + min-width: 12em; + max-width: 12em; + min-height: 44px; + border: none; + margin: 1px; +} + +.quick-toggle { + background-color: rgba(251, 241, 199, 0.12) !important; + color: #282828; + /* Move padding into the box; this is to allow menu arrows + to extend to the border */ +} + +.quick-toggle:hover { + background-color: rgba(125, 174, 163, 0.25) !important; + color: #282828; +} + +.quick-toggle:active { + background-color: rgba(125, 174, 163, 0.5) !important; +} + +.quick-toggle:checked { + background-color: rgba(125, 174, 163, 0.95) !important; + color: #282828; +} + +.quick-toggle:checked:hover { + background-color: #afc9b1 !important; + color: #282828; +} + +.quick-toggle:checked:active { + background-color: #96bbaa !important; + color: #282828; +} + +.quick-toggle > StBoxLayout { + spacing: 6px; +} + +.quick-toggle.button { + padding: 0; +} + +.quick-toggle > StBoxLayout { + padding: 0 12px; +} + +.quick-toggle:ltr > StBoxLayout { + padding-left: 15px; +} + +.quick-toggle:rtl > StBoxLayout { + padding-right: 15px; +} + +.quick-toggle .quick-toggle-title { + font-weight: bold; +} + +.quick-toggle .quick-toggle-subtitle { + font-weight: normal; + font-size: 12px; +} + +.quick-toggle .quick-toggle-icon { + icon-size: 16px; +} + +.quick-toggle-has-menu .quick-toggle { + min-width: auto; + max-width: auto; +} + +.quick-toggle-has-menu .quick-toggle:ltr { + border-radius: 12px 0 0 12px; +} + +.quick-toggle-has-menu .quick-toggle:ltr { + padding-right: 9px; +} + +.quick-toggle-has-menu .quick-toggle:rtl { + border-radius: 0 12px 12px 0; +} + +.quick-toggle-has-menu .quick-toggle:rtr { + padding-left: 9px; +} + +.quick-toggle-has-menu .quick-toggle:ltr:last-child { + border-radius: 12px; +} + +.quick-toggle-has-menu .quick-toggle:rtl:last-child { + border-radius: 12px; +} + +.quick-toggle-has-menu .quick-toggle-menu-button { + padding: 6px 10.5px; + border: none !important; + margin: 1px; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:ltr { + border-radius: 0 12px 12px 0; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:rtl { + border-radius: 12px 0 0 12px; +} + +.quick-toggle-has-menu .quick-toggle-separator { + width: 0; +} + +.quick-toggle-has-menu .quick-toggle-menu-button { + background-color: rgba(251, 241, 199, 0.12) !important; + color: #fbf1c7; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:hover { + background-color: rgba(125, 174, 163, 0.25) !important; + color: #fbf1c7; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:active { + background-color: rgba(251, 241, 199, 0.15) !important; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:checked { + background-color: rgba(125, 174, 163, 0.75) !important; + color: #282828; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:checked:hover { + background-color: #afc9b1 !important; + color: #282828; +} + +.quick-toggle-has-menu .quick-toggle-menu-button:checked:active { + background-color: #96bbaa !important; + color: #282828; +} + +.quick-slider > StBoxLayout { + spacing: 6px; +} + +.quick-slider .slider-bin { + min-height: 16px; + padding: 6px; + border-radius: 9999px; +} + +.quick-slider .slider-bin:focus { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.08); + box-shadow: none !important; +} + +.quick-slider .quick-toggle-icon { + icon-size: 16px; +} + +.quick-slider .icon-button, .quick-slider .message .message-header .message-expand-button, .message .message-header .quick-slider .message-expand-button, +.quick-slider .message .message-header .message-close-button, +.message .message-header .quick-slider .message-close-button, .quick-slider .message-notification-group .message-collapse-button, .message-notification-group .quick-slider .message-collapse-button, .quick-slider .background-app-item .close-button, .background-app-item .quick-slider .close-button { + background-color: rgba(251, 241, 199, 0.08) !important; + color: #7daea3 !important; + border-radius: 12px; + padding: 9px; +} + +.quick-slider .icon-button:hover, .quick-slider .message .message-header .message-expand-button:hover, .message .message-header .quick-slider .message-expand-button:hover, +.quick-slider .message .message-header .message-close-button:hover, +.message .message-header .quick-slider .message-close-button:hover, .quick-slider .message-notification-group .message-collapse-button:hover, .message-notification-group .quick-slider .message-collapse-button:hover, .quick-slider .background-app-item .close-button:hover, .background-app-item .quick-slider .close-button:hover { + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.quick-slider .icon-button:active, .quick-slider .message .message-header .message-expand-button:active, .message .message-header .quick-slider .message-expand-button:active, +.quick-slider .message .message-header .message-close-button:active, +.message .message-header .quick-slider .message-close-button:active, .quick-slider .message-notification-group .message-collapse-button:active, .message-notification-group .quick-slider .message-collapse-button:active, .quick-slider .background-app-item .close-button:active, .background-app-item .quick-slider .close-button:active { + background-color: rgba(251, 241, 199, 0.04); +} + +.quick-toggle-menu { + background-color: #242220 !important; + color: #fbf1c7 !important; + border-radius: 24px !important; + padding: 12px; + margin: 12px 18px 0; +} + +.quick-toggle-menu .popup-menu-item { + border-radius: 12px !important; +} + +.quick-toggle-menu .popup-menu-item:focus, .quick-toggle-menu .popup-menu-item:hover, .quick-toggle-menu .popup-menu-item.selected { + color: #7daea3 !important; + background-color: rgba(251, 241, 199, 0.1) !important; +} + +.quick-toggle-menu .popup-menu-item:active { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.2) !important; +} + +.quick-toggle-menu .popup-menu-item > StIcon { + -st-icon-style: symbolic; +} + +.quick-toggle-menu .header { + spacing-rows: 3px; + spacing-columns: 12px; + padding-bottom: 12px; +} + +.quick-toggle-menu .header .icon { + icon-size: 24px; + border-radius: 12px; + padding: 9px; + background-color: rgba(251, 241, 199, 0.12) !important; +} + +.quick-toggle-menu .header .icon.active { + background-color: #7daea3 !important; + color: rgba(40, 40, 40, 0.87); +} + +.quick-settings-system-item > StBoxLayout { + spacing: 12px; +} + +.quick-settings-system-item .icon-button, .quick-settings-system-item .message .message-header .message-expand-button, .message .message-header .quick-settings-system-item .message-expand-button, +.quick-settings-system-item .message .message-header .message-close-button, +.message .message-header .quick-settings-system-item .message-close-button, .quick-settings-system-item .message-notification-group .message-collapse-button, .message-notification-group .quick-settings-system-item .message-collapse-button, .quick-settings-system-item .background-app-item .close-button, .background-app-item .quick-settings-system-item .close-button { + background-color: rgba(251, 241, 199, 0.08); + color: #7daea3 !important; + border-radius: 12px; +} + +.quick-settings-system-item .icon-button > StIcon, .quick-settings-system-item .message .message-header .message-expand-button > StIcon, .message .message-header .quick-settings-system-item .message-expand-button > StIcon, +.quick-settings-system-item .message .message-header .message-close-button > StIcon, +.message .message-header .quick-settings-system-item .message-close-button > StIcon, .quick-settings-system-item .message-notification-group .message-collapse-button > StIcon, .message-notification-group .quick-settings-system-item .message-collapse-button > StIcon, .quick-settings-system-item .background-app-item .close-button > StIcon, .background-app-item .quick-settings-system-item .close-button > StIcon { + -st-icon-style: symbolic; + icon-size: 16px; +} + +.quick-settings-system-item .power-item { + color: #7daea3 !important; + min-height: 0; + min-width: 0; +} + +.quick-settings-system-item .power-item:insensitive { + color: #fbf1c7; + background-color: #282524; + box-shadow: none !important; + background-color: transparent; +} + +.nm-network-item .wireless-secure-icon { + icon-size: 8px; +} + +.bt-device-item .popup-menu-icon { + -st-icon-style: symbolic; +} + +.bt-menu-placeholder.popup-menu-item { + text-align: center; + padding: 2em 4em; +} + +.device-subtitle { + color: rgba(251, 241, 199, 0.5); +} + +.background-apps-quick-toggle { + min-height: 40px; + background-color: transparent; +} + +.background-apps-quick-toggle StIcon { + icon-size: 16px !important; +} + +.background-app-item .popup-menu-icon { + icon-size: 32px !important; + -st-icon-style: regular !important; +} + +.background-app-item .close-button { + padding: 6px; +} + +.background-app-item.popup-inactive-menu-item { + color: #fbf1c7; +} + +.search-entry { + margin-top: 24px; + margin-bottom: 6px; +} + +/* Search */ +.list-search-result, .search-provider-icon { + border-radius: 12px; + padding: 6px; + transition-duration: 100ms; + text-align: center; + background-color: transparent; +} + +.list-search-result:focus, .search-provider-icon:focus, .list-search-result:hover, .search-provider-icon:hover, .list-search-result:selected, .search-provider-icon:selected { + background-color: rgba(251, 241, 199, 0.12); + transition-duration: 0; +} + +.list-search-result:active, .search-provider-icon:active, .list-search-result:checked, .search-provider-icon:checked { + background-color: rgba(251, 241, 199, 0.2); +} + +#searchResults { + margin: 0 4px; +} + +#searchResultsContent { + max-width: 1044px; +} + +.search-section { + spacing: 18px; +} + +.search-section .search-section-separator { + height: 8px; + background-color: transparent; +} + +.search-section-content { + border-radius: 27px; + padding: 12px; + margin: 0 12px; + border: none; + box-shadow: none; + background: none; + text-shadow: none; + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.12); +} + +.search-statustext { + color: rgba(251, 241, 199, 0.5); +} + +.grid-search-results { + spacing: 30px; + margin: 0 12px; +} + +.search-provider-icon:ltr { + margin-right: 4px; +} + +.search-provider-icon:rtl { + margin-left: 4px; +} + +.search-provider-icon .list-search-provider-content { + spacing: 12px; +} + +.search-provider-icon .list-search-provider-content .list-search-provider-details { + width: 120px; + color: rgba(251, 241, 199, 0.7); +} + +.list-search-results { + spacing: 6px; +} + +.list-search-result .list-search-result-content { + spacing: 6px; +} + +.list-search-result .list-search-result-title { + spacing: 12px; +} + +.list-search-result .list-search-result-description { + color: rgba(251, 241, 199, 0.7); +} + +.icon-label-button-container { + spacing: 6px; +} + +.icon-label-button-container StIcon { + icon-size: 32px; +} + +.screenshot-ui-panel { + border-radius: 39px; + padding: 18px; + padding-bottom: 12px; + margin-bottom: 4em; + spacing: 12px; +} + +.screenshot-ui-close-button { + padding: 6px !important; + margin-top: 12px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.15); +} + +.screenshot-ui-close-button.left { + margin-left: 12px; +} + +.screenshot-ui-close-button.right { + margin-right: 12px; +} + +.screenshot-ui-type-button { + min-width: 48px; + padding: 12px 18px !important; + border-radius: 21px; +} + +.screenshot-ui-capture-button { + width: 36px; + height: 36px; + border-radius: 9999px; + border: 4px #fbf1c7; + padding: 4px; +} + +.screenshot-ui-capture-button .screenshot-ui-capture-button-circle { + background-color: #fbf1c7; + transition-duration: 200ms; + border-radius: 9999px; +} + +.screenshot-ui-capture-button .screenshot-ui-capture-button-circle:hover, .screenshot-ui-capture-button .screenshot-ui-capture-button-circle:focus { + background-color: rgba(251, 241, 199, 0.12); +} + +.screenshot-ui-capture-button:hover .screenshot-ui-capture-button-circle, .screenshot-ui-capture-button:focus .screenshot-ui-capture-button-circle { + background-color: #f6df80; +} + +.screenshot-ui-capture-button:active .screenshot-ui-capture-button-circle { + background-color: #b6960d; +} + +.screenshot-ui-capture-button:cast .screenshot-ui-capture-button-circle { + background-color: #c14a4a; +} + +.screenshot-ui-capture-button:cast:hover .screenshot-ui-capture-button-circle, .screenshot-ui-capture-button:cast:focus .screenshot-ui-capture-button-circle { + background-color: #c85d5d; +} + +.screenshot-ui-capture-button:cast:active .screenshot-ui-capture-button-circle { + background-color: #ac3b3b; +} + +.screenshot-ui-shot-cast-container { + background-color: #353535; + border-radius: 18px; + padding: 3px; + spacing: 3px; +} + +.screenshot-ui-shot-cast-container:ltr { + margin-left: 3px; +} + +.screenshot-ui-shot-cast-container:rtl { + margin-right: 3px; +} + +.screenshot-ui-shot-cast-button { + padding: 6px 12px; + background-color: transparent; + border-radius: 15px; +} + +.screenshot-ui-shot-cast-button:hover, .screenshot-ui-shot-cast-button:focus { + background-color: #424242; +} + +.screenshot-ui-shot-cast-button:active { + background-color: rgba(251, 241, 199, 0.3); +} + +.screenshot-ui-shot-cast-button:checked { + background-color: #fbf1c7; + color: #282828; +} + +.screenshot-ui-shot-cast-button:insensitive { + color: rgba(251, 241, 199, 0.5); +} + +.screenshot-ui-shot-cast-button StIcon { + icon-size: 16px; +} + +.screenshot-ui-show-pointer-button { + border-radius: 9999px; + padding: 12px !important; +} + +.screenshot-ui-show-pointer-button StIcon { + icon-size: 16px; +} + +.screenshot-ui-area-indicator-shade { + background-color: rgba(0, 0, 0, 0.3); +} + +.screenshot-ui-area-selector .screenshot-ui-area-indicator-shade { + background-color: rgba(0, 0, 0, 0.5); +} + +.screenshot-ui-area-selector .screenshot-ui-area-indicator-selection { + border: 2px solid #fbf1c7; +} + +.screenshot-ui-area-selector-handle { + border-radius: 9999px; + background-color: #7daea3; + box-shadow: 0 1px 3px 2px rgba(0, 0, 0, 0.2); + width: 24px; + height: 24px; +} + +.screenshot-ui-window-selector { + background-color: #242220; +} + +.screenshot-ui-window-selector .screenshot-ui-window-selector-window-container { + margin: 100px; +} + +.screenshot-ui-window-selector:primary-monitor .screenshot-ui-window-selector-window-container { + margin-bottom: 200px; +} + +.screenshot-ui-window-selector-window-border { + transition-duration: 200ms; + border-radius: 18px; + border: 6px transparent; +} + +.screenshot-ui-window-selector-check { + transition-duration: 200ms; + color: transparent; + border-radius: 9999px; + border-width: 12px; + icon-size: 24px; +} + +.screenshot-ui-window-selector-window:hover .screenshot-ui-window-selector-window-border { + border-color: #55897d; +} + +.screenshot-ui-window-selector-window:checked .screenshot-ui-window-selector-window-border { + border-color: #7daea3; + background-color: rgba(125, 174, 163, 0.2); +} + +.screenshot-ui-window-selector-window:checked .screenshot-ui-window-selector-check { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +.screenshot-ui-screen-selector { + transition-duration: 200ms; + background-color: rgba(0, 0, 0, 0.5); +} + +.screenshot-ui-screen-selector:hover { + background-color: rgba(0, 0, 0, 0.3); +} + +.screenshot-ui-screen-selector:active { + background-color: rgba(0, 0, 0, 0.7); +} + +.screenshot-ui-screen-selector:checked { + background-color: transparent; + border: 2px solid #fbf1c7; +} + +.screenshot-ui-tooltip { + color: #fbf1c7; + background-color: #282828; + border-radius: 9999px; + padding: 6px 12px; + text-align: center; + -y-offset: 24px; +} + +/* Switches */ +.toggle-switch { + width: 46px; + height: 24px; + background-size: contain; + background-image: url("assets/toggle-off.svg"); + transition-duration: 100ms; + color: transparent; +} + +.toggle-switch:checked { + background-image: url("assets/toggle-on.svg"); + color: transparent; +} + +.toggle-switch:checked .handle { + background: none; +} + +.toggle-switch StIcon { + icon-size: 0; +} + +.toggle-switch .handle { + margin: 0; + width: 0; + height: 0; + background: none; + box-shadow: none; + transition-duration: 0; +} + +.window-picker { + spacing: 6px; +} + +.window-caption { + color: #fbf1c7; + background-color: #282828; + border-radius: 9999px; + padding: 6px 12px; +} + +.window-close, .screenshot-ui-close-button { + background-color: #242220; + color: #fbf1c7; + border-radius: 9999px; + padding: 3px; + height: 30px; + width: 30px; + box-shadow: -1px 1px 5px 0px rgba(0, 0, 0, 0.5); + transition-duration: 300ms; +} + +.window-close:hover, .screenshot-ui-close-button:hover { + color: #fbf1c7; + background-color: #34312e; +} + +.window-close:active, .screenshot-ui-close-button:active { + color: #fbf1c7; + background-color: #141312; +} + +.workspace-background { + border-radius: 30px; + background-color: #282828; + box-shadow: 0 4px 16px 4px rgba(0, 0, 0, 0.3); +} + +/* Workspace pager */ +.workspace-thumbnails { + visible-width: 32px; + spacing: 6px; + padding: 6px; +} + +.workspace-thumbnails .workspace-thumbnail { + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.12); + border: none; + border-radius: 12px; +} + +.workspace-thumbnails .placeholder { + background-image: url("assets/dash-placeholder.svg"); + background-size: contain; + width: 18px; + height: 24px; +} + +.workspace-thumbnail-indicator { + border: 3px solid #7daea3; + border-radius: 3px; + padding: 0px; +} + +.bottom #dashtodockDashScrollview, +.top #dashtodockDashScrollview { + -st-hfade-offset: 24px; +} + +.left #dashtodockDashScrollview, +.right #dashtodockDashScrollview { + -st-vfade-offset: 24px; +} + +#dashtodockContainer { + background-color: transparent; +} + +#dashtodockContainer .number-overlay { + color: #fbf1c7; + background-color: rgba(0, 0, 0, 0.75); + text-align: center; +} + +#dashtodockContainer .notification-badge { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; + box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.25); + border-radius: 9999px; + margin: 2px; + padding: 0.25em 0.6em; + font-weight: bold; + text-align: center; +} + +#dashtodockContainer.straight-corner #dash, #dashtodockContainer.shrink.straight-corner #dash { + border-radius: 0; + margin: 0; +} + +#dashtodockContainer.straight-corner #dash .dash-background, #dashtodockContainer.shrink.straight-corner #dash .dash-background { + border-radius: 0; +} + +#dashtodockContainer.extended.top #dash, #dashtodockContainer.extended.bottom #dash, #dashtodockContainer.extended.right #dash, #dashtodockContainer.extended.left #dash { + margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0; + padding: 0 0; +} + +#dashtodockContainer.extended.top #dash .dash-background, #dashtodockContainer.extended.bottom #dash .dash-background, #dashtodockContainer.extended.right #dash .dash-background, #dashtodockContainer.extended.left #dash .dash-background { + border-radius: 0; + margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0; +} + +#dashtodockContainer.left #dash, #dashtodockContainer.right #dash { + margin-top: 0; + padding: 12px 0; +} + +#dashtodockContainer.left #dash .dash-background, #dashtodockContainer.right #dash .dash-background { + margin-bottom: 0; +} + +#dashtodockContainer.left .dash-item-container .app-well-app, +#dashtodockContainer.left .show-apps, #dashtodockContainer.right .dash-item-container .app-well-app, +#dashtodockContainer.right .show-apps { + padding: 6px; +} + +#dashtodockContainer.left #dash { + margin-left: 6px; +} + +#dashtodockContainer.right #dash { + margin-right: 6px; +} + +#dashtodockContainer.dashtodock #dash .dash-background { + background-color: rgba(40, 40, 40, 0.6); +} + +#dashtodockContainer #dash .dash-background { + background-color: rgba(40, 40, 40, 0.85); + border: 2px solid #7daea3; +} + +#dashtodockContainer .app-well-app-running-dot { + background-color: rgba(251, 241, 199, 0.3) !important; +} + +#dashtodockContainer StWidget.focused .app-well-app-running-dot { + background-color: #fbf1c7 !important; +} + +#dashtodockContainer:overview #dash .app-well-app-running-dot { + background-color: rgba(251, 241, 199, 0.3) !important; +} + +#dashtodockContainer:overview #dash StWidget.focused .app-well-app-running-dot { + background-color: #fbf1c7 !important; +} + +#dashtodockContainer .show-apps .overview-icon, +#dashtodockContainer .app-well-app .overview-icon { + color: rgba(251, 241, 199, 0.7); +} + +#dashtodockContainer .show-apps:hover .overview-icon, #dashtodockContainer .show-apps:focus .overview-icon, #dashtodockContainer .show-apps:selected .overview-icon, +#dashtodockContainer .app-well-app:hover .overview-icon, +#dashtodockContainer .app-well-app:focus .overview-icon, +#dashtodockContainer .app-well-app:selected .overview-icon { + background-color: rgba(251, 241, 199, 0.12); +} + +#dashtodockContainer .show-apps:active .overview-icon, #dashtodockContainer .show-apps:checked .overview-icon, +#dashtodockContainer .app-well-app:active .overview-icon, +#dashtodockContainer .app-well-app:checked .overview-icon { + background-color: rgba(251, 241, 199, 0.3); +} + +#dashtodockContainer:overview #dash .show-apps .overview-icon, #dashtodockContainer:overview #dash .app-well-app .overview-icon { + color: rgba(251, 241, 199, 0.7); +} + +#dashtodockContainer:overview #dash .show-apps:hover .overview-icon, #dashtodockContainer:overview #dash .show-apps:focus .overview-icon, #dashtodockContainer:overview #dash .show-apps:selected .overview-icon, #dashtodockContainer:overview #dash .app-well-app:hover .overview-icon, #dashtodockContainer:overview #dash .app-well-app:focus .overview-icon, #dashtodockContainer:overview #dash .app-well-app:selected .overview-icon { + background-color: rgba(251, 241, 199, 0.12); +} + +#dashtodockContainer:overview #dash .show-apps:active .overview-icon, #dashtodockContainer:overview #dash .show-apps:checked .overview-icon, #dashtodockContainer:overview #dash .app-well-app:active .overview-icon, #dashtodockContainer:overview #dash .app-well-app:checked .overview-icon { + background-color: rgba(251, 241, 199, 0.3); +} + +#dashtodockContainer .app-well-app-running-dot { + background-color: rgba(251, 241, 199, 0.3); +} + +#dashtodockContainer StWidget.focused .app-well-app-running-dot { + background-color: #fbf1c7; +} + +#dashtodockContainer.opaque #dash .dash-background { + background-color: rgba(40, 40, 40, 0.6); +} + +#dashtodockContainer.transparent #dash .dash-background { + background-color: rgba(40, 40, 40, 0.35); +} + +#dashtodockContainer:overview #dash .dash-background { + background-color: rgba(251, 241, 199, 0.12); + border: 2px solid transparent; +} + +#dashtodockContainer.opaque:overview #dash .dash-background, #dashtodockContainer.transparent:overview #dash .dash-background { + background-color: transparent !important; + box-shadow: none !important; +} + +#dashtodockContainer.extended:overview #dash .dash-background, #dashtodockContainer.opaque.extended:overview #dash .dash-background, #dashtodockContainer.transparent.extended:overview #dash .dash-background { + background-color: rgba(40, 40, 40, 0.6); +} + +#dashtodockContainer.running-dots .dash-item-container > StButton, #dashtodockContainer.dashtodock .dash-item-container > StButton { + transition-duration: 250ms; + background-size: contain; +} + +#dashtodockContainer.extended .app-well-app .overview-icon, +#dashtodockContainer.extended .show-apps .overview-icon, #dashtodockContainer.extended:overview .app-well-app .overview-icon, +#dashtodockContainer.extended:overview .show-apps .overview-icon { + border-radius: 12px; +} + +#dashtodockContainer .metro .overview-icon { + border-radius: 0; +} + +.dashtodock-app-well-preview-menu-item { + padding: 1em 1em 0.5em 1em; +} + +#dashtodockPreviewSeparator.popup-separator-menu-item-horizontal { + background-color: rgba(251, 241, 199, 0.25); + width: 1px; + height: auto; + border-right-width: 1px; + margin: 32px 0; +} + +.openweather-button, .openweather-button-action, .openweather-menu-button-container, .openweather-button-box { + border: 1px solid transparent; +} + +.openweather-provider { + padding: 0 16px; + font-weight: 500; + border: 1px solid transparent; +} + +.openweather-current-icon, .openweather-current-summary, .openweather-current-summarybox { + background: none; + color: #fbf1c7; +} + +.openweather-current-databox-values { + background: none; + color: rgba(251, 241, 199, 0.5); +} + +.openweather-current-databox-captions { + background: none; + color: rgba(251, 241, 199, 0.5); +} + +.openweather-forecast-icon, .openweather-forecast-summary { + background: none; + color: rgba(251, 241, 199, 0.7); +} + +.openweather-forecast-day, .openweather-forecast-temperature { + background: none; + color: rgba(251, 241, 199, 0.5); +} + +.openweather-sunrise-icon, .openweather-sunset-icon, .openweather-build-icon { + color: rgba(251, 241, 199, 0.7); +} + +.cosmic-dock #dock { + border-radius: 16px !important; + border: none !important; + margin: 6px !important; + background-color: rgba(40, 37, 36, 0.65) !important; + box-shadow: inset 0 1px rgba(255, 255, 255, 0.08) !important; +} + +.cosmic-dock #dock .dash-background { + background-color: transparent !important; + margin-bottom: 0 !important; + padding: 0; + box-shadow: none !important; +} + +.cosmic-application-dialog { + border-radius: 18px; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.08); + background-color: #242220; + color: #fbf1c7; +} + +.cosmic-application-dialog .overview-icon { + color: #fbf1c7; +} + +.cosmic-applications-separator { + background: rgba(251, 241, 199, 0.12); +} + +.cosmic-folder-edit-button { + box-shadow: none; + border-radius: 12px; + border-width: 0; + color: #fbf1c7; + background: rgba(251, 241, 199, 0.04); +} + +.cosmic-folder-edit-button .cosmic-folder-edit-button:hover { + background: rgba(251, 241, 199, 0.12); +} + +.cosmic-applications-icon { + color: rgba(251, 241, 199, 0.7); +} + +.cosmic-applications-folder-title { + color: rgba(251, 241, 199, 0.7); +} + +.cosmic-applications-available { + color: #fbf1c7; +} + +.pop-shell-active-hint { + border-style: solid; + border-color: #b47109; + border-radius: 12px; + box-shadow: none; +} + +.pop-shell-overlay { + background-color: rgba(125, 174, 163, 0.3); +} + +.pop-shell-search-element:select { + background: rgba(251, 241, 199, 0.12); + border-radius: 12px; + color: #fbf1c7; +} + +.pop-shell-tab { + border: 1px solid rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.pop-shell-tab-active { + background: #b47109; +} + +.pop-shell-tab-inactive { + background: rgba(180, 113, 9, 0.35); +} + +.pop-shell-tab-urgent { + background: #c14a4a; +} + +#panel.light-panel .panel-button, +#panel.dark-panel .panel-button, +#panel.transparent-panel .panel-button { + color: rgba(251, 241, 199, 0.7) !important; +} + +#panel.light-panel .panel-button.clock-display .clock, +#panel.dark-panel .panel-button.clock-display .clock, +#panel.transparent-panel .panel-button.clock-display .clock { + color: rgba(251, 241, 199, 0.7) !important; +} + +#panel.light-panel .panel-button:hover, +#panel.dark-panel .panel-button:hover, +#panel.transparent-panel .panel-button:hover { + color: rgba(251, 241, 199, 0.7) !important; + background-color: rgba(251, 241, 199, 0.12) !important; +} + +#panel.light-panel .panel-button:hover.clock-display .clock, +#panel.dark-panel .panel-button:hover.clock-display .clock, +#panel.transparent-panel .panel-button:hover.clock-display .clock { + background-color: rgba(251, 241, 199, 0.12) !important; +} + +#panel.light-panel .panel-button:active, #panel.light-panel .panel-button:checked, #panel.light-panel .panel-button:focus, +#panel.dark-panel .panel-button:active, +#panel.dark-panel .panel-button:checked, +#panel.dark-panel .panel-button:focus, +#panel.transparent-panel .panel-button:active, +#panel.transparent-panel .panel-button:checked, +#panel.transparent-panel .panel-button:focus { + color: #fbf1c7 !important; + background-color: rgba(251, 241, 199, 0.3) !important; +} + +#panel.light-panel .panel-button:active.clock-display .clock, #panel.light-panel .panel-button:checked.clock-display .clock, #panel.light-panel .panel-button:focus.clock-display .clock, +#panel.dark-panel .panel-button:active.clock-display .clock, +#panel.dark-panel .panel-button:checked.clock-display .clock, +#panel.dark-panel .panel-button:focus.clock-display .clock, +#panel.transparent-panel .panel-button:active.clock-display .clock, +#panel.transparent-panel .panel-button:checked.clock-display .clock, +#panel.transparent-panel .panel-button:focus.clock-display .clock { + background-color: rgba(251, 241, 199, 0.3) !important; +} + +#panel.light-panel .panel-button:hover.clock-display, #panel.light-panel .panel-button:active.clock-display, #panel.light-panel .panel-button:overview.clock-display, #panel.light-panel .panel-button:focus.clock-display, #panel.light-panel .panel-button:checked.clock-display, +#panel.dark-panel .panel-button:hover.clock-display, +#panel.dark-panel .panel-button:active.clock-display, +#panel.dark-panel .panel-button:overview.clock-display, +#panel.dark-panel .panel-button:focus.clock-display, +#panel.dark-panel .panel-button:checked.clock-display, +#panel.transparent-panel .panel-button:hover.clock-display, +#panel.transparent-panel .panel-button:active.clock-display, +#panel.transparent-panel .panel-button:overview.clock-display, +#panel.transparent-panel .panel-button:focus.clock-display, +#panel.transparent-panel .panel-button:checked.clock-display { + background-color: transparent !important; +} + +#panel.light-panel .panel-button:hover.clock-display .clock, #panel.light-panel .panel-button:active.clock-display .clock, #panel.light-panel .panel-button:overview.clock-display .clock, #panel.light-panel .panel-button:focus.clock-display .clock, #panel.light-panel .panel-button:checked.clock-display .clock, +#panel.dark-panel .panel-button:hover.clock-display .clock, +#panel.dark-panel .panel-button:active.clock-display .clock, +#panel.dark-panel .panel-button:overview.clock-display .clock, +#panel.dark-panel .panel-button:focus.clock-display .clock, +#panel.dark-panel .panel-button:checked.clock-display .clock, +#panel.transparent-panel .panel-button:hover.clock-display .clock, +#panel.transparent-panel .panel-button:active.clock-display .clock, +#panel.transparent-panel .panel-button:overview.clock-display .clock, +#panel.transparent-panel .panel-button:focus.clock-display .clock, +#panel.transparent-panel .panel-button:checked.clock-display .clock { + color: #fbf1c7 !important; +} + +.overview-components-transparent .search-entry, +.overview-components-light .search-entry, +.overview-components-dark .search-entry { + caret-color: #fbf1c7 !important; +} + +.overview-components-transparent .search-entry .search-entry-icon, +.overview-components-light .search-entry .search-entry-icon, +.overview-components-dark .search-entry .search-entry-icon { + color: rgba(251, 241, 199, 0.7) !important; +} + +.overview-components-transparent .search-entry StLabel.hint-text, +.overview-components-light .search-entry StLabel.hint-text, +.overview-components-dark .search-entry StLabel.hint-text { + color: rgba(251, 241, 199, 0.3) !important; +} + +.overview-components-transparent .search-section-content, +.overview-components-light .search-section-content, +.overview-components-dark .search-section-content { + border-radius: 16px; +} + +.overview-components-transparent .search-section-separator, +.overview-components-light .search-section-separator, +.overview-components-dark .search-section-separator { + height: 0 !important; + background-color: transparent !important; +} diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-events.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-events.svg new file mode 120000 index 0000000..d2fcad0 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-events.svg @@ -0,0 +1 @@ +assets/no-events.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-notifications.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-notifications.svg new file mode 120000 index 0000000..175731c --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/no-notifications.svg @@ -0,0 +1 @@ +assets/no-notifications.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/pad-osd.css b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/pad-osd.css new file mode 100755 index 0000000..8db7cf0 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/pad-osd.css @@ -0,0 +1,31 @@ +.Leader { + stroke-width: 0.5 !important; + stroke: #535353; + fill: none !important; +} + +.Button { + stroke-width: 0.25; + stroke: #ededed; + fill: #ededed; +} + +.Ring { + stroke-width: 0.5 !important; + stroke: #535353 !important; + fill: none !important; +} + +.Label { + stroke: none !important; + stroke-width: 0.1 !important; + font-size: 0.1 !important; + fill: transparent !important; +} + +.TouchStrip, +.TouchRing { + stroke-width: 0.1 !important; + stroke: #ededed !important; + fill: #535353 !important; +} diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/process-working.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/process-working.svg new file mode 120000 index 0000000..a6586c3 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gnome-shell/process-working.svg @@ -0,0 +1 @@ +assets/process-working.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/apps.rc b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/apps.rc new file mode 100755 index 0000000..530e72f --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/apps.rc @@ -0,0 +1,92 @@ +# vim:set ft=gtkrc ts=2 sw=2 sts=2 ai et: +# +# This file, unlike hacks.rc, contains legitimate cases we need to handle, e.g. +# custom widgets, programs giving us a chance to alter their UI to fit more with +# the theme or stuff that is supposed to look different, like panels. + +# TODO: This could really look nicer +style "gimp_spin_scale" { + # Spin background + bg[NORMAL] = @base_color + + engine "pixmap" { + image { + function = BOX + state = NORMAL + detail = "spinbutton_up" + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_up" + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_up" + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_up" + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = NORMAL + detail = "spinbutton_down" + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_down" + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_down" + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_down" + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + } + } +} + +style "chrome_gtk_frame" { + ChromeGtkFrame::frame-color = @titlebar_bg_color + ChromeGtkFrame::inactive-frame-color = @titlebar_bg_color + ChromeGtkFrame::incognito-frame-color = @titlebar_bg_color + ChromeGtkFrame::incognito-inactive-frame-color = @titlebar_bg_color + + ChromeGtkFrame::frame-gradient-size = 0 +} + +# Disable spin button assets for GimpSpinScale +class "GimpSpinScale" style "gimp_spin_scale" + +# Chromium lets us define some colours and settings for better integration +class "ChromeGtkFrame" style "chrome_gtk_frame" diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/border.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/border.png new file mode 100755 index 0000000..b0bc0a0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/border.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-active.png new file mode 100755 index 0000000..f671a33 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-disabled.png new file mode 100755 index 0000000..30be7d2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-hover.png new file mode 100755 index 0000000..09002d7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button.png new file mode 100755 index 0000000..2815719 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/button.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-active.png new file mode 100755 index 0000000..a190aa8 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-disabled.png new file mode 100755 index 0000000..149c764 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-hover.png new file mode 100755 index 0000000..f5183a2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked.png new file mode 100755 index 0000000..a3aa014 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-checked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-active.png new file mode 100755 index 0000000..70300a1 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-disabled.png new file mode 100755 index 0000000..4dbf927 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-hover.png new file mode 100755 index 0000000..cbadcaf Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed.png new file mode 100755 index 0000000..31a9833 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-mixed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-active.png new file mode 100755 index 0000000..c515eb7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-disabled.png new file mode 100755 index 0000000..63516cb Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-hover.png new file mode 100755 index 0000000..f1e9be5 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked.png new file mode 100755 index 0000000..900c1a0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/checkbox-unchecked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-active.png new file mode 100755 index 0000000..f55b47b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-disabled.png new file mode 100755 index 0000000..e194aa4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-hover.png new file mode 100755 index 0000000..866edb1 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry.png new file mode 100755 index 0000000..bf1011a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-left-entry.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-active.png new file mode 100755 index 0000000..36de538 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-disabled.png new file mode 100755 index 0000000..f9f1a87 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-hover.png new file mode 100755 index 0000000..b907093 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry.png new file mode 100755 index 0000000..6992de4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/combo-right-entry.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-active.png new file mode 100755 index 0000000..ffa4b94 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background-disabled.png new file mode 100755 index 0000000..50199da Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background.png new file mode 100755 index 0000000..b541bbc Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-background.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-disabled.png new file mode 100755 index 0000000..30be7d2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-hover.png new file mode 100755 index 0000000..99c7b0a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry.png new file mode 100755 index 0000000..2815719 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/entry.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-active.png new file mode 100755 index 0000000..f671a33 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-disabled.png new file mode 100755 index 0000000..481dc96 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-hover.png new file mode 100755 index 0000000..09002d7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button.png new file mode 100755 index 0000000..481dc96 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/flat-button.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/focus.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/focus.png new file mode 100755 index 0000000..1d745e7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/focus.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-inline.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-inline.png new file mode 100755 index 0000000..ea449e8 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-inline.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-notebook.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-notebook.png new file mode 100755 index 0000000..e73b543 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame-notebook.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame.png new file mode 100755 index 0000000..e73b543 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/frame.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-active.png new file mode 100755 index 0000000..92c51eb Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-hover.png new file mode 100755 index 0000000..3d51d2f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz.png new file mode 100755 index 0000000..7084b69 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-horz.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-active.png new file mode 100755 index 0000000..53bc1a7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-hover.png new file mode 100755 index 0000000..9e9535e Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert.png new file mode 100755 index 0000000..768bc88 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/handle-vert.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked-disabled.png new file mode 100755 index 0000000..918bd59 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked.png new file mode 100755 index 0000000..4a3eb8e Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-checked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed-disabled.png new file mode 100755 index 0000000..b7cb12b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed.png new file mode 100755 index 0000000..d473719 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-mixed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png new file mode 100755 index 0000000..fc60b56 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked.png new file mode 100755 index 0000000..28a4762 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-checkbox-unchecked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked-disabled.png new file mode 100755 index 0000000..954e3b2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked.png new file mode 100755 index 0000000..2cfc4a5 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-checked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed-disabled.png new file mode 100755 index 0000000..b7cb12b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed.png new file mode 100755 index 0000000..d473719 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-mixed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked-disabled.png new file mode 100755 index 0000000..fc60b56 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked.png new file mode 100755 index 0000000..28a4762 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/menu-radio-unchecked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt-disabled.png new file mode 100755 index 0000000..f5a28c6 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt.png new file mode 100755 index 0000000..e1dd8d7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-alt.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-disabled.png new file mode 100755 index 0000000..3010107 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down.png new file mode 100755 index 0000000..cf54a11 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-down.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt-disabled.png new file mode 100755 index 0000000..ef9eae3 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt.png new file mode 100755 index 0000000..ee684d2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-alt.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-disabled.png new file mode 100755 index 0000000..f65f8d4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-semi.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-semi.png new file mode 100755 index 0000000..8c857b0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left-semi.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left.png new file mode 100755 index 0000000..fd14eed Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-left.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt-disabled.png new file mode 100755 index 0000000..fde3e2b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt.png new file mode 100755 index 0000000..091aecb Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-alt.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-disabled.png new file mode 100755 index 0000000..84abb27 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-semi.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-semi.png new file mode 100755 index 0000000..58ca863 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right-semi.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right.png new file mode 100755 index 0000000..0910b61 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-right.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt-disabled.png new file mode 100755 index 0000000..da61224 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt.png new file mode 100755 index 0000000..376945b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-alt.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-disabled.png new file mode 100755 index 0000000..5a35705 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up.png new file mode 100755 index 0000000..bd21166 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/pan-up.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-progress.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-progress.png new file mode 100755 index 0000000..c7f27d5 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-progress.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-trough.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-trough.png new file mode 100755 index 0000000..b884aca Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/progressbar-trough.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-active.png new file mode 100755 index 0000000..e0b5f22 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-disabled.png new file mode 100755 index 0000000..3d13631 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-hover.png new file mode 100755 index 0000000..033354f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked.png new file mode 100755 index 0000000..8a3465e Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-checked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-active.png new file mode 100755 index 0000000..70300a1 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-disabled.png new file mode 100755 index 0000000..4dbf927 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-hover.png new file mode 100755 index 0000000..cbadcaf Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed.png new file mode 100755 index 0000000..31a9833 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-mixed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-active.png new file mode 100755 index 0000000..c515eb7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-disabled.png new file mode 100755 index 0000000..63516cb Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-hover.png new file mode 100755 index 0000000..f1e9be5 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked.png new file mode 100755 index 0000000..900c1a0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/radio-unchecked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-active.png new file mode 100755 index 0000000..de3e3c9 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-disabled.png new file mode 100755 index 0000000..452a158 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough.png new file mode 100755 index 0000000..452181f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-horz-trough.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-active.png new file mode 100755 index 0000000..5f914fd Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-disabled.png new file mode 100755 index 0000000..cbef6fd Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-hover.png new file mode 100755 index 0000000..1d5ab6f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider.png new file mode 100755 index 0000000..583d46b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-active.png new file mode 100755 index 0000000..df9a64b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-disabled.png new file mode 100755 index 0000000..ccc0b14 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough.png new file mode 100755 index 0000000..d61b728 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scale-vert-trough.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-active.png new file mode 100755 index 0000000..4408c6d Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-disabled.png new file mode 100755 index 0000000..f6b9949 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-hover.png new file mode 100755 index 0000000..8098d38 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider.png new file mode 100755 index 0000000..7131cdc Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-trough.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-trough.png new file mode 100755 index 0000000..73905be Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-horz-trough.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png new file mode 100755 index 0000000..7dfe04d Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png new file mode 100755 index 0000000..d0ddd54 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png new file mode 100755 index 0000000..8e61baa Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider.png new file mode 100755 index 0000000..6ee8a9d Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-trough.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-trough.png new file mode 100755 index 0000000..e502307 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-ltr-trough.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png new file mode 100755 index 0000000..edb3e7b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png new file mode 100755 index 0000000..96dd85c Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png new file mode 100755 index 0000000..70bc773 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider.png new file mode 100755 index 0000000..38bf515 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-trough.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-trough.png new file mode 100755 index 0000000..daa1695 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/scrollbar-vert-rtl-trough.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-active.png new file mode 100755 index 0000000..c9b22e9 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-disabled.png new file mode 100755 index 0000000..e8bfc89 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-hover.png new file mode 100755 index 0000000..87541cc Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down.png new file mode 100755 index 0000000..6470665 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-down.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-active.png new file mode 100755 index 0000000..d463491 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-disabled.png new file mode 100755 index 0000000..b632c27 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-hover.png new file mode 100755 index 0000000..47a4a34 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up.png new file mode 100755 index 0000000..02f6880 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-ltr-up.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-active.png new file mode 100755 index 0000000..852d267 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-disabled.png new file mode 100755 index 0000000..fe9f834 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-hover.png new file mode 100755 index 0000000..0fd9387 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down.png new file mode 100755 index 0000000..192d3b7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-down.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-active.png new file mode 100755 index 0000000..632dbe3 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-disabled.png new file mode 100755 index 0000000..a00638a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-hover.png new file mode 100755 index 0000000..85f3cfe Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up.png new file mode 100755 index 0000000..d916a2a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/spin-rtl-up.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/tab.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/tab.png new file mode 100755 index 0000000..c62ec85 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/tab.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-active.png new file mode 100755 index 0000000..0536751 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-hover.png new file mode 100755 index 0000000..15e37e2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button.png new file mode 100755 index 0000000..c6741d2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-ltr-button.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-active.png new file mode 100755 index 0000000..6c66172 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-hover.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-hover.png new file mode 100755 index 0000000..b967a0a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button-hover.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button.png new file mode 100755 index 0000000..c6741d2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/assets/treeview-rtl-button.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/gtkrc b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/gtkrc new file mode 100755 index 0000000..e5d5f0d --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/gtkrc @@ -0,0 +1,36 @@ +# Based on Bridge by ScionicSpectre and Adwaita by GNOME +# vim:set ts=2 sw=2 sts=2 ai et: +# +# This is the GTK 2 version of Materia. It's whole purpose is to look as the +# GTK 3 version as much as possible until GTK 2 dies completely. +# +# Note: comments for explaining styles are on the bottom of each file beside the +# widget matches. + +# Declare the colours used throughout the theme. +# There shouldn't be any fiddling with them in the theme files themselves in +# order to not mess up the dark theme. + +# Text/base +gtk-color-scheme = "text_color:#F9F5D7\nbase_color:#1D2021" +# Foreground/background +gtk-color-scheme = "fg_color:#F9F5D7\nbg_color:#1D2021" +# Selected foreground/background +gtk-color-scheme = "selected_fg_color:#F9F5D7\nselected_bg_color:#7DAEA3" +# Titlebar foreground/background +gtk-color-scheme = "titlebar_fg_color:#F9F5D7\ntitlebar_bg_color:#282828" +# Menus +gtk-color-scheme = "menu_color:#3C3836" +# Tooltips foreground/background +gtk-color-scheme = "tooltip_fg_color:#F9F5D7\ntooltip_bg_color:#504945" +# Links +gtk-color-scheme = "link_color:#80AA9E\nvisited_link_color:#D386CD" + +# Set GTK settings +gtk-auto-mnemonics = 1 +gtk-primary-button-warps-slider = 1 + +# And hand over the control to the theme files +include "main.rc" +include "apps.rc" +include "hacks.rc" diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/hacks.rc b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/hacks.rc new file mode 100755 index 0000000..c288da3 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/hacks.rc @@ -0,0 +1,36 @@ +# vim:set ft=gtkrc ts=2 sw=2 sts=2 ai et: +# +# This file contains horrible hacks to make this theme work with some programs +# This is mostly due to the limitations of GTK 2 but sometimes its the fault of +# the programs themselves. Not going to point fingers. +# +# Either way, it's a WONTFIX for both, hence this horrible file. + +style "toplevel_hack" { + engine "adwaita" {} +} + +style "chrome_entry" { + base[NORMAL] = @base_color + base[INSENSITIVE] = @base_color +} + +style "vim_notebook" { + bg[NORMAL] = @base_color + bg[ACTIVE] = @bg_color +} + +# Vim puts an eventbox between the tab and the label and colours it, +# we need to handle that +widget "vim-main-window*GtkNotebook.GtkEventBox" style "vim_notebook" + +# (he)xchat input box +class "SexySpellEntry" style:highest "normal_entry" + +# Chromium uses base as the fill colour of its own entries +# This would be fine but GTK uses it to fill the surrounding space, so its set to bg +# That results in Chromium using it for the fill, so we need to handle that +widget_class "*Chrom*<GtkEntry>" style "chrome_entry" + +# Hack to be able to match widgets in LibreOffice +class "GtkWindow" style "toplevel_hack" diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/main.rc b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/main.rc new file mode 100755 index 0000000..8349b0e --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-2.0/main.rc @@ -0,0 +1,2708 @@ +# vim:set ft=gtkrc ts=2 sw=2 sts=2 ai et: +# +# This is the main theme file, handling all the default widgets and theme +# properties. Since GTK 2 is old, we need to overcome some of its limitations, +# which is also mostly done in this file. Sadly not all of them can be overcome +# so there will always be a visible difference between the GTK 2 and 3 theme. + +style "default" { + xthickness = 1 + ythickness = 1 + + #################### + # Style Properties # + #################### + + GtkWidget::focus-padding = 0 + GtkWidget::focus-line-width = 2 + GtkWidget::focus-line-pattern = "\2\1" + + GtkToolbar::space-size = 5 # 1 + 2*2 (separator + margins) + GtkToolbar::internal-padding = 2 + GtkToolButton::icon-spacing = 4 + + GtkWidget::tooltip-radius = 4 + GtkWidget::tooltip-alpha = 230 + GtkWidget::new-tooltip-style = 1 #for compatibility + + GtkWidget::link-color = @link_color + GtkWidget::visited-link-color = @visited_link_color + GnomeHRef::link_color = @link_color + GtkHTML::link-color = @link_color + GtkHTML::vlink-color = @visited_link_color + GtkIMHtml::hyperlink-color = @link_color + GtkIMHtml::hyperlink-visited-color = @visited_link_color + + GtkSeparatorMenuItem::horizontal-padding = 0 + GtkSeparatorMenuItem::wide-separators = 1 + GtkSeparatorMenuItem::separator-height = 3 + + GtkButton::child-displacement-y = 0 + + GtkButton::default-border = {0, 0, 0, 0} + GtkButton::default-outside-border = {0, 0, 0, 0} + GtkButton::inner-border = {0, 0, 0, 0} + + GtkEntry::state-hint = 1 + GtkEntry::inner-border = {0, 0, 0, 0} + + GtkPaned::handle-size = 8 + GtkHPaned::handle-size = 8 + GtkVPaned::handle-size = 8 + + GtkScrollbar::trough-border = 0 + GtkRange::trough-border = 0 + GtkRange::slider-width = 17 + GtkRange::stepper-size = 0 + GtkRange::activate-slider = 1 + + GtkScrollbar::activate-slider = 1 + GtkScrollbar::stepper-size = 0 + GtkScrollbar::has-backward-stepper = 0 + GtkScrollbar::has-forward-stepper = 0 + GtkScrollbar::min-slider-length = 32 # 24 + 2*4 (margins) + GtkScrolledWindow::scrollbar-spacing = 0 + GtkScrolledWindow::scrollbars-within-bevel = 1 + + GtkScale::slider_length = 24 + GtkScale::slider_width = 24 + GtkScale::trough-side-details = 1 + + GtkProgressBar::min-horizontal-bar-height = 4 + GtkProgressBar::min-vertical-bar-width = 4 + GtkProgressBar::xspacing = 4 + GtkProgressBar::yspacing = 4 + + GtkStatusbar::shadow_type = GTK_SHADOW_NONE + GtkSpinButton::shadow_type = GTK_SHADOW_NONE + GtkMenuBar::shadow-type = GTK_SHADOW_NONE + GtkToolbar::shadow-type = GTK_SHADOW_NONE + # TODO: find out what this comment means: + # ( every window is misaligned for the sake of menus ): + GtkMenuBar::internal-padding = 0 + GtkMenu::horizontal-padding = 0 + GtkMenu::vertical-padding = 4 + GtkMenu::double-arrows = 0 + GtkMenuItem::arrow-scaling = 1 + GtkMenuItem::toggle-spacing = 12 + + GtkCheckButton::indicator-size = 24 + GtkCheckButton::indicator_spacing = 2 + GtkOptionMenu::indicator_spacing = {8, 8, 4, 4} + + GtkTreeView::expander-size = 16 + GtkTreeView::vertical-separator = 0 + GtkTreeView::horizontal-separator = 4 + GtkTreeView::allow-rules = 0 + # Set this because some apps read it + GtkTreeView::odd-row-color = @base_color + GtkTreeView::even-row-color = @base_color + + GtkExpander::expander-size = 16 + + GtkNotebook::tab-overlap = 0 + + ########## + # Colors # + ########## + + bg[NORMAL] = @bg_color + bg[PRELIGHT] = @bg_color + bg[SELECTED] = mix (0.24, @selected_bg_color, @bg_color) + bg[INSENSITIVE] = @bg_color + bg[ACTIVE] = @bg_color + + fg[NORMAL] = @fg_color + fg[PRELIGHT] = @fg_color + fg[SELECTED] = @fg_color + fg[INSENSITIVE] = mix (0.5, @fg_color, @bg_color) + fg[ACTIVE] = @fg_color + + text[NORMAL] = @text_color + text[PRELIGHT] = @text_color + text[SELECTED] = @text_color + text[INSENSITIVE] = mix (0.5, @text_color, @base_color) + text[ACTIVE] = @text_color + + base[NORMAL] = @base_color + base[PRELIGHT] = mix (0.08, @text_color, @base_color) + base[SELECTED] = mix (0.24, @selected_bg_color, @base_color) + base[INSENSITIVE] = mix (0.5, @base_color, @bg_color) + base[ACTIVE] = mix (0.24, @selected_bg_color, @base_color) + + # For succinctness, all reasonable pixmap options remain here + + # Draw frame around menu in a non-compositied environment + # This needs to go before pixmap because we need to override some stuff + engine "adwaita" {} + + engine "pixmap" { + + ################# + # Check Buttons # + ################# + + image { + function = CHECK + state = NORMAL + shadow = OUT + overlay_file = "assets/checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = OUT + overlay_file = "assets/checkbox-unchecked-hover.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = OUT + overlay_file = "assets/checkbox-unchecked-active.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = SELECTED + shadow = OUT + overlay_file = "assets/checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/checkbox-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = IN + overlay_file = "assets/checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = IN + overlay_file = "assets/checkbox-checked-hover.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = IN + overlay_file = "assets/checkbox-checked-active.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = SELECTED + shadow = IN + overlay_file = "assets/checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = IN + overlay_file = "assets/checkbox-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed-hover.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed-active.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = SELECTED + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/checkbox-mixed-disabled.png" + overlay_stretch = FALSE + } + + ################# + # Radio Buttons # + ################# + + image { + function = OPTION + state = NORMAL + shadow = OUT + overlay_file = "assets/radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = OUT + overlay_file = "assets/radio-unchecked-hover.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = OUT + overlay_file = "assets/radio-unchecked-active.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = SELECTED + shadow = OUT + overlay_file = "assets/radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/radio-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = IN + overlay_file = "assets/radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = IN + overlay_file = "assets/radio-checked-hover.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = IN + overlay_file = "assets/radio-checked-active.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = SELECTED + shadow = IN + overlay_file = "assets/radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = IN + overlay_file = "assets/radio-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed-hover.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed-active.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = SELECTED + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/radio-mixed-disabled.png" + overlay_stretch = FALSE + } + + ########## + # Arrows # + ########## + + # Overrides + + # Disable arrows in spinbuttons + image { + function = ARROW + detail = "spinbutton" + } + + # Disable arrows for qt in scrollbars + + image { + function = ARROW + detail = "vscrollbar" + } + + image { + function = ARROW + detail = "hscrollbar" + } + + # Menu arrows + + image { + function = ARROW + state = NORMAL + detail = "menuitem" + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = PRELIGHT + detail = "menuitem" + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menuitem" + overlay_file = "assets/pan-left-disabled.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = NORMAL + detail = "menuitem" + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = PRELIGHT + detail = "menuitem" + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menuitem" + overlay_file = "assets/pan-right-disabled.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menu_scroll_arrow_up" + overlay_file = "assets/pan-up-disabled.png" + overlay_stretch = FALSE + } + + image { + function = ARROW + detail = "menu_scroll_arrow_up" + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + } + + image { + function = ARROW + state = INSENSITIVE + detail = "menu_scroll_arrow_down" + overlay_file = "assets/pan-down-disabled.png" + overlay_stretch = FALSE + } + + image { + function = ARROW + detail = "menu_scroll_arrow_down" + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + # Regular arrows + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-left-alt.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-left.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-left-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = LEFT + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-right-alt.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + image { + function = ARROW + state = INSENSITIVE + overlay_file = "assets/pan-right-alt-disabled.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + + ###################### + # Option Menu Arrows # + ###################### + + image { + function = TAB + state = NORMAL + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + } + + image { + function = TAB + state = PRELIGHT + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = TAB + state = ACTIVE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + } + + image { + function = TAB + state = INSENSITIVE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + } + + ######### + # Lines # + ######### + + image { + function = VLINE + file = "assets/border.png" + border = {1, 0, 0, 0} + } + + image { + function = HLINE + file = "assets/border.png" + border = {0, 0, 1, 0} + } + + ######### + # Focus # + ######### + + image { + function = FOCUS + file = "assets/focus.png" + border = {5, 5, 5, 5} # Super strange, {4, 4, 4, 4} does not work properly... + stretch = TRUE + } + + ########### + # Handles # + ########### + + image { + function = HANDLE + detail = "handlebox" + overlay_file = "assets/handle-vert.png" + overlay_stretch = FALSE + } + + image { + function = HANDLE + state = NORMAL + overlay_file = "assets/handle-horz.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + + image { + function = HANDLE + state = PRELIGHT + overlay_file = "assets/handle-horz-hover.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + + image { + function = HANDLE + state = ACTIVE + overlay_file = "assets/handle-horz-active.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + + image { + function = HANDLE + state = NORMAL + overlay_file = "assets/handle-vert.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + + image { + function = HANDLE + state = PRELIGHT + overlay_file = "assets/handle-vert-hover.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + + image { + function = HANDLE + state = ACTIVE + overlay_file = "assets/handle-vert-active.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + + image { + function = RESIZE_GRIP + } + + ############# + # Expanders # + ############# + + image { + function = EXPANDER + expander_style = EXPANDED + state = NORMAL + file = "assets/pan-down-alt.png" + } + + image { + function = EXPANDER + expander_style = EXPANDED + state = PRELIGHT + file = "assets/pan-down.png" + } + + image { + function = EXPANDER + expander_style = EXPANDED + state = ACTIVE + file = "assets/pan-down.png" + } + + image { + function = EXPANDER + expander_style = EXPANDED + state = INSENSITIVE + file = "assets/pan-down-alt-disabled.png" + } + + # LTR + + image { + function = EXPANDER + expander_style = COLLAPSED + state = NORMAL + file = "assets/pan-right-alt.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = PRELIGHT + file = "assets/pan-right.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = ACTIVE + file = "assets/pan-right.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = INSENSITIVE + file = "assets/pan-right-alt-disabled.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = SEMI_COLLAPSED + file = "assets/pan-right-semi.png" + direction = LTR + } + + image { + function = EXPANDER + expander_style = SEMI_EXPANDED + file = "assets/pan-right-semi.png" + direction = LTR + } + + # RTL + + image { + function = EXPANDER + expander_style = COLLAPSED + state = NORMAL + file = "assets/pan-left-alt.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = PRELIGHT + file = "assets/pan-left.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = ACTIVE + file = "assets/pan-left.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = COLLAPSED + state = INSENSITIVE + file = "assets/pan-left-alt-disabled.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = SEMI_COLLAPSED + file = "assets/pan-left-semi.png" + direction = RTL + } + + image { + function = EXPANDER + expander_style = SEMI_EXPANDED + file = "assets/pan-left-semi.png" + direction = RTL + } + + ############# + # Notebooks # + ############# + + # Left + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {0, 1, 0, 0} + stretch = TRUE + gap_side = RIGHT + } + + image { + function = EXTENSION + gap_side = RIGHT + } + + # Right + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {1, 0, 0, 0} + stretch = TRUE + gap_side = LEFT + } + + image { + function = EXTENSION + gap_side = LEFT + } + + # Up + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {0, 0, 0, 1} + stretch = TRUE + gap_side = BOTTOM + } + + image { + function = EXTENSION + gap_side = BOTTOM + } + + # Down + + image { + function = EXTENSION + state = NORMAL + file = "assets/tab.png" + border = {0, 0, 1, 0} + stretch = TRUE + gap_side = TOP + } + + image { + function = EXTENSION + gap_side = TOP + } + + # Inner frame + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {1, 0, 0, 0} + gap_side = LEFT + } + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {0, 1, 0, 0} + gap_side = RIGHT + } + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {0, 0, 1, 0} + gap_side = TOP + } + + image { + function = BOX_GAP + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_file = "assets/tab.png" + gap_border = {0, 0, 0, 1} + gap_side = BOTTOM + } + + # Standalone frame + image { + function = BOX + detail = "notebook" + file = "assets/frame-notebook.png" + border = {1, 1, 1, 1} + stretch = TRUE + } + + ############## + # Scrollbars # + ############## + + image { + function = BOX + detail = "trough" + file = "assets/scrollbar-horz-trough.png" + border = {0, 0, 1, 0} + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough" + file = "assets/scrollbar-vert-ltr-trough.png" + border = {1, 0, 0, 0} + orientation = VERTICAL + direction = LTR + } + + image { + function = BOX + detail = "trough" + file = "assets/scrollbar-vert-rtl-trough.png" + border = {0, 1, 0, 0} + orientation = VERTICAL + direction = RTL + } + + # Horizontal sliders + + image { + function = SLIDER + state = NORMAL + detail = "slider" + file = "assets/scrollbar-horz-slider.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = SLIDER + state = PRELIGHT + detail = "slider" + file = "assets/scrollbar-horz-slider-hover.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = SLIDER + state = ACTIVE + detail = "slider" + file = "assets/scrollbar-horz-slider-active.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "slider" + file = "assets/scrollbar-horz-slider-disabled.png" + border = {8, 8, 9, 8 } + stretch = TRUE + orientation = HORIZONTAL + } + + # Vertical sliders + + image { + function = SLIDER + state = NORMAL + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + image { + function = SLIDER + state = PRELIGHT + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider-hover.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + image { + function = SLIDER + state = ACTIVE + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider-active.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "slider" + file = "assets/scrollbar-vert-ltr-slider-disabled.png" + border = {9, 8, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = LTR + } + + # RTL + + image { + function = SLIDER + state = NORMAL + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + image { + function = SLIDER + state = PRELIGHT + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider-hover.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + image { + function = SLIDER + state = ACTIVE + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider-active.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "slider" + file = "assets/scrollbar-vert-rtl-slider-disabled.png" + border = {8, 9, 8, 8} + stretch = TRUE + orientation = VERTICAL + direction = RTL + } + + ########## + # Scales # + ########## + + # Troughs, overrided later on. We set them here too because some widgets + # don't specify their orientation. + + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-horz-trough.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-upper" + file = "assets/scale-horz-trough-disabled.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-horz-trough-active.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-lower" + file = "assets/scale-horz-trough-disabled.png" + border = {6, 6, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-vert-trough.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-upper" + file = "assets/scale-vert-trough-disabled.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-vert-trough-active.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + image { + function = BOX + state = INSENSITIVE + detail = "trough-lower" + file = "assets/scale-vert-trough-disabled.png" + border = {0, 0, 6, 6} + stretch = TRUE + orientation = VERTICAL + } + + # Sliders + + image { + function = SLIDER + state = NORMAL + detail = "hscale" + file = "assets/scale-slider.png" + } + + image { + function = SLIDER + state = PRELIGHT + detail = "hscale" + file = "assets/scale-slider-hover.png" + } + + image { + function = SLIDER + state = ACTIVE + detail = "hscale" + file = "assets/scale-slider-active.png" + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "hscale" + file = "assets/scale-slider-disabled.png" + } + + image { + function = SLIDER + state = NORMAL + detail = "vscale" + file = "assets/scale-slider.png" + } + + image { + function = SLIDER + state = PRELIGHT + detail = "vscale" + file = "assets/scale-slider-hover.png" + } + + image { + function = SLIDER + state = ACTIVE + detail = "vscale" + file = "assets/scale-slider-active.png" + } + + image { + function = SLIDER + state = INSENSITIVE + detail = "vscale" + file = "assets/scale-slider-disabled.png" + } + + ########### + # Menubar # + ########### + + image { + function = BOX + detail = "menubar" + file = "assets/border.png" + border = {0, 0, 0, 1} + } + + ######### + # Menus # + ######### + + image { + function = BOX + state = PRELIGHT + detail = "menu_scroll_arrow_up" + file = "assets/border.png" + } + + image { + function = BOX + detail = "menu_scroll_arrow_up" + file = "assets/border.png" + border = {0, 0, 0, 1} + } + + image { + function = BOX + state = PRELIGHT + detail = "menu_scroll_arrow_down" + file = "assets/border.png" + } + + image { + function = BOX + detail = "menu_scroll_arrow_down" + file = "assets/border.png" + border = {0, 0, 1, 0} + } + + ########### + # Entries # + ########### + + image { + function = SHADOW + state = ACTIVE + detail = "entry" + file = "assets/entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = SHADOW + state = INSENSITIVE + detail = "entry" + file = "assets/entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = SHADOW + detail = "entry" + file = "assets/entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = FLAT_BOX + state = ACTIVE + detail = "entry_bg" + file = "assets/entry-background.png" + } + + image { + function = FLAT_BOX + state = INSENSITIVE + detail = "entry_bg" + file = "assets/entry-background-disabled.png" + } + + image { + function = FLAT_BOX + detail = "entry_bg" + file = "assets/entry-background.png" + } + + ######### + # Spins # + ######### + + # Spin-Up LTR + + image { + function = BOX + state = NORMAL + detail = "spinbutton_up" + file = "assets/spin-ltr-up.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_up" + file = "assets/spin-ltr-up-hover.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_up" + file = "assets/spin-ltr-up-active.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_up" + file = "assets/spin-ltr-up-disabled.png" + border = {0, 8, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + direction = LTR + } + + # Spin-Up RTL + + image { + function = BOX + state = NORMAL + detail = "spinbutton_up" + file = "assets/spin-rtl-up.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_up" + file = "assets/spin-rtl-up-hover.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_up" + file = "assets/spin-rtl-up-hover.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_up" + file = "assets/spin-rtl-up-disabled.png" + border = {8, 0, 8, 0} + stretch = TRUE + overlay_file = "assets/pan-up-alt-disabled.png" + overlay_stretch = FALSE + direction = RTL + } + + # Spin-Down LTR + + image { + function = BOX + state = NORMAL + detail = "spinbutton_down" + file = "assets/spin-ltr-down.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_down" + file = "assets/spin-ltr-down-hover.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_down" + file = "assets/spin-ltr-down-active.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = LTR + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_down" + file = "assets/spin-ltr-down-disabled.png" + border = {0, 8, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + direction = LTR + } + + # Spin-Down RTL + + image { + function = BOX + state = NORMAL + detail = "spinbutton_down" + file = "assets/spin-rtl-down.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + detail = "spinbutton_down" + file = "assets/spin-rtl-down-hover.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + detail = "spinbutton_down" + file = "assets/spin-rtl-down-active.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + direction = RTL + } + + image { + function = BOX + state = INSENSITIVE + detail = "spinbutton_down" + file = "assets/spin-rtl-down-disabled.png" + border = {8, 0, 0, 8} + stretch = TRUE + overlay_file = "assets/pan-down-alt-disabled.png" + overlay_stretch = FALSE + direction = RTL + } + + ############## + # Scrollbars # + ############## + + image { + function = BOX + detail = "bar" + file = "assets/progressbar-progress.png" + stretch = TRUE + border = {0, 0, 0, 0} + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "bar" + file = "assets/progressbar-progress.png" + stretch = TRUE + border = {0, 0, 0, 0} + orientation = VERTICAL + } + + ############# + # Treeviews # + ############# + + # Disable active the column highlight + # We need to match specific cells or we break stuff + # Looking at you deadbeef + + image { + function = FLAT_BOX + detail = "cell_even_sorted" + state = NORMAL + } + + image { + function = FLAT_BOX + detail = "cell_odd_sorted" + state = NORMAL + } + + # Disable all the other shadows + # This prevents the Raleigh effect + image { + function = SHADOW + } + } +} + +style "menubar" { + bg[NORMAL] = @titlebar_bg_color + fg[NORMAL] = mix(0.7, @titlebar_fg_color, @titlebar_bg_color) + fg[PRELIGHT] = @titlebar_fg_color + fg[INSENSITIVE] = mix(0.3, @titlebar_fg_color, @titlebar_bg_color) + bg[INSENSITIVE] = @bg_color + # Needed to fix Firefox's menubar text + bg[SELECTED] = mix(0.12, @titlebar_fg_color, @titlebar_bg_color) + fg[SELECTED] = @titlebar_fg_color +} + +style "menubar_item" { + xthickness = 3 + ythickness = 4 + + fg[NORMAL] = mix(0.7, @titlebar_fg_color, @titlebar_bg_color) + bg[PRELIGHT] = mix(0.12, @titlebar_fg_color, @titlebar_bg_color) + fg[PRELIGHT] = @titlebar_fg_color + fg[INSENSITIVE] = mix(0.3, @titlebar_fg_color, @titlebar_bg_color) +} + +style "menu" { + xthickness = 0 + ythickness = 0 + + bg[NORMAL] = @menu_color + bg[INSENSITIVE] = @menu_color + bg[PRELIGHT] = @menu_color + bg[SELECTED] = mix(0.08, @fg_color, @menu_color) +} + +style "menu_item" { + xthickness = 4 + ythickness = 4 + + bg[PRELIGHT] = mix(0.08, @fg_color, @menu_color) + fg[PRELIGHT] = @fg_color + # Chromium uses this setting + bg[SELECTED] = mix(0.08, @fg_color, @menu_color) + text[SELECTED] = @fg_color + # Some widgets use text, we need to handle that + text[NORMAL] = @fg_color + text[PRELIGHT] = @fg_color + + # Unfortunately we can't tell regular and menu checks/radios apart + # Without the heirarchy + engine "pixmap" { + + ################# + # Check Buttons # + ################# + + image { + function = CHECK + state = NORMAL + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/menu-checkbox-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = IN + overlay_file = "assets/menu-checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = IN + overlay_file = "assets/menu-checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = IN + overlay_file = "assets/menu-checkbox-checked.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = IN + overlay_file = "assets/menu-checkbox-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed.png" + overlay_stretch = FALSE + } + + image { + function = CHECK + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-checkbox-mixed-disabled.png" + overlay_stretch = FALSE + } + + ################# + # Radio Buttons # + ################# + + image { + function = OPTION + state = NORMAL + shadow = OUT + overlay_file = "assets/menu-radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = OUT + overlay_file = "assets/menu-radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = OUT + overlay_file = "assets/menu-radio-unchecked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = OUT + overlay_file = "assets/menu-radio-unchecked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = IN + overlay_file = "assets/menu-radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = IN + overlay_file = "assets/menu-radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = IN + overlay_file = "assets/menu-radio-checked.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = IN + overlay_file = "assets/menu-radio-checked-disabled.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = NORMAL + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = PRELIGHT + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = ACTIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed.png" + overlay_stretch = FALSE + } + + image { + function = OPTION + state = INSENSITIVE + shadow = ETCHED_IN + overlay_file = "assets/menu-radio-mixed-disabled.png" + overlay_stretch = FALSE + } + } +} + +style "separator_menu_item" { + xthickness = 0 + ythickness = 2 + + engine "pixmap" { + image { + function = BOX + file = "assets/border.png" + border = {0, 0, 0, 1} + } + } +} + +style "button_label" { + # fg[NORMAL] = mix(0.7, @fg_color, @bg_color) + # fg[INSENSITIVE] = mix(0.3, @fg_color, @bg_color) + + font_name = "Medium" +} + +style "normal_button_label" { + # fg[NORMAL] = @fg_color + # fg[INSENSITIVE] = mix(0.5, @fg_color, @bg_color) + + font_name = "Regular" +} + +style "button" { + xthickness = 6 + ythickness = 6 + + # For the sake of sanity style buttons this way + engine "pixmap" { + + ########### + # Buttons # + ########### + + image { + function = BOX + state = NORMAL + file = "assets/button.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = PRELIGHT + shadow = OUT + file = "assets/button-hover.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + # Don't add hover effect on pressed buttons + image { + function = BOX + state = PRELIGHT + shadow = IN + file = "assets/button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = ACTIVE + file = "assets/button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + file = "assets/button-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + } +} + +style "link_button" { + # Disable the button effect, leave just the link + engine "pixmap" { + image { + function = BOX + } + } +} + +style "entry" { + base[NORMAL] = @bg_color + base[SELECTED] = mix (0.24, @selected_bg_color, @bg_color) + base[INSENSITIVE] = @bg_color + base[ACTIVE] = mix (0.24, @selected_bg_color, @bg_color) + + # We set this same as the border of the border of the entry + # This way there's no overlap + xthickness = 6 + ythickness = 6 +} + +style "combobox" { + xthickness = 6 + ythickness = 6 + + # This affects only the button beside an entry + GtkButton::inner-border = {0, 0, 0, 0} + + # For the sake of sanity style buttons this way + engine "pixmap" { + + ########### + # Buttons # + ########### + + image { + function = BOX + state = NORMAL + file = "assets/entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = PRELIGHT + file = "assets/entry-hover.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = ACTIVE + file = "assets/entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + file = "assets/entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + } +} + +style "combobox_cellview" { + # text[NORMAL] = mix(0.7, @fg_color, @bg_color) + # text[INSENSITIVE] = mix(0.3, @fg_color, @bg_color) +} + +style "combobox_entry" { + # Since one side of the button is missing, we need to shift the arrow a little to the right + GtkButton::inner-border = {0, 2, 0, 0} + + base[NORMAL] = @base_color + base[ACTIVE] = @base_color + + engine "pixmap" { + + ############# + # LTR entry # + ############# + + image { + function = SHADOW + state = NORMAL + detail = "entry" + file = "assets/combo-left-entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = SHADOW + state = ACTIVE + detail = "entry" + file = "assets/combo-left-entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = SHADOW + state = INSENSITIVE + detail = "entry" + file = "assets/combo-left-entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + ############# + # RTL entry # + ############# + + image { + function = SHADOW + state = NORMAL + detail = "entry" + file = "assets/combo-right-entry.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = SHADOW + state = ACTIVE + detail = "entry" + file = "assets/combo-right-entry-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = SHADOW + state = INSENSITIVE + detail = "entry" + file = "assets/combo-right-entry-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + direction = RTL + } + + ############## + # LTR button # + ############## + + image { + function = BOX + state = NORMAL + detail = "button" + file = "assets/combo-right-entry.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + detail = "button" + file = "assets/combo-right-entry-hover.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + detail = "button" + file = "assets/combo-right-entry-active.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = INSENSITIVE + detail = "button" + file = "assets/combo-right-entry-disabled.png" + border = {0, 6, 6, 6} + stretch = TRUE + direction = LTR + } + + ############## + # RTL button # + ############## + + image { + function = BOX + state = NORMAL + detail = "button" + file = "assets/combo-left-entry.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + detail = "button" + file = "assets/combo-left-entry-hover.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + detail = "button" + file = "assets/combo-left-entry-active.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = INSENSITIVE + detail = "button" + file = "assets/combo-left-entry-disabled.png" + border = {6, 0, 6, 6} + stretch = TRUE + direction = RTL + } + } +} + +style "combo_button_padding" { + # Since one side of the button is missing, we need to shift the arrow a + # little to the right. + # This is the same thing we've done above but the combo, unlike the combobox, + # uses padding the same way as a button. + GtkButton::inner-border = {3, 6, 3, 3} +} + +style "notebook" { + xthickness = 3 + ythickness = 3 + bg[NORMAL] = @base_color +} + +style "notebook_tab_label" { + fg[ACTIVE] = mix(0.7, @fg_color, @bg_color) + + font_name = "Medium" +} + +style "notebook_viewport" { + bg[NORMAL] = @base_color +} + +style "notebook_bg" { + bg[NORMAL] = @base_color + bg[PRELIGHT] = @base_color + bg[INSENSITIVE] = @base_color +} + +style "notebook_entry" { + base[NORMAL] = @base_color + base[SELECTED] = mix (0.24, @selected_bg_color, @base_color) + base[INSENSITIVE] = @base_color + base[ACTIVE] = mix (0.24, @selected_bg_color, @base_color) +} + +style "normal_bg" { + bg[NORMAL] = @bg_color + bg[PRELIGHT] = @bg_color + bg[INSENSITIVE] = @bg_color +} + +style "normal_entry" { + base[NORMAL] = @bg_color + base[SELECTED] = mix (0.24, @selected_bg_color, @bg_color) + base[INSENSITIVE] = @bg_color + base[ACTIVE] = mix (0.24, @selected_bg_color, @bg_color) +} + +style "textview" { + bg[NORMAL] = @base_color +} + +style "scale_horz" { + engine "pixmap" { + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-horz-trough.png" + border = {6, 6, 0, 0} + stretch = TRUE + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-horz-trough-active.png" + border = {6, 6, 0, 0} + stretch = TRUE + } + } +} + +style "scale_vert" { + engine "pixmap" { + image { + function = BOX + detail = "trough-upper" + file = "assets/scale-vert-trough.png" + border = {0, 0, 6, 6} + stretch = TRUE + } + + image { + function = BOX + detail = "trough-lower" + file = "assets/scale-vert-trough-active.png" + border = {0, 0, 6, 6} + stretch = TRUE + } + } +} + +style "progressbar" { + xthickness = 0 + ythickness = 0 + + fg[PRELIGHT] = @selected_fg_color + + engine "pixmap" { + image { + function = BOX + detail = "trough" + file = "assets/progressbar-trough.png" + border = {0, 0, 0, 0} + stretch = TRUE + orientation = HORIZONTAL + } + + image { + function = BOX + detail = "trough" + file = "assets/progressbar-trough.png" + border = {0, 0, 0, 0} + stretch = TRUE + orientation = VERTICAL + } + } +} + +style "treeview_header" { + xthickness = 2 + ythickness = 2 + + fg[NORMAL] = mix(0.7, @fg_color, @base_color) + fg[PRELIGHT] = @fg_color + + font_name = "Medium" + + GtkButton::inner-border = {4, 4, 0, 2} + + engine "pixmap" { + image { + function = BOX + state = NORMAL + file = "assets/treeview-ltr-button.png" + border = {0, 1, 0, 1} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = PRELIGHT + file = "assets/treeview-ltr-button-hover.png" + border = {0, 1, 0, 1} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = ACTIVE + file = "assets/treeview-ltr-button-active.png" + border = {0, 1, 0, 1} + stretch = TRUE + direction = LTR + } + + image { + function = BOX + state = NORMAL + file = "assets/treeview-rtl-button.png" + border = {1, 0, 0, 1} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = PRELIGHT + file = "assets/treeview-rtl-button-hover.png" + border = {1, 0, 0, 1} + stretch = TRUE + direction = RTL + } + + image { + function = BOX + state = ACTIVE + file = "assets/treeview-rtl-button-active.png" + border = {1, 0, 0, 1} + stretch = TRUE + direction = RTL + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-up-alt.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-up.png" + overlay_stretch = FALSE + arrow_direction = UP + } + + image { + function = ARROW + state = NORMAL + overlay_file = "assets/pan-down-alt.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = PRELIGHT + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + + image { + function = ARROW + state = ACTIVE + overlay_file = "assets/pan-down.png" + overlay_stretch = FALSE + arrow_direction = DOWN + } + } +} + +style "scrolled_window" { + engine "pixmap" { + image { + function = SHADOW + file = "assets/frame.png" + border = {1, 1, 1, 1} + stretch = TRUE + } + } +} + +style "frame" { + engine "pixmap" { + image { + function = SHADOW + shadow = NONE + } + + image { + function = SHADOW + file = "assets/frame.png" + border = {1, 1, 1, 1} + stretch = TRUE + } + + image { + function = SHADOW_GAP + file = "assets/frame.png" + border = {1, 1, 1, 1} + stretch = TRUE + gap_start_file = "assets/border.png" + gap_end_file = "assets/border.png" + } + } +} + +style "tool_button" { + GtkButton::inner-border = {2, 2, 2, 2} + + # For the sake of sanity style buttons this way + engine "pixmap" { + image { + function = BOX + state = NORMAL + file = "assets/flat-button.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = PRELIGHT + shadow = OUT + file = "assets/flat-button-hover.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + # Don't add hover effect on pressed buttons + image { + function = BOX + state = PRELIGHT + shadow = IN + file = "assets/flat-button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = ACTIVE + file = "assets/flat-button-active.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + shadow = OUT + file = "assets/flat-button-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + + image { + function = BOX + state = INSENSITIVE + shadow = IN + file = "assets/button-disabled.png" + border = {6, 6, 6, 6} + stretch = TRUE + } + } +} + +style "toolbar_separator" { + GtkWidget::wide-separators = 1 + GtkWidget::separator-width = 1 + GtkWidget::separator-height = 1 + + engine "pixmap" { + image { + function = BOX + file = "assets/border.png" + } + } +} + +style "inline_toolbar" { + # GtkToolbar::button-relief = GTK_RELIEF_NORMAL + bg[NORMAL] = @base_color + + engine "pixmap" { + image { + function = BOX + file = "assets/frame-inline.png" + border = {1, 1, 0, 1} + stretch = TRUE + } + } +} + +style "tooltip" { + xthickness = 8 + ythickness = 8 + + bg[NORMAL] = @tooltip_bg_color + fg[NORMAL] = @tooltip_fg_color + bg[SELECTED] = @tooltip_bg_color +} + +style "disable_text_shadow" { + engine "murrine" { + textstyle = 0 + } +} + +style "disable_separator" { + xthickness = 0 + ythickness = 0 + + GtkWidget::wide-separators = 1 +} + +# Default style, containing theme properties and trying to match every widget as +# much as possible, which is not only faster than trying to match every widget +# by its own but also less bug-prune and more consistent. However there is some +# widget specific stuff that needs to be taken care of, which is the point of +# every other style below. +class "GtkWidget" style "default" + +###################################### +# Override padding, style and colour # +###################################### + +class "GtkButton" style "button" +class "GtkLinkButton" style "link_button" +class "GtkEntry" style "entry" +class "GtkOldEditable" style "entry" +class "GtkNotebook" style "notebook" +class "GtkHScale" style "scale_horz" +class "GtkVScale" style "scale_vert" +class "GtkProgressBar" style "progressbar" +class "GtkScrolledWindow" style "scrolled_window" +class "GtkFrame" style "frame" +class "GtkSeparatorToolItem" style "toolbar_separator" +class "GtkMenuBar" style "menubar" +class "GtkMenu" style "menu" +class "GtkTextView" style "textview" + +# Menu and menubar items +widget_class "*<GtkMenuItem>*" style "menu_item" +widget_class "*<GtkMenuBar>.<GtkMenuItem>*" style "menubar_item" +widget_class "*<GtkSeparatorMenuItem>*" style "separator_menu_item" + +# Treeview buttons +widget_class "*<GtkTreeView>*<GtkButton>*" style "treeview_header" + +# Give the file chooser toolbar a border +widget_class "*<GtkFileChooserDefault>*<GtkToolbar>" style "inline_toolbar" + +# Fix padding on regular comboboxes +widget_class "*<GtkComboBox>.<GtkButton>" style "combobox" +widget_class "*<GtkOptionMenu>" style "combobox" + +# And disable separators on them +widget_class "*<GtkComboBox>.<GtkButton>*<GtkSeparator>" style "disable_separator" +widget_class "*<GtkFontButton>*<GtkSeparator>" style "disable_separator" +widget_class "*<GtkFileChooserButton>*<GtkSeparator>" style "disable_separator" + +# Join together the ComboBoxEntry entry and button +widget_class "*<GtkComboBoxEntry>*" style "combobox_entry" + +# Join the Combo entry and button +widget_class "*<GtkCombo>*" style "combobox_entry" + +# Tweak the padding on the button a little bit because it +# uses it a bit differently +widget_class "*<GtkCombo>.<GtkButton>" style "combo_button_padding" + +# Alas we cannot do the same for ComboBoxText because there +# isn't a way to apply the style to only the comboboxes that +# have an entry inside + +# Tool buttons have different styles +widget_class "*<GtkToolButton>*<GtkButton>" style "tool_button" +widget_class "*<GtkVBox>*<GtkEventBox>.<GtkToolbar>*<GtkButton>" style "tool_button" + +# Notebooks +widget_class "*<GtkNotebook>.<GtkLabel>" style "notebook_tab_label" +widget_class "*<GtkNotebook>.<GtkHBox>.<GtkLabel>" style "notebook_tab_label" + +# Notebooks are white, act accordingly +widget_class "*<GtkNotebook>*<GtkEntry>" style "notebook_entry" +widget_class "*<GtkNotebook>*<GtkProgressBar>" style "notebook_bg" +widget_class "*<GtkNotebook>*<GtkSpinButton>" style "notebook_bg" +widget_class "*<GtkNotebook>*<GtkScrolledWindow>*<GtkViewport>" style "notebook_bg" +widget_class "*<GtkNotebook>*<GimpRuler>" style "notebook_bg" +widget_class "*<GtkNotebook>.<GimpDisplayShell>*<GtkEventBox>" style "notebook_bg" + +# However, stuff inside eventboxes inside notebooks is grey +# again, react +widget_class "*<GtkNotebook>*<GtkEventBox>*<GtkEntry>" style "normal_entry" +widget_class "*<GtkNotebook>*<GtkEventBox>*<GtkProgressBar>" style "normal_bg" +widget_class "*<GtkNotebook>*<GtkEventBox>*<GtkSpinButton>" style "normal_bg" + +# Button labels +widget_class "*<GtkButton>.<GtkLabel>" style "button_label" + +# Normalize button labels +widget_class "*<GtkCheckButton>.<GtkLabel>" style "normal_button_label" +widget_class "*<GtkOptionMenu>.<GtkLabel>" style "normal_button_label" + +# ComboBoxes tend to draw the button label with text[] +# instead of fg[], we need to fix that +widget_class "*<GtkComboBox>*<GtkCellView>" style "combobox_cellview" + +# Disable white text shadows +widget_class "*<GtkLabel>" style "disable_text_shadow" +widget_class "*<GtkCellView>" style "disable_text_shadow" + +# GTK tooltips +widget "gtk-tooltip*" style "tooltip" diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg new file mode 100755 index 0000000..c3eedb0 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic.svg @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="20" + height="20" + version="1.1" + viewBox="0 0 20 20" + id="svg4" + sodipodi:docname="checkbox-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="true" + inkscape:snap-global="false" + inkscape:zoom="10.547676" + inkscape:cx="13.510085" + inkscape:cy="10.902876" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 16.363961,5.7576864 c -0.391736,-0.3917365 -1.022477,-0.3917368 -1.414214,0 L 8.5857865,12.121648 5.0502526,8.5861135 c -0.3917367,-0.3917368 -1.0224771,-0.3917365 -1.4142135,0 -0.3917365,0.3917362 -0.3917368,1.0224772 0,1.4142135 l 4.2426407,4.242641 c 0.024483,0.02448 0.049725,0.04625 0.075958,0.06767 0.3935113,0.321347 0.9710025,0.299581 1.3382554,-0.06767 L 16.363961,7.1718999 c 0.391737,-0.3917367 0.391736,-1.0224771 0,-1.4142135 z" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..96be359 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-checked-symbolic@2.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="40" + height="40" + version="1.1" + viewBox="0 0 40 40" + id="svg4" + sodipodi:docname="checkbox-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:snap-global="false" + inkscape:zoom="10.547676" + inkscape:cx="5.8306685" + inkscape:cy="13.273066" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 32.727894,11.515401 c -0.783472,-0.783473 -2.044954,-0.783473 -2.828428,0 L 17.171545,24.243326 10.100478,17.172255 c -0.7834739,-0.783473 -2.0449547,-0.783473 -2.8284282,1e-6 -0.7834731,0.783472 -0.7834745,2.044955 0,2.828427 l 8.4852812,8.485281 c 0.04896,0.04896 0.09952,0.09245 0.151973,0.135285 0.787025,0.642691 1.942005,0.599161 2.676511,-0.135341 L 32.727951,14.343772 c 0.783473,-0.783474 0.783472,-2.044954 0,-2.828428 z" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..f016658 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="20" + height="20" + version="1.1" + viewBox="0 0 20 20" + id="svg4" + sodipodi:docname="checkbox-mixed-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="true" + inkscape:zoom="21.095352" + inkscape:cx="7.0868692" + inkscape:cy="12.988643" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + width="20px" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="10" + height="2" + x="5" + y="9" + rx="1" + ry="1" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..1bc6987 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/checkbox-mixed-symbolic@2.svg @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="40" + height="40" + version="1.1" + viewBox="0 0 40 40" + id="svg4" + sodipodi:docname="checkbox-mixed-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="10.547676" + inkscape:cx="-0.047403807" + inkscape:cy="19.340753" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + width="20px" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="20" + height="4" + x="10" + y="18" + rx="2" + ry="2" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/close.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/close.svg new file mode 100755 index 0000000..06201c3 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/close.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + sodipodi:docname="close.svg" + id="svg824" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs5" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="11.5625" + inkscape:cx="7.3513514" + inkscape:cy="13.837838" + inkscape:window-width="1440" + inkscape:window-height="742" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg824" /> + <path + d="m 4.464745,3.96488 c -0.12775,0 -0.2555,0.0486 -0.35339,0.14649 -0.19578,0.19586 -0.19578,0.51116 0,0.70703 L 7.292955,8 l -3.1816,3.1816 c -0.19578,0.19586 -0.19578,0.51116 0,0.70703 0.19578,0.19586 0.51118,0.19586 0.70704,0 l 3.18161,-3.1816 3.1816,3.1816 c 0.19578,0.19586 0.51114,0.19586 0.70704,0 0.19578,-0.19586 0.19578,-0.51116 0,-0.70703 L 8.707045,8 l 3.1816,-3.1816 c 0.19578,-0.19586 0.19578,-0.51116 0,-0.70703 -0.19578,-0.19586 -0.51117,-0.19586 -0.70704,0 l -3.1816,3.1816 -3.18161,-3.1816 C 4.720495,4.01347 4.592755,3.96488 4.465005,3.96488 Z" + id="path2928" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg new file mode 100755 index 0000000..e2a252b --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/cursor-handle-symbolic.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"> + <path d="M0 0h12A12 12 0 1 1 0 12z"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/maximize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/maximize.svg new file mode 100755 index 0000000..39316eb --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/maximize.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + sodipodi:docname="maximize.svg" + id="svg825" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs5" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="11.243243" + inkscape:cy="11.978378" + inkscape:window-width="1440" + inkscape:window-height="742" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg825" /> + <path + d="M 6,4 C 4.892,4 4,4.892 4,6 v 4 c 0,1.108 0.89201,2 2,2 h 4 c 1.10801,0 2,-0.892 2,-2 V 6 C 12,4.892 11.10799,4 10,4 Z m 0,1 h 4 c 0.554,0 1,0.44602 1,1 v 4 c 0,0.55398 -0.44602,1 -1,1 H 6 C 5.44603,11 5.00001,10.55398 5.00001,10 V 6 C 5.00001,5.44602 5.44604,5 6,5 Z" + id="path2930" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/minimize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/minimize.svg new file mode 100755 index 0000000..f3683b9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/minimize.svg @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + id="svg4" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + sodipodi:docname="minimize.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs5" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="5.7513514" + inkscape:cy="9.8162162" + inkscape:window-width="1440" + inkscape:window-height="742" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <rect + x="4" + y="8" + width="8" + height="1" + rx="0.5" + ry="0.5" + id="rect2932" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic.svg new file mode 100755 index 0000000..d13b029 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="20" + height="20" + version="1.1" + viewBox="0 0 20 20" + id="svg4" + sodipodi:docname="radio-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="9.6368716" + inkscape:cy="12" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="path2" + d="m 10,6 c 2.209138,0 4,1.790862 4,4 0,2.209138 -1.790862,4 -4,4 C 7.790862,14 6,12.209138 6,10 6,7.790862 7.790862,6 10,6 Z" + sodipodi:nodetypes="sssss" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg new file mode 100755 index 0000000..ed8d87a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-checked-symbolic@2.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="40" + height="40" + version="1.1" + viewBox="0 0 40 40" + id="svg4" + sodipodi:docname="radio-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="3.7291666" + inkscape:cx="-8.4469275" + inkscape:cy="25.743017" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="path2" + d="m 20,12 c 4.418276,0 8,3.581724 8,8 0,4.418276 -3.581724,8 -8,8 -4.418276,0 -8,-3.581724 -8,-8 0,-4.418276 3.581724,-8 8,-8 z" + sodipodi:nodetypes="sssss" + style="stroke-width:4" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg new file mode 120000 index 0000000..79b7355 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..b68859d --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..de0d789 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-after-slider-symbolic.svg @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg17" + sodipodi:docname="scale-horz-marks-after-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview19" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg17" /> + <defs + id="defs6"> + <linearGradient + id="color-primary-dark"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + <linearGradient + id="a" + x1="-3.5527e-15" + x2="24" + gradientUnits="userSpaceOnUse" + xlink:href="#color-primary-dark" /> + </defs> + <path + d="m 12,20.485281 -4.2426407,-4.24264 a 6,6 0 1 1 8.4852817,0 z" + fill="#000000" + id="path10" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..7f0235f --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-horz-marks-before-slider-symbolic.svg @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg12" + sodipodi:docname="scale-horz-marks-before-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="14.916667" + inkscape:cx="3.2178771" + inkscape:cy="15.821229" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5"> + <linearGradient + id="a" + x2="24" + gradientUnits="userSpaceOnUse"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + </defs> + <path + d="m 12,3.5147186 4.242641,4.2426407 a 6,6 0 1 1 -8.4852817,0 z" + id="path9" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg new file mode 100755 index 0000000..993f308 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg12" + sodipodi:docname="scale-slider-hover-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="12" + inkscape:cy="12.226415" + inkscape:window-width="1368" + inkscape:window-height="704" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="12" + cy="12" + r="8" + id="circle9" + style="stroke-width:1.33333" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg new file mode 100755 index 0000000..740bc8b --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-hover-symbolic@2.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="48" + version="1.1" + viewBox="0 0 48 48" + id="svg12" + sodipodi:docname="scale-slider-hover-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="3.4867923" + inkscape:cy="12.226415" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="24" + cy="24" + r="16" + id="circle9" + style="stroke-width:2.66666" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic.svg new file mode 100755 index 0000000..73a1dbe --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic.svg @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg12" + sodipodi:docname="scale-slider-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="11.864151" + inkscape:cy="12.226415" + inkscape:window-width="1368" + inkscape:window-height="700" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="12" + cy="12" + r="6" + id="circle9" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg new file mode 100755 index 0000000..bec2ee4 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-slider-symbolic@2.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="48" + version="1.1" + viewBox="0 0 48 48" + id="svg12" + sodipodi:docname="scale-slider-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="3.3056603" + inkscape:cy="12.226415" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="24" + cy="24" + r="12" + id="circle9" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..37d9c04 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-after-slider-symbolic.svg @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg17" + sodipodi:docname="scale-vert-marks-after-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview19" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg17" /> + <defs + id="defs6"> + <linearGradient + id="color-primary-dark"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + <linearGradient + id="a" + x2="24" + gradientUnits="userSpaceOnUse" + xlink:href="#color-primary-dark" /> + </defs> + <path + d="m 20.485281,12 -4.24264,4.242641 a 6,6 0 1 1 0,-8.4852817 z" + fill="#000000" + id="path10" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..1bc5cb6 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/scale-vert-marks-before-slider-symbolic.svg @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg17" + sodipodi:docname="scale-vert-marks-before-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview19" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg17" /> + <defs + id="defs6"> + <linearGradient + id="color-primary-dark"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + <linearGradient + id="a" + x1="-2.6324e-15" + x2="24" + y1="-3.5527e-15" + y2="-3.5527e-15" + gradientUnits="userSpaceOnUse" + xlink:href="#color-primary-dark" /> + </defs> + <path + d="M 3.5147186,12 7.7573593,7.7573593 a 6,6 0 1 1 0,8.4852817 z" + fill="#000000" + id="path10" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg new file mode 100755 index 0000000..caed76f --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="small-checkbox-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="true" + inkscape:snap-global="false" + inkscape:zoom="31.643028" + inkscape:cx="9.1489348" + inkscape:cy="7.3001863" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid1068" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 12.596166,4.818375 c -0.391736,-0.3917359 -1.022477,-0.3917367 -1.414214,2e-7 L 6.9393399,9.0609886 4.8180203,6.9396678 c -0.3917368,-0.3917368 -1.0224772,-0.3917365 -1.4142136,0 -0.3917366,0.3917363 -0.3917373,1.0224777 0,1.4142138 l 2.8284271,2.8284274 c 0.02448,0.02448 0.049752,0.04622 0.075986,0.06764 0.3935135,0.321347 0.9710033,0.299582 1.3382562,-0.06767 l 4.949717,-4.949718 c 0.391738,-0.3917362 0.391736,-1.0224769 0,-1.4142136 z" + sodipodi:nodetypes="cscsscsccccc" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..58aa5ff --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-checked-symbolic@2.svg @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="32" + height="32" + version="1.1" + viewBox="0 0 32 32" + id="svg4" + sodipodi:docname="small-checkbox-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:snap-global="false" + inkscape:zoom="11.1875" + inkscape:cx="23.106146" + inkscape:cy="24.134079" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid1068" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 25.192327,9.6367502 c -0.783471,-0.783472 -2.044952,-0.783474 -2.828426,-10e-7 L 13.878679,18.121974 9.6360416,13.879333 c -0.783474,-0.783473 -2.044953,-0.783472 -2.828426,10e-7 -0.783473,0.783472 -0.783474,2.044955 1e-6,2.828427 l 5.6568514,5.656851 c 0.04896,0.04896 0.0995,0.09243 0.151974,0.135287 0.787026,0.642691 1.942006,0.599162 2.676511,-0.13534 l 9.899431,-9.899434 c 0.783476,-0.783471 0.783471,-2.044952 0,-2.8284258 z" + sodipodi:nodetypes="cscsscsccccc" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..0e477a9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="small-checkbox-mixed-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="22.375" + inkscape:cx="7.1284916" + inkscape:cy="13.810056" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid967" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="8" + height="2" + x="4" + y="7" + rx="1" + ry="1" + style="stroke-width:0.894427" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..d0980e2 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-checkbox-mixed-symbolic@2.svg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="32" + height="32" + version="1.1" + viewBox="0 0 32 32" + id="svg4" + sodipodi:docname="small-checkbox-mixed-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="11.1875" + inkscape:cx="5.4972067" + inkscape:cy="19.843575" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid967" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="16" + height="4" + x="8" + y="14" + rx="2" + ry="2" + style="stroke-width:1.78885" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg new file mode 100755 index 0000000..0fdb530 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="small-radio-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="22.375" + inkscape:cx="8.5139665" + inkscape:cy="11.486034" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + <path + id="path2" + d="m 8,4 c 2.209139,0 4,1.790861 4,4 0,2.209139 -1.790861,4 -4,4 C 5.790861,12 4,10.209139 4,8 4,5.790861 5.790861,4 8,4 Z" + sodipodi:nodetypes="sssss" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg new file mode 100755 index 0000000..251e2f5 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-checked-symbolic@2.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="32" + height="32" + version="1.1" + viewBox="0 0 32 32" + id="svg4" + sodipodi:docname="small-radio-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="22.375" + inkscape:cx="8.5139665" + inkscape:cy="11.486034" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + <path + id="path2" + d="m 16,8 c 4.418278,0 8,3.581722 8,8 0,4.418278 -3.581722,8 -8,8 -4.418278,0 -8,-3.581722 -8,-8 0,-4.418278 3.581722,-8 8,-8 z" + sodipodi:nodetypes="sssss" + style="stroke-width:4" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg new file mode 120000 index 0000000..86dfcec --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..bafb558 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/small-radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/unmaximize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/unmaximize.svg new file mode 100755 index 0000000..492d47a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scalable/unmaximize.svg @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + sodipodi:docname="unmaximize.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + id="svg831" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs6" /> + <sodipodi:namedview + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1440" + inkscape:window-height="742" + id="namedview6" + showgrid="true" + inkscape:zoom="29.580633" + inkscape:cx="2.095966" + inkscape:cy="10.006547" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:pagecheckerboard="0" + inkscape:current-layer="svg831" /> + <path + d="M 6,6 C 4.892,6 4,6.892 4,8 v 2 c 0,1.108 0.892,2 2,2 h 2 c 1.108,0 2,-0.892 2,-2 V 8 C 10,6.892 9.108,6 8,6 Z m 0,1 h 2 c 0.554,0 1,0.446 1,1 v 2 c 0,0.554 -0.446,1 -1,1 H 6 C 5.446,11 5,10.554 5,10 V 8 C 5,7.446 5.446,7 6,7 Z" + id="path2896" + style="fill:#ffffff" /> + <path + d="M 8,4 C 6.892,4 6,4.892 6,6 H 7 C 7,5.446 7.446,5 8,5 h 2 c 0.554,0 1,0.446 1,1 v 2 c 0,0.554 -0.446,1 -1,1 v 1 c 1.108,0 2,-0.892 2,-2 V 6 C 12,4.892 11.108,4 10,4 Z" + opacity="0.35" + id="path2898" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png new file mode 100755 index 0000000..3c28e2e Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png new file mode 100755 index 0000000..6f7cfe0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png new file mode 100755 index 0000000..0ce5620 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png new file mode 100755 index 0000000..809d772 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png new file mode 100755 index 0000000..06220f9 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png new file mode 100755 index 0000000..f7699ef Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider-disabled@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider.png new file mode 100755 index 0000000..f794bee Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider@2.png new file mode 100755 index 0000000..ab09641 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-after-slider@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png new file mode 100755 index 0000000..4cba793 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png new file mode 100755 index 0000000..cd88858 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png new file mode 100755 index 0000000..f6dfce1 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png new file mode 100755 index 0000000..f7e1c8c Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png new file mode 100755 index 0000000..5172280 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png new file mode 100755 index 0000000..40f21e2 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider-disabled@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider.png new file mode 100755 index 0000000..6c425ca Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider@2.png new file mode 100755 index 0000000..30ea290 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-horz-marks-before-slider@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png new file mode 100755 index 0000000..4ac9177 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png new file mode 100755 index 0000000..3db31b1 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png new file mode 100755 index 0000000..0233a35 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png new file mode 100755 index 0000000..7e679c3 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png new file mode 100755 index 0000000..74c3013 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png new file mode 100755 index 0000000..38e2e0b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider-disabled@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider.png new file mode 100755 index 0000000..f13c099 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider@2.png new file mode 100755 index 0000000..815ea0d Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-after-slider@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png new file mode 100755 index 0000000..00f9bb4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png new file mode 100755 index 0000000..6470e79 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png new file mode 100755 index 0000000..2051840 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png new file mode 100755 index 0000000..17786ae Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png new file mode 100755 index 0000000..6a0dc1b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png new file mode 100755 index 0000000..2fca190 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider-disabled@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider.png new file mode 100755 index 0000000..46cd1c0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider@2.png new file mode 100755 index 0000000..e6b548f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/scale-vert-marks-before-slider@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png new file mode 100755 index 0000000..d606fd6 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png new file mode 100755 index 0000000..4c39926 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked.png new file mode 100755 index 0000000..602114e Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked@2.png new file mode 100755 index 0000000..adca465 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-checked@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png new file mode 100755 index 0000000..e09e654 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png new file mode 100755 index 0000000..1b454df Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked-dark@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked.png new file mode 100755 index 0000000..5792f1f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png new file mode 100755 index 0000000..01f7523 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/assets/selectionmode-checkbox-unchecked@2.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk-dark.css b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk-dark.css new file mode 100755 index 0000000..fdd02f9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk-dark.css @@ -0,0 +1,8576 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #7daea3 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #7daea3 100%, transparent 0%); + } +} + +* { + background-clip: padding-box; + -gtktoolbutton-icon-spacing: 4; + -gtktextview-error-underline-color: #c14a4a; + -gtkscrolledwindow-scrollbar-spacing: 0; + -gtktoolitemgroup-expander-size: 11; + -gtkwidget-text-handle-width: 20; + -gtkwidget-text-handle-height: 20; + -gtkdialog-button-spacing: 6; + -gtkdialog-action-area-border: 4; + -gtkdialog-content-area-border: 4; + outline-style: solid; + outline-width: 0; + outline-color: alpha(currentColor, 0.15); + outline-offset: -4px; + -gtk-outline-radius: 12px; + -gtk-secondary-caret-color: #7daea3; +} + +.thunar .standard-view.frame widget.view:selected, XfdesktopIconView.view:active, calendar.raven-calendar:selected, box.vertical > widget > widget:selected, calendar:selected, modelbutton.flat:selected, +.menuitem.button.flat:selected, .background.csd .view:selected { + color: #fbf1c7; + background-color: alpha(currentColor, 0.1); +} + +.nautilus-window notebook .view:not(treeview) selection, .nautilus-window notebook .view:not(treeview):selected, .nautilus-window flowboxchild:selected .icon-item-background, label selection, flowbox flowboxchild:selected { + color: #7daea3; + background-color: rgba(125, 174, 163, 0.2); +} + +.nemo-window .nemo-window-pane widget.entry:selected, window.background.csd evview.view.content-view:selected, window.background.csd evview.view.content-view:selected:backdrop, .nautilus-window.background.csd notebook widget.view:selected, spinbutton.vertical selection, spinbutton:not(.vertical) selection, +entry selection, textview text selection:focus, textview text selection, widget.view:selected, .view:selected { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +treeview.view:selected { + color: rgba(40, 40, 40, 0.87); + background-color: #fbf1c7; +} + +.linked:not(.vertical) > button, .linked:not(.vertical) > spinbutton.vertical, .linked:not(.vertical) > spinbutton:not(.vertical), .linked:not(.vertical) > entry { + border-radius: 0; +} + +.linked:not(.vertical) > button:first-child, .linked:not(.vertical) > spinbutton.vertical:first-child, .linked:not(.vertical) > spinbutton:first-child:not(.vertical), .linked:not(.vertical) > entry:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > button:last-child, .linked:not(.vertical) > spinbutton.vertical:last-child, .linked:not(.vertical) > spinbutton:last-child:not(.vertical), .linked:not(.vertical) > entry:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > button:only-child, .linked:not(.vertical) > spinbutton.vertical:only-child, .linked:not(.vertical) > spinbutton:only-child:not(.vertical), .linked:not(.vertical) > entry:only-child { + border-radius: 12px; +} + +.linked.vertical > button, .linked.vertical > spinbutton.vertical, .linked.vertical > spinbutton:not(.vertical), .linked.vertical > entry { + border-radius: 0; +} + +.linked.vertical > button:first-child, .linked.vertical > spinbutton.vertical:first-child, .linked.vertical > spinbutton:first-child:not(.vertical), .linked.vertical > entry:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > button:last-child, .linked.vertical > spinbutton.vertical:last-child, .linked.vertical > spinbutton:last-child:not(.vertical), .linked.vertical > entry:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > button:only-child, .linked.vertical > spinbutton.vertical:only-child, .linked.vertical > spinbutton:only-child:not(.vertical), .linked.vertical > entry:only-child { + border-radius: 12px; +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #282828; + color: #fbf1c7; +} + +.background.csd { + border-radius: 0 0 12px 12px; +} + +.background.maximized, .background.solid-csd { + border-radius: 0; +} + +*:disabled { + -gtk-icon-effect: dim; +} + +.gtkstyle-fallback { + background-color: #282828; + color: #fbf1c7; +} + +.gtkstyle-fallback:hover { + background-color: #1b1b1b; + color: #fbf1c7; +} + +.gtkstyle-fallback:active { + background-color: #0f0f0f; + color: #fbf1c7; +} + +.gtkstyle-fallback:disabled { + background-color: #282828; + color: rgba(251, 241, 199, 0.5); +} + +.gtkstyle-fallback:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.view { + background-color: #282524; + color: #fbf1c7; +} + +.view:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.view:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.view:selected:hover { + box-shadow: none; +} + +window.background.csd > stack.view { + border-radius: 0 0 12px 12px; +} + +textview text { + background-color: #282524; +} + +textview border { + background-color: #282524; + color: rgba(251, 241, 199, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 12px; +} + +flowbox rubberband, +.rubberband, +rubberband, +XfdesktopIconView.view .rubberband, +.content-view rubberband, +.content-view .rubberband, +treeview.view rubberband { + border: 1px solid #7daea3; + background-color: rgba(125, 174, 163, 0.3); +} + +flowbox flowboxchild { + padding: 3px; + border-radius: 12px; + color: #fbf1c7; +} + +flowbox flowboxchild button.osd.remove-button { + min-height: 28px; + min-width: 28px; + padding: 0; + margin: 6px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +label { + caret-color: currentColor; +} + +label.separator { + color: rgba(251, 241, 199, 0.7); +} + +label:disabled { + color: rgba(251, 241, 199, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; +} + +label.osd { + border-radius: 12px; + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; +} + +.dim-label { + color: rgba(251, 241, 199, 0.7); +} + +assistant .sidebar { + padding: 4px 0; +} + +assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(251, 241, 199, 0.5); + font-weight: 500; +} + +assistant .sidebar label.highlight { + color: #fbf1c7; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + -gtk-icon-transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry { + background-color: rgba(40, 40, 40, 0.04); + color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus { + color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active) { + color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled { + background-color: rgba(40, 40, 40, 0.04); + color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image { + color: rgba(40, 40, 40, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled { + color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image { + color: rgba(40, 40, 40, 0.87); +} + +spinbutton.vertical, spinbutton:not(.vertical), +entry { + min-height: 34px; + padding: 0 8px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton.vertical:focus, spinbutton:focus:not(.vertical), +entry:focus { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #7daea3; +} + +spinbutton.vertical:drop(active), spinbutton:drop(active):not(.vertical), +entry:drop(active) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + +spinbutton.vertical:disabled, spinbutton:disabled:not(.vertical), +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.flat.vertical, spinbutton.flat:not(.vertical), +entry.flat { + min-height: 0; + padding: 2px; + border-radius: 0; + background-color: transparent; +} + +spinbutton.vertical image, spinbutton:not(.vertical) image, +entry image { + color: rgba(251, 241, 199, 0.7); +} + +spinbutton.vertical image:hover, spinbutton:not(.vertical) image:hover, spinbutton.vertical image:active, spinbutton:not(.vertical) image:active, +entry image:hover, +entry image:active { + color: #fbf1c7; +} + +spinbutton.vertical image:disabled, spinbutton:not(.vertical) image:disabled, +entry image:disabled { + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.vertical image.left, spinbutton:not(.vertical) image.left, +entry image.left { + margin-left: 1px; + margin-right: 6px; +} + +spinbutton.vertical image.right, spinbutton:not(.vertical) image.right, +entry image.right { + margin-left: 6px; + margin-right: 1px; +} + +spinbutton.vertical undershoot.left, spinbutton:not(.vertical) undershoot.left, +entry undershoot.left { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(251, 241, 199, 0.3) 50%); + padding-left: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: left top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.vertical undershoot.right, spinbutton:not(.vertical) undershoot.right, +entry undershoot.right { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(251, 241, 199, 0.3) 50%); + padding-right: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: right top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.error.vertical, spinbutton.error:not(.vertical), +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton.error.vertical:focus, spinbutton.error:focus:not(.vertical), +entry.error:focus { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #c14a4a; +} + +spinbutton.error.vertical:disabled, spinbutton.error:disabled:not(.vertical), +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.warning.vertical, spinbutton.warning:not(.vertical), +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton.warning.vertical:focus, spinbutton.warning:focus:not(.vertical), +entry.warning:focus { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #b47109; +} + +spinbutton.warning.vertical:disabled, spinbutton.warning:disabled:not(.vertical), +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.vertical progress, spinbutton:not(.vertical) progress, +entry progress { + margin: 2px -8px; + border-bottom: 2px solid #7daea3; + background-color: transparent; +} + +treeview entry.flat, treeview entry { + background-color: #282524; +} + +treeview entry.flat, treeview entry.flat:focus, treeview entry, treeview entry:focus { + border-image: none; + box-shadow: none; +} + +.entry-tag, .photos-entry-tag, .documents-entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.entry-tag:hover, .photos-entry-tag:hover, .documents-entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag, :dir(ltr) .photos-entry-tag, :dir(ltr) .documents-entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag, :dir(rtl) .photos-entry-tag, :dir(rtl) .documents-entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button, .button.photos-entry-tag, .button.documents-entry-tag { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active), .button.photos-entry-tag:not(:hover):not(:active), .button.documents-entry-tag:not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.001, to(#7daea3), to(transparent)); + } + to { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(#7daea3), to(transparent)); + } +} + +.xfce4-panel.background button, .raven-mpris button.image-button, .mate-panel-menu-bar button, infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button { + color: rgba(251, 241, 199, 0.7); +} + +.xfce4-panel.background button:focus, .raven-mpris button.image-button:focus, .mate-panel-menu-bar button:focus, infobar.warning > revealer > box button:focus, .xfce4-panel.background button:hover, .raven-mpris button.image-button:hover, .mate-panel-menu-bar button:hover, infobar.warning > revealer > box button:hover, .xfce4-panel.background button:active, .raven-mpris button.image-button:active, .mate-panel-menu-bar button:active, infobar.warning > revealer > box button:active, .xfce4-panel.background button:checked, .raven-mpris button.image-button:checked, .mate-panel-menu-bar button:checked, infobar.warning > revealer > box button:checked { + color: #fbf1c7; +} + +.xfce4-panel.background button:disabled, .raven-mpris button.image-button:disabled, .mate-panel-menu-bar button:disabled, infobar.warning > revealer > box button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.xfce4-panel.background button:checked:disabled, .raven-mpris button.image-button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, infobar.warning > revealer > box button:checked:disabled { + color: rgba(251, 241, 199, 0.5); +} + +actionbar > revealer > box button:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: #282524; + color: #fbf1c7; +} + +actionbar > revealer > box button:checked:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: rgba(40, 40, 40, 0.87); + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat, terminal-window notebook > header > box button.flat { + color: rgba(40, 40, 40, 0.6); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:hover, terminal-window notebook > header > box button.flat:hover, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:active, terminal-window notebook > header > box button.flat:active, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:focus, terminal-window notebook > header > box button.flat:focus { + color: rgba(40, 40, 40, 0.87); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:checked, terminal-window notebook > header > box button.flat:checked { + background-color: rgba(40, 40, 40, 0.87); + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:disabled, terminal-window notebook > header > box button.flat:disabled { + color: rgba(40, 40, 40, 0.3); +} + +button { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(251, 241, 199, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #fbf1c7; +} + +button:focus { + box-shadow: 0 0 0 2px rgba(125, 174, 163, 0.35); +} + +button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +button:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +button:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +button:checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +button:checked:hover { + box-shadow: inset 0 0 0 9999px transparent; +} + +button:checked:disabled { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.1); + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +.raven .expander-button, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, .nautilus-window headerbar revealer > button, button.titlebutton:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, button.close, button.circular, .inline-toolbar button:not(.text-button) { + border-radius: 9999px; +} + +.raven .expander-button label, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle label, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat) label, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, .nautilus-window headerbar revealer > button label, button.titlebutton:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, button.close label, button.circular label, .inline-toolbar button:not(.text-button) label { + padding: 0; +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat, .gedit-document-panel row button.flat, .nautilus-window .floating-bar button, placessidebar.sidebar row button.sidebar-button, notebook > header tab button.flat, +notebook > header tab button.close-button, spinbutton.vertical button, spinbutton:not(.vertical) button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button, .drop-shadow button, .budgie-panel button, .budgie-popover row button, .budgie-settings-window buttonbox.inline-toolbar button, #mate-menu button, #MatePanelPopupWindow button, popover.messagepopover .popover-action-area button, tabbox > tab button, placessidebar.sidebar row button.sidebar-button, calendar.button, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular, treeview.view header button button.circular, row.activatable button.circular, notebook > header > tabs > arrow, modelbutton.flat, +.menuitem.button.flat, spinbutton.vertical button, spinbutton:not(.vertical) button, .nemo-window .toolbar button, #buttonbox_frame button, .xfce4-panel.background button, .raven stackswitcher.linked > button, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button, .lock-dialog button, .mate-panel-menu-bar button, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, layouttabbar button, filechooser #pathbarbox > stack > box > button, messagedialog .dialog-action-box button, +messagedialog .dialog-action-box .linked:not(.vertical) > button, .app-notification button, popover.background.menu button, +popover.background button.model, .nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action), button.flat { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: rgba(251, 241, 199, 0.7); +} + +.budgie-session-dialog .linked.horizontal > button:focus, +.budgie-polkit-dialog .linked.horizontal > button:focus, +.budgie-run-dialog .linked.horizontal > button:focus, .drop-shadow button:focus, .budgie-panel button:focus, .budgie-popover row button:focus, .budgie-settings-window buttonbox.inline-toolbar button:focus, #mate-menu button:focus, #MatePanelPopupWindow button:focus, popover.messagepopover .popover-action-area button:focus, tabbox > tab button:focus, placessidebar.sidebar row button.sidebar-button:focus, calendar.button:focus, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:focus, treeview.view header button button.circular:focus, row.activatable button.circular:focus, notebook > header > tabs > arrow:focus, modelbutton.flat:focus, +.menuitem.button.flat:focus, spinbutton.vertical button:focus, spinbutton:not(.vertical) button:focus, .nemo-window .toolbar button:focus, #buttonbox_frame button:focus, .xfce4-panel.background button:focus, .raven stackswitcher.linked > button:focus, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:focus, .lock-dialog button:focus, .mate-panel-menu-bar button:focus, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, layouttabbar button:focus, filechooser #pathbarbox > stack > box > button:focus, messagedialog .dialog-action-box button:focus, +messagedialog .dialog-action-box .linked:not(.vertical) > button:focus, .app-notification button:focus, popover.background.menu button:focus, +popover.background button.model:focus, .nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), button.flat:focus { + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + color: #fbf1c7; +} + +.budgie-session-dialog .linked.horizontal > button:hover, +.budgie-polkit-dialog .linked.horizontal > button:hover, +.budgie-run-dialog .linked.horizontal > button:hover, .drop-shadow button:hover, .budgie-panel button:hover, .budgie-popover row button:hover, .budgie-settings-window buttonbox.inline-toolbar button:hover, #mate-menu button:hover, #MatePanelPopupWindow button:hover, popover.messagepopover .popover-action-area button:hover, tabbox > tab button:hover, placessidebar.sidebar row button.sidebar-button:hover, calendar.button:hover, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:hover, treeview.view header button button.circular:hover, row.activatable button.circular:hover, notebook > header > tabs > arrow:hover, modelbutton.flat:hover, +.menuitem.button.flat:hover, spinbutton.vertical button:hover, spinbutton:not(.vertical) button:hover, .nemo-window .toolbar button:hover, #buttonbox_frame button:hover, .xfce4-panel.background button:hover, .raven stackswitcher.linked > button:hover, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:hover, .lock-dialog button:hover, .mate-panel-menu-bar button:hover, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, layouttabbar button:hover, filechooser #pathbarbox > stack > box > button:hover, messagedialog .dialog-action-box button:hover, +messagedialog .dialog-action-box .linked:not(.vertical) > button:hover, .app-notification button:hover, popover.background.menu button:hover, +popover.background button.model:hover, .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), button.flat:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #fbf1c7; +} + +.budgie-session-dialog .linked.horizontal > button:active, +.budgie-polkit-dialog .linked.horizontal > button:active, +.budgie-run-dialog .linked.horizontal > button:active, .drop-shadow button:active, .budgie-panel button:active, .budgie-popover row button:active, .budgie-settings-window buttonbox.inline-toolbar button:active, #mate-menu button:active, #MatePanelPopupWindow button:active, popover.messagepopover .popover-action-area button:active, tabbox > tab button:active, placessidebar.sidebar row button.sidebar-button:active, calendar.button:active, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:active, treeview.view header button button.circular:active, row.activatable button.circular:active, notebook > header > tabs > arrow:active, modelbutton.flat:active, +.menuitem.button.flat:active, spinbutton.vertical button:active, spinbutton:not(.vertical) button:active, .nemo-window .toolbar button:active, #buttonbox_frame button:active, .xfce4-panel.background button:active, .raven stackswitcher.linked > button:active, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:active, .lock-dialog button:active, .mate-panel-menu-bar button:active, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, layouttabbar button:active, filechooser #pathbarbox > stack > box > button:active, messagedialog .dialog-action-box button:active, +messagedialog .dialog-action-box .linked:not(.vertical) > button:active, .app-notification button:active, popover.background.menu button:active, +popover.background button.model:active, .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), button.flat:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #fbf1c7; +} + +.budgie-session-dialog .linked.horizontal > button:disabled, +.budgie-polkit-dialog .linked.horizontal > button:disabled, +.budgie-run-dialog .linked.horizontal > button:disabled, .drop-shadow button:disabled, .budgie-panel button:disabled, .budgie-popover row button:disabled, .budgie-settings-window buttonbox.inline-toolbar button:disabled, #mate-menu button:disabled, #MatePanelPopupWindow button:disabled, popover.messagepopover .popover-action-area button:disabled, tabbox > tab button:disabled, placessidebar.sidebar row button.sidebar-button:disabled, calendar.button:disabled, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:disabled, treeview.view header button button.circular:disabled, row.activatable button.circular:disabled, notebook > header > tabs > arrow:disabled, modelbutton.flat:disabled, +.menuitem.button.flat:disabled, spinbutton.vertical button:disabled, spinbutton:not(.vertical) button:disabled, .nemo-window .toolbar button:disabled, #buttonbox_frame button:disabled, .xfce4-panel.background button:disabled, .raven stackswitcher.linked > button:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:disabled, .lock-dialog button:disabled, .mate-panel-menu-bar button:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, layouttabbar button:disabled, filechooser #pathbarbox > stack > box > button:disabled, messagedialog .dialog-action-box button:disabled, +messagedialog .dialog-action-box .linked:not(.vertical) > button:disabled, .app-notification button:disabled, popover.background.menu button:disabled, +popover.background button.model:disabled, .nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action), button.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .toolbar button:checked, #buttonbox_frame button:checked, .xfce4-panel.background button:checked, .raven stackswitcher.linked > button:checked, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked, .lock-dialog button:checked, .mate-panel-menu-bar button:checked, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, layouttabbar button:checked, filechooser #pathbarbox > stack > box > button:checked, messagedialog .dialog-action-box button:checked, +messagedialog .dialog-action-box .linked:not(.vertical) > button:checked, .app-notification button:checked, popover.background.menu button:checked, +popover.background button.model:checked, .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action), button.flat:checked, button.flat:checked:hover { + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +.nemo-window .toolbar button:checked:disabled, #buttonbox_frame button:checked:disabled, .xfce4-panel.background button:checked:disabled, .raven stackswitcher.linked > button:checked:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked:disabled, .lock-dialog button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, layouttabbar button:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, messagedialog .dialog-action-box button:checked:disabled, .app-notification button:checked:disabled, popover.background.menu button:checked:disabled, +popover.background button.model:checked:disabled, .nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(251, 241, 199, 0.5); +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child) { + margin: 0 4px; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + border-radius: 12px; +} + +button.osd { + min-width: 24px; + min-width: 24px; + padding: 5px; + background-color: #282828; + color: #fbf1c7; +} + +button.osd:focus { + box-shadow: none; +} + +button.osd:hover { + background-color: #484640; + color: #fbf1c7; +} + +button.osd:active { + background-color: #5d5a50; + color: #fbf1c7; +} + +button.osd:disabled { + opacity: 0; +} + +button.osd.image-button, button.osd.circular { + padding: 11px; +} + +button.osd.image-button > image, button.osd.circular > image { + padding: 0; +} + +button.suggested-action { + background-color: #45707a; + color: #fbf1c7; + box-shadow: none; +} + +button.suggested-action:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(69, 112, 122, 0.2), 0 4px 3px 0 rgba(69, 112, 122, 0.14), 0 1px 6px 0 rgba(69, 112, 122, 0.12); +} + +button.suggested-action:checked { + background-color: #7c9791; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(69, 112, 122, 0.3), 0 2px 3px -1px rgba(69, 112, 122, 0.24), 0 2px 5px 0 rgba(69, 112, 122, 0.12); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(69, 112, 122, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #45707a; +} + +button.suggested-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +button.suggested-action.flat:checked { + background-color: rgba(69, 112, 122, 0.3); +} + +button.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; + box-shadow: none; +} + +button.destructive-action:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(193, 74, 74, 0.2), 0 4px 3px 0 rgba(193, 74, 74, 0.14), 0 1px 6px 0 rgba(193, 74, 74, 0.12); +} + +button.destructive-action:checked { + background-color: #d27c70; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(193, 74, 74, 0.3), 0 2px 3px -1px rgba(193, 74, 74, 0.24), 0 2px 5px 0 rgba(193, 74, 74, 0.12); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(193, 74, 74, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #c14a4a; +} + +button.destructive-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +button.destructive-action.flat:checked { + background-color: rgba(193, 74, 74, 0.3); +} + +.stack-switcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +.stack-switcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +.stack-switcher > button.needs-attention:checked > label, +.stack-switcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +.primary-toolbar button { + -gtk-icon-shadow: none; +} + +button.close, button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +stacksidebar.sidebar row.needs-attention > label, .stack-switcher > button.needs-attention > label, +.stack-switcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar.sidebar row.needs-attention > label:dir(rtl), .stack-switcher > button.needs-attention > label:dir(rtl), +.stack-switcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + +/********* + * Links * + *********/ +*:link, +link { + color: #83b193; +} + +*:visited { + color: #ab62b1; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #83b193; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #ab62b1; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton:not(.vertical) { + padding: 0; +} + +spinbutton:not(.vertical) entry { + min-width: 30px; + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +spinbutton:not(.vertical) button { + border: solid 6px transparent; +} + +spinbutton:not(.vertical) button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(251, 241, 199, 0.7); +} + +spinbutton:not(.vertical) button.up:dir(ltr), spinbutton:not(.vertical) button.down:dir(rtl) { + margin-left: -3px; +} + +spinbutton:not(.vertical) button.up:dir(rtl), spinbutton:not(.vertical) button.down:dir(ltr) { + margin-right: -3px; +} + +spinbutton.vertical { + padding: 0; +} + +spinbutton.vertical:disabled { + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.vertical entry { + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical button { + padding: 0; + border: solid 6px transparent; +} + +spinbutton.vertical button:focus:not(:hover):not(:active) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(251, 241, 199, 0.7); +} + +spinbutton.vertical button.up { + margin: 0 3px; +} + +spinbutton.vertical button.down { + margin: 0 3px; +} + +treeview spinbutton:not(.vertical) { + min-height: 0; + border-style: none; + border-radius: 0; +} + +treeview spinbutton:not(.vertical) entry { + min-height: 0; + padding: 1px 2px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-radius: 0 9px 9px 0; + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #e78a4e; + box-shadow: inset 0 0 0 2px #e78a4e; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #fbf1c7; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top), combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) { + background-color: transparent; + background-image: linear-gradient(to left, transparent 50%, rgba(251, 241, 199, 0.3) 50%); + padding-top: 1px; + background-size: 12px 1px; + background-repeat: repeat-x; + background-origin: content-box; + background-position: left top; + margin: 0 4px; +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +toolbar { + -gtkwidget-window-dragging: true; + padding: 2px 3px; + background-color: #282828; +} + +.osd toolbar { + background-color: transparent; +} + +frame.documents-dropdown, .app-notification, toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +frame.documents-dropdown:backdrop, .app-notification:backdrop, toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +frame.left.documents-dropdown, .left.app-notification, frame.right.documents-dropdown, .right.app-notification, frame.top.documents-dropdown, .top.app-notification, frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.left, toolbar.osd.right, toolbar.osd.top, toolbar.osd.bottom { + border-radius: 0; +} + +frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +toolbar.horizontal > separator { + margin: 2px; +} + +toolbar.vertical > separator { + margin: 2px; +} + +toolbar:not(.inline-toolbar):not(.osd) scale, +toolbar:not(.inline-toolbar):not(.osd) entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton, +toolbar:not(.inline-toolbar):not(.osd) button { + margin: 2px 1px; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:first-child) { + margin-left: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:last-child) { + margin-right: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) spinbutton entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton button { + margin: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) switch { + margin: 8px 2px; +} + +.toolbar { + background-color: #282524; +} + +frame .toolbar { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.inline-toolbar { + padding: 6px; + border-style: solid; + border-width: 0 1px 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +.frame .inline-toolbar { + border-width: 1px 0 0; + background-color: transparent; +} + +searchbar > revealer > box, +.location-bar { + padding: 6px; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282828; + background-clip: border-box; +} + +searchbar > revealer > box { + margin: -6px; +} + +/*************** + * Header bars * + ***************/ +.nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar .linked:not(.vertical) > button:not(.text-button), headerbar .linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + border-radius: 12px; +} + +.nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +.nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:not(.text-button), headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:focus:not(.text-button), headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:hover:not(.text-button), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:active:not(.text-button), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:disabled:not(.text-button), headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar button:backdrop:checked:not(.text-button), headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:checked:disabled:not(.text-button), headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar entry, .titlebar entry { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +.nemo-window .primary-toolbar entry:disabled, .titlebar entry:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar entry image, .titlebar entry image { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar entry image:hover, .titlebar entry image:hover, .nemo-window .primary-toolbar entry image:active, .titlebar entry image:active { + color: #fbf1c7; +} + +.nemo-window .primary-toolbar entry image:disabled, .titlebar entry image:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.titlebar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #282828; + color: #fbf1c7; + border-radius: 12px 12px 0 0; + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* @if $outline == 'false' { */ + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* } */ +} + +.titlebar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.titlebar:backdrop { + color: rgba(251, 241, 199, 0.7); +} + +.titlebar:backdrop:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.csd .titlebar:backdrop { + background-color: #282828; +} + +.titlebar .title { + padding: 0 12px; + font-weight: bold; +} + +.titlebar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +.titlebar .subtitle, +.titlebar .dim-label { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(251, 241, 199, 0.7); +} + +.titlebar .subtitle:backdrop, +.titlebar .dim-label:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +.titlebar .titlebar { + background-color: transparent; + box-shadow: none; +} + +.titlebar + separator, +.titlebar + separator.sidebar { + background-color: #282828; + background-image: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +.titlebar + separator:backdrop, +.titlebar + separator.sidebar:backdrop { + background-color: #282828; +} + +.titlebar.selection-mode + separator, .titlebar.selection-mode + separator.sidebar, .selection-mode .titlebar + separator, .selection-mode .titlebar + separator.sidebar { + background-color: #7daea3; +} + +.titlebar.selection-mode + separator:backdrop, .titlebar.selection-mode + separator.sidebar:backdrop, .selection-mode .titlebar + separator:backdrop, .selection-mode .titlebar + separator.sidebar:backdrop { + background-color: #7daea3; +} + +.background.csd.unified .titlebar + separator, .background.csd.unified .titlebar + separator.sidebar { + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.titlebar .linked:not(.vertical) > entry { + border-radius: 12px; + margin-left: 3px; + margin-right: 3px; +} + +.titlebar button.suggested-action:disabled, +.titlebar button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +.titlebar .path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; + padding-left: 5px; + padding-right: 5px; +} + +.titlebar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + animation: ripple-on-headerbar 225ms cubic-bezier(0, 0, 0.2, 1); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode:backdrop { + color: rgba(40, 40, 40, 0.6); + background-color: #90bab0; +} + +.titlebar.selection-mode .subtitle:link { + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):disabled { + color: rgba(40, 40, 40, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked { + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked:disabled { + color: rgba(40, 40, 40, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:not(.titlebutton) { + color: rgba(40, 40, 40, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:disabled { + color: rgba(40, 40, 40, 0.3); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked { + color: rgba(40, 40, 40, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked:disabled { + color: rgba(40, 40, 40, 0.3); +} + +.titlebar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +.titlebar.selection-mode .selection-menu arrow { + -gtkarrow-arrow-scaling: 1; +} + +.titlebar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +.tiled .titlebar, .tiled-top .titlebar, .tiled-right .titlebar, .tiled-bottom .titlebar, .tiled-left .titlebar, .maximized .titlebar, .fullscreen .titlebar { + border-radius: 0; +} + +.titlebar.default-decoration { + min-height: 24px; + padding: 6px 12px; + border-radius: 12px 12px 0 0; + border: none; + background-color: #282828; + background-image: none; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +.titlebar.default-decoration:backdrop { + background-color: #282828; +} + +.tiled .titlebar.default-decoration, .maximized .titlebar.default-decoration, .fullscreen .titlebar.default-decoration { + box-shadow: none; + border-radius: 0; +} + +.titlebar.default-decoration button.titlebutton { + min-height: 24px; + min-width: 24px; + margin: 0; + padding: 0; +} + +.background.csd .titlebar.default-decoration { + padding: 6px; + box-shadow: none; +} + +.background:not(.csd) .titlebar.default-decoration button.titlebutton:active { + background-size: 1000% 1000%; +} + +.solid-csd .titlebar:dir(rtl), .solid-csd .titlebar:dir(ltr) { + border-radius: 0; + box-shadow: none; +} + +headerbar { + min-height: 46px; + padding: 0 6px; +} + +box.vertical headerbar { + background-color: #282828; +} + +headerbar entry, +headerbar spinbutton, +headerbar button, +headerbar stackswitcher { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar button, +headerbar button.image-button { + border-radius: 12px; +} + +headerbar > box.left, +headerbar > box.right { + padding: 0 4px; +} + +headerbar separator.titlebutton, +headerbar separator.sidebar { + margin-top: 11.5px; + margin-bottom: 11.5px; + background-color: transparent; +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar spinbutton button { + margin-top: 0; + margin-bottom: 0; +} + +headerbar .entry-tag, headerbar .photos-entry-tag, headerbar .documents-entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar.windowhandle viewswitcher { + border-radius: 0 0 12px 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) { + border-radius: 9px; + margin: 6px 3px; + min-width: 120px; + padding: 0; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) > stack > box { + padding: 0 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +):focus { + box-shadow: none; +} + +headerbar.windowhandle > button.popup label, +headerbar.windowhandle > button.popup image { + min-height: 0; +} + +headerbar.windowhandle viewswitchertitle > squeezer { + margin-top: 0; + margin-bottom: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher { + margin: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher > box.horizontal > button.radio { + margin: 0; + padding: 0; + border-radius: 0; +} + +/************ + * Pathbars * + ************/ +.caja-pathbar button, +.path-bar.linked:not(.vertical) > button { + padding-left: 5px; + padding-right: 5px; + border-radius: 6px; + margin-left: 1px; + margin-right: 1px; + background-color: alpha(currentColor, 0.08); +} + +.caja-pathbar button:disabled, +.path-bar.linked:not(.vertical) > button:disabled { + background-color: alpha(currentColor, 0.05); +} + +.caja-pathbar button:first-child, +.path-bar.linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.caja-pathbar button:last-child, +.path-bar.linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.caja-pathbar button:checked, +.path-bar.linked:not(.vertical) > button:checked { + background-color: alpha(currentColor, 0.16); + color: #fbf1c7; +} + +.caja-pathbar button label, +.caja-pathbar button image, +.path-bar.linked:not(.vertical) > button label, +.path-bar.linked:not(.vertical) > button image { + margin-left: 3px; + margin-right: 3px; +} + +.caja-pathbar button.slider-button, +.path-bar.linked:not(.vertical) > button.slider-button { + padding-left: 4px; + padding-right: 4px; +} + +/************** + * Tree Views * + **************/ +treeview.view { + border-left-color: rgba(251, 241, 199, 0.12); + border-top-color: rgba(251, 241, 199, 0.12); +} + +* { + -gtktreeview-horizontal-separator: 4; + -gtktreeview-grid-line-width: 1; + -gtktreeview-grid-line-pattern: ''; + -gtktreeview-tree-line-width: 1; + -gtktreeview-tree-line-pattern: ''; + -gtktreeview-expander-size: 16; +} + +.csd +treeview.view:not(:selected):not(:hover):not(.progressbar):not(.expander):not( +.trough +):not(.separator) { + background-color: transparent; +} + +treeview.view.separator { + min-height: 6px; + color: rgba(251, 241, 199, 0.12); +} + +treeview.view:drop(active) { + border-style: solid none; + border-width: 9999px; + border-color: alpha(currentColor, 0.08); +} + +treeview.view:drop(active).after { + border-top-style: none; +} + +treeview.view:drop(active).before { + border-bottom-style: none; +} + +treeview.view.expander { + color: rgba(251, 241, 199, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); +} + +treeview.view.expander:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view.expander:checked { + -gtk-icon-transform: unset; +} + +treeview.view.expander:hover, treeview.view.expander:active { + color: #fbf1c7; +} + +treeview.view.expander:disabled { + color: rgba(251, 241, 199, 0.32); +} + +treeview.view.expander:selected { + color: rgba(40, 40, 40, 0.6); +} + +treeview.view.expander:selected:hover, treeview.view.expander:selected:active { + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.expander:selected:disabled { + color: rgba(40, 40, 40, 0.3); +} + +treeview.view.progressbar { + border: none; + box-shadow: none; + background-color: #7daea3; + background-image: none; + border-radius: 9999px; + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.progressbar:selected, treeview.view.progressbar:selected:hover, treeview.view.progressbar:selected:focus { + box-shadow: none; + background-color: #90b8a8; + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.progressbar:selected:backdrop, treeview.view.progressbar:selected:hover:backdrop, treeview.view.progressbar:selected:focus:backdrop { + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.progressbar:backdrop, treeview.view.progressbar:selected:backdrop { + background-color: rgba(251, 241, 199, 0.3); +} + +treeview.view.trough { + border: none; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); + background-image: none; + border-radius: 9999px; + padding: 0; + margin: 0; +} + +treeview.view.trough:selected, treeview.view.trough:selected:hover, treeview.view.trough:selected:focus { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); +} + +treeview.view.trough:backdrop, treeview.view.trough:selected:backdrop { + background-color: rgba(251, 241, 199, 0.12); +} + +treeview.view header button { + padding: 2px 6px; + border: none; + border-right: 1px solid transparent; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; + background-clip: border-box; + border-image: linear-gradient(to bottom, transparent 20%, rgba(251, 241, 199, 0.12) 20%, rgba(251, 241, 199, 0.12) 80%, transparent 80%) 0 1 0 0/0 1px 0 0 stretch; +} + +treeview.view header button:not(:focus):not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +treeview.view header button, treeview.view header button:disabled { + background-color: #282524; +} + +treeview.view header button:last-child { + border-right: none; + border-image: none; +} + +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #282524; + background-clip: border-box; + color: #7daea3; +} + +treeview.view acceleditor > label { + background-color: #7daea3; +} + +/********* + * Menus * + *********/ +menubar, +.menubar { + -gtkwidget-window-dragging: true; + padding: 0; + background-color: #282828; + color: #fbf1c7; + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +menubar:backdrop, +.menubar:backdrop { + color: rgba(251, 241, 199, 0.7); + background-color: #282828; +} + +.csd menubar, .csd .menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > menuitem, +.menubar > menuitem { + transition: none; + min-height: 20px; + padding: 4px 8px; + color: rgba(251, 241, 199, 0.7); + border-radius: 12px; +} + +menubar > menuitem:hover, +.menubar > menuitem:hover { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +menubar > menuitem:backdrop, +.menubar > menuitem:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +menubar > menuitem:disabled, +.menubar > menuitem:disabled { + color: rgba(251, 241, 199, 0.32); +} + +menubar > menuitem label:disabled, +.menubar > menuitem label:disabled { + color: inherit; +} + +menubar > menuitem > window.popup.background > menu menuitem, +.menubar > menuitem > window.popup.background > menu menuitem { + transition: none; +} + +.background.popup { + background-color: transparent; +} + +menu { + margin: 6px; + padding: 6px; + background-color: #141617; + background-clip: border-box; + border-radius: 12px; + border: 2px solid #7daea3; +} + +.csd menu { + border: none; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.1); +} + +menu menuitem { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + min-width: 40px; + padding: 4px 8px; + color: #fbf1c7; + font: initial; + text-shadow: none; + border-radius: 12px; +} + +menu menuitem:hover { + background-color: alpha(currentColor, 0.08); +} + +menu menuitem:active { + background-color: alpha(currentColor, 0.12); +} + +menu menuitem:disabled { + color: rgba(251, 241, 199, 0.5); +} + +menu menuitem accelerator { + color: rgba(251, 241, 199, 0.7); +} + +menu menuitem:disabled accelerator { + color: rgba(251, 241, 199, 0.32); +} + +menu menuitem arrow { + min-height: 16px; + min-width: 16px; +} + +menu menuitem arrow:dir(ltr) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + margin-left: 8px; +} + +menu menuitem arrow:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); + margin-right: 8px; +} + +menu menuitem label:dir(rtl), menu menuitem label:dir(ltr) { + color: inherit; +} + +menu .view:selected { + background-color: #3a3731; +} + +menu > arrow { + min-height: 16px; + min-width: 16px; + padding: 4px; + background-color: #242220; + color: rgba(251, 241, 199, 0.7); +} + +menu > arrow.top { + margin-top: 0; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menu > arrow.bottom { + margin-top: 8px; + margin-bottom: -12px; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menu > arrow:hover { + background-image: image(alpha(currentColor, 0.08)); + color: #fbf1c7; +} + +menu > arrow:disabled { + border-color: transparent; + background-color: transparent; + color: transparent; +} + +menu separator { + margin: 4px 0; +} + +/************ + * Popovers * + ************/ +popover.background { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 0; + background-color: #141617; + border-radius: 12px; +} + +popover.background, .csd popover.background { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +popover.background > stack { + margin: 0; +} + +popover.background > toolbar { + margin: 0; +} + +popover.background > list, +popover.background > .view, +popover.background > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover.background > scrolledwindow > viewport.frame > list { + background-color: transparent; + padding: 6px; +} + +popover.background > scrolledwindow > viewport.frame > list > row { + border-radius: 12px; + padding: 6px; +} + +popover.background .view:not(:selected), +popover.background toolbar { + background-color: #141617; +} + +popover.background button, +popover.background entry, +popover.background combobox { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio) { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):first-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):last-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.background.menu button, +popover.background button.model { + min-height: 32px; + padding: 0 8px; + border-radius: 12px; +} + +popover.background separator { + margin: 3px 0; + background-color: transparent; +} + +popover.background list separator { + margin: 0; +} + +modelbutton.flat, +.menuitem.button.flat { + min-height: 28px; + padding: 0 8px; + border-radius: 12px; + color: #fbf1c7; +} + +modelbutton.flat arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +modelbutton.flat arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +/************* + * Notebooks * + *************/ +tabbox > tab, notebook > header tab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + padding: 3px 12px; + border: none; + outline: none; + background-clip: padding-box; + color: rgba(251, 241, 199, 0.7); + font-weight: 500; + border-radius: 9px; +} + +tabbox > tab:hover, notebook > header tab:hover { + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +tabbox > tab:disabled, notebook > header tab:disabled { + color: rgba(251, 241, 199, 0.32); +} + +tabbox > tab:checked, notebook > header tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbox > tab:checked:disabled, notebook > header tab:checked:disabled { + color: rgba(251, 241, 199, 0.5); +} + +notebook { + background-color: rgba(251, 241, 199, 0.04); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: transparent; +} + +notebook.frame { + border-radius: 15px; +} + +notebook.frame scrolledwindow.frame { + border: none; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(251, 241, 199, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header tab > box:drop(active) { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +notebook > header tab button.flat:last-child, +notebook > header tab button.close-button:last-child { + margin-left: 6px; + margin-right: -6px; +} + +notebook > header tab button.flat:first-child, +notebook > header tab button.close-button:first-child { + margin-left: -6px; + margin-right: 6px; +} + +notebook > header.top tabs > tab + tab, notebook > header.bottom tabs > tab + tab { + margin-left: 3px; +} + +notebook > header.top tabs:not(:only-child):first-child, notebook > header.bottom tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top tabs:not(:only-child):last-child, notebook > header.bottom tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top tabs tab.reorderable-page, notebook > header.bottom tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left tabs > tab + tab, notebook > header.right tabs > tab + tab { + margin-top: 3px; +} + +notebook > header.left tabs:not(:only-child):first-child, notebook > header.right tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left tabs:not(:only-child):last-child, notebook > header.right tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left tabs tab.reorderable-page, notebook > header.right tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > button.image-button { + min-height: 24px; + min-width: 24px; + padding: 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); +} + +* { + -gtkscrollbar-has-backward-stepper: false; + -gtkscrollbar-has-forward-stepper: false; +} + +scrollbar, +scrollbar button { + border: none; + min-width: 0; + min-height: 0; + padding: 0; + border-radius: 0; + background-color: transparent; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 12px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(251, 241, 199, 0.5); +} + +scrollbar slider:hover { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar slider:active { + background-color: rgba(251, 241, 199, 0.7); +} + +scrollbar slider:disabled { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar.fine-tune slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.fine-tune.horizontal slider { + border-width: 5px 4px; +} + +scrollbar.fine-tune.vertical slider { + border-width: 4px 5px; +} + +scrollbar.overlay-indicator trough { + background-color: rgba(251, 241, 199, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal slider { + min-width: 40px; +} + +scrollbar.vertical slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border: none; + border-radius: 9999px; + background-color: rgba(251, 241, 199, 0.5); + background-clip: padding-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #7daea3; +} + +switch:disabled { + opacity: 0.5; +} + +switch slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #fbf1c7; + border: none; + color: transparent; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12); +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; +} + +checkbutton.text-button, +radiobutton.text-button { + padding: 2px; +} + +checkbutton.text-button label:not(:only-child), +radiobutton.text-button label:not(:only-child) { + margin: 0 4px; +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate), +actionbar > revealer > box radio:not(:checked):not(:indeterminate) { + background-color: rgba(40, 40, 40, 0.12); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):hover, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):hover { + box-shadow: 0 0 0 6px rgba(40, 40, 40, 0.04); + background-color: rgba(40, 40, 40, 0.15); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):active, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):active { + box-shadow: 0 0 0 6px rgba(40, 40, 40, 0.12); + background-color: rgba(40, 40, 40, 0.2); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):disabled, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):disabled { + background-color: rgba(40, 40, 40, 0.04); +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + color: transparent; + background-color: rgba(251, 241, 199, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.04); + background-color: rgba(251, 241, 199, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(251, 241, 199, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(40, 40, 40, 0.6); + background-color: #7daea3; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.15); + background-color: #9cc2b9; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.2); + background-color: #7daea3; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(40, 40, 40, 0.3); + background-color: rgba(125, 174, 163, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem radio { + transition: none; + margin: 0; + padding: 0; +} + +menu menuitem check:dir(ltr), menu menuitem radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +menu menuitem check:dir(rtl), menu menuitem radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem check:hover, menu menuitem check:disabled, menu menuitem check:checked:hover, menu menuitem check:indeterminate:hover, menu menuitem radio, menu menuitem radio:hover, menu menuitem radio:disabled, menu menuitem radio:checked:hover, menu menuitem radio:indeterminate:hover { + box-shadow: none; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic@2.svg"))); +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check, +menu menuitem check { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > checkbutton > check:checked, +menu menuitem check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check:indeterminate, +menu menuitem check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio, +menu menuitem radio { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > radiobutton > radio:checked, +menu menuitem radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio:indeterminate, +menu menuitem radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +check:not(:checked):indeterminate:active, +radio:not(:checked):indeterminate:active { + -gtk-icon-transform: scaleX(-1); +} + +treeview.view radio, +treeview.view check { + padding: 0; + margin: 0; + background-color: rgba(251, 241, 199, 0.12); +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view radio:selected:not(:disabled):not(:checked):not(:indeterminate), +treeview.view check:selected:not(:disabled):not(:checked):not(:indeterminate) { + background-color: rgba(40, 40, 40, 0.12); +} + +treeview.view radio:checked, treeview.view radio:indeterminate, +treeview.view check:checked, +treeview.view check:indeterminate { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + background-image: none; +} + +.view.content-view.check:not(list), +.content-view .tile check:not(list) { + min-height: 40px; + min-width: 40px; + margin: 0; + padding: 0; + border-radius: 9999px; +} + +.view.content-view.check:not(list):not(:checked), +.content-view .tile check:not(list):not(:checked) { + background-image: image(rgba(251, 241, 199, 0.25)); +} + +.view.content-view.check:not(list):hover, .view.content-view.check:not(list):checked, +.content-view .tile check:not(list):hover, +.content-view .tile check:not(list):checked { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1); +} + +.view.content-view.check:not(list):checked, +.content-view .tile check:not(list):checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale slider { + min-height: 18px; + min-width: 18px; + margin: -8px; +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune slider { + margin: -7px; +} + +scale trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(251, 241, 199, 0.3); +} + +scale trough:disabled { + background-color: rgba(251, 241, 199, 0.12); +} + +scale highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#7daea3); +} + +scale highlight:disabled { + background-color: #282828; + background-image: image(rgba(251, 241, 199, 0.32)); +} + +scale fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.3); +} + +scale fill:disabled { + background-color: transparent; +} + +scale slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #7daea3; + background-color: #282524; + box-shadow: inset 0 0 0 2px #7daea3; +} + +scale slider:hover { + box-shadow: inset 0 0 0 2px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale slider:active { + box-shadow: inset 0 0 0 4px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale slider:disabled { + box-shadow: inset 0 0 0 2px rgba(251, 241, 199, 0.32); +} + +scale marks, +scale value { + color: rgba(251, 241, 199, 0.7); +} + +scale indicator { + background-color: rgba(251, 241, 199, 0.3); + color: transparent; +} + +scale.horizontal marks.top { + margin-bottom: 7px; + margin-top: -15px; +} + +scale.horizontal.fine-tune marks.top { + margin-bottom: 6px; + margin-top: -14px; +} + +scale.horizontal marks.bottom { + margin-top: 7px; + margin-bottom: -15px; +} + +scale.horizontal.fine-tune marks.bottom { + margin-top: 6px; + margin-bottom: -14px; +} + +scale.vertical marks.top { + margin-right: 7px; + margin-left: -15px; +} + +scale.vertical.fine-tune marks.top { + margin-right: 6px; + margin-left: -14px; +} + +scale.vertical marks.bottom { + margin-left: 7px; + margin-right: -15px; +} + +scale.vertical.fine-tune marks.bottom { + margin-left: 6px; + margin-right: -14px; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.horizontal.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-before:not(.marks-after) slider, scale.horizontal.marks-before:not(.marks-after) slider:hover, scale.horizontal.marks-before:not(.marks-after) slider:active, scale.horizontal.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-disabled-dark.svg"), url("assets/scale-horz-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-after:not(.marks-before) slider, scale.horizontal.marks-after:not(.marks-before) slider:hover, scale.horizontal.marks-after:not(.marks-before) slider:active, scale.horizontal.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-disabled-dark.svg"), url("assets/scale-horz-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-before:not(.marks-after) slider, scale.vertical.marks-before:not(.marks-after) slider:hover, scale.vertical.marks-before:not(.marks-after) slider:active, scale.vertical.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-disabled-dark.svg"), url("assets/scale-vert-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-after:not(.marks-before) slider, scale.vertical.marks-after:not(.marks-before) slider:hover, scale.vertical.marks-after:not(.marks-before) slider:active, scale.vertical.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-disabled-dark.svg"), url("assets/scale-vert-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal slider:dir(ltr), scale.color.horizontal slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(251, 241, 199, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #7daea3; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #7daea3; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #b47109; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #7daea3; +} + +levelbar block.full { + background-color: #6c782e; +} + +levelbar block.empty { + background-color: rgba(251, 241, 199, 0.12); +} + +/**************** + * Print dialog * +*****************/ +printdialog paper { + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; + color: #fbf1c7; +} + +printdialog .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame > border, .frame { + margin: 0; + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0; + box-shadow: none; +} + +.frame.view { + border-radius: 12px; +} + +.frame.flat { + border-style: none; +} + +frame.flat > border, frame > border.flat, statusbar frame > border { + border: none; +} + +actionbar > revealer > box { + margin: 6px 0 0 0; + padding: 6px; + border: none; + color: #fbf1c7; + background-color: #282828; + border-radius: 0 0 12px 12px; +} + +actionbar > revealer > box button { + border-radius: 6px; +} + +actionbar > revealer > box button.combo:only-child { + border-radius: 6px; + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); +} + +actionbar > revealer > box button.combo:only-child:hover, actionbar > revealer > box button.combo:only-child:active { + color: #7daea3; +} + +actionbar > revealer > box button.combo:only-child:disabled { + color: #7daea3; +} + +actionbar > revealer > box stackswitcher { + background-color: rgba(40, 40, 40, 0.04); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + color: rgba(40, 40, 40, 0.6); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover, actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: rgba(40, 40, 40, 0.87); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + background-color: #282524; + color: #fbf1c7; +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked:hover { + background-color: #282524; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +overshoot.top { + background-image: -gtk-gradient(radial, center top, 0, center top, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, center top, 0, center top, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center top; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.bottom { + background-image: -gtk-gradient(radial, center bottom, 0, center bottom, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, center bottom, 0, center bottom, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.left { + background-image: -gtk-gradient(radial, left center, 0, left center, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, left center, 0, left center, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: left center; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.right { + background-image: -gtk-gradient(radial, right center, 0, right center, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, right center, 0, right center, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: right center; + background-color: transparent; + border: none; + box-shadow: none; +} + +junction { + border-style: solid none none solid; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +junction:dir(rtl) { + border-style: solid solid none none; +} + +separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +preferences stacksidebar.sidebar list separator, placessidebar.sidebar list > separator, stacksidebar.sidebar + separator.vertical, +stacksidebar.sidebar separator.horizontal, button.font separator, button.file separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +/********* + * Lists * + *********/ +window.background.csd stack stack stack frame > list, +window.background.csd > stack > stack > box > frame > list, +window.background.csd > stack > stack > box > box > frame > list, +window.background.csd > stack > box > stack > box > frame > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > list, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list, window.background.csd > stack > list, +window.background.csd > stack > scrolledwindow > viewport > box > list, +window.background.csd > box > stack > scrolledwindow > viewport > box > list, preferencesgroup list, +.geary-accounts-editor-pane list, window.background.csd.unified > deck > deck > deck list, hdyleaflet list.view, +hdyleaflet list.frame, +leaflet list.view, +leaflet list.frame, +box.horizontal > stack.background list.view, +box.horizontal > stack.background list.frame, hdyleaflet stack.background scrolledwindow > viewport list, +hdyleaflet overlay scrolledwindow > viewport list, +leaflet stack.background scrolledwindow > viewport list, +leaflet overlay scrolledwindow > viewport list, +box.horizontal > stack.background stack.background scrolledwindow > viewport list, +box.horizontal > stack.background overlay scrolledwindow > viewport list, hdyleaflet frame:not(.view) list:not(.contacts-contact-list), +leaflet frame:not(.view) list:not(.contacts-contact-list), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list), list.tweak-group list, list.content:not(.conversation-listbox) { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.csd stack stack stack frame > list > separator, +window.background.csd > stack > stack > box > frame > list > separator, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list > separator, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list > separator, window.background.csd > stack > list > separator, +window.background.csd > stack > scrolledwindow > viewport > box > list > separator, preferencesgroup list > separator, +.geary-accounts-editor-pane list > separator, window.background.csd.unified > deck > deck > deck list > separator, hdyleaflet list.view > separator, +hdyleaflet list.frame > separator, +leaflet list.view > separator, +leaflet list.frame > separator, +box.horizontal > stack.background list.view > separator, +box.horizontal > stack.background list.frame > separator, hdyleaflet stack.background scrolledwindow > viewport list > separator, +hdyleaflet overlay scrolledwindow > viewport list > separator, +leaflet stack.background scrolledwindow > viewport list > separator, +leaflet overlay scrolledwindow > viewport list > separator, +box.horizontal > stack.background stack.background scrolledwindow > viewport list > separator, +box.horizontal > stack.background overlay scrolledwindow > viewport list > separator, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +leaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) > separator, list.tweak-group list > separator, list.content:not(.conversation-listbox) > separator { + background: none; + min-height: 0; +} + +window.background.csd stack stack stack frame > list row, +window.background.csd > stack > stack > box > frame > list row, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list row, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list row, window.background.csd > stack > list row, +window.background.csd > stack > scrolledwindow > viewport > box > list row, preferencesgroup list row, +.geary-accounts-editor-pane list row, window.background.csd.unified > deck > deck > deck list row, hdyleaflet list.view row, +hdyleaflet list.frame row, +leaflet list.view row, +leaflet list.frame row, +box.horizontal > stack.background list.view row, +box.horizontal > stack.background list.frame row, hdyleaflet stack.background scrolledwindow > viewport list row, +hdyleaflet overlay scrolledwindow > viewport list row, +leaflet stack.background scrolledwindow > viewport list row, +leaflet overlay scrolledwindow > viewport list row, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row, +box.horizontal > stack.background overlay scrolledwindow > viewport list row, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row, +leaflet frame:not(.view) list:not(.contacts-contact-list) row, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row, list.tweak-group list > row, list.content:not(.conversation-listbox) > row { + border-radius: 0; +} + +window.background.csd stack stack stack frame > list row:not(:first-child), window.background.csd > stack > list row:not(:first-child), preferencesgroup list row:not(:first-child), +.geary-accounts-editor-pane list row:not(:first-child), window.background.csd.unified > deck > deck > deck list row:not(:first-child), hdyleaflet list.view row:not(:first-child), +hdyleaflet list.frame row:not(:first-child), +leaflet list.view row:not(:first-child), +leaflet list.frame row:not(:first-child), +box.horizontal > stack.background list.view row:not(:first-child), +box.horizontal > stack.background list.frame row:not(:first-child), hdyleaflet stack.background scrolledwindow > viewport list row:not(:first-child), +hdyleaflet overlay scrolledwindow > viewport list row:not(:first-child), +leaflet stack.background scrolledwindow > viewport list row:not(:first-child), +leaflet overlay scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background overlay scrolledwindow > viewport list row:not(:first-child), hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +leaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), list.tweak-group list > row:not(:first-child), list.content:not(.conversation-listbox) > row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +window.background.csd stack stack stack frame > list row:first-child, window.background.csd > stack > list row:first-child, preferencesgroup list row:first-child, +.geary-accounts-editor-pane list row:first-child, window.background.csd.unified > deck > deck > deck list row:first-child, hdyleaflet list.view row:first-child, +hdyleaflet list.frame row:first-child, +leaflet list.view row:first-child, +leaflet list.frame row:first-child, +box.horizontal > stack.background list.view row:first-child, +box.horizontal > stack.background list.frame row:first-child, hdyleaflet stack.background scrolledwindow > viewport list row:first-child, +hdyleaflet overlay scrolledwindow > viewport list row:first-child, +leaflet stack.background scrolledwindow > viewport list row:first-child, +leaflet overlay scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:first-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:first-child, list.tweak-group list > row:first-child, list.content:not(.conversation-listbox) > row:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:last-child, window.background.csd > stack > list row:last-child, preferencesgroup list row:last-child, +.geary-accounts-editor-pane list row:last-child, window.background.csd.unified > deck > deck > deck list row:last-child, hdyleaflet list.view row:last-child, +hdyleaflet list.frame row:last-child, +leaflet list.view row:last-child, +leaflet list.frame row:last-child, +box.horizontal > stack.background list.view row:last-child, +box.horizontal > stack.background list.frame row:last-child, hdyleaflet stack.background scrolledwindow > viewport list row:last-child, +hdyleaflet overlay scrolledwindow > viewport list row:last-child, +leaflet stack.background scrolledwindow > viewport list row:last-child, +leaflet overlay scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:last-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:last-child, list.tweak-group list > row:last-child, list.content:not(.conversation-listbox) > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:only-child, window.background.csd > stack > list row:only-child, preferencesgroup list row:only-child, +.geary-accounts-editor-pane list row:only-child, window.background.csd.unified > deck > deck > deck list row:only-child, hdyleaflet list.view row:only-child, +hdyleaflet list.frame row:only-child, +leaflet list.view row:only-child, +leaflet list.frame row:only-child, +box.horizontal > stack.background list.view row:only-child, +box.horizontal > stack.background list.frame row:only-child, hdyleaflet stack.background scrolledwindow > viewport list row:only-child, +hdyleaflet overlay scrolledwindow > viewport list row:only-child, +leaflet stack.background scrolledwindow > viewport list row:only-child, +leaflet overlay scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:only-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:only-child, list.tweak-group list > row:only-child, list.content:not(.conversation-listbox) > row:only-child { + border-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:focus, window.background.csd > stack > list row:focus, preferencesgroup list row:focus, +.geary-accounts-editor-pane list row:focus, window.background.csd.unified > deck > deck > deck list row:focus, hdyleaflet list.view row:focus, +hdyleaflet list.frame row:focus, +leaflet list.view row:focus, +leaflet list.frame row:focus, +box.horizontal > stack.background list.view row:focus, +box.horizontal > stack.background list.frame row:focus, hdyleaflet stack.background scrolledwindow > viewport list row:focus, +hdyleaflet overlay scrolledwindow > viewport list row:focus, +leaflet stack.background scrolledwindow > viewport list row:focus, +leaflet overlay scrolledwindow > viewport list row:focus, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:focus, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:focus, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:focus, list.tweak-group list > row:focus, list.content:not(.conversation-listbox) > row:focus { + box-shadow: inset 0 0 0 1000px alpha(currentColor, 0.05); +} + +list { + border-color: rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); +} + +list row { + padding: 6px; + background-clip: padding-box; +} + +list.navigation-sidebar { + padding: 3px; +} + +list.navigation-sidebar > row { + border-radius: 12px; +} + +paned scrolledwindow > viewport.frame > list { + background-color: transparent; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable, treeview.view header button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:focus, treeview.view header button:focus, row.activatable:focus { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:hover, treeview.view header button:hover, row.activatable:hover { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.has-open-popup.activatable, treeview.view header button.has-open-popup, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:active, treeview.view header button:active, row.activatable.has-open-popup, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; +} + +row:selected { + color: inherit; + background-color: alpha(currentColor, 0.06); +} + +row:selected image, +row:selected label { + color: #fbf1c7; +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled image, +row:selected:disabled label { + color: rgba(251, 241, 199, 0.5); +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 8px; + padding: 6px 15px; +} + +.app-notification button.flat:last-child { + margin-right: -9px; +} + +.app-notification button.text-button:not(:disabled) { + color: #7daea3; +} + +.app-notification.frame, +.app-notification border { + border-style: none; +} + +/************* + * Expanders * + *************/ +expander title > arrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); + color: rgba(251, 241, 199, 0.7); +} + +expander title > arrow:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +expander title > arrow:checked { + -gtk-icon-transform: unset; +} + +expander title > arrow:hover, expander title > arrow:active { + color: #fbf1c7; +} + +expander title > arrow:disabled { + color: rgba(251, 241, 199, 0.32); +} + +/************ + * Calendar * + ************/ +calendar { + padding: 1px; + border: 1px solid rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +calendar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +calendar:selected { + border-radius: 13px; +} + +calendar.header { + border-style: none none solid; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; +} + +calendar.highlight { + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +calendar:indeterminate { + color: rgba(251, 241, 199, 0.32); +} + +/*********** + * Dialogs * + ***********/ +messagedialog.background { + background-color: #282828; +} + +messagedialog.background .titlebar { + min-height: 12px; +} + +messagedialog.background .titlebar, messagedialog.background .titlebar:backdrop { + background-color: #282828; +} + +messagedialog.background.csd { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +messagedialog .titlebar, messagedialog.background.csd .titlebar { + border: none; + /* box-shadow: inset 0 1px highlight($surface); */ +} + +messagedialog .dialog-action-box { + margin-top: -6px; +} + +messagedialog .dialog-action-box button, messagedialog .dialog-action-box button:first-child, messagedialog .dialog-action-box button:last-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button, +messagedialog .dialog-action-box .linked:not(.vertical) > button:first-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button:last-child { + border-radius: 12px; +} + +messagedialog .dialog-action-box button:not(:last-child), +messagedialog .dialog-action-box .linked:not(.vertical) > button:not(:last-child) { + margin-right: 6px; +} + +messagedialog .dialog-action-box button.suggested-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.suggested-action:not(:disabled) { + color: #45707a; +} + +messagedialog .dialog-action-box button.destructive-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.destructive-action:not(:disabled) { + color: #c14a4a; +} + +.csd filechooser { + background-color: #282828; + border-radius: 0 0 12px 12px; +} + +filechooser .dialog-action-box { + border-top: 1px solid transparent; +} + +filechooser treeview.view header > button { + background-color: #0f0e0e; +} + +filechooser #pathbarbox { + background-color: #0f0e0e; + border-radius: 12px 12px 0 0; + margin: 0 4px; +} + +filechooser stack.view { + background-color: transparent; + padding: 0 4px; +} + +filechooser stack.view scrolledwindow { + background-color: #0f0e0e; + border-radius: 0 0 12px 12px; +} + +filechooser stack.view scrolledwindow list { + background-color: transparent; +} + +filechooser stack.view > placesview { + background-color: transparent; + padding: 4px; +} + +filechooser stack.view frame > border { + border: none; +} + +.csd filechooser placessidebar { + background: none; + border-bottom-left-radius: 12px; +} + +filechooser paned > separator { + background: none; +} + +filechooser paned box.vertical { + background-color: #0f0e0e; + border-radius: 12px; + margin: 0 6px 0 1px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; +} + +stacksidebar.sidebar:dir(ltr) list, stacksidebar.sidebar.left list, stacksidebar.sidebar.left:dir(rtl) list, .sidebar:not(separator):dir(ltr), .sidebar:not(separator).left { + border-right: 1px solid rgba(251, 241, 199, 0.12); + border-left-style: none; +} + +stacksidebar.sidebar:dir(rtl) list, stacksidebar.sidebar.right list, .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { + border-left: 1px solid rgba(251, 241, 199, 0.12); + border-right-style: none; +} + +.sidebar list { + background-color: transparent; +} + +paned .sidebar.left, paned .sidebar.right, paned .sidebar.left:dir(rtl), paned .sidebar:dir(rtl), paned .sidebar:dir(ltr), paned .sidebar { + border-style: none; +} + +stacksidebar.sidebar list { + padding: 3px; + background-color: #282524; +} + +stacksidebar.sidebar row { + min-height: 34px; + padding: 0 3px; + border-radius: 12px; +} + +stacksidebar.sidebar row + row { + margin-top: 3px; +} + +stacksidebar.sidebar row:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + font-weight: 500; +} + +stacksidebar.sidebar row:selected label, +stacksidebar.sidebar row:selected image { + color: rgba(40, 40, 40, 0.87); +} + +stacksidebar.sidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +/**************** + * File chooser * + ****************/ +placessidebar.sidebar { + margin: 0 0 0 4px; + padding: 0; +} + +placessidebar.sidebar > viewport.frame { + border-style: none; +} + +placessidebar.sidebar list { + background-color: transparent; + color: #fbf1c7; +} + +placessidebar.sidebar row { + min-height: 32px; + margin: 0; + padding: 0; + color: #fbf1c7; + border-radius: 6px; +} + +placessidebar.sidebar row:hover, placessidebar.sidebar row:active { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #7daea3; +} + +placessidebar.sidebar row > revealer { + padding: 0 8px 0 16px; +} + +placessidebar.sidebar row:selected { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #7daea3; + font-weight: 500; +} + +placessidebar.sidebar row:disabled { + color: rgba(40, 40, 40, 0.3); +} + +placessidebar.sidebar row image.sidebar-icon { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar.sidebar row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar.sidebar row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar.sidebar row label.sidebar-label { + color: inherit; +} + +placessidebar.sidebar row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar.sidebar row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar.sidebar row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar.sidebar row.sidebar-new-bookmark-row { + color: #7daea3; +} + +placessidebar.sidebar row.sidebar-new-bookmark-row image.sidebar-icon { + color: #7daea3; +} + +placessidebar.sidebar row:drop(active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + padding-left: 8px; + padding-right: 8px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(rgba(251, 241, 199, 0.12)); + background-size: 1px 1px; + background-clip: content-box; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #282828; + background-image: image(rgba(251, 241, 199, 0.12)), image(rgba(251, 241, 199, 0.12)); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************** + * GtkInfoBar * + **************/ +infobar { + border: none; + margin-bottom: 0; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #282524; +} + +infobar.info > revealer > box, +infobar.info > revealer > box link:link, +infobar.info > revealer > box flowboxchild, infobar.info:hover > revealer > box, +infobar.info:hover > revealer > box link:link, +infobar.info:hover > revealer > box flowboxchild, infobar.info:backdrop > revealer > box, +infobar.info:backdrop > revealer > box link:link, +infobar.info:backdrop > revealer > box flowboxchild { + color: #7daea3; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #7daea3; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #7daea3; +} + +infobar.action > revealer > box, +infobar.action > revealer > box link:link, +infobar.action > revealer > box flowboxchild, infobar.action:backdrop > revealer > box, +infobar.action:backdrop > revealer > box link:link, +infobar.action:backdrop > revealer > box flowboxchild, infobar.question > revealer > box, +infobar.question > revealer > box link:link, +infobar.question > revealer > box flowboxchild, infobar.question:backdrop > revealer > box, +infobar.question:backdrop > revealer > box link:link, +infobar.question:backdrop > revealer > box flowboxchild { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #6da498; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #b47109; +} + +infobar.warning > revealer > box, +infobar.warning > revealer > box link:link, +infobar.warning > revealer > box flowboxchild, infobar.warning:backdrop > revealer > box, +infobar.warning:backdrop > revealer > box link:link, +infobar.warning:backdrop > revealer > box flowboxchild { + color: #fbf1c7; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.warning:hover > revealer > box { + background-color: #9c6208; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #c14a4a; + color: #fbf1c7; +} + +infobar.error > revealer > box, +infobar.error > revealer > box link:link, +infobar.error > revealer > box flowboxchild, infobar.error:backdrop > revealer > box, +infobar.error:backdrop > revealer > box link:link, +infobar.error:backdrop > revealer > box flowboxchild { + color: #fbf1c7; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.error:hover > revealer > box { + background-color: #b43e3e; +} + +/************ + * Tooltips * + ************/ +tooltip { + box-shadow: none; +} + +tooltip.background { + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; + border-radius: 12px; +} + +tooltip.background.csd { + border-radius: 12px; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +tooltip decoration { + background-color: transparent; +} + +tooltip > box { + margin: -6px; + min-height: 24px; + padding: 4px 8px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #fbf1c7; +} + +colorswatch.light { + color: rgba(40, 40, 40, 0.87); +} + +colorswatch overlay { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +colorswatch overlay:hover { + box-shadow: 0 0 0 2px #7daea3; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(251, 241, 199, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(251, 241, 199, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #282828; +} + +/********************** + * Window Decorations * + **********************/ +decoration { + transition: none; + /* border-radius: $window-radius; */ + border-radius: 12px 12px 0 0; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; + margin: 10px; +} + +decoration:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +.tiled decoration, .tiled-top decoration, .tiled-right decoration, .tiled-bottom decoration, .tiled-left decoration { + border-radius: 0; +} + +.maximized decoration, .fullscreen decoration { + border-radius: 0; + box-shadow: none; +} + +.popup decoration { + box-shadow: none; + border: none; +} + +.ssd decoration { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #7daea3; +} + +.ssd decoration:backdrop { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #242220; +} + +.metacity decoration { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border: none; +} + +.csd.popup decoration { + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3; +} + +tooltip.csd decoration { + border-radius: 12px; + box-shadow: none; + border: none; +} + +messagedialog.background.csd decoration { + border-radius: 12px; + border: 1px solid rgba(251, 241, 199, 0.1); + background-color: #242220; + background-clip: border-box; +} + +.solid-csd decoration { + margin: 0; + padding: 2px; + border-radius: 0; + box-shadow: none; + background-color: #282828; + border: 1px solid #423f3e; +} + +.solid-csd decoration:backdrop { + background-color: #282828; +} + +button.titlebutton:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + /* min-height: 22px; */ + /* min-width: 22px; */ + padding: 0; + margin: 0 0px; +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:not(.suggested-action):not(.destructive-action), button.close.titlebutton:not(.suggested-action):not(.destructive-action) { + background-color: rgba(251, 241, 199, 0.12); + color: rgba(251, 241, 199, 0.7); +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.maximize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.close.titlebutton:not(.suggested-action):not(.destructive-action) image { + padding: 0; + background: none; + box-shadow: none; +} + +button.minimize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; + background-color: alpha(currentColor, 0.15); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), inset 0 1px rgba(251, 241, 199, 0.1); +} + +button.minimize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.close.titlebutton:active:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; + background-color: alpha(currentColor, 0.2); +} + +button.minimize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +button.minimize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; + background-color: alpha(currentColor, 0.15); +} + +.monospace { + font-family: monospace; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #7daea3; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.top:dir(ltr), cursor-handle.bottom:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +cursor-handle.bottom:dir(ltr), cursor-handle.top:dir(rtl) { + -gtk-icon-transform: unset; +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; + -gtk-icon-transform: rotate(45deg); +} + +.context-menu { + font: initial; +} + +.keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(251, 241, 199, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(251, 241, 199, 0.12); + background-color: #242220; + color: #fbf1c7; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #7daea3; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) + button { + margin-left: 3px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker.background entry { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +popover.emoji-picker.background entry:focus { + border-bottom: 1px solid #7daea3; + box-shadow: inset 0 -1px #7daea3; + background-color: transparent; +} + +popover.emoji-picker scrolledwindow { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +button.emoji-section { + margin: 4px; +} + +button.emoji-section:checked { + color: #7daea3; +} + +button.emoji-section:not(:last-child) { + margin-right: 0; +} + +popover.emoji-picker .emoji { + min-width: 3em; + min-height: 3em; + padding: 0 8px; +} + +popover.emoji-picker .emoji widget { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker .emoji widget:hover { + background-color: alpha(currentColor, 0.08); +} + +popover.emoji-completion { + padding: 8px 0; +} + +popover.emoji-completion arrow { + border: none; + background: none; +} + +popover.emoji-completion .emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +popover.emoji-completion .emoji:hover { + background-color: alpha(currentColor, 0.08); +} + +/************ + * Nautilus * + ************/ +.nautilus-window.background.csd { + border-radius: 0 0 12px 12px; + background-color: #282524; +} + +.nautilus-window.background.csd:backdrop { + background-color: #282524; +} + +.nautilus-window.background.csd > grid.horizontal > paned.horizontal > separator, +.nautilus-window.background.csd > deck > box.vertical > paned.horizontal > separator { + margin-left: 0; +} + +.nautilus-window.background.csd placessidebar > viewport.frame > list > separator { + background: none; +} + +.nautilus-window.background.csd.unified notebook { + border-radius: 0; +} + +.nautilus-window.background.csd:not(.unified) .nautilus-list-view { + background-color: transparent; + border-bottom-right-radius: 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook { + background-color: #282524; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook > stack { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook scrolledwindow +> .view:not(:selected):not(:hover):not(:checked) { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > stack > frame > scrolledwindow > viewport > list { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar { + background-color: transparent; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar > revealer > box { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) paned > separator.wide { + min-width: 12px; + box-shadow: 12px 0 #282524; + background-color: #282524; + background-image: image(#423f3e); +} + +.nautilus-window.maximized, +.nautilus-window.maximized placessidebar { + border-radius: 0; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border: none; + border-radius: 12px; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(40, 40, 40, 0.87); +} + +.nautilus-canvas-item.dim-label, +.nautilus-list-dim-label { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-desktop.nemo-canvas-item, .caja-desktop.caja-canvas-item, +.nautilus-desktop.nautilus-canvas-item { + color: #fbf1c7; +} + +@keyframes nautilus-operations-button-needs-attention { + to { + background-color: alpha(currentColor, 0.08); + } +} + +.nautilus-operations-button-needs-attention { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 2 alternate; +} + +.nautilus-operations-button-needs-attention-multiple { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 6 alternate; +} + +.path-bar-box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border-radius: 12px; +} + +.path-bar-box button { + margin: 0; +} + +.path-bar-box.width-maximized { + background-color: rgba(251, 241, 199, 0.04); +} + +.path-bar-box.background.frame { + border-style: none; + background-color: rgba(251, 241, 199, 0.04); +} + +.path-bar-box .path-bar button label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .path-bar button label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) { + padding-left: 11px; + padding-right: 11px; + margin-left: 1px; + margin-right: 1px; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button.image-button image:not(:only-child) { + margin: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr), .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl) { + background-color: rgba(251, 241, 199, 0.08); +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr):disabled, .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl):disabled { + background-color: transparent; + color: rgba(251, 241, 199, 0.5); +} + +.windowhandle .linked.nautilus-path-bar { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action) { + margin-top: 0; + margin-bottom: 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir { + color: #fbf1c7; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:hover, .windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:active { + background: none; + box-shadow: none; +} + +.disk-space-display.unknown { + background-color: rgba(251, 241, 199, 0.3); + color: rgba(251, 241, 199, 0.3); +} + +.disk-space-display.used { + background-color: #7daea3; + color: #7daea3; +} + +.disk-space-display.free { + background-color: rgba(251, 241, 199, 0.12); + color: rgba(251, 241, 199, 0.12); +} + +.search-information { + padding: 2px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; + color: #fbf1c7; +} + +.conflict-row:not(:selected) { + background-color: #523c1c; +} + +.nautilus-window flowboxchild .icon-item-background { + padding: 4px; + border-radius: 6px; +} + +.nautilus-window flowboxchild:selected { + background-color: transparent; +} + +.nautilus-window notebook :not(treeview).view { + border-radius: 6px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > scrolledwindow.frame { + border-style: none; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child { + margin: -6px 0 0 -6px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > label { + margin: 0 8px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > box > button { + border-radius: 0; +} + +.nautilus-window > popover.menu:not(:last-child) { + padding: 3px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box { + margin-top: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box { + margin-bottom: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box.linked { + margin-top: 1px; +} + +.nautilus-window > popover.menu:not(:last-child) separator { + margin-bottom: -2px; +} + +.nautilus-menu-sort-heading { + margin: 1px 3px; + font-weight: 500; +} + +.nautilus-menu-sort-heading:disabled { + color: rgba(251, 241, 199, 0.7); +} + +.nautilus-window paned > separator { + background-color: #282524; +} + +/********* + * gedit * + *********/ +window.org-gnome-gedit > paned.titlebar > separator { + background-color: transparent; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > box.horizontal { + margin: 4px 0; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > scrolledwindow { + border-bottom-left-radius: 12px; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned stack scrolledwindow viewport.frame list.gedit-document-panel { + background: none; +} + +.open-document-selector-path-label { + color: rgba(251, 241, 199, 0.7); + font-size: smaller; +} + +.open-document-selector-match { + background-color: #b47109; + color: #fbf1c7; +} + +.gedit-document-panel { + background-color: #282524; +} + +.gedit-document-panel row button.flat { + margin-top: 8px; + margin-bottom: 8px; +} + +.gedit-document-panel-group-row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.gedit-side-panel-paned statusbar { + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0 0 12px 12px; +} + +.gedit-search-slider { + margin: 0 6px 10px; + padding: 6px; + background-color: #242220; + border-radius: 0 0 12px 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05), 0 0 0 2px #fbf1c7; +} + +.gedit-search-slider .linked:not(.vertical) > entry .gedit-search-entry-occurrences-tag { + all: unset; + color: rgba(251, 241, 199, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) .gedit-search-entry-occurrences-tag { + margin-left: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) image.right { + margin-right: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) .gedit-search-entry-occurrences-tag { + margin-right: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) image.left { + margin-left: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:not(.error) { + background-color: #242220; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button { + color: rgba(251, 241, 199, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:hover, .gedit-search-slider .linked:not(.vertical) > entry.error ~ button:active { + color: #fbf1c7; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +frame.gedit-map-frame > border:dir(ltr) { + border-style: none none none solid; +} + +frame.gedit-map-frame > border:dir(rtl) { + border-style: none solid none none; +} + +/********** + * Tweaks * + **********/ +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame { + background-color: #282828; + color: #fbf1c7; + border-radius: 12px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + background-color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:hover { + background-color: rgba(40, 40, 40, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:active { + background-color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:disabled { + background-color: rgba(40, 40, 40, 0.3); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(40, 40, 40, 0.3); +} + +leaflet.unfolded > box.vertical:last-child > scrolledwindow > viewport.frame, +leaflet.unfolded > box.vertical:last-child > stack > scrolledwindow > viewport.frame { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + padding: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > separator { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row { + padding: 0; + margin: -1px; + color: #fbf1c7; + border-radius: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:active, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:focus { + color: #fbf1c7; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected { + font-weight: 500; + background-color: rgba(251, 241, 199, 0.04); + border-radius: 9px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected label, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected image { + color: #7daea3; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:focus { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row + row { + margin-top: 3px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + border: none; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar trough { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + border: 4px solid transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + border: none; + margin: 1px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.tweak { + padding: 3px; +} + +.tweak.title:hover { + box-shadow: none; +} + +.tweak-group-startup { + border: 1px solid rgba(251, 241, 199, 0.12); +} + +.tweak-group-startup > row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +row#Focus, +row#ClickMethod, +row#PrimaryWorkspaceTweak, +row#workspaces-only-on-primary { + margin-top: 4px; +} + +leaflet.titlebar > .titlebar.tweak-titlebar-left, +leaflet.titlebar > .titlebar.tweak-titlebar-right, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-left, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-right { + background-color: inherit; + box-shadow: inherit; + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + background-color: transparent; + margin: 0; +} + +/************************ + * Gnome Control Center * + ************************/ +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:not(:only-child) { + border-top-left-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:not(:only-child) { + border-top-right-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:only-child, window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:only-child { + border-top-right-radius: 12px; + border-top-left-radius: 12px; +} + +window.background.csd > stack:not(.titlebar) > stack.background { + border-radius: 0 0 12px 12px; +} + +window.background.csd > leaflet > stack.background, +window.background.csd > hdyleaflet > stack.background, +window.background.csd > box.horizontal > stack.background { + background: none; +} + +window.background.csd > leaflet > stack.background frame > border, +window.background.csd > hdyleaflet > stack.background frame > border, +window.background.csd > box.horizontal > stack.background frame > border { + border: none; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame { + background-color: #282524; + border-bottom-right-radius: 12px; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view { + background: none; +} + +window.background.csd > leaflet frame.view, +window.background.csd > hdyleaflet frame.view, +window.background.csd > box.horizontal frame.view { + border-radius: 12px; + background: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + margin: 6px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list { + border-top-width: 0; + border-bottom-width: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list > row { + border-radius: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list { + border-top-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list > row { + border-radius: 12px 12px 0 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list { + border-bottom-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list > row { + border-radius: 0 0 12px 12px; +} + +window.background.csd hdycolumn stack frame.view > stack > stack list > separator { + background-color: rgba(251, 241, 199, 0.12); +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack > box.horizontal > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list { + background: none; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list > row:not(:hover):not(:active):not(:selected) { + background-color: transparent; +} + +/************************ + * Gnome system monitor * + ************************/ +window#gnome-system-monitor.background.csd > box.vertical > stack { + background-color: #282524; + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background.csd > box.vertical > stack > box.vertical > revealer > actionbar > revealer > box { + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background:not(.csd) > box.vertical > headerbar { + box-shadow: none; +} + +/************************ + * Gnome Sound Recorder * + ************************/ +stack > grid.vertical > scrolledwindow { + border: none; + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical > scrolledwindow > viewport.frame list { + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical scrolledwindow.frame.emptyGrid { + border: none; +} + +/****************** + * Gnome Contacts * + ******************/ +window.background.csd scrolledwindow.contacts-contact-form { + border-bottom-right-radius: 12px; +} + +/************************ + * Epiphany (Gnome Web) * + ************************/ +tabbox { + border: none; + background-color: rgba(251, 241, 199, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +tabbox > tab button { + min-height: 24px; + min-width: 24px; + border-radius: 9999px; + border: none; + padding: 0; + margin-right: -6px; +} + +/***************** + * Gnome Weather * + *****************/ +#weather-page, +#weekly-forecast-frame { + border-bottom-right-radius: 12px; +} + +#weather-page-content-view { + border-bottom-right-radius: 12px; + border-bottom-left-radius: 12px; +} + +/*************** + * Gnome Music * + ***************/ +window.background.csd box.vertical > overlay > stack.background { + border-radius: 0 0 12px 12px; +} + +/**************** + * Gnome Clocks * + ****************/ +/************* + * Rhythmbox * + *************/ +window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.background > box.vertical > toolbar.primary-toolbar > toolitem button.flat.scale, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + min-height: 24px; + min-width: 24px; + padding: 5px; + margin: 0; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.12); +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button { + border-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:first-child), .sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:last-child) { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):first-child { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):last-child { + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button > widget > box > image { + padding: 0; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal { + padding: 6px; + margin: -1px 0; + border-bottom: none; + border-top: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: transparent; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + margin: 6px 0; +} + +window.csd > box.vertical > box.vertical > frame, +window.solid-csd > box.vertical > box.vertical > frame { + margin: -1px 0; + padding: 0; +} + +window.csd > box.vertical > box.vertical > frame > border, +window.solid-csd > box.vertical > box.vertical > frame > border { + border: none; +} + +window.background > box.vertical > toolbar.primary-toolbar { + padding: 0 12px 0 6px; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(251, 241, 199, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #fbf1c7; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised > widget > box > image { + padding: 0 3px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + padding: 6px; + margin: -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > box { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + padding: 0 6px 6px; + margin: 0 -6px -6px 0; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(251, 241, 199, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + padding: 3px; + margin: -1px -6px -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(251, 241, 199, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > paned > box:first-child > box { + padding: 0 6px 6px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +/********** + * Polari * + **********/ +.polari-room-list .sidebar { + background: none; +} + +.polari-room-list .sidebar > row.activatable:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +stack.view.polari-entry-area { + background-color: #282828; + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-bottom-right-radius: 12px; +} + +stack:disabled.view.polari-entry-area { + background-image: image(#282828); +} + +/*********** + * Builder * + ***********/ +layouttabbar { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282828; +} + +layouttabbar > box > button { + margin: 3px 0; +} + +layouttab { + margin: 0 8px; + border-style: none solid; + border-width: 1px; + border-color: rgba(40, 40, 40, 0.2); + box-shadow: inset 0 -2px #7daea3; + background-color: #282524; +} + +layouttab separator.vertical { + margin: 8px 4px; +} + +layouttab button.text-button, layouttab button.image-button, layouttab button { + margin-top: 8px; + margin-bottom: 8px; + padding: 0 4px; +} + +layout { + border: 1px solid rgba(40, 40, 40, 0.2); + -pnldockbin-handle-size: 1; +} + +entry.search-missing { + background-color: #c14a4a; + color: #fbf1c7; +} + +window.workbench treeview.image { + color: rgba(251, 241, 199, 0.7); +} + +popover.popover-selector list { + padding: 6px; +} + +popover.popover-selector list row { + border-radius: 12px; +} + +popover.popover-selector list row image:dir(ltr) { + margin-right: 6px; +} + +popover.popover-selector list row image:dir(rtl) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(ltr) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(rtl) { + margin-right: 6px; +} + +omnibar.linked:not(.vertical) entry { + border-radius: 12px; +} + +omnibar:not(:hover):not(:active) entry { + color: rgba(251, 241, 199, 0.7); +} + +popover.omnibar list row:not(:last-child) { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +entry.preferences-search { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: #282524; +} + +preferences stacksidebar.sidebar list { + background-color: #282524; +} + +preferences stacksidebar.sidebar:dir(ltr) list, preferences stacksidebar.sidebar:dir(rtl) list { + border-style: none; +} + +preferences > box > box:dir(ltr) { + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +preferences > box > box:dir(rtl) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +popover.messagepopover.background { + padding: 0; +} + +popover.messagepopover .popover-action-area button { + padding: 8px 16px; + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0; +} + +popover.messagepopover .popover-action-area button:first-child { + border-bottom-left-radius: 12px; +} + +popover.messagepopover .popover-action-area button:last-child { + border-bottom-right-radius: 12px; +} + +popover.messagepopover .popover-content-area { + margin: 16px; +} + +popover.transfers list { + background-color: transparent; +} + +popover.transfers list row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +popover.transfers list row > box { + padding: 10px; +} + +dockbin { + border: 1px solid rgba(40, 40, 40, 0.2); + -pnldockbin-handle-size: 1; +} + +dockpaned { + border: 1px solid rgba(40, 40, 40, 0.2); +} + +eggsearchbar box.search-bar { + padding: 0 8px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282828; +} + +docktabstrip { + padding: 0 8px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282828; +} + +docktab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + margin-bottom: -1px; + padding: 6px 6px; + border-width: 1px; + border-color: transparent; + box-shadow: inset 0 -2px transparent; + background-image: radial-gradient(circle, #7daea3 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 0% 0%; + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +docktab:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +docktab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 225ms cubic-bezier(0, 0, 0.2, 1), background-image 525ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 -2px #7daea3; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-size: 1000% 1000%; + color: #fbf1c7; +} + +dockoverlayedge { + background-color: #282828; +} + +dockoverlayedge docktabstrip { + padding: 0; + border: none; +} + +dockoverlayedge.left-edge docktab:checked { + box-shadow: inset -2px 0 #7daea3; +} + +dockoverlayedge.right-edge docktab:checked { + box-shadow: inset 2px 0 #7daea3; +} + +pillbox { + background-color: #282828; + border-radius: 12px; +} + +layoutpane entry.search { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: #282524; +} + +editortweak entry.search { + margin-bottom: -1px; + box-shadow: none; + background-color: transparent; +} + +.gb-search-entry-occurrences-tag { + box-shadow: none; + background-color: transparent; +} + +docktabstrip { + min-height: 39px; +} + +window.workbench preferences preferencesgroup list entry { + padding-top: 8px; + padding-bottom: 8px; +} + +button.run-arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.dzlmenubutton image { + min-width: 28px; +} + +button.dzlmenubutton image.arrow { + min-width: 25px; +} + +button.dzlmenubuttonitem { + color: #fbf1c7; + font-weight: normal; +} + +button.dzlmenubuttonitem:disabled { + color: rgba(251, 241, 199, 0.5); +} + +idelayoutstackheader { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +idelayoutstackheader button:checked { + color: #fbf1c7; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher { + padding: 8px 0; + background-color: #282828; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(ltr) { + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(rtl) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button { + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:active { + background-image: radial-gradient(circle, rgba(125, 174, 163, 0.7) 10%, transparent 0%); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:checked { + background-color: transparent; + color: #fbf1c7; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr) { + margin-right: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr):checked { + box-shadow: inset -2px 0 #7daea3; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl) { + margin-left: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl):checked { + box-shadow: inset 2px 0 #7daea3; +} + +ideeditorsidebar notebook header { + background: transparent; +} + +popover.messagepopover list { + border: 1px solid rgba(251, 241, 199, 0.12); +} + +popover.messagepopover list row:not(:last-child) { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +/********** + * Photos * + **********/ +GdMainIconView.content-view { + -gdmainiconview-icon-size: 48; +} + +.documents-counter { + margin: 8px; + border-radius: 9999px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + font-weight: bold; +} + +.documents-scrolledwin.frame { + border-style: none; +} + +.documents-scrolledwin.frame frame.content-view > border { + border-style: none; +} + +.photos-fade-in { + opacity: 1; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.photos-fade-out { + opacity: 0; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +button.photos-filter-preview { + color: #fbf1c7; + font-weight: normal; +} + +button.photos-filter-preview:checked { + background-color: alpha(currentColor, 0.06); + color: #fbf1c7; +} + +button.photos-filter-preview:checked image { + color: #fbf1c7; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(ltr) { + border-style: none none none solid; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(rtl) { + border-style: none solid none none; +} + +/********* + * Music * + *********/ +.side-panel:dir(ltr) { + border-style: solid; + border-color: rgba(251, 241, 199, 0.12); +} + +.side-panel:dir(rtl) { + border-style: solid; + border-color: rgba(251, 241, 199, 0.12); +} + +.side-panel .view { + background-image: image(#282524); +} + +.side-panel .view:hover { + background-image: image(#393531); +} + +.side-panel .view:selected { + background-image: image(#7daea3); +} + +.side-panel .view:selected:hover { + background-image: image(rgba(120, 166, 155, 0.9896)); +} + +.songs-list:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +frame.documents-dropdown { + margin: 8px; +} + +frame.documents-dropdown > border { + border: none; +} + +box.vertical > revealer > toolbar.search-bar { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; +} + +box.vertical > revealer > toolbar.search-bar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +/************* + * Documents * + *************/ +.documents-scrolledwin { + background-color: transparent; +} + +.documents-scrolledwin .content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) border { + border: none; +} + +window.background.csd > stack > box > revealer > actionbar > revealer > box { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +/******************* + * Document Viewer * + *******************/ +window.background.csd evview.view.content-view { + border-radius: 0 0 12px 12px; +} + +/********************************* + * Archive Manager (File roller) * + *********************************/ +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #282524; +} + +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow > treeview.view:not(:hover):not(:selected):not(:selected):not( +:hover +):not(.progressbar):not(.expander):not(.trough):not( +.separator +) { + background-color: #282524; +} + +.background.csd > grid.horizontal > paned.horizontal > box.vertical > scrolledwindow { + border-radius: 0 0 0 12px; + background-color: #282828; +} + +/************ + * Terminal * + ************/ +terminal-window decoration { + border-radius: 12px 12px 0 0; +} + +terminal-window.background.csd, terminal-window.background.csd.maximized { + border-radius: 0; +} + +terminal-window notebook > header > box { + margin: -2px -2px -2px 1px; +} + +terminal-window notebook > header > box button.flat { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; +} + +window.background > box.vertical > box.horizontal > frame > border { + border: none; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list { + /* border-radius: $corner-radius; */ + margin: 0 6px 6px; + background-color: #282828; + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row { + padding: 0 2px; + margin: 2px 0; + border-radius: 12px; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:selected, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:hover { + color: #7daea3; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:active { + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > stack > widget > notebook.frame { + margin: 0 6px 6px 0; +} + +.terminal-window { + background-color: #282828; +} + +.terminal-window tabbar tabbox { + background-color: #282524; + margin: 0; + border-radius: 0; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; +} + +/********* + * To Do * + *********/ +task-list-view taskrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 0 -8px; +} + +task-list-view taskrow:hover { + transition: none; +} + +task-list-view taskrow label { + margin: 0 8px; +} + +task-list-view taskrow image.dim-label { + min-width: 16px; +} + +task-list-view > box > revealer > box > button { + margin: -5px; +} + +task-list-view > box > revealer > box > button .dim-label { + color: inherit; +} + +tasklistview taskrow { + outline: none; +} + +tasklistview taskrow entry, tasklistview taskrow entry:focus, tasklistview taskrow entry:disabled { + box-shadow: none; +} + +tasklistview taskrow image.dim-label { + min-width: 16px; +} + +tasklistview > box > revealer > box > button { + margin: -5px; +} + +tasklistview > box > revealer > box > button .dim-label { + color: inherit; +} + +/******* + * Eog * + *******/ +#eog-thumb-nav scrolledwindow { + border-top: none; +} + +/************* + * Evolution * + *************/ +frame.taskbar > border { + border-style: solid none none; +} + +box.vertical > paned.horizontal notebook widget .frame { + border-style: none; +} + +/*********** + * Fractal * + ***********/ +.background.csd.main-window .sidebar.rooms-sidebar { + border-bottom-left-radius: 12px; +} + +/******** + * Gitg * + ********/ +frame.commit-frame > border { + border-style: solid none none; +} + +/************** + * Characters * + **************/ +box.dialog-vbox scrolledwindow.related { + border: 1px solid rgba(40, 40, 40, 0.2); +} + +list.categories { + background-image: image(#282524); +} + +/********* + * Boxes * + *********/ +.transparent-bg + stack overlay > label { + min-height: 24px; + padding: 0 4px; + border-radius: 12px; + background-color: #242220; + color: #fbf1c7; +} + +/************** + * Calculator * + **************/ +button.title label { + min-height: 34px; +} + +/********* + * Geary * + *********/ +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer, +window#GearyMainWindow.background.csd stack#conversation_viewer { + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox, +window#GearyMainWindow.background.csd stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox { + background: none; + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded { + animation: none; + background-image: none; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box { + border-radius: 0; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar { + color: #fbf1c7; + background-color: #282828; + box-shadow: none; + border-bottom: 1px solid rgba(40, 40, 40, 0.2); +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-composer-box actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-composer-box actionbar > revealer > box { + border-bottom-left-radius: 0; +} + +.geary-accounts-editor-pane frame:not(.geary-signature) > border, +.geary-accounts-editor-pane scrolledwindow.frame { + border: none; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout { + background-color: #282524; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar { + background-color: #282828; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar:backdrop, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar:backdrop { + background-color: #282828; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > box.vertical + separator.sidebar { + min-width: 1px; + background-color: rgba(251, 241, 199, 0.12); +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow { + padding: 3px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view { + border: 1px solid transparent; + border-radius: 12px; + padding: 6px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:selected, .geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:active { + border-radius: 12px; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.geary-main-window.unified separator.geary-sidebar-pane-separator { + min-width: 1px; + background-color: rgba(251, 241, 199, 0.12); +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable { + border: 1px solid rgba(251, 241, 199, 0.12); + border-bottom-width: 0; + background-color: #282524; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane { + border-radius: 0 0 8px 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background { + background-color: transparent; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background > revealer > box { + border-radius: 0 0 6px 6px; +} + +/************** + * Extensions * + **************/ +window.background.csd stack stack stack frame > border, +window.background.csd > stack > stack > box > frame > border, +window.background.csd > stack > stack > box > box > frame > border, +window.background.csd > stack > box > stack > box > frame > border, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > border, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > border, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > border { + border: none; +} + +window.background.csd > stack > box > box > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport > list { + border-bottom-left-radius: 12px; +} + +window.background.csd > stack > box > .sidebar > scrolledwindow > viewport > list { + padding: 0 0; +} + +/*********** + * Dialogs * + ***********/ +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:first-child { + border-radius: 0 0 0 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:last-child { + border-radius: 0 0 12px 0; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow, +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #282524; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active), +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list row.activatable:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack toolbar.toolbar { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd stack scrolledwindow.frame { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view > text { + background: none; +} + +dialog.background.csd stack scrolledwindow viewport.frame.view { + border-radius: 12px; +} + +window.background.csd.unified { + background-color: #282828; +} + +window.background.csd.unified headerbar { + box-shadow: none; +} + +window.background.csd.unified > decoration-overlay { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +window.background.csd.unified, +window.background.csd.unified > decoration, +window.background.csd.unified > decoration-overlay { + border-radius: 12px; +} + +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen > decoration-overlay { + box-shadow: none; +} + +window.background.csd.unified.tiled, +window.background.csd.unified.tiled > decoration, +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top, +window.background.csd.unified.tiled-top > decoration, +window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right, +window.background.csd.unified.tiled-right > decoration, +window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom, +window.background.csd.unified.tiled-bottom > decoration, +window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left, +window.background.csd.unified.tiled-left > decoration, +window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized, +window.background.csd.unified.maximized > decoration, +window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen, +window.background.csd.unified.fullscreen > decoration, +window.background.csd.unified.fullscreen > decoration-overlay { + border-radius: 0; +} + +/********* + * Tilix * + *********/ +overlay > revealer.left > scrolledwindow.frame, overlay > revealer.right > scrolledwindow.frame { + border-style: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +overlay > revealer.left > scrolledwindow.frame { + margin-right: 32px; +} + +overlay > revealer.right > scrolledwindow.frame { + margin-left: 32px; +} + +.terminix-session-sidebar, +.tilix-session-sidebar { + background-image: image(#242220); +} + +.terminal-titlebar button { + border-radius: 0; +} + +button.image-button.session-new-button { + min-width: 30px; +} + +notebook.tilix-background tab > box > stack { + margin: -6px; +} + +button.flat.tilix-small-button { + min-height: 20px; + min-width: 16px; +} + +/************** + * Terminator * + **************/ +.terminator-terminal-window paned > separator { + background-color: #282828; +} + +.terminator-terminal-window notebook.frame { + border-style: none; +} + +/************* + * Ubitquity * + *************/ +#live_installer .menubar progressbar trough { + border-radius: 4px; + background-color: rgba(251, 241, 199, 0.12); +} + +/********* + * Meld * + ********/ +.meld-notebook, +.meld-notebook > stack { + background: none; + border-radius: 0 0 12px 12px; +} + +.meld-notebook-child { + background-color: #282524; + border-radius: 0 0 12px 12px; +} + +statusbar.meld-status-bar { + background: none; +} + +/*********** + * Eclipse * + ***********/ +window.background > box.vertical > scrolledwindow > widget toolbar { + padding: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar separator, +window.background > box.vertical > scrolledwindow > widget toolbar button { + margin: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar button { + border-radius: 12px; +} + +/************ + * Chromium * + ************/ +window.background.chromium { + background-color: #282524; + color: #fbf1c7; +} + +window.background.chromium headerbar.titlebar { + padding: 0 12px; + /* border-radius: $corner-radius $corner-radius 0 0; */ +} + +window.background.chromium headerbar.titlebar button.toggle { + border: none; + background-color: transparent; + background-image: none; +} + +window.background.chromium headerbar.titlebar button.toggle:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #fbf1c7; +} + +window.background.chromium headerbar.titlebar button.toggle:checked, window.background.chromium headerbar.titlebar button.toggle:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #fbf1c7; +} + +window.background.chromium headerbar.titlebar button.titlebutton { + min-width: 16px; + min-height: 16px; + margin: 0; + padding: 0; + background-size: 16px 16px; + border: none; +} + +window.background.chromium button { + border-width: 1px; + border-style: solid; + border-color: #423f3e; + background-color: #282828; + color: #fbf1c7; +} + +window.background.chromium entry.chromium { + background-color: rgba(251, 241, 199, 0.06); +} + +window.background.chromium entry.chromium, window.background.chromium entry.chromium:focus { + border-image: none; + color: #fbf1c7; +} + +window.background.chromium > textview.view, +window.background.chromium textview { + background-color: rgba(251, 241, 199, 0.06); + color: #fbf1c7; +} + +window.background.chromium > menubar { + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.chromium menu { + background-color: #211f1e; + /* border: 0px solid if($variant == 'light', $solid-border, $window-border); */ + border-radius: 0; +} + +window.background.chromium menu menuitem { + border-radius: 0; + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.chromium menu menuitem:hover { + background-color: #242220; + color: #7daea3; +} + +/*********** + * Firefox * + ***********/ +#MozillaGtkWidget decoration { + border: none; +} + +#MozillaGtkWidget > widget text { + background-color: #282828; +} + +#MozillaGtkWidget > widget text:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +#MozillaGtkWidget > widget > separator { + color: #423f3e; +} + +#MozillaGtkWidget > widget > scrollbar { + background-clip: border-box; +} + +#MozillaGtkWidget > widget > frame > border { + border-color: #423f3e; +} + +#MozillaGtkWidget > widget > entry, +#MozillaGtkWidget > widget > button > button { + border: 1px solid #423f3e; + border-radius: 12px; + box-shadow: none; +} + +#MozillaGtkWidget > widget > entry:disabled, +#MozillaGtkWidget > widget > button > button:disabled { + border-color: rgba(251, 241, 199, 0.12); +} + +#MozillaGtkWidget > widget > entry { + min-height: 30px; + background-color: #282524; +} + +#MozillaGtkWidget > widget > entry:focus { + border-color: #7daea3; + box-shadow: inset 0 0 0 1px #7daea3; +} + +#MozillaGtkWidget > widget > entry:disabled { + background-color: #282524; +} + +#MozillaGtkWidget > widget > button > button { + padding: 4px 8px; + background-size: auto; +} + +#MozillaGtkWidget > widget > button > button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +#MozillaGtkWidget > widget > button > button:active { + background-image: image(alpha(currentColor, 0.12)); +} + +#MozillaGtkWidget > widget > checkbutton > check, +#MozillaGtkWidget > widget > radiobutton > radio { + margin: 0; + padding: 0; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate), +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate) { + color: #504945; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):hover, #MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):active, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):hover, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):active { + color: #7c6f64; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):disabled, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):disabled { + color: rgba(80, 73, 69, 0.5); +} + +#MozillaGtkWidget menu { + border: none; +} + +#MozillaGtkWidget > widget > menubar { + color: rgba(251, 241, 199, 0.7); +} + +#MozillaGtkWidget > widget > menubar:hover { + color: #fbf1c7; +} + +#MozillaGtkWidget > widget > menubar:disabled { + color: rgba(251, 241, 199, 0.32); +} + +#MozillaGtkWidget > widget > frame { + color: #423f3e; +} + +#MozillaGtkWidget menu > separator { + color: #423f3e; +} + +window.background:not(.csd) > window > menu menuitem { + transition: none; +} + +/************ + * Inkscape * + ************/ +#ToolboxCommon > #AuxToolbox #StyleSwatch { + font-size: smaller; +} + +#ToolboxCommon > #AuxToolbox #Kludge { + padding: 0; +} + +#ToolboxCommon > #AuxToolbox spinbutton, +#ToolboxCommon > #AuxToolbox entry { + min-height: 32px; +} + +#ToolboxCommon > #AuxToolbox button:not(.up):not(.down) { + min-height: 24px; + min-width: 16px; + padding: 4px 8px; +} + +#ToolboxCommon > #AuxToolbox spinbutton button { + border-width: 4px; +} + +#ToolboxCommon > toolbar.vertical { + margin-top: -4px; +} + +#ToolboxCommon > toolbar.vertical button { + min-height: 24px; + min-width: 24px; + padding: 4px; +} + +#CanvasTable button { + min-height: 16px; + min-width: 16px; + padding: 0; +} + +#CanvasTable #HorizontalScrollbar { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(ltr) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(rtl) { + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +#Canvas_and_Dock frame > border { + border: none; +} + +#Canvas_and_Dock widget > widget > button.flat { + min-height: 16px; + min-width: 16px; + padding: 4px; +} + +#Canvas_and_Dock widget > widget > box.horizontal image { + padding: 4px; +} + +#Canvas_and_Dock box.horizontal > box.vertical > button.flat { + min-height: 16px; + min-width: 24px; + padding: 8px 4px; +} + +scrolledwindow#DialogNotebook > viewport.frame > notebook.frame button.close-button image { + padding: 4px; +} + +#InKscapeCanvas { + background-color: #282524; + border-radius: 12px; +} + +/*********** + * Synapse * + ***********/ +/*************** + * Libreoffice * + ***************/ +window.background > grid +> widget +> widget +> scrolledwindow +> viewport +> grid +> box +> box +> frame +> box { + background-color: #282828; +} + +/********* + * Pamac * + *********/ +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list { + border: none; + border-radius: 0; +} + +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list > row.activatable { + border-radius: 12px; +} + +dialog-host > floating-sheet > sheet > widget.response-area { + padding: 6px; +} + +window.background:not(.csd):not(.solid-csd) > button:not(:hover):not(:active):not(:checked):not(:disabled):not(.flat) { + /* background-color: if($variant == 'light', $grey-100, $grey-900); */ + background-color: #282828; +} + +window.background:not(.csd) > box +> widget +> widget +> widget +> widget +> widget +> widget +> widget +> scrolledwindow entry:focus { + background-color: #333333; +} + +/********* + * Unity * + *********/ +UnityDecoration { + -unitydecoration-extents: 28px 0 0 0; + -unitydecoration-input-extents: 8px; + -unitydecoration-shadow-offset-x: 0; + -unitydecoration-shadow-offset-y: 3px; + -unitydecoration-active-shadow-color: rgba(0, 0, 0, 0.48); + -unitydecoration-active-shadow-radius: 18px; + -unitydecoration-inactive-shadow-color: rgba(0, 0, 0, 0.32); + -unitydecoration-inactive-shadow-radius: 6px; + -unitydecoration-glow-size: 8px; + -unitydecoration-glow-color: #7daea3; + -unitydecoration-title-indent: 4px; + -unitydecoration-title-fade: 32px; + -unitydecoration-title-alignment: 0; +} + +UnityDecoration .top { + padding: 0 2px; + border-style: none; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #282828; + color: #fbf1c7; +} + +UnityDecoration .top:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.7); +} + +UnityDecoration .menuitem { + color: rgba(251, 241, 199, 0.7); +} + +UnityDecoration .menuitem:hover { + box-shadow: inset 0 -2px #fbf1c7; + background-color: transparent; + color: #fbf1c7; +} + +.background:not(.csd) headerbar:not(.titlebar) { + border-radius: 0; + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +.background:not(.csd) headerbar:not(.titlebar).inline-toolbar { + border-style: none; +} + +UnityPanelWidget, +.unity-panel { + background-color: #282828; + color: #fbf1c7; +} + +UnityPanelWidget:backdrop, +.unity-panel:backdrop { + color: rgba(251, 241, 199, 0.7); +} + +.unity-panel.menuitem, +.unity-panel .menuitem { + color: rgba(251, 241, 199, 0.7); +} + +.unity-panel.menubar.menuitem:hover, +.unity-panel.menubar .menuitem *:hover { + box-shadow: inset 0 -2px #fbf1c7; + background-color: transparent; + color: #fbf1c7; +} + +.menu IdoPlaybackMenuItem.menuitem:active { + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); + animation: spin 1s linear infinite; + color: #7daea3; +} + +/************** + * Mate-Panel * + **************/ +.mate-panel-menu-bar menubar, +#PanelApplet-window-menu-applet-button { + background-color: transparent; +} + +.mate-panel-menu-bar { + background-color: rgba(40, 40, 40, 0.6); + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +.mate-panel-menu-bar button { + min-height: 16px; + min-width: 16px; + padding: 0; + border-radius: 0; +} + +PanelToplevel.horizontal > grid > button { + min-width: 24px; +} + +PanelToplevel.vertical > grid > button { + min-height: 24px; +} + +PanelSeparator { + color: rgba(251, 241, 199, 0.12); +} + +MatePanelAppletFrameDBus { + border-style: solid; + border-color: rgba(251, 241, 199, 0.12); +} + +.mate-panel-menu-bar.horizontal MatePanelAppletFrameDBus { + border-width: 0 1px; +} + +.mate-panel-menu-bar.vertical MatePanelAppletFrameDBus { + border-width: 1px 0; +} + +.mate-panel-menu-bar menubar > menuitem { + color: rgba(251, 241, 199, 0.7); +} + +.mate-panel-menu-bar menubar > menuitem:hover { + color: #fbf1c7; +} + +.mate-panel-menu-bar menubar > menuitem:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.mate-panel-menu-bar.horizontal menubar > menuitem { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical menubar > menuitem { + padding: 8px 0; +} + +.mate-panel-menu-bar menubar menu > menuitem { + min-height: 28px; + padding: 0 6px; +} + +.mate-panel-menu-bar #PanelApplet button { + -gtkwidget-window-dragging: true; +} + +.mate-panel-menu-bar #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0/0 0 0px; +} + +.mate-panel-menu-bar #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2/0 0 2px; +} + +.mate-panel-menu-bar #tasklist-button image:dir(ltr), +.mate-panel-menu-bar #tasklist-button label:dir(rtl) { + padding-left: 4px; +} + +.mate-panel-menu-bar #tasklist-button label:dir(ltr), +.mate-panel-menu-bar #tasklist-button image:dir(rtl) { + padding-right: 4px; +} + +.mate-panel-menu-bar.vertical #tasklist-button { + min-height: 32px; +} + +.mate-panel-menu-bar.horizontal #showdesktop-button image { + min-width: 24px; + padding: 0 4px; +} + +.mate-panel-menu-bar.vertical #showdesktop-button image { + min-height: 24px; + padding: 4px 0; +} + +PanelApplet.wnck-applet .wnck-pager { + background-color: transparent; + color: #7daea3; +} + +PanelApplet.wnck-applet .wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +PanelApplet.wnck-applet .wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +PanelApplet.wnck-applet .wnck-pager:selected { + background-color: #7daea3; +} + +.mate-panel-menu-bar.horizontal #clock-applet-button label { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical #clock-applet-button label { + padding: 8px 0; +} + +#MatePanelPopupWindow { + border: 1px solid rgba(40, 40, 40, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +#MatePanelPopupWindow frame > border { + border-style: none; +} + +#MatePanelPopupWindow calendar { + border-style: none; +} + +#MatePanelPopupWindow calendar:not(:selected) { + background-color: transparent; +} + +#MatePanelPopupWindow calendar + box { + margin-top: -5px; + padding-top: 5px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +#MatePanelPopupWindow expander > title { + min-height: 32px; +} + +#MatePanelPopupWindow button { + padding: 4px 16px; +} + +#MatePanelPopupWindow > frame > box > box > box > widget { + color: rgba(251, 241, 199, 0.12); +} + +na-tray-applet { + -natrayapplet-icon-padding: 3px; + -natrayapplet-icon-size: 16; +} + +.mate-panel-menu-bar { + -panelmenubar-icon-visible: true; +} + +.mate-panel-applet-slider { + border: 1px solid rgba(40, 40, 40, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.mate-panel-applet-slider frame > border { + border-style: none; +} + +#PanelApplet:not(:selected) > box { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +#PanelApplet:selected > box { + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +#mate-menu { + border: 1px solid rgba(40, 40, 40, 0.2); + background-color: #242220; +} + +#mate-menu button { + min-height: 24px; + min-width: 24px; + padding: 4px 0; + color: #fbf1c7; + font-weight: normal; +} + +#mate-menu button:not(.flat) { + background-color: alpha(currentColor, 0.1); +} + +#mate-menu button image, +#mate-menu button label + label { + color: rgba(251, 241, 199, 0.7); +} + +#mate-menu entry { + margin: 0 0 4px; +} + +#mate-menu entry image { + margin: 0; +} + +#mate-menu entry + button { + margin: 0 4px 4px; + padding: 5px; +} + +.brisk-menu { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.brisk-menu entry { + margin-bottom: -2px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.brisk-menu entry + box > box:dir(ltr) { + margin-right: -2px; + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +.brisk-menu entry + box > box:dir(rtl) { + margin-left: -2px; + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +.brisk-menu .categories-list { + padding-top: 4px; +} + +.brisk-menu .categories-list button { + margin: 0 4px; +} + +.brisk-menu .categories-list button:checked { + color: #7daea3; +} + +.brisk-menu .session-button { + padding: 11px; +} + +.brisk-menu .frame { + border-style: none; +} + +.brisk-menu .apps-list { + padding: 4px 0; + background-color: transparent; +} + +.brisk-menu .apps-list row { + padding: 0; +} + +.brisk-menu .apps-list row:hover { + box-shadow: none; +} + +.brisk-menu .apps-list button { + border-radius: 0; + color: #fbf1c7; + font-weight: normal; +} + +/********************* + * CAJA File manager * + *********************/ +.caja-navigation-window button.toggle.image-button { + border-radius: 12px; +} + +.caja-pathbar button { + margin: 0 -1px 0 -2px; +} + +.caja-pathbar button.slider-button { + min-width: 24px; +} + +.caja-pathbar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.caja-side-pane notebook viewport.frame, +.caja-side-pane notebook widget .vertical { + background-color: #282524; +} + +.caja-side-pane notebook, +.caja-notebook { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.caja-side-pane notebook .frame, +.caja-notebook .frame { + border-style: none; +} + +.caja-canvas-item { + border-radius: 12px; +} + +.caja-desktop.view .entry, +.caja-navigation-window .view .entry { + border: none; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + background-image: none; + color: #fbf1c7; +} + +.caja-desktop.view .entry:selected, +.caja-navigation-window .view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-desktop.view .entry { + background-color: #282524; + color: #fbf1c7; + caret-color: currentColor; +} + +.caja-desktop.view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-navigation-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.caja-notebook frame > border { + border-style: none; +} + +#caja-extra-view-widget { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +#caja-extra-view-widget > box > box > label { + font-weight: bold; +} + +/********* + * Pluma * + *********/ +.pluma-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.pluma-window statusbar frame > border { + border-style: none; +} + +.pluma-window statusbar frame button.flat { + padding: 0 4px; + border-radius: 0; +} + +.pluma-window statusbar frame button.flat widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.pluma-print-preview toolbar { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat { + margin: 1px; +} + +.pluma-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.pluma-window paned.horizontal box.vertical notebook.frame { + margin-top: -1px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.pluma-window paned.horizontal box.vertical notebook.frame box.vertical toolbar.horizontal { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +/********* + * Atril * + *********/ +.atril-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.atril-window paned.horizontal box.vertical notebook .frame { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +/* mate-screensaver lock dialog */ +.lock-dialog { + border: 1px solid rgba(40, 40, 40, 0.2); + border-radius: 13px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.lock-dialog frame > border { + border-style: none; +} + +.lock-dialog button:not(:disabled) { + color: #7daea3; +} + +/* multimedia OSD */ +MsdOsdWindow.background.osd { + border-radius: 12px; + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; +} + +MsdOsdWindow.background.osd .trough { + border-radius: 0; + background-color: rgba(251, 241, 199, 0.12); +} + +MsdOsdWindow.background.osd .progressbar { + border-radius: 0; + background-color: #7daea3; +} + +/****************** + * Budgie Desktop * + ******************/ +.budgie-container { + background-color: transparent; +} + +.budgie-settings-window list.sidebar { + background: none; + border-radius: 0 0 0 12px; +} + +.budgie-settings-window buttonbox.inline-toolbar { + border-style: none none solid; +} + +.budgie-settings-window buttonbox.inline-toolbar button { + border-radius: 12px; +} + +.budgie-popover { + border-color: #242220; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #fbf1c7; + background-clip: border-box; + background-color: #242220; + border-radius: 12px; +} + +.budgie-popover frame.container { + padding: 6px; + border: none; +} + +.budgie-popover frame.container .container { + padding: 0; +} + +.budgie-popover list, +.budgie-popover row { + padding: 0; +} + +.budgie-popover separator { + margin: 3px 0; +} + +.budgie-popover border { + border: none; +} + +.budgie-popover list { + background-color: transparent; +} + +.budgie-popover row:hover { + box-shadow: none; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) { + background-color: rgba(251, 241, 199, 0.04); + border-right: none; + border-bottom-left-radius: 12px; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable { + padding: 6px 8px; +} + +.budgie-popover treeview.view.sidebar { + border-right: none; + background: none; +} + +.budgie-popover treeview.view.sidebar:hover { + background-color: alpha(currentColor, 0.08); +} + +.budgie-popover treeview.view.sidebar:selected { + background-color: alpha(currentColor, 0.12); +} + +.budgie-popover.bottom scrolledwindow.sidebar:not(.categories) { + padding-top: 12px; + border-top-left-radius: 12px; + border-bottom-left-radius: 0; +} + +.budgie-popover > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.budgie-popover.bottom > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: none; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.budgie-popover.budgie-menu .container { + padding: 0; +} + +.budgie-popover.budgie-menu .sidebar, +.budgie-popover.budgie-menu scrollbar, +.budgie-popover.budgie-menu entry.search { + background-color: transparent; +} + +.budgie-popover.budgie-menu entry.search { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + font-size: 120%; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories { + background-color: rgba(251, 241, 199, 0.04); + padding-bottom: 12px; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button { + border-radius: 0; +} + +.budgie-popover.budgie-menu scrolledwindow > viewport.frame > list > row.activatable > button.flat { + border-radius: 0; +} + +.budgie-popover.budgie-menu list.left-overlay-menu { + border-radius: 12px; + background-color: #282524; + padding: 6px; + margin: 6px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #fbf1c7; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable { + border-radius: 12px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable:not(:last-child) { + margin-bottom: 3px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable button.menuitem { + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer { + border-top: 1px solid rgba(251, 241, 199, 0.12); + padding: 6px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat { + padding: 3px; + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat.image-button { + border-radius: 9999px; + padding: 6px; + min-height: 16px; + min-width: 16px; + margin-left: 6px; + background-clip: border-box; +} + +.budgie-popover.user-menu list, +.budgie-popover.user-menu row { + border: none; + background: none; + box-shadow: none; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child { + margin-bottom: 0; + outline-width: 0; + border-radius: 12px; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child button.indicator-item { + transition: none; + animation: none; +} + +.budgie-popover.night-light-indicator .view-header { + margin: 0 6px; +} + +.budgie-popover.places-menu .name-button image:dir(ltr) { + margin-right: 3px; +} + +.budgie-popover.places-menu .name-button image:dir(rtl) { + margin-left: 3px; +} + +.budgie-popover.places-menu .unmount-button { + margin: 2px; + padding: 0; +} + +.budgie-popover.places-menu .places-list:not(.always-expand) { + margin-top: 3px; + padding-top: 3px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.budgie-popover.places-menu .alternative-label { + padding: 3px; + font-size: 15px; +} + +.budgie-popover.workspace-popover flowboxchild { + padding: 0; +} + +.workspace-switcher .workspace-layout { + border: 0 solid rgba(251, 241, 199, 0.12); +} + +.top .workspace-switcher .workspace-layout:dir(ltr), .bottom .workspace-switcher .workspace-layout:dir(ltr) { + border-left-width: 1px; +} + +.top .workspace-switcher .workspace-layout:dir(rtl), .bottom .workspace-switcher .workspace-layout:dir(rtl) { + border-right-width: 1px; +} + +.left .workspace-switcher .workspace-layout, .right .workspace-switcher .workspace-layout { + border-top-width: 1px; +} + +.workspace-switcher .workspace-item, +.workspace-switcher .workspace-add-button { + border: 0 solid rgba(251, 241, 199, 0.12); +} + +.top .workspace-switcher .workspace-item:dir(ltr), .bottom .workspace-switcher .workspace-item:dir(ltr), .top .workspace-switcher .workspace-add-button:dir(ltr), .bottom .workspace-switcher .workspace-add-button:dir(ltr) { + border-right-width: 1px; +} + +.top .workspace-switcher .workspace-item:dir(rtl), .bottom .workspace-switcher .workspace-item:dir(rtl), .top .workspace-switcher .workspace-add-button:dir(rtl), .bottom .workspace-switcher .workspace-add-button:dir(rtl) { + border-left-width: 1px; +} + +.left .workspace-switcher .workspace-item, .right .workspace-switcher .workspace-item, .left .workspace-switcher .workspace-add-button, .right .workspace-switcher .workspace-add-button { + border-bottom-width: 1px; +} + +.workspace-switcher .workspace-item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.workspace-switcher .workspace-item.current-workspace { + background-color: alpha(currentColor, 0.1); +} + +.workspace-switcher .workspace-add-button:hover { + box-shadow: none; +} + +.workspace-switcher .workspace-add-button:active { + background-image: none; +} + +.workspace-switcher .workspace-add-button:active image { + margin: 1px 0 -1px; +} + +.budgie-panel .workspace-switcher .workspace-icon-button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 12px; +} + +.budgie-panel { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(40, 40, 40, 0.6); + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +.budgie-panel.transparent { + background-color: rgba(40, 40, 40, 0.75); +} + +.budgie-panel .icon-tasklist button.launcher:checked, .budgie-panel .icon-tasklist button.launcher:active { + color: #fbf1c7; +} + +.top .budgie-panel.dock-mode { + border-radius: 0 0 12px 12px; +} + +.bottom .budgie-panel.dock-mode { + border-radius: 12px 12px 0 0; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:first-child > button.launcher { + border-top-left-radius: 12px; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:last-child > button.launcher { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode { + border-radius: 0 12px 12px 0; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-right-radius: 12px; +} + +.right .budgie-panel.dock-mode { + border-radius: 12px 0 0 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-left-radius: 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-left-radius: 12px; +} + +.budgie-panel button { + color: rgba(251, 241, 199, 0.7); + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 0; +} + +.budgie-panel button:hover { + color: #fbf1c7; +} + +.budgie-panel button:active { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel button.budgie-menu-launcher { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel button.budgie-menu-launcher:focus { + box-shadow: none; + border: none; + color: #fbf1c7; +} + +.budgie-panel button.raven-trigger { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel.horizontal button { + padding: 0 4px; +} + +.budgie-panel.vertical button { + padding: 4px 0; +} + +.budgie-panel separator { + background-color: rgba(251, 241, 199, 0.12); +} + +.budgie-panel .alert { + color: #c14a4a; +} + +.budgie-panel > box > widget > widget > image, +.budgie-panel > box > widget > widget > stack > image, +.budgie-panel > box > widget > widget > box > image { + margin-left: 6px; + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > image + label { + margin-left: -4px; +} + +.budgie-panel > box > widget > widget > box > widget > image { + margin-left: 6px; +} + +.budgie-panel > box > widget > widget > box > stack > widget > label { + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > widget > widget > image { + margin-left: 2px; + margin-right: 2px; +} + +.budgie-panel .budgie-clock-applet > widget > box, +.budgie-panel .budgie-calendar-applet > widget > box { + padding-left: 3px; + padding-right: 3px; +} + +.budgie-panel .titlebar:not(headerbar) { + min-height: 0; + padding: 0; + box-shadow: none; + background-color: transparent; + color: #fbf1c7; +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):hover, .budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):active { + color: #fbf1c7; +} + +.budgie-panel menubar, +.budgie-panel .menubar { + color: rgba(251, 241, 199, 0.7); + box-shadow: none; + border: none; +} + +.budgie-panel menubar > menuitem, +.budgie-panel .menubar > menuitem { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel menubar > menuitem:hover, .budgie-panel menubar > menuitem:active, +.budgie-panel .menubar > menuitem:hover, +.budgie-panel .menubar > menuitem:active { + color: #fbf1c7; +} + +.budgie-panel menubar menu separator, +.budgie-panel .menubar menu separator { + background-color: rgba(251, 241, 199, 0.12); +} + +.budgie-panel #tasklist-button { + padding: 0 4px; +} + +.budgie-panel.vertical #tasklist-button { + min-height: 32px; +} + +.budgie-panel button.flat.launcher { + padding: 0; +} + +.budgie-panel button.flat.launcher:not(:checked) { + color: rgba(251, 241, 199, 0.5); +} + +.budgie-panel button.flat.launcher:not(:checked):hover, .budgie-panel button.flat.launcher:not(:checked):active { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel button.flat.launcher:not(:checked):disabled { + color: rgba(251, 241, 199, 0.32); +} + +.top .budgie-panel .unpinned button.flat.launcher:checked, .top .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel .unpinned button.flat.launcher:checked, .bottom .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel .unpinned button.flat.launcher:checked, .left .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel .unpinned button.flat.launcher:checked, .right .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +.top .budgie-panel #tasklist-button, .budgie-panel .top #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.top .budgie-panel #tasklist-button:checked, .budgie-panel .top #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel #tasklist-button, .budgie-panel .bottom #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.bottom .budgie-panel #tasklist-button:checked, .budgie-panel .bottom #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel #tasklist-button, .budgie-panel .left #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.left .budgie-panel #tasklist-button:checked, .budgie-panel .left #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel #tasklist-button, .budgie-panel .right #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.right .budgie-panel #tasklist-button:checked, .budgie-panel .right #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +frame.raven-frame > border { + border-style: none; +} + +.top frame.raven-frame > border { + margin-bottom: 32px; +} + +.bottom frame.raven-frame > border { + margin-top: 32px; +} + +.left frame.raven-frame > border { + margin-right: 32px; +} + +.right frame.raven-frame > border { + margin-left: 32px; +} + +.raven { + background-color: #242220; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +.raven > box { + margin-bottom: -10px; +} + +.raven stackswitcher.linked { + margin: 6px 16px; +} + +.raven stackswitcher.linked > button:focus { + box-shadow: none; +} + +.raven .raven-header { + min-height: 34px; + padding: 3px; +} + +.raven .raven-header.top { + padding: 0; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.raven .raven-header.top stackswitcher button { + margin: -4px 0 -5px; + padding: 0 16px; + min-height: 24px; +} + +.raven .raven-header.bottom { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.raven stack .raven-header { + margin-top: -6px; +} + +.raven stack scrolledwindow .raven-header { + margin-top: -8px; +} + +.raven .raven-background { + border-style: solid none; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +.raven .raven-background > overlay > widget > image { + color: rgba(251, 241, 199, 0.12); +} + +.raven scrolledwindow.raven-background { + border-bottom-style: none; +} + +.raven .powerstrip button { + margin: 2px 0 1px; + padding: 11px; + border-radius: 9999px; +} + +.raven .option-subtitle { + font-size: smaller; +} + +.raven .audio-widget scale.marks-after { + padding-top: 0; + padding-bottom: 0; +} + +.raven .audio-widget scale.marks-after label { + font-size: 90%; + padding: 0; + margin: -10px 0 0 6px; +} + +.raven .audio-widget button.flat.expander-button { + margin-top: 4px; + margin-bottom: 4px; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked { + background-color: rgba(251, 241, 199, 0.06); + color: #fbf1c7; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected label, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked label { + color: #fbf1c7; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable label { + padding-left: 12px; +} + +.raven levelbar, +.raven levelbar trough, +.raven levelbar block { + border-radius: 9999px; +} + +calendar.raven-calendar { + border-style: none; + background-color: transparent; +} + +calendar.raven-calendar:selected { + border-radius: 12px; +} + +.raven-mpris { + background-color: #242220; + color: #fbf1c7; +} + +.raven-mpris label { + min-height: 24px; +} + +.raven-mpris button.image-button { + padding: 11px; +} + +image.raven-mpris { + background-color: rgba(251, 241, 199, 0.12); + color: rgba(251, 241, 199, 0.7); + border-radius: 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame { + padding: 0; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable { + margin-left: -6px; + margin-right: -3px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable .raven-notifications-group-header { + padding: 0 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list { + padding: 6px; + background: none; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable { + border: none; + padding: 6px; + padding-left: 12px; + margin: 3px; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:selected { + background-color: rgba(251, 241, 199, 0.12); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:active, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:focus { + background: none; + box-shadow: none; +} + +.budgie-notification-window, .budgie-switcher-window, .budgie-osd-window { + background-color: transparent; +} + +.budgie-notification .notification-title, .budgie-switcher .notification-title { + font-size: 120%; +} + +.budgie-notification .notification-body, .budgie-switcher .notification-body { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-osd .budgie-osd-text { + font-size: 120%; +} + +.budgie-panel .lock-keys image:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.drop-shadow { + margin: 5px 9px; + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.drop-shadow .linked > button { + border-radius: 12px; +} + +.budgie-session-dialog, +.budgie-polkit-dialog, +.budgie-run-dialog { + background-color: #242220; + border: none; + padding: 0; +} + +.budgie-session-dialog > box > grid, +.budgie-polkit-dialog > box > grid, +.budgie-run-dialog > box > grid { + padding: 24px; +} + +.budgie-session-dialog.background, .budgie-session-dialog > decoration, +.budgie-polkit-dialog.background, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog.background, +.budgie-run-dialog > decoration { + border-radius: 12px; +} + +.budgie-session-dialog > decoration, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog > decoration { + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(40, 40, 40, 0.75); +} + +.budgie-session-dialog label:not(:last-child), +.budgie-session-dialog .dialog-title, +.budgie-polkit-dialog label:not(:last-child), +.budgie-polkit-dialog .dialog-title, +.budgie-run-dialog label:not(:last-child), +.budgie-run-dialog .dialog-title { + font-size: 120%; +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button { + padding: 8px 16px; + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0; +} + +.budgie-session-dialog .linked.horizontal > button:first-child, +.budgie-polkit-dialog .linked.horizontal > button:first-child, +.budgie-run-dialog .linked.horizontal > button:first-child { + border-bottom-left-radius: 12px; +} + +.budgie-session-dialog .linked.horizontal > button:last-child, +.budgie-polkit-dialog .linked.horizontal > button:last-child, +.budgie-run-dialog .linked.horizontal > button:last-child { + border-bottom-right-radius: 12px; +} + +.budgie-polkit-dialog .message { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-polkit-dialog .failure { + color: #c14a4a; +} + +.budgie-polkit-dialog > box > grid { + padding-bottom: 0; +} + +.budgie-run-dialog entry.search { + font-size: 120%; + padding: 6px 14px; + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.budgie-run-dialog list .dim-label { + color: #fbf1c7; +} + +.budgie-run-dialog scrolledwindow { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +/************** + * Xfce4 Apps * + **************/ +.XfceHeading { + background-color: #282524; +} + +/*************** + * xfce4-panel * + ***************/ +.xfce4-panel.background { + border: none; + background-color: rgba(40, 40, 40, 0.6); + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +.xfce4-panel.background button { + min-height: 16px; + min-width: 16px; + padding: 0 6px; + border-radius: 0; +} + +.xfce4-panel.background button.flat.toggle { + padding: 0 6px; +} + +.xfce4-panel.background .tasklist button image { + padding: 4px; +} + +wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +wnck-pager:selected { + background-color: #7daea3; +} + +#xfce4-mpc-plugin-26 > frame > border { + border: none; +} + +#xfce-panel-button { + -gtk-icon-style: symbolic; +} + +XfdesktopIconView.view { + border-radius: 12px; + background-color: transparent; + color: #fbf1c7; +} + +XfdesktopIconView.view:active { + box-shadow: none; +} + +XfdesktopIconView.view .rubberband { + border-radius: 0; +} + +window#whiskermenu-window { + border-radius: 12px; + background-color: transparent; + border: none; +} + +window#whiskermenu-window entry.search:focus { + background-color: #282524; +} + +window#whiskermenu-window > frame > border { + border-radius: 12px; + padding: 6px 8px 6px 9px; + margin: 6px; + border: none; + background-color: #242220; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3; +} + +window#whiskermenu-window box.categories > button.radio { + padding: 3px 6px; + margin: 1px 0; +} + +window#whiskermenu-window box.categories > button.radio:hover { + background-color: rgba(251, 241, 199, 0.12); +} + +window#whiskermenu-window box.categories > button.radio:checked, window#whiskermenu-window box.categories > button.radio:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +window#whiskermenu-window box.categories > button.radio:checked:hover, window#whiskermenu-window box.categories > button.radio:active:hover { + background-image: none; +} + +window#whiskermenu-window scrolledwindow.frame { + padding: 3px; + background-color: #282524; + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view { + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:not(:hover):not(:selected) { + background: none; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:selected:hover { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:checked, window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +#XfceNotifyWindow { + background-color: #282524; + border-radius: 12px; + border: 2px solid #7daea3; +} + +#XfceNotifyWindow buttonbox { + padding: 0; +} + +#XfceNotifyWindow label#summary { + font-weight: bold; +} + +dialog.xfsm-logout-dialog { + border-radius: 12px; + background-color: rgba(36, 34, 32, 0.97); + border: 2px solid #7daea3; +} + +#xfwm-tabwin { + padding: 12px; + border-radius: 12px; + -xfwmtabwinwidget-icon-size: 64px; + -xfwmtabwinwidget-preview-size: 64px; +} + +/********** + * Thunar * + **********/ +.thunar toolbar { + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.thunar .standard-view.frame { + border: none; +} + +.thunar scrolledwindow.frame.sidebar { + border-top: none; +} + +.thunar .path-bar.linked:not(.vertical) > button.path-bar-button { + margin-left: 2px; + margin-right: 2px; +} + +.thunar statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-top: none; +} + +window.background.csd.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-bottom-left-radius: 12px; +} + +menubar.-vala-panel-appmenu-private, +menubar.-vala-panel-background { + background: none; + border: none; + box-shadow: none; + animation: none; +} + +menubar.-vala-panel-appmenu-private > menuitem, +menubar.-vala-panel-background > menuitem { + color: rgba(251, 241, 199, 0.7); + font-weight: normal; +} + +menubar.-vala-panel-appmenu-private > menuitem:hover, +menubar.-vala-panel-background > menuitem:hover { + color: #fbf1c7; + border-radius: 0; +} + +menubar.-vala-panel-appmenu-private > menuitem:disabled, +menubar.-vala-panel-background > menuitem:disabled { + color: rgba(251, 241, 199, 0.32); +} + +/************************ + * LightDM GTK+ Greeter * + ************************/ +#panel_window { + background-color: #282524; + color: #fbf1c7; +} + +#panel_window menubar, +#panel_window separator { + background-color: transparent; +} + +#panel_window separator { + padding: 0 4px; +} + +#panel_window separator:first-child { + padding: 0 8px; +} + +#panel_window menubar > menuitem { + color: rgba(251, 241, 199, 0.7); +} + +#panel_window menubar > menuitem:hover { + color: #fbf1c7; +} + +#panel_window menubar > menuitem:disabled label { + color: rgba(251, 241, 199, 0.32); +} + +#login_window, +#shutdown_dialog, +#restart_dialog { + margin: 8px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +#content_frame { + padding-bottom: 16px; +} + +#buttonbox_frame { + padding-top: 24px; +} + +#buttonbox_frame > box, +#buttonbox_frame > buttonbox { + margin: -16px; +} + +#buttonbox_frame button:not(:disabled) { + color: #7daea3; +} + +/******** + * Nemo * + ********/ +.nemo-window .primary-toolbar { + background-color: #282828; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.nemo-window .primary-toolbar entry { + min-height: 0; + margin: 0; +} + +.nemo-window .primary-toolbar > toolitem > .linked > button.image-button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar button.text-button { + padding-left: 8px; + padding-right: 8px; + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar button.text-button:hover, .nemo-window .primary-toolbar button.text-button:active, .nemo-window .primary-toolbar button.text-button:checked { + color: #fbf1c7; +} + +.nemo-window .primary-toolbar button.text-button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar button.text-button:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button:checked { + box-shadow: none; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button { + border-radius: 6px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.nemo-window .primary-toolbar button:not(.text-button):not(.image-button) { + padding-left: 4px; + padding-right: 4px; +} + +.nemo-window scrolledwindow.frame { + border-style: none; +} + +.nemo-window scrolledwindow.frame .view:not(:selected) { + background-color: transparent; +} + +.nemo-window .nemo-inactive-pane .view:not(:selected) { + background-color: #282524; +} + +.nemo-window .nemo-window-pane widget.entry { + border-radius: 6px; + background-color: rgba(251, 241, 199, 0.04); +} + +.nemo-window .nemo-window-pane > notebook { + border-radius: 0; +} + +.places-treeview { + -nemoplacestreeview-disk-full-bg-color: #676458; + -nemoplacestreeview-disk-full-fg-color: #7daea3; + -nemoplacestreeview-disk-full-bar-width: 2px; + -nemoplacestreeview-disk-full-bar-radius: 0; + -nemoplacestreeview-disk-full-bottom-padding: 1px; + -nemoplacestreeview-disk-full-max-length: 80px; + padding-top: 3px; + padding-bottom: 3px; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #fbf1c7; +/* text color for entries, views and content in general */ +@define-color theme_text_color #fbf1c7; +/* widget base background color */ +@define-color theme_bg_color #282828; +/* text widgets and the like base background color */ +@define-color theme_base_color #282524; +/* base background color of selections */ +@define-color theme_selected_bg_color #7daea3; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(40, 40, 40, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #282828; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(251, 241, 199, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #282524; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #fbf1c7; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #fbf1c7; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #282828; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #282524; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #7daea3; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(40, 40, 40, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(251, 241, 199, 0.5); +/* widgets main borders color */ +@define-color borders rgba(251, 241, 199, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(251, 241, 199, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #b47109; +@define-color error_color #c14a4a; +@define-color success_color #6c782e; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #fbf1c7; +@define-color wm_unfocused_title rgba(251, 241, 199, 0.7); +@define-color wm_highlight rgba(251, 241, 199, 0.1); +@define-color wm_border #080707; +@define-color wm_focused_bg #282828; +@define-color wm_unfocused_bg #282828; +@define-color wm_button_icon #fbf1c7; +@define-color wm_button_icon alpha(black, 0.5); +@define-color wm_button_focused_bg #353432; +@define-color wm_button_unfocused_bg #353432; +@define-color wm_button_hover_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_active_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_hover_bg #fbf1c7; +@define-color wm_button_active_bg #fbf1c7; +/* FIXME this is really an API */ +@define-color content_view_bg #282524; +@define-color placeholder_text_color #bcb496; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #282524; +@define-color budgie_tasklist_indicator_color rgba(132, 128, 110, 0.7); +@define-color budgie_tasklist_indicator_color_active #7daea3; +@define-color budgie_tasklist_indicator_color_active_window rgba(102, 138, 130, 0.816); +@define-color budgie_tasklist_indicator_color_attention #b47109; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk.css b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk.css new file mode 100755 index 0000000..fdd02f9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/gtk.css @@ -0,0 +1,8576 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #7daea3 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #7daea3 100%, transparent 0%); + } +} + +* { + background-clip: padding-box; + -gtktoolbutton-icon-spacing: 4; + -gtktextview-error-underline-color: #c14a4a; + -gtkscrolledwindow-scrollbar-spacing: 0; + -gtktoolitemgroup-expander-size: 11; + -gtkwidget-text-handle-width: 20; + -gtkwidget-text-handle-height: 20; + -gtkdialog-button-spacing: 6; + -gtkdialog-action-area-border: 4; + -gtkdialog-content-area-border: 4; + outline-style: solid; + outline-width: 0; + outline-color: alpha(currentColor, 0.15); + outline-offset: -4px; + -gtk-outline-radius: 12px; + -gtk-secondary-caret-color: #7daea3; +} + +.thunar .standard-view.frame widget.view:selected, XfdesktopIconView.view:active, calendar.raven-calendar:selected, box.vertical > widget > widget:selected, calendar:selected, modelbutton.flat:selected, +.menuitem.button.flat:selected, .background.csd .view:selected { + color: #fbf1c7; + background-color: alpha(currentColor, 0.1); +} + +.nautilus-window notebook .view:not(treeview) selection, .nautilus-window notebook .view:not(treeview):selected, .nautilus-window flowboxchild:selected .icon-item-background, label selection, flowbox flowboxchild:selected { + color: #7daea3; + background-color: rgba(125, 174, 163, 0.2); +} + +.nemo-window .nemo-window-pane widget.entry:selected, window.background.csd evview.view.content-view:selected, window.background.csd evview.view.content-view:selected:backdrop, .nautilus-window.background.csd notebook widget.view:selected, spinbutton.vertical selection, spinbutton:not(.vertical) selection, +entry selection, textview text selection:focus, textview text selection, widget.view:selected, .view:selected { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +treeview.view:selected { + color: rgba(40, 40, 40, 0.87); + background-color: #fbf1c7; +} + +.linked:not(.vertical) > button, .linked:not(.vertical) > spinbutton.vertical, .linked:not(.vertical) > spinbutton:not(.vertical), .linked:not(.vertical) > entry { + border-radius: 0; +} + +.linked:not(.vertical) > button:first-child, .linked:not(.vertical) > spinbutton.vertical:first-child, .linked:not(.vertical) > spinbutton:first-child:not(.vertical), .linked:not(.vertical) > entry:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > button:last-child, .linked:not(.vertical) > spinbutton.vertical:last-child, .linked:not(.vertical) > spinbutton:last-child:not(.vertical), .linked:not(.vertical) > entry:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > button:only-child, .linked:not(.vertical) > spinbutton.vertical:only-child, .linked:not(.vertical) > spinbutton:only-child:not(.vertical), .linked:not(.vertical) > entry:only-child { + border-radius: 12px; +} + +.linked.vertical > button, .linked.vertical > spinbutton.vertical, .linked.vertical > spinbutton:not(.vertical), .linked.vertical > entry { + border-radius: 0; +} + +.linked.vertical > button:first-child, .linked.vertical > spinbutton.vertical:first-child, .linked.vertical > spinbutton:first-child:not(.vertical), .linked.vertical > entry:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > button:last-child, .linked.vertical > spinbutton.vertical:last-child, .linked.vertical > spinbutton:last-child:not(.vertical), .linked.vertical > entry:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > button:only-child, .linked.vertical > spinbutton.vertical:only-child, .linked.vertical > spinbutton:only-child:not(.vertical), .linked.vertical > entry:only-child { + border-radius: 12px; +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #282828; + color: #fbf1c7; +} + +.background.csd { + border-radius: 0 0 12px 12px; +} + +.background.maximized, .background.solid-csd { + border-radius: 0; +} + +*:disabled { + -gtk-icon-effect: dim; +} + +.gtkstyle-fallback { + background-color: #282828; + color: #fbf1c7; +} + +.gtkstyle-fallback:hover { + background-color: #1b1b1b; + color: #fbf1c7; +} + +.gtkstyle-fallback:active { + background-color: #0f0f0f; + color: #fbf1c7; +} + +.gtkstyle-fallback:disabled { + background-color: #282828; + color: rgba(251, 241, 199, 0.5); +} + +.gtkstyle-fallback:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.view { + background-color: #282524; + color: #fbf1c7; +} + +.view:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.view:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.view:selected:hover { + box-shadow: none; +} + +window.background.csd > stack.view { + border-radius: 0 0 12px 12px; +} + +textview text { + background-color: #282524; +} + +textview border { + background-color: #282524; + color: rgba(251, 241, 199, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 12px; +} + +flowbox rubberband, +.rubberband, +rubberband, +XfdesktopIconView.view .rubberband, +.content-view rubberband, +.content-view .rubberband, +treeview.view rubberband { + border: 1px solid #7daea3; + background-color: rgba(125, 174, 163, 0.3); +} + +flowbox flowboxchild { + padding: 3px; + border-radius: 12px; + color: #fbf1c7; +} + +flowbox flowboxchild button.osd.remove-button { + min-height: 28px; + min-width: 28px; + padding: 0; + margin: 6px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +label { + caret-color: currentColor; +} + +label.separator { + color: rgba(251, 241, 199, 0.7); +} + +label:disabled { + color: rgba(251, 241, 199, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; +} + +label.osd { + border-radius: 12px; + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; +} + +.dim-label { + color: rgba(251, 241, 199, 0.7); +} + +assistant .sidebar { + padding: 4px 0; +} + +assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(251, 241, 199, 0.5); + font-weight: 500; +} + +assistant .sidebar label.highlight { + color: #fbf1c7; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + -gtk-icon-transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry { + background-color: rgba(40, 40, 40, 0.04); + color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus { + color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:drop(active) { + color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:disabled { + background-color: rgba(40, 40, 40, 0.04); + color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image { + color: rgba(40, 40, 40, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry image:disabled { + color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:hover image, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack entry:focus image { + color: rgba(40, 40, 40, 0.87); +} + +spinbutton.vertical, spinbutton:not(.vertical), +entry { + min-height: 34px; + padding: 0 8px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton.vertical:focus, spinbutton:focus:not(.vertical), +entry:focus { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #7daea3; +} + +spinbutton.vertical:drop(active), spinbutton:drop(active):not(.vertical), +entry:drop(active) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + +spinbutton.vertical:disabled, spinbutton:disabled:not(.vertical), +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.flat.vertical, spinbutton.flat:not(.vertical), +entry.flat { + min-height: 0; + padding: 2px; + border-radius: 0; + background-color: transparent; +} + +spinbutton.vertical image, spinbutton:not(.vertical) image, +entry image { + color: rgba(251, 241, 199, 0.7); +} + +spinbutton.vertical image:hover, spinbutton:not(.vertical) image:hover, spinbutton.vertical image:active, spinbutton:not(.vertical) image:active, +entry image:hover, +entry image:active { + color: #fbf1c7; +} + +spinbutton.vertical image:disabled, spinbutton:not(.vertical) image:disabled, +entry image:disabled { + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.vertical image.left, spinbutton:not(.vertical) image.left, +entry image.left { + margin-left: 1px; + margin-right: 6px; +} + +spinbutton.vertical image.right, spinbutton:not(.vertical) image.right, +entry image.right { + margin-left: 6px; + margin-right: 1px; +} + +spinbutton.vertical undershoot.left, spinbutton:not(.vertical) undershoot.left, +entry undershoot.left { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(251, 241, 199, 0.3) 50%); + padding-left: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: left top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.vertical undershoot.right, spinbutton:not(.vertical) undershoot.right, +entry undershoot.right { + background-color: transparent; + background-image: linear-gradient(to top, transparent 50%, rgba(251, 241, 199, 0.3) 50%); + padding-right: 1px; + background-size: 1px 12px; + background-repeat: repeat-y; + background-origin: content-box; + background-position: right top; + margin: 0 4px; + margin: 4px 0; +} + +spinbutton.error.vertical, spinbutton.error:not(.vertical), +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton.error.vertical:focus, spinbutton.error:focus:not(.vertical), +entry.error:focus { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #c14a4a; +} + +spinbutton.error.vertical:disabled, spinbutton.error:disabled:not(.vertical), +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.warning.vertical, spinbutton.warning:not(.vertical), +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton.warning.vertical:focus, spinbutton.warning:focus:not(.vertical), +entry.warning:focus { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #b47109; +} + +spinbutton.warning.vertical:disabled, spinbutton.warning:disabled:not(.vertical), +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.vertical progress, spinbutton:not(.vertical) progress, +entry progress { + margin: 2px -8px; + border-bottom: 2px solid #7daea3; + background-color: transparent; +} + +treeview entry.flat, treeview entry { + background-color: #282524; +} + +treeview entry.flat, treeview entry.flat:focus, treeview entry, treeview entry:focus { + border-image: none; + box-shadow: none; +} + +.entry-tag, .photos-entry-tag, .documents-entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.entry-tag:hover, .photos-entry-tag:hover, .documents-entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag, :dir(ltr) .photos-entry-tag, :dir(ltr) .documents-entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag, :dir(rtl) .photos-entry-tag, :dir(rtl) .documents-entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button, .button.photos-entry-tag, .button.documents-entry-tag { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active), .button.photos-entry-tag:not(:hover):not(:active), .button.documents-entry-tag:not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.001, to(#7daea3), to(transparent)); + } + to { + background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(#7daea3), to(transparent)); + } +} + +.xfce4-panel.background button, .raven-mpris button.image-button, .mate-panel-menu-bar button, infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button { + color: rgba(251, 241, 199, 0.7); +} + +.xfce4-panel.background button:focus, .raven-mpris button.image-button:focus, .mate-panel-menu-bar button:focus, infobar.warning > revealer > box button:focus, .xfce4-panel.background button:hover, .raven-mpris button.image-button:hover, .mate-panel-menu-bar button:hover, infobar.warning > revealer > box button:hover, .xfce4-panel.background button:active, .raven-mpris button.image-button:active, .mate-panel-menu-bar button:active, infobar.warning > revealer > box button:active, .xfce4-panel.background button:checked, .raven-mpris button.image-button:checked, .mate-panel-menu-bar button:checked, infobar.warning > revealer > box button:checked { + color: #fbf1c7; +} + +.xfce4-panel.background button:disabled, .raven-mpris button.image-button:disabled, .mate-panel-menu-bar button:disabled, infobar.warning > revealer > box button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.xfce4-panel.background button:checked:disabled, .raven-mpris button.image-button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, infobar.warning > revealer > box button:checked:disabled { + color: rgba(251, 241, 199, 0.5); +} + +actionbar > revealer > box button:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: #282524; + color: #fbf1c7; +} + +actionbar > revealer > box button:checked:not(.suggested-action):not(.destructive-action):not(.combo) { + background-color: rgba(40, 40, 40, 0.87); + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat, terminal-window notebook > header > box button.flat { + color: rgba(40, 40, 40, 0.6); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:hover, terminal-window notebook > header > box button.flat:hover, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:active, terminal-window notebook > header > box button.flat:active, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:focus, terminal-window notebook > header > box button.flat:focus { + color: rgba(40, 40, 40, 0.87); +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:checked, terminal-window notebook > header > box button.flat:checked { + background-color: rgba(40, 40, 40, 0.87); + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list button.flat:disabled, terminal-window notebook > header > box button.flat:disabled { + color: rgba(40, 40, 40, 0.3); +} + +button { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(251, 241, 199, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #fbf1c7; +} + +button:focus { + box-shadow: 0 0 0 2px rgba(125, 174, 163, 0.35); +} + +button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +button:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +button:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +button:checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +button:checked:hover { + box-shadow: inset 0 0 0 9999px transparent; +} + +button:checked:disabled { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.1); + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +.raven .expander-button, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, .nautilus-window headerbar revealer > button, button.titlebutton:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, button.close, button.circular, .inline-toolbar button:not(.text-button) { + border-radius: 9999px; +} + +.raven .expander-button label, window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle label, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat) label, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button label, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button label, .nautilus-window headerbar revealer > button label, button.titlebutton:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, button.close label, button.circular label, .inline-toolbar button:not(.text-button) label { + padding: 0; +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat, .gedit-document-panel row button.flat, .nautilus-window .floating-bar button, placessidebar.sidebar row button.sidebar-button, notebook > header tab button.flat, +notebook > header tab button.close-button, spinbutton.vertical button, spinbutton:not(.vertical) button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button, .drop-shadow button, .budgie-panel button, .budgie-popover row button, .budgie-settings-window buttonbox.inline-toolbar button, #mate-menu button, #MatePanelPopupWindow button, popover.messagepopover .popover-action-area button, tabbox > tab button, placessidebar.sidebar row button.sidebar-button, calendar.button, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular, treeview.view header button button.circular, row.activatable button.circular, notebook > header > tabs > arrow, modelbutton.flat, +.menuitem.button.flat, spinbutton.vertical button, spinbutton:not(.vertical) button, .nemo-window .toolbar button, #buttonbox_frame button, .xfce4-panel.background button, .raven stackswitcher.linked > button, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button, .lock-dialog button, .mate-panel-menu-bar button, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button, layouttabbar button, filechooser #pathbarbox > stack > box > button, messagedialog .dialog-action-box button, +messagedialog .dialog-action-box .linked:not(.vertical) > button, .app-notification button, popover.background.menu button, +popover.background button.model, .nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action), button.flat { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: rgba(251, 241, 199, 0.7); +} + +.budgie-session-dialog .linked.horizontal > button:focus, +.budgie-polkit-dialog .linked.horizontal > button:focus, +.budgie-run-dialog .linked.horizontal > button:focus, .drop-shadow button:focus, .budgie-panel button:focus, .budgie-popover row button:focus, .budgie-settings-window buttonbox.inline-toolbar button:focus, #mate-menu button:focus, #MatePanelPopupWindow button:focus, popover.messagepopover .popover-action-area button:focus, tabbox > tab button:focus, placessidebar.sidebar row button.sidebar-button:focus, calendar.button:focus, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:focus, treeview.view header button button.circular:focus, row.activatable button.circular:focus, notebook > header > tabs > arrow:focus, modelbutton.flat:focus, +.menuitem.button.flat:focus, spinbutton.vertical button:focus, spinbutton:not(.vertical) button:focus, .nemo-window .toolbar button:focus, #buttonbox_frame button:focus, .xfce4-panel.background button:focus, .raven stackswitcher.linked > button:focus, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:focus, .lock-dialog button:focus, .mate-panel-menu-bar button:focus, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:focus, layouttabbar button:focus, filechooser #pathbarbox > stack > box > button:focus, messagedialog .dialog-action-box button:focus, +messagedialog .dialog-action-box .linked:not(.vertical) > button:focus, .app-notification button:focus, popover.background.menu button:focus, +popover.background button.model:focus, .nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), button.flat:focus { + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + color: #fbf1c7; +} + +.budgie-session-dialog .linked.horizontal > button:hover, +.budgie-polkit-dialog .linked.horizontal > button:hover, +.budgie-run-dialog .linked.horizontal > button:hover, .drop-shadow button:hover, .budgie-panel button:hover, .budgie-popover row button:hover, .budgie-settings-window buttonbox.inline-toolbar button:hover, #mate-menu button:hover, #MatePanelPopupWindow button:hover, popover.messagepopover .popover-action-area button:hover, tabbox > tab button:hover, placessidebar.sidebar row button.sidebar-button:hover, calendar.button:hover, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:hover, treeview.view header button button.circular:hover, row.activatable button.circular:hover, notebook > header > tabs > arrow:hover, modelbutton.flat:hover, +.menuitem.button.flat:hover, spinbutton.vertical button:hover, spinbutton:not(.vertical) button:hover, .nemo-window .toolbar button:hover, #buttonbox_frame button:hover, .xfce4-panel.background button:hover, .raven stackswitcher.linked > button:hover, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:hover, .lock-dialog button:hover, .mate-panel-menu-bar button:hover, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:hover, layouttabbar button:hover, filechooser #pathbarbox > stack > box > button:hover, messagedialog .dialog-action-box button:hover, +messagedialog .dialog-action-box .linked:not(.vertical) > button:hover, .app-notification button:hover, popover.background.menu button:hover, +popover.background button.model:hover, .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), button.flat:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #fbf1c7; +} + +.budgie-session-dialog .linked.horizontal > button:active, +.budgie-polkit-dialog .linked.horizontal > button:active, +.budgie-run-dialog .linked.horizontal > button:active, .drop-shadow button:active, .budgie-panel button:active, .budgie-popover row button:active, .budgie-settings-window buttonbox.inline-toolbar button:active, #mate-menu button:active, #MatePanelPopupWindow button:active, popover.messagepopover .popover-action-area button:active, tabbox > tab button:active, placessidebar.sidebar row button.sidebar-button:active, calendar.button:active, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:active, treeview.view header button button.circular:active, row.activatable button.circular:active, notebook > header > tabs > arrow:active, modelbutton.flat:active, +.menuitem.button.flat:active, spinbutton.vertical button:active, spinbutton:not(.vertical) button:active, .nemo-window .toolbar button:active, #buttonbox_frame button:active, .xfce4-panel.background button:active, .raven stackswitcher.linked > button:active, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:active, .lock-dialog button:active, .mate-panel-menu-bar button:active, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:active, layouttabbar button:active, filechooser #pathbarbox > stack > box > button:active, messagedialog .dialog-action-box button:active, +messagedialog .dialog-action-box .linked:not(.vertical) > button:active, .app-notification button:active, popover.background.menu button:active, +popover.background button.model:active, .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), button.flat:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #fbf1c7; +} + +.budgie-session-dialog .linked.horizontal > button:disabled, +.budgie-polkit-dialog .linked.horizontal > button:disabled, +.budgie-run-dialog .linked.horizontal > button:disabled, .drop-shadow button:disabled, .budgie-panel button:disabled, .budgie-popover row button:disabled, .budgie-settings-window buttonbox.inline-toolbar button:disabled, #mate-menu button:disabled, #MatePanelPopupWindow button:disabled, popover.messagepopover .popover-action-area button:disabled, tabbox > tab button:disabled, placessidebar.sidebar row button.sidebar-button:disabled, calendar.button:disabled, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable button.circular:disabled, treeview.view header button button.circular:disabled, row.activatable button.circular:disabled, notebook > header > tabs > arrow:disabled, modelbutton.flat:disabled, +.menuitem.button.flat:disabled, spinbutton.vertical button:disabled, spinbutton:not(.vertical) button:disabled, .nemo-window .toolbar button:disabled, #buttonbox_frame button:disabled, .xfce4-panel.background button:disabled, .raven stackswitcher.linked > button:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:disabled, .lock-dialog button:disabled, .mate-panel-menu-bar button:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:disabled, layouttabbar button:disabled, filechooser #pathbarbox > stack > box > button:disabled, messagedialog .dialog-action-box button:disabled, +messagedialog .dialog-action-box .linked:not(.vertical) > button:disabled, .app-notification button:disabled, popover.background.menu button:disabled, +popover.background button.model:disabled, .nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action), button.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .toolbar button:checked, #buttonbox_frame button:checked, .xfce4-panel.background button:checked, .raven stackswitcher.linked > button:checked, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked, .lock-dialog button:checked, .mate-panel-menu-bar button:checked, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked, layouttabbar button:checked, filechooser #pathbarbox > stack > box > button:checked, messagedialog .dialog-action-box button:checked, +messagedialog .dialog-action-box .linked:not(.vertical) > button:checked, .app-notification button:checked, popover.background.menu button:checked, +popover.background button.model:checked, .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action), button.flat:checked, button.flat:checked:hover { + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +.nemo-window .toolbar button:checked:disabled, #buttonbox_frame button:checked:disabled, .xfce4-panel.background button:checked:disabled, .raven stackswitcher.linked > button:checked:disabled, .budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button:checked:disabled, .lock-dialog button:checked:disabled, .mate-panel-menu-bar button:checked:disabled, window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar button:checked:disabled, layouttabbar button:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, messagedialog .dialog-action-box button:checked:disabled, .app-notification button:checked:disabled, popover.background.menu button:checked:disabled, +popover.background button.model:checked:disabled, .nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(251, 241, 199, 0.5); +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child) { + margin: 0 4px; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + border-radius: 12px; +} + +button.osd { + min-width: 24px; + min-width: 24px; + padding: 5px; + background-color: #282828; + color: #fbf1c7; +} + +button.osd:focus { + box-shadow: none; +} + +button.osd:hover { + background-color: #484640; + color: #fbf1c7; +} + +button.osd:active { + background-color: #5d5a50; + color: #fbf1c7; +} + +button.osd:disabled { + opacity: 0; +} + +button.osd.image-button, button.osd.circular { + padding: 11px; +} + +button.osd.image-button > image, button.osd.circular > image { + padding: 0; +} + +button.suggested-action { + background-color: #45707a; + color: #fbf1c7; + box-shadow: none; +} + +button.suggested-action:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(69, 112, 122, 0.2), 0 4px 3px 0 rgba(69, 112, 122, 0.14), 0 1px 6px 0 rgba(69, 112, 122, 0.12); +} + +button.suggested-action:checked { + background-color: #7c9791; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(69, 112, 122, 0.3), 0 2px 3px -1px rgba(69, 112, 122, 0.24), 0 2px 5px 0 rgba(69, 112, 122, 0.12); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(69, 112, 122, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #45707a; +} + +button.suggested-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +button.suggested-action.flat:checked { + background-color: rgba(69, 112, 122, 0.3); +} + +button.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; + box-shadow: none; +} + +button.destructive-action:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(193, 74, 74, 0.2), 0 4px 3px 0 rgba(193, 74, 74, 0.14), 0 1px 6px 0 rgba(193, 74, 74, 0.12); +} + +button.destructive-action:checked { + background-color: #d27c70; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(193, 74, 74, 0.3), 0 2px 3px -1px rgba(193, 74, 74, 0.24), 0 2px 5px 0 rgba(193, 74, 74, 0.12); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(193, 74, 74, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #c14a4a; +} + +button.destructive-action.flat:disabled { + box-shadow: none; + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +button.destructive-action.flat:checked { + background-color: rgba(193, 74, 74, 0.3); +} + +.stack-switcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +.stack-switcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +.stack-switcher > button.needs-attention:checked > label, +.stack-switcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +.primary-toolbar button { + -gtk-icon-shadow: none; +} + +button.close, button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +stacksidebar.sidebar row.needs-attention > label, .stack-switcher > button.needs-attention > label, +.stack-switcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar.sidebar row.needs-attention > label:dir(rtl), .stack-switcher > button.needs-attention > label:dir(rtl), +.stack-switcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + +/********* + * Links * + *********/ +*:link, +link { + color: #83b193; +} + +*:visited { + color: #ab62b1; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #83b193; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #ab62b1; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton:not(.vertical) { + padding: 0; +} + +spinbutton:not(.vertical) entry { + min-width: 30px; + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +spinbutton:not(.vertical) button { + border: solid 6px transparent; +} + +spinbutton:not(.vertical) button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(251, 241, 199, 0.7); +} + +spinbutton:not(.vertical) button.up:dir(ltr), spinbutton:not(.vertical) button.down:dir(rtl) { + margin-left: -3px; +} + +spinbutton:not(.vertical) button.up:dir(rtl), spinbutton:not(.vertical) button.down:dir(ltr) { + margin-right: -3px; +} + +spinbutton.vertical { + padding: 0; +} + +spinbutton.vertical:disabled { + color: rgba(251, 241, 199, 0.5); +} + +spinbutton.vertical entry { + margin: 0; + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical button { + padding: 0; + border: solid 6px transparent; +} + +spinbutton.vertical button:focus:not(:hover):not(:active) { + box-shadow: inset 0 0 0 9999px transparent; + color: rgba(251, 241, 199, 0.7); +} + +spinbutton.vertical button.up { + margin: 0 3px; +} + +spinbutton.vertical button.down { + margin: 0 3px; +} + +treeview spinbutton:not(.vertical) { + min-height: 0; + border-style: none; + border-radius: 0; +} + +treeview spinbutton:not(.vertical) entry { + min-height: 0; + padding: 1px 2px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-radius: 0 9px 9px 0; + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #e78a4e; + box-shadow: inset 0 0 0 2px #e78a4e; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #fbf1c7; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top), combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) { + background-color: transparent; + background-image: linear-gradient(to left, transparent 50%, rgba(251, 241, 199, 0.3) 50%); + padding-top: 1px; + background-size: 12px 1px; + background-repeat: repeat-x; + background-origin: content-box; + background-position: left top; + margin: 0 4px; +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +toolbar { + -gtkwidget-window-dragging: true; + padding: 2px 3px; + background-color: #282828; +} + +.osd toolbar { + background-color: transparent; +} + +frame.documents-dropdown, .app-notification, toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +frame.documents-dropdown:backdrop, .app-notification:backdrop, toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +frame.left.documents-dropdown, .left.app-notification, frame.right.documents-dropdown, .right.app-notification, frame.top.documents-dropdown, .top.app-notification, frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.left, toolbar.osd.right, toolbar.osd.top, toolbar.osd.bottom { + border-radius: 0; +} + +frame.bottom.documents-dropdown, .bottom.app-notification, toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +toolbar.horizontal > separator { + margin: 2px; +} + +toolbar.vertical > separator { + margin: 2px; +} + +toolbar:not(.inline-toolbar):not(.osd) scale, +toolbar:not(.inline-toolbar):not(.osd) entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton, +toolbar:not(.inline-toolbar):not(.osd) button { + margin: 2px 1px; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:first-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:first-child) { + margin-left: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) .linked entry:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked spinbutton:not(:last-child), +toolbar:not(.inline-toolbar):not(.osd) .linked button:not(:last-child) { + margin-right: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) spinbutton entry, +toolbar:not(.inline-toolbar):not(.osd) spinbutton button { + margin: 0; +} + +toolbar:not(.inline-toolbar):not(.osd) switch { + margin: 8px 2px; +} + +.toolbar { + background-color: #282524; +} + +frame .toolbar { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.inline-toolbar { + padding: 6px; + border-style: solid; + border-width: 0 1px 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +.frame .inline-toolbar { + border-width: 1px 0 0; + background-color: transparent; +} + +searchbar > revealer > box, +.location-bar { + padding: 6px; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282828; + background-clip: border-box; +} + +searchbar > revealer > box { + margin: -6px; +} + +/*************** + * Header bars * + ***************/ +.nemo-window .primary-toolbar button:not(.text-button), headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar .linked:not(.vertical) > button:not(.text-button), headerbar .linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + border-radius: 12px; +} + +.nemo-window .primary-toolbar button:focus:not(.text-button), headerbar button:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:hover:not(.text-button), headerbar button:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:active:not(.text-button), headerbar button:active:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:checked:not(.text-button), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +.nemo-window .primary-toolbar button:disabled:not(.text-button), headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar button:checked:disabled:not(.text-button), headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:not(.text-button), headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar button:backdrop:focus:not(.text-button), headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:hover:not(.text-button), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), .nemo-window .primary-toolbar button:backdrop:active:not(.text-button), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:disabled:not(.text-button), headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar button:backdrop:checked:not(.text-button), headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar button:backdrop:checked:disabled:not(.text-button), headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar entry, .titlebar entry { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +.nemo-window .primary-toolbar entry:disabled, .titlebar entry:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar entry image, .titlebar entry image { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar entry image:hover, .titlebar entry image:hover, .nemo-window .primary-toolbar entry image:active, .titlebar entry image:active { + color: #fbf1c7; +} + +.nemo-window .primary-toolbar entry image:disabled, .titlebar entry image:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.titlebar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #282828; + color: #fbf1c7; + border-radius: 12px 12px 0 0; + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* @if $outline == 'false' { */ + /* box-shadow: inset 0 1px highlight($titlebar); */ + /* } */ +} + +.titlebar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.titlebar:backdrop { + color: rgba(251, 241, 199, 0.7); +} + +.titlebar:backdrop:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.csd .titlebar:backdrop { + background-color: #282828; +} + +.titlebar .title { + padding: 0 12px; + font-weight: bold; +} + +.titlebar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +.titlebar .subtitle, +.titlebar .dim-label { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(251, 241, 199, 0.7); +} + +.titlebar .subtitle:backdrop, +.titlebar .dim-label:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +.titlebar .titlebar { + background-color: transparent; + box-shadow: none; +} + +.titlebar + separator, +.titlebar + separator.sidebar { + background-color: #282828; + background-image: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +.titlebar + separator:backdrop, +.titlebar + separator.sidebar:backdrop { + background-color: #282828; +} + +.titlebar.selection-mode + separator, .titlebar.selection-mode + separator.sidebar, .selection-mode .titlebar + separator, .selection-mode .titlebar + separator.sidebar { + background-color: #7daea3; +} + +.titlebar.selection-mode + separator:backdrop, .titlebar.selection-mode + separator.sidebar:backdrop, .selection-mode .titlebar + separator:backdrop, .selection-mode .titlebar + separator.sidebar:backdrop { + background-color: #7daea3; +} + +.background.csd.unified .titlebar + separator, .background.csd.unified .titlebar + separator.sidebar { + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.titlebar .linked:not(.vertical) > entry { + border-radius: 12px; + margin-left: 3px; + margin-right: 3px; +} + +.titlebar button.suggested-action:disabled, +.titlebar button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +.titlebar .path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; + padding-left: 5px; + padding-right: 5px; +} + +.titlebar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + animation: ripple-on-headerbar 225ms cubic-bezier(0, 0, 0.2, 1); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode:backdrop { + color: rgba(40, 40, 40, 0.6); + background-color: #90bab0; +} + +.titlebar.selection-mode .subtitle:link { + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):disabled { + color: rgba(40, 40, 40, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked { + color: rgba(40, 40, 40, 0.87); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):checked:disabled { + color: rgba(40, 40, 40, 0.38); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:not(.titlebutton) { + color: rgba(40, 40, 40, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:disabled { + color: rgba(40, 40, 40, 0.3); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked { + color: rgba(40, 40, 40, 0.6); +} + +.titlebar.selection-mode button:not(.suggested-action):not(.destructive-action):backdrop:checked:disabled { + color: rgba(40, 40, 40, 0.3); +} + +.titlebar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +.titlebar.selection-mode .selection-menu arrow { + -gtkarrow-arrow-scaling: 1; +} + +.titlebar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +.tiled .titlebar, .tiled-top .titlebar, .tiled-right .titlebar, .tiled-bottom .titlebar, .tiled-left .titlebar, .maximized .titlebar, .fullscreen .titlebar { + border-radius: 0; +} + +.titlebar.default-decoration { + min-height: 24px; + padding: 6px 12px; + border-radius: 12px 12px 0 0; + border: none; + background-color: #282828; + background-image: none; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +.titlebar.default-decoration:backdrop { + background-color: #282828; +} + +.tiled .titlebar.default-decoration, .maximized .titlebar.default-decoration, .fullscreen .titlebar.default-decoration { + box-shadow: none; + border-radius: 0; +} + +.titlebar.default-decoration button.titlebutton { + min-height: 24px; + min-width: 24px; + margin: 0; + padding: 0; +} + +.background.csd .titlebar.default-decoration { + padding: 6px; + box-shadow: none; +} + +.background:not(.csd) .titlebar.default-decoration button.titlebutton:active { + background-size: 1000% 1000%; +} + +.solid-csd .titlebar:dir(rtl), .solid-csd .titlebar:dir(ltr) { + border-radius: 0; + box-shadow: none; +} + +headerbar { + min-height: 46px; + padding: 0 6px; +} + +box.vertical headerbar { + background-color: #282828; +} + +headerbar entry, +headerbar spinbutton, +headerbar button, +headerbar stackswitcher { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar button, +headerbar button.image-button { + border-radius: 12px; +} + +headerbar > box.left, +headerbar > box.right { + padding: 0 4px; +} + +headerbar separator.titlebutton, +headerbar separator.sidebar { + margin-top: 11.5px; + margin-bottom: 11.5px; + background-color: transparent; +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar spinbutton button { + margin-top: 0; + margin-bottom: 0; +} + +headerbar .entry-tag, headerbar .photos-entry-tag, headerbar .documents-entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar.windowhandle viewswitcher { + border-radius: 0 0 12px 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) { + border-radius: 9px; + margin: 6px 3px; + min-width: 120px; + padding: 0; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +) > stack > box { + padding: 0 12px; +} + +headerbar.windowhandle viewswitcher button:not(.titlebutton):not(.suggested-action):not( +.destructive-action +):focus { + box-shadow: none; +} + +headerbar.windowhandle > button.popup label, +headerbar.windowhandle > button.popup image { + min-height: 0; +} + +headerbar.windowhandle viewswitchertitle > squeezer { + margin-top: 0; + margin-bottom: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher { + margin: 0; + background: none; +} + +headerbar.windowhandle viewswitchertitle > squeezer > viewswitcher > box.horizontal > button.radio { + margin: 0; + padding: 0; + border-radius: 0; +} + +/************ + * Pathbars * + ************/ +.caja-pathbar button, +.path-bar.linked:not(.vertical) > button { + padding-left: 5px; + padding-right: 5px; + border-radius: 6px; + margin-left: 1px; + margin-right: 1px; + background-color: alpha(currentColor, 0.08); +} + +.caja-pathbar button:disabled, +.path-bar.linked:not(.vertical) > button:disabled { + background-color: alpha(currentColor, 0.05); +} + +.caja-pathbar button:first-child, +.path-bar.linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.caja-pathbar button:last-child, +.path-bar.linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.caja-pathbar button:checked, +.path-bar.linked:not(.vertical) > button:checked { + background-color: alpha(currentColor, 0.16); + color: #fbf1c7; +} + +.caja-pathbar button label, +.caja-pathbar button image, +.path-bar.linked:not(.vertical) > button label, +.path-bar.linked:not(.vertical) > button image { + margin-left: 3px; + margin-right: 3px; +} + +.caja-pathbar button.slider-button, +.path-bar.linked:not(.vertical) > button.slider-button { + padding-left: 4px; + padding-right: 4px; +} + +/************** + * Tree Views * + **************/ +treeview.view { + border-left-color: rgba(251, 241, 199, 0.12); + border-top-color: rgba(251, 241, 199, 0.12); +} + +* { + -gtktreeview-horizontal-separator: 4; + -gtktreeview-grid-line-width: 1; + -gtktreeview-grid-line-pattern: ''; + -gtktreeview-tree-line-width: 1; + -gtktreeview-tree-line-pattern: ''; + -gtktreeview-expander-size: 16; +} + +.csd +treeview.view:not(:selected):not(:hover):not(.progressbar):not(.expander):not( +.trough +):not(.separator) { + background-color: transparent; +} + +treeview.view.separator { + min-height: 6px; + color: rgba(251, 241, 199, 0.12); +} + +treeview.view:drop(active) { + border-style: solid none; + border-width: 9999px; + border-color: alpha(currentColor, 0.08); +} + +treeview.view:drop(active).after { + border-top-style: none; +} + +treeview.view:drop(active).before { + border-bottom-style: none; +} + +treeview.view.expander { + color: rgba(251, 241, 199, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); +} + +treeview.view.expander:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view.expander:checked { + -gtk-icon-transform: unset; +} + +treeview.view.expander:hover, treeview.view.expander:active { + color: #fbf1c7; +} + +treeview.view.expander:disabled { + color: rgba(251, 241, 199, 0.32); +} + +treeview.view.expander:selected { + color: rgba(40, 40, 40, 0.6); +} + +treeview.view.expander:selected:hover, treeview.view.expander:selected:active { + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.expander:selected:disabled { + color: rgba(40, 40, 40, 0.3); +} + +treeview.view.progressbar { + border: none; + box-shadow: none; + background-color: #7daea3; + background-image: none; + border-radius: 9999px; + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.progressbar:selected, treeview.view.progressbar:selected:hover, treeview.view.progressbar:selected:focus { + box-shadow: none; + background-color: #90b8a8; + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.progressbar:selected:backdrop, treeview.view.progressbar:selected:hover:backdrop, treeview.view.progressbar:selected:focus:backdrop { + color: rgba(40, 40, 40, 0.87); +} + +treeview.view.progressbar:backdrop, treeview.view.progressbar:selected:backdrop { + background-color: rgba(251, 241, 199, 0.3); +} + +treeview.view.trough { + border: none; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); + background-image: none; + border-radius: 9999px; + padding: 0; + margin: 0; +} + +treeview.view.trough:selected, treeview.view.trough:selected:hover, treeview.view.trough:selected:focus { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); +} + +treeview.view.trough:backdrop, treeview.view.trough:selected:backdrop { + background-color: rgba(251, 241, 199, 0.12); +} + +treeview.view header button { + padding: 2px 6px; + border: none; + border-right: 1px solid transparent; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; + background-clip: border-box; + border-image: linear-gradient(to bottom, transparent 20%, rgba(251, 241, 199, 0.12) 20%, rgba(251, 241, 199, 0.12) 80%, transparent 80%) 0 1 0 0/0 1px 0 0 stretch; +} + +treeview.view header button:not(:focus):not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +treeview.view header button, treeview.view header button:disabled { + background-color: #282524; +} + +treeview.view header button:last-child { + border-right: none; + border-image: none; +} + +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #282524; + background-clip: border-box; + color: #7daea3; +} + +treeview.view acceleditor > label { + background-color: #7daea3; +} + +/********* + * Menus * + *********/ +menubar, +.menubar { + -gtkwidget-window-dragging: true; + padding: 0; + background-color: #282828; + color: #fbf1c7; + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +menubar:backdrop, +.menubar:backdrop { + color: rgba(251, 241, 199, 0.7); + background-color: #282828; +} + +.csd menubar, .csd .menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > menuitem, +.menubar > menuitem { + transition: none; + min-height: 20px; + padding: 4px 8px; + color: rgba(251, 241, 199, 0.7); + border-radius: 12px; +} + +menubar > menuitem:hover, +.menubar > menuitem:hover { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +menubar > menuitem:backdrop, +.menubar > menuitem:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +menubar > menuitem:disabled, +.menubar > menuitem:disabled { + color: rgba(251, 241, 199, 0.32); +} + +menubar > menuitem label:disabled, +.menubar > menuitem label:disabled { + color: inherit; +} + +menubar > menuitem > window.popup.background > menu menuitem, +.menubar > menuitem > window.popup.background > menu menuitem { + transition: none; +} + +.background.popup { + background-color: transparent; +} + +menu { + margin: 6px; + padding: 6px; + background-color: #141617; + background-clip: border-box; + border-radius: 12px; + border: 2px solid #7daea3; +} + +.csd menu { + border: none; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.1); +} + +menu menuitem { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + min-width: 40px; + padding: 4px 8px; + color: #fbf1c7; + font: initial; + text-shadow: none; + border-radius: 12px; +} + +menu menuitem:hover { + background-color: alpha(currentColor, 0.08); +} + +menu menuitem:active { + background-color: alpha(currentColor, 0.12); +} + +menu menuitem:disabled { + color: rgba(251, 241, 199, 0.5); +} + +menu menuitem accelerator { + color: rgba(251, 241, 199, 0.7); +} + +menu menuitem:disabled accelerator { + color: rgba(251, 241, 199, 0.32); +} + +menu menuitem arrow { + min-height: 16px; + min-width: 16px; +} + +menu menuitem arrow:dir(ltr) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + margin-left: 8px; +} + +menu menuitem arrow:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); + margin-right: 8px; +} + +menu menuitem label:dir(rtl), menu menuitem label:dir(ltr) { + color: inherit; +} + +menu .view:selected { + background-color: #3a3731; +} + +menu > arrow { + min-height: 16px; + min-width: 16px; + padding: 4px; + background-color: #242220; + color: rgba(251, 241, 199, 0.7); +} + +menu > arrow.top { + margin-top: 0; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menu > arrow.bottom { + margin-top: 8px; + margin-bottom: -12px; + border-radius: 12px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menu > arrow:hover { + background-image: image(alpha(currentColor, 0.08)); + color: #fbf1c7; +} + +menu > arrow:disabled { + border-color: transparent; + background-color: transparent; + color: transparent; +} + +menu separator { + margin: 4px 0; +} + +/************ + * Popovers * + ************/ +popover.background { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 0; + background-color: #141617; + border-radius: 12px; +} + +popover.background, .csd popover.background { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +popover.background > stack { + margin: 0; +} + +popover.background > toolbar { + margin: 0; +} + +popover.background > list, +popover.background > .view, +popover.background > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover.background > scrolledwindow > viewport.frame > list { + background-color: transparent; + padding: 6px; +} + +popover.background > scrolledwindow > viewport.frame > list > row { + border-radius: 12px; + padding: 6px; +} + +popover.background .view:not(:selected), +popover.background toolbar { + background-color: #141617; +} + +popover.background button, +popover.background entry, +popover.background combobox { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio) { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):first-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):last-child { + border-radius: 12px; +} + +popover.background .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.background.menu button, +popover.background button.model { + min-height: 32px; + padding: 0 8px; + border-radius: 12px; +} + +popover.background separator { + margin: 3px 0; + background-color: transparent; +} + +popover.background list separator { + margin: 0; +} + +modelbutton.flat, +.menuitem.button.flat { + min-height: 28px; + padding: 0 8px; + border-radius: 12px; + color: #fbf1c7; +} + +modelbutton.flat arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +modelbutton.flat arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +/************* + * Notebooks * + *************/ +tabbox > tab, notebook > header tab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + padding: 3px 12px; + border: none; + outline: none; + background-clip: padding-box; + color: rgba(251, 241, 199, 0.7); + font-weight: 500; + border-radius: 9px; +} + +tabbox > tab:hover, notebook > header tab:hover { + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +tabbox > tab:disabled, notebook > header tab:disabled { + color: rgba(251, 241, 199, 0.32); +} + +tabbox > tab:checked, notebook > header tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbox > tab:checked:disabled, notebook > header tab:checked:disabled { + color: rgba(251, 241, 199, 0.5); +} + +notebook { + background-color: rgba(251, 241, 199, 0.04); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: transparent; +} + +notebook.frame { + border-radius: 15px; +} + +notebook.frame scrolledwindow.frame { + border: none; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(251, 241, 199, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header tab > box:drop(active) { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +notebook > header tab button.flat:last-child, +notebook > header tab button.close-button:last-child { + margin-left: 6px; + margin-right: -6px; +} + +notebook > header tab button.flat:first-child, +notebook > header tab button.close-button:first-child { + margin-left: -6px; + margin-right: 6px; +} + +notebook > header.top tabs > tab + tab, notebook > header.bottom tabs > tab + tab { + margin-left: 3px; +} + +notebook > header.top tabs:not(:only-child):first-child, notebook > header.bottom tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top tabs:not(:only-child):last-child, notebook > header.bottom tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top tabs tab.reorderable-page, notebook > header.bottom tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left tabs > tab + tab, notebook > header.right tabs > tab + tab { + margin-top: 3px; +} + +notebook > header.left tabs:not(:only-child):first-child, notebook > header.right tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left tabs:not(:only-child):last-child, notebook > header.right tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left tabs tab.reorderable-page, notebook > header.right tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > button.image-button { + min-height: 24px; + min-width: 24px; + padding: 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); +} + +* { + -gtkscrollbar-has-backward-stepper: false; + -gtkscrollbar-has-forward-stepper: false; +} + +scrollbar, +scrollbar button { + border: none; + min-width: 0; + min-height: 0; + padding: 0; + border-radius: 0; + background-color: transparent; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 12px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(251, 241, 199, 0.5); +} + +scrollbar slider:hover { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar slider:active { + background-color: rgba(251, 241, 199, 0.7); +} + +scrollbar slider:disabled { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar.fine-tune slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.fine-tune.horizontal slider { + border-width: 5px 4px; +} + +scrollbar.fine-tune.vertical slider { + border-width: 4px 5px; +} + +scrollbar.overlay-indicator trough { + background-color: rgba(251, 241, 199, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal slider { + min-width: 40px; +} + +scrollbar.vertical slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border: none; + border-radius: 9999px; + background-color: rgba(251, 241, 199, 0.5); + background-clip: padding-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #7daea3; +} + +switch:disabled { + opacity: 0.5; +} + +switch slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #fbf1c7; + border: none; + color: transparent; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12); +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; +} + +checkbutton.text-button, +radiobutton.text-button { + padding: 2px; +} + +checkbutton.text-button label:not(:only-child), +radiobutton.text-button label:not(:only-child) { + margin: 0 4px; +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate), +actionbar > revealer > box radio:not(:checked):not(:indeterminate) { + background-color: rgba(40, 40, 40, 0.12); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):hover, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):hover { + box-shadow: 0 0 0 6px rgba(40, 40, 40, 0.04); + background-color: rgba(40, 40, 40, 0.15); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):active, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):active { + box-shadow: 0 0 0 6px rgba(40, 40, 40, 0.12); + background-color: rgba(40, 40, 40, 0.2); +} + +actionbar > revealer > box check:not(:checked):not(:indeterminate):disabled, +actionbar > revealer > box radio:not(:checked):not(:indeterminate):disabled { + background-color: rgba(40, 40, 40, 0.04); +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + color: transparent; + background-color: rgba(251, 241, 199, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.04); + background-color: rgba(251, 241, 199, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(251, 241, 199, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(40, 40, 40, 0.6); + background-color: #7daea3; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.15); + background-color: #9cc2b9; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.2); + background-color: #7daea3; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(40, 40, 40, 0.3); + background-color: rgba(125, 174, 163, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem radio { + transition: none; + margin: 0; + padding: 0; +} + +menu menuitem check:dir(ltr), menu menuitem radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +menu menuitem check:dir(rtl), menu menuitem radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +menu menuitem check, menu menuitem check:hover, menu menuitem check:disabled, menu menuitem check:checked:hover, menu menuitem check:indeterminate:hover, menu menuitem radio, menu menuitem radio:hover, menu menuitem radio:disabled, menu menuitem radio:checked:hover, menu menuitem radio:indeterminate:hover { + box-shadow: none; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-mixed-symbolic@2.svg"))); +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/radio-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check, +menu menuitem check { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > checkbutton > check:checked, +menu menuitem check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > checkbutton > check:indeterminate, +menu menuitem check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-checkbox-mixed-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio, +menu menuitem radio { + min-height: 16px; + min-width: 16px; +} + +#MozillaGtkWidget > widget > radiobutton > radio:checked, +menu menuitem radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-checked-symbolic@2.svg"))); +} + +#MozillaGtkWidget > widget > radiobutton > radio:indeterminate, +menu menuitem radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/scalable/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +check:not(:checked):indeterminate:active, +radio:not(:checked):indeterminate:active { + -gtk-icon-transform: scaleX(-1); +} + +treeview.view radio, +treeview.view check { + padding: 0; + margin: 0; + background-color: rgba(251, 241, 199, 0.12); +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view radio:selected:not(:disabled):not(:checked):not(:indeterminate), +treeview.view check:selected:not(:disabled):not(:checked):not(:indeterminate) { + background-color: rgba(40, 40, 40, 0.12); +} + +treeview.view radio:checked, treeview.view radio:indeterminate, +treeview.view check:checked, +treeview.view check:indeterminate { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + background-image: none; +} + +.view.content-view.check:not(list), +.content-view .tile check:not(list) { + min-height: 40px; + min-width: 40px; + margin: 0; + padding: 0; + border-radius: 9999px; +} + +.view.content-view.check:not(list):not(:checked), +.content-view .tile check:not(list):not(:checked) { + background-image: image(rgba(251, 241, 199, 0.25)); +} + +.view.content-view.check:not(list):hover, .view.content-view.check:not(list):checked, +.content-view .tile check:not(list):hover, +.content-view .tile check:not(list):checked { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1); +} + +.view.content-view.check:not(list):checked, +.content-view .tile check:not(list):checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/scalable/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/scalable/checkbox-checked-symbolic@2.svg"))); +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale slider { + min-height: 18px; + min-width: 18px; + margin: -8px; +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune slider { + margin: -7px; +} + +scale trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(251, 241, 199, 0.3); +} + +scale trough:disabled { + background-color: rgba(251, 241, 199, 0.12); +} + +scale highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#7daea3); +} + +scale highlight:disabled { + background-color: #282828; + background-image: image(rgba(251, 241, 199, 0.32)); +} + +scale fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.3); +} + +scale fill:disabled { + background-color: transparent; +} + +scale slider { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #7daea3; + background-color: #282524; + box-shadow: inset 0 0 0 2px #7daea3; +} + +scale slider:hover { + box-shadow: inset 0 0 0 2px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale slider:active { + box-shadow: inset 0 0 0 4px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale slider:disabled { + box-shadow: inset 0 0 0 2px rgba(251, 241, 199, 0.32); +} + +scale marks, +scale value { + color: rgba(251, 241, 199, 0.7); +} + +scale indicator { + background-color: rgba(251, 241, 199, 0.3); + color: transparent; +} + +scale.horizontal marks.top { + margin-bottom: 7px; + margin-top: -15px; +} + +scale.horizontal.fine-tune marks.top { + margin-bottom: 6px; + margin-top: -14px; +} + +scale.horizontal marks.bottom { + margin-top: 7px; + margin-bottom: -15px; +} + +scale.horizontal.fine-tune marks.bottom { + margin-top: 6px; + margin-bottom: -14px; +} + +scale.vertical marks.top { + margin-right: 7px; + margin-left: -15px; +} + +scale.vertical.fine-tune marks.top { + margin-right: 6px; + margin-left: -14px; +} + +scale.vertical marks.bottom { + margin-left: 7px; + margin-right: -15px; +} + +scale.vertical.fine-tune marks.bottom { + margin-left: 6px; + margin-right: -14px; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.horizontal.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-before:not(.marks-after) slider, scale.horizontal.marks-before:not(.marks-after) slider:hover, scale.horizontal.marks-before:not(.marks-after) slider:active, scale.horizontal.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-disabled-dark.svg"), url("assets/scale-horz-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-before-slider-dark.svg"), url("assets/scale-horz-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.horizontal.marks-after:not(.marks-before) slider, scale.horizontal.marks-after:not(.marks-before) slider:hover, scale.horizontal.marks-after:not(.marks-before) slider:active, scale.horizontal.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.horizontal.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-disabled-dark.svg"), url("assets/scale-horz-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.horizontal.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-horz-marks-after-slider-dark.svg"), url("assets/scale-horz-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-before:not(.marks-after) slider, scale.vertical.marks-before:not(.marks-after) slider:hover, scale.vertical.marks-before:not(.marks-after) slider:active, scale.vertical.marks-before:not(.marks-after) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-before:not(.marks-after) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-before:not(.marks-after) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-disabled-dark.svg"), url("assets/scale-vert-marks-before-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-before:not(.marks-after) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-before-slider-dark.svg"), url("assets/scale-vert-marks-before-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + min-height: 32px; + min-width: 32px; + margin: -15px; + border-radius: 50%; + background-size: auto, 1000% 1000%; + background-repeat: no-repeat; + background-position: center center; + background-color: transparent; +} + +scale.vertical.marks-after:not(.marks-before) slider, scale.vertical.marks-after:not(.marks-before) slider:hover, scale.vertical.marks-after:not(.marks-before) slider:active, scale.vertical.marks-after:not(.marks-before) slider:disabled { + box-shadow: none; +} + +scale.vertical.marks-after:not(.marks-before) slider:focus { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:hover { + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider:focus:hover { + background-color: alpha(currentColor, 0.16); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple-on-slider 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-size: auto, 0% 0%; + background-color: alpha(currentColor, 0.08); +} + +scale.vertical.marks-after:not(.marks-before) slider { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:disabled { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-disabled-dark.svg"), url("assets/scale-vert-marks-after-slider-disabled-dark@2.svg")), radial-gradient(circle, transparent 10%, transparent 0%); +} + +scale.vertical.marks-after:not(.marks-before) slider:active { + background-image: -gtk-scaled(url("assets/scale-vert-marks-after-slider-dark.svg"), url("assets/scale-vert-marks-after-slider-dark@2.svg")), radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal slider:dir(ltr), scale.color.horizontal slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(251, 241, 199, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #7daea3; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #7daea3; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #b47109; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #7daea3; +} + +levelbar block.full { + background-color: #6c782e; +} + +levelbar block.empty { + background-color: rgba(251, 241, 199, 0.12); +} + +/**************** + * Print dialog * +*****************/ +printdialog paper { + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; + color: #fbf1c7; +} + +printdialog .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame > border, .frame { + margin: 0; + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0; + box-shadow: none; +} + +.frame.view { + border-radius: 12px; +} + +.frame.flat { + border-style: none; +} + +frame.flat > border, frame > border.flat, statusbar frame > border { + border: none; +} + +actionbar > revealer > box { + margin: 6px 0 0 0; + padding: 6px; + border: none; + color: #fbf1c7; + background-color: #282828; + border-radius: 0 0 12px 12px; +} + +actionbar > revealer > box button { + border-radius: 6px; +} + +actionbar > revealer > box button.combo:only-child { + border-radius: 6px; + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.04); +} + +actionbar > revealer > box button.combo:only-child:hover, actionbar > revealer > box button.combo:only-child:active { + color: #7daea3; +} + +actionbar > revealer > box button.combo:only-child:disabled { + color: #7daea3; +} + +actionbar > revealer > box stackswitcher { + background-color: rgba(40, 40, 40, 0.04); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + color: rgba(40, 40, 40, 0.6); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover, actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: rgba(40, 40, 40, 0.87); +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + background-color: #282524; + color: #fbf1c7; +} + +actionbar > revealer > box stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked:hover { + background-color: #282524; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +overshoot.top { + background-image: -gtk-gradient(radial, center top, 0, center top, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, center top, 0, center top, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center top; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.bottom { + background-image: -gtk-gradient(radial, center bottom, 0, center bottom, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, center bottom, 0, center bottom, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 100% 5%, 100% 100%; + background-repeat: no-repeat; + background-position: center bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.left { + background-image: -gtk-gradient(radial, left center, 0, left center, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, left center, 0, left center, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: left center; + background-color: transparent; + border: none; + box-shadow: none; +} + +overshoot.right { + background-image: -gtk-gradient(radial, right center, 0, right center, 0.5, to(rgba(251, 241, 199, 0.12)), to(rgba(251, 241, 199, 0))), -gtk-gradient(radial, right center, 0, right center, 0.6, from(rgba(251, 241, 199, 0.07)), to(rgba(251, 241, 199, 0))); + background-size: 5% 100%, 100% 100%; + background-repeat: no-repeat; + background-position: right center; + background-color: transparent; + border: none; + box-shadow: none; +} + +junction { + border-style: solid none none solid; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +junction:dir(rtl) { + border-style: solid solid none none; +} + +separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +preferences stacksidebar.sidebar list separator, placessidebar.sidebar list > separator, stacksidebar.sidebar + separator.vertical, +stacksidebar.sidebar separator.horizontal, button.font separator, button.file separator { + min-width: 0; + min-height: 0; + background-color: transparent; +} + +/********* + * Lists * + *********/ +window.background.csd stack stack stack frame > list, +window.background.csd > stack > stack > box > frame > list, +window.background.csd > stack > stack > box > box > frame > list, +window.background.csd > stack > box > stack > box > frame > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > list, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list, window.background.csd > stack > list, +window.background.csd > stack > scrolledwindow > viewport > box > list, +window.background.csd > box > stack > scrolledwindow > viewport > box > list, preferencesgroup list, +.geary-accounts-editor-pane list, window.background.csd.unified > deck > deck > deck list, hdyleaflet list.view, +hdyleaflet list.frame, +leaflet list.view, +leaflet list.frame, +box.horizontal > stack.background list.view, +box.horizontal > stack.background list.frame, hdyleaflet stack.background scrolledwindow > viewport list, +hdyleaflet overlay scrolledwindow > viewport list, +leaflet stack.background scrolledwindow > viewport list, +leaflet overlay scrolledwindow > viewport list, +box.horizontal > stack.background stack.background scrolledwindow > viewport list, +box.horizontal > stack.background overlay scrolledwindow > viewport list, hdyleaflet frame:not(.view) list:not(.contacts-contact-list), +leaflet frame:not(.view) list:not(.contacts-contact-list), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list), list.tweak-group list, list.content:not(.conversation-listbox) { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.csd stack stack stack frame > list > separator, +window.background.csd > stack > stack > box > frame > list > separator, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list > separator, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list > separator, window.background.csd > stack > list > separator, +window.background.csd > stack > scrolledwindow > viewport > box > list > separator, preferencesgroup list > separator, +.geary-accounts-editor-pane list > separator, window.background.csd.unified > deck > deck > deck list > separator, hdyleaflet list.view > separator, +hdyleaflet list.frame > separator, +leaflet list.view > separator, +leaflet list.frame > separator, +box.horizontal > stack.background list.view > separator, +box.horizontal > stack.background list.frame > separator, hdyleaflet stack.background scrolledwindow > viewport list > separator, +hdyleaflet overlay scrolledwindow > viewport list > separator, +leaflet stack.background scrolledwindow > viewport list > separator, +leaflet overlay scrolledwindow > viewport list > separator, +box.horizontal > stack.background stack.background scrolledwindow > viewport list > separator, +box.horizontal > stack.background overlay scrolledwindow > viewport list > separator, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +leaflet frame:not(.view) list:not(.contacts-contact-list) > separator, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) > separator, list.tweak-group list > separator, list.content:not(.conversation-listbox) > separator { + background: none; + min-height: 0; +} + +window.background.csd stack stack stack frame > list row, +window.background.csd > stack > stack > box > frame > list row, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > list row, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > list row, window.background.csd > stack > list row, +window.background.csd > stack > scrolledwindow > viewport > box > list row, preferencesgroup list row, +.geary-accounts-editor-pane list row, window.background.csd.unified > deck > deck > deck list row, hdyleaflet list.view row, +hdyleaflet list.frame row, +leaflet list.view row, +leaflet list.frame row, +box.horizontal > stack.background list.view row, +box.horizontal > stack.background list.frame row, hdyleaflet stack.background scrolledwindow > viewport list row, +hdyleaflet overlay scrolledwindow > viewport list row, +leaflet stack.background scrolledwindow > viewport list row, +leaflet overlay scrolledwindow > viewport list row, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row, +box.horizontal > stack.background overlay scrolledwindow > viewport list row, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row, +leaflet frame:not(.view) list:not(.contacts-contact-list) row, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row, list.tweak-group list > row, list.content:not(.conversation-listbox) > row { + border-radius: 0; +} + +window.background.csd stack stack stack frame > list row:not(:first-child), window.background.csd > stack > list row:not(:first-child), preferencesgroup list row:not(:first-child), +.geary-accounts-editor-pane list row:not(:first-child), window.background.csd.unified > deck > deck > deck list row:not(:first-child), hdyleaflet list.view row:not(:first-child), +hdyleaflet list.frame row:not(:first-child), +leaflet list.view row:not(:first-child), +leaflet list.frame row:not(:first-child), +box.horizontal > stack.background list.view row:not(:first-child), +box.horizontal > stack.background list.frame row:not(:first-child), hdyleaflet stack.background scrolledwindow > viewport list row:not(:first-child), +hdyleaflet overlay scrolledwindow > viewport list row:not(:first-child), +leaflet stack.background scrolledwindow > viewport list row:not(:first-child), +leaflet overlay scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:not(:first-child), +box.horizontal > stack.background overlay scrolledwindow > viewport list row:not(:first-child), hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +leaflet frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:not(:first-child), list.tweak-group list > row:not(:first-child), list.content:not(.conversation-listbox) > row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +window.background.csd stack stack stack frame > list row:first-child, window.background.csd > stack > list row:first-child, preferencesgroup list row:first-child, +.geary-accounts-editor-pane list row:first-child, window.background.csd.unified > deck > deck > deck list row:first-child, hdyleaflet list.view row:first-child, +hdyleaflet list.frame row:first-child, +leaflet list.view row:first-child, +leaflet list.frame row:first-child, +box.horizontal > stack.background list.view row:first-child, +box.horizontal > stack.background list.frame row:first-child, hdyleaflet stack.background scrolledwindow > viewport list row:first-child, +hdyleaflet overlay scrolledwindow > viewport list row:first-child, +leaflet stack.background scrolledwindow > viewport list row:first-child, +leaflet overlay scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:first-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:first-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:first-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:first-child, list.tweak-group list > row:first-child, list.content:not(.conversation-listbox) > row:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:last-child, window.background.csd > stack > list row:last-child, preferencesgroup list row:last-child, +.geary-accounts-editor-pane list row:last-child, window.background.csd.unified > deck > deck > deck list row:last-child, hdyleaflet list.view row:last-child, +hdyleaflet list.frame row:last-child, +leaflet list.view row:last-child, +leaflet list.frame row:last-child, +box.horizontal > stack.background list.view row:last-child, +box.horizontal > stack.background list.frame row:last-child, hdyleaflet stack.background scrolledwindow > viewport list row:last-child, +hdyleaflet overlay scrolledwindow > viewport list row:last-child, +leaflet stack.background scrolledwindow > viewport list row:last-child, +leaflet overlay scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:last-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:last-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:last-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:last-child, list.tweak-group list > row:last-child, list.content:not(.conversation-listbox) > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:only-child, window.background.csd > stack > list row:only-child, preferencesgroup list row:only-child, +.geary-accounts-editor-pane list row:only-child, window.background.csd.unified > deck > deck > deck list row:only-child, hdyleaflet list.view row:only-child, +hdyleaflet list.frame row:only-child, +leaflet list.view row:only-child, +leaflet list.frame row:only-child, +box.horizontal > stack.background list.view row:only-child, +box.horizontal > stack.background list.frame row:only-child, hdyleaflet stack.background scrolledwindow > viewport list row:only-child, +hdyleaflet overlay scrolledwindow > viewport list row:only-child, +leaflet stack.background scrolledwindow > viewport list row:only-child, +leaflet overlay scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:only-child, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:only-child, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:only-child, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:only-child, list.tweak-group list > row:only-child, list.content:not(.conversation-listbox) > row:only-child { + border-radius: 12px; +} + +window.background.csd stack stack stack frame > list row:focus, window.background.csd > stack > list row:focus, preferencesgroup list row:focus, +.geary-accounts-editor-pane list row:focus, window.background.csd.unified > deck > deck > deck list row:focus, hdyleaflet list.view row:focus, +hdyleaflet list.frame row:focus, +leaflet list.view row:focus, +leaflet list.frame row:focus, +box.horizontal > stack.background list.view row:focus, +box.horizontal > stack.background list.frame row:focus, hdyleaflet stack.background scrolledwindow > viewport list row:focus, +hdyleaflet overlay scrolledwindow > viewport list row:focus, +leaflet stack.background scrolledwindow > viewport list row:focus, +leaflet overlay scrolledwindow > viewport list row:focus, +box.horizontal > stack.background stack.background scrolledwindow > viewport list row:focus, +box.horizontal > stack.background overlay scrolledwindow > viewport list row:focus, hdyleaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +leaflet frame:not(.view) list:not(.contacts-contact-list) row:focus, +box.horizontal > stack.background frame:not(.view) list:not(.contacts-contact-list) row:focus, list.tweak-group list > row:focus, list.content:not(.conversation-listbox) > row:focus { + box-shadow: inset 0 0 0 1000px alpha(currentColor, 0.05); +} + +list { + border-color: rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); +} + +list row { + padding: 6px; + background-clip: padding-box; +} + +list.navigation-sidebar { + padding: 3px; +} + +list.navigation-sidebar > row { + border-radius: 12px; +} + +paned scrolledwindow > viewport.frame > list { + background-color: transparent; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable, treeview.view header button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:focus, treeview.view header button:focus, row.activatable:focus { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:hover, treeview.view header button:hover, row.activatable:hover { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.has-open-popup.activatable, treeview.view header button.has-open-popup, .budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable:active, treeview.view header button:active, row.activatable.has-open-popup, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.05); + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; +} + +row:selected { + color: inherit; + background-color: alpha(currentColor, 0.06); +} + +row:selected image, +row:selected label { + color: #fbf1c7; +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled image, +row:selected:disabled label { + color: rgba(251, 241, 199, 0.5); +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 8px; + padding: 6px 15px; +} + +.app-notification button.flat:last-child { + margin-right: -9px; +} + +.app-notification button.text-button:not(:disabled) { + color: #7daea3; +} + +.app-notification.frame, +.app-notification border { + border-style: none; +} + +/************* + * Expanders * + *************/ +expander title > arrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtk-icon-transform: rotate(-90deg); + color: rgba(251, 241, 199, 0.7); +} + +expander title > arrow:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +expander title > arrow:checked { + -gtk-icon-transform: unset; +} + +expander title > arrow:hover, expander title > arrow:active { + color: #fbf1c7; +} + +expander title > arrow:disabled { + color: rgba(251, 241, 199, 0.32); +} + +/************ + * Calendar * + ************/ +calendar { + padding: 1px; + border: 1px solid rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +calendar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +calendar:selected { + border-radius: 13px; +} + +calendar.header { + border-style: none none solid; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; +} + +calendar.highlight { + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +calendar:indeterminate { + color: rgba(251, 241, 199, 0.32); +} + +/*********** + * Dialogs * + ***********/ +messagedialog.background { + background-color: #282828; +} + +messagedialog.background .titlebar { + min-height: 12px; +} + +messagedialog.background .titlebar, messagedialog.background .titlebar:backdrop { + background-color: #282828; +} + +messagedialog.background.csd { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +messagedialog .titlebar, messagedialog.background.csd .titlebar { + border: none; + /* box-shadow: inset 0 1px highlight($surface); */ +} + +messagedialog .dialog-action-box { + margin-top: -6px; +} + +messagedialog .dialog-action-box button, messagedialog .dialog-action-box button:first-child, messagedialog .dialog-action-box button:last-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button, +messagedialog .dialog-action-box .linked:not(.vertical) > button:first-child, +messagedialog .dialog-action-box .linked:not(.vertical) > button:last-child { + border-radius: 12px; +} + +messagedialog .dialog-action-box button:not(:last-child), +messagedialog .dialog-action-box .linked:not(.vertical) > button:not(:last-child) { + margin-right: 6px; +} + +messagedialog .dialog-action-box button.suggested-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.suggested-action:not(:disabled) { + color: #45707a; +} + +messagedialog .dialog-action-box button.destructive-action:not(:disabled), +messagedialog .dialog-action-box .linked:not(.vertical) > button.destructive-action:not(:disabled) { + color: #c14a4a; +} + +.csd filechooser { + background-color: #282828; + border-radius: 0 0 12px 12px; +} + +filechooser .dialog-action-box { + border-top: 1px solid transparent; +} + +filechooser treeview.view header > button { + background-color: #0f0e0e; +} + +filechooser #pathbarbox { + background-color: #0f0e0e; + border-radius: 12px 12px 0 0; + margin: 0 4px; +} + +filechooser stack.view { + background-color: transparent; + padding: 0 4px; +} + +filechooser stack.view scrolledwindow { + background-color: #0f0e0e; + border-radius: 0 0 12px 12px; +} + +filechooser stack.view scrolledwindow list { + background-color: transparent; +} + +filechooser stack.view > placesview { + background-color: transparent; + padding: 4px; +} + +filechooser stack.view frame > border { + border: none; +} + +.csd filechooser placessidebar { + background: none; + border-bottom-left-radius: 12px; +} + +filechooser paned > separator { + background: none; +} + +filechooser paned box.vertical { + background-color: #0f0e0e; + border-radius: 12px; + margin: 0 6px 0 1px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; +} + +stacksidebar.sidebar:dir(ltr) list, stacksidebar.sidebar.left list, stacksidebar.sidebar.left:dir(rtl) list, .sidebar:not(separator):dir(ltr), .sidebar:not(separator).left { + border-right: 1px solid rgba(251, 241, 199, 0.12); + border-left-style: none; +} + +stacksidebar.sidebar:dir(rtl) list, stacksidebar.sidebar.right list, .sidebar:not(separator):dir(rtl), .sidebar:not(separator).right { + border-left: 1px solid rgba(251, 241, 199, 0.12); + border-right-style: none; +} + +.sidebar list { + background-color: transparent; +} + +paned .sidebar.left, paned .sidebar.right, paned .sidebar.left:dir(rtl), paned .sidebar:dir(rtl), paned .sidebar:dir(ltr), paned .sidebar { + border-style: none; +} + +stacksidebar.sidebar list { + padding: 3px; + background-color: #282524; +} + +stacksidebar.sidebar row { + min-height: 34px; + padding: 0 3px; + border-radius: 12px; +} + +stacksidebar.sidebar row + row { + margin-top: 3px; +} + +stacksidebar.sidebar row:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + font-weight: 500; +} + +stacksidebar.sidebar row:selected label, +stacksidebar.sidebar row:selected image { + color: rgba(40, 40, 40, 0.87); +} + +stacksidebar.sidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +/**************** + * File chooser * + ****************/ +placessidebar.sidebar { + margin: 0 0 0 4px; + padding: 0; +} + +placessidebar.sidebar > viewport.frame { + border-style: none; +} + +placessidebar.sidebar list { + background-color: transparent; + color: #fbf1c7; +} + +placessidebar.sidebar row { + min-height: 32px; + margin: 0; + padding: 0; + color: #fbf1c7; + border-radius: 6px; +} + +placessidebar.sidebar row:hover, placessidebar.sidebar row:active { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #7daea3; +} + +placessidebar.sidebar row > revealer { + padding: 0 8px 0 16px; +} + +placessidebar.sidebar row:selected { + /* background-color: if($variant == 'light', rgba($base, 0.4), $fill); */ + background-color: alpha(currentColor, 0.08); + color: #7daea3; + font-weight: 500; +} + +placessidebar.sidebar row:disabled { + color: rgba(40, 40, 40, 0.3); +} + +placessidebar.sidebar row image.sidebar-icon { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar.sidebar row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar.sidebar row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar.sidebar row label.sidebar-label { + color: inherit; +} + +placessidebar.sidebar row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar.sidebar row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar.sidebar row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar.sidebar row.sidebar-new-bookmark-row { + color: #7daea3; +} + +placessidebar.sidebar row.sidebar-new-bookmark-row image.sidebar-icon { + color: #7daea3; +} + +placessidebar.sidebar row:drop(active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 0ms, background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + padding-left: 8px; + padding-right: 8px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(rgba(251, 241, 199, 0.12)); + background-size: 1px 1px; + background-clip: content-box; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #282828; + background-image: image(rgba(251, 241, 199, 0.12)), image(rgba(251, 241, 199, 0.12)); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************** + * GtkInfoBar * + **************/ +infobar { + border: none; + margin-bottom: 0; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #282524; +} + +infobar.info > revealer > box, +infobar.info > revealer > box link:link, +infobar.info > revealer > box flowboxchild, infobar.info:hover > revealer > box, +infobar.info:hover > revealer > box link:link, +infobar.info:hover > revealer > box flowboxchild, infobar.info:backdrop > revealer > box, +infobar.info:backdrop > revealer > box link:link, +infobar.info:backdrop > revealer > box flowboxchild { + color: #7daea3; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #7daea3; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #7daea3; +} + +infobar.action > revealer > box, +infobar.action > revealer > box link:link, +infobar.action > revealer > box flowboxchild, infobar.action:backdrop > revealer > box, +infobar.action:backdrop > revealer > box link:link, +infobar.action:backdrop > revealer > box flowboxchild, infobar.question > revealer > box, +infobar.question > revealer > box link:link, +infobar.question > revealer > box flowboxchild, infobar.question:backdrop > revealer > box, +infobar.question:backdrop > revealer > box link:link, +infobar.question:backdrop > revealer > box flowboxchild { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #6da498; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #b47109; +} + +infobar.warning > revealer > box, +infobar.warning > revealer > box link:link, +infobar.warning > revealer > box flowboxchild, infobar.warning:backdrop > revealer > box, +infobar.warning:backdrop > revealer > box link:link, +infobar.warning:backdrop > revealer > box flowboxchild { + color: #fbf1c7; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.warning:hover > revealer > box { + background-color: #9c6208; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #c14a4a; + color: #fbf1c7; +} + +infobar.error > revealer > box, +infobar.error > revealer > box link:link, +infobar.error > revealer > box flowboxchild, infobar.error:backdrop > revealer > box, +infobar.error:backdrop > revealer > box link:link, +infobar.error:backdrop > revealer > box flowboxchild { + color: #fbf1c7; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.error:hover > revealer > box { + background-color: #b43e3e; +} + +/************ + * Tooltips * + ************/ +tooltip { + box-shadow: none; +} + +tooltip.background { + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; + border-radius: 12px; +} + +tooltip.background.csd { + border-radius: 12px; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +tooltip decoration { + background-color: transparent; +} + +tooltip > box { + margin: -6px; + min-height: 24px; + padding: 4px 8px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #fbf1c7; +} + +colorswatch.light { + color: rgba(40, 40, 40, 0.87); +} + +colorswatch overlay { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +colorswatch overlay:hover { + box-shadow: 0 0 0 2px #7daea3; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(251, 241, 199, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(251, 241, 199, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #282828; +} + +/********************** + * Window Decorations * + **********************/ +decoration { + transition: none; + /* border-radius: $window-radius; */ + border-radius: 12px 12px 0 0; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; + margin: 10px; +} + +decoration:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +.tiled decoration, .tiled-top decoration, .tiled-right decoration, .tiled-bottom decoration, .tiled-left decoration { + border-radius: 0; +} + +.maximized decoration, .fullscreen decoration { + border-radius: 0; + box-shadow: none; +} + +.popup decoration { + box-shadow: none; + border: none; +} + +.ssd decoration { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #7daea3; +} + +.ssd decoration:backdrop { + border: none; + border-radius: 12px 12px 0 0; + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.16), 0 0 0 2px #242220; +} + +.metacity decoration { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border: none; +} + +.csd.popup decoration { + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3; +} + +tooltip.csd decoration { + border-radius: 12px; + box-shadow: none; + border: none; +} + +messagedialog.background.csd decoration { + border-radius: 12px; + border: 1px solid rgba(251, 241, 199, 0.1); + background-color: #242220; + background-clip: border-box; +} + +.solid-csd decoration { + margin: 0; + padding: 2px; + border-radius: 0; + box-shadow: none; + background-color: #282828; + border: 1px solid #423f3e; +} + +.solid-csd decoration:backdrop { + background-color: #282828; +} + +button.titlebutton:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + /* min-height: 22px; */ + /* min-width: 22px; */ + padding: 0; + margin: 0 0px; +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:not(.suggested-action):not(.destructive-action), button.close.titlebutton:not(.suggested-action):not(.destructive-action) { + background-color: rgba(251, 241, 199, 0.12); + color: rgba(251, 241, 199, 0.7); +} + +button.minimize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.maximize.titlebutton:not(.suggested-action):not(.destructive-action) image, button.close.titlebutton:not(.suggested-action):not(.destructive-action) image { + padding: 0; + background: none; + box-shadow: none; +} + +button.minimize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; + background-color: alpha(currentColor, 0.15); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), inset 0 1px rgba(251, 241, 199, 0.1); +} + +button.minimize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:active:not(.suggested-action):not(.destructive-action), button.close.titlebutton:active:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; + background-color: alpha(currentColor, 0.2); +} + +button.minimize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +button.minimize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.maximize.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action), button.close.titlebutton:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; + background-color: alpha(currentColor, 0.15); +} + +.monospace { + font-family: monospace; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #7daea3; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.top:dir(ltr), cursor-handle.bottom:dir(rtl) { + -gtk-icon-transform: rotate(90deg); +} + +cursor-handle.bottom:dir(ltr), cursor-handle.top:dir(rtl) { + -gtk-icon-transform: unset; +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; + -gtk-icon-transform: rotate(45deg); +} + +.context-menu { + font: initial; +} + +.keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(251, 241, 199, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(251, 241, 199, 0.12); + background-color: #242220; + color: #fbf1c7; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #7daea3; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) + button { + margin-left: 3px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker.background entry { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +popover.emoji-picker.background entry:focus { + border-bottom: 1px solid #7daea3; + box-shadow: inset 0 -1px #7daea3; + background-color: transparent; +} + +popover.emoji-picker scrolledwindow { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +button.emoji-section { + margin: 4px; +} + +button.emoji-section:checked { + color: #7daea3; +} + +button.emoji-section:not(:last-child) { + margin-right: 0; +} + +popover.emoji-picker .emoji { + min-width: 3em; + min-height: 3em; + padding: 0 8px; +} + +popover.emoji-picker .emoji widget { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker .emoji widget:hover { + background-color: alpha(currentColor, 0.08); +} + +popover.emoji-completion { + padding: 8px 0; +} + +popover.emoji-completion arrow { + border: none; + background: none; +} + +popover.emoji-completion .emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +popover.emoji-completion .emoji:hover { + background-color: alpha(currentColor, 0.08); +} + +/************ + * Nautilus * + ************/ +.nautilus-window.background.csd { + border-radius: 0 0 12px 12px; + background-color: #282524; +} + +.nautilus-window.background.csd:backdrop { + background-color: #282524; +} + +.nautilus-window.background.csd > grid.horizontal > paned.horizontal > separator, +.nautilus-window.background.csd > deck > box.vertical > paned.horizontal > separator { + margin-left: 0; +} + +.nautilus-window.background.csd placessidebar > viewport.frame > list > separator { + background: none; +} + +.nautilus-window.background.csd.unified notebook { + border-radius: 0; +} + +.nautilus-window.background.csd:not(.unified) .nautilus-list-view { + background-color: transparent; + border-bottom-right-radius: 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook { + background-color: #282524; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook > stack { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook scrolledwindow +> .view:not(:selected):not(:hover):not(:checked) { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > stack > frame > scrolledwindow > viewport > list { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar { + background-color: transparent; + border-radius: 0 0 12px 12px; +} + +.nautilus-window.background.csd:not(.unified) notebook placesview > actionbar > revealer > box { + background-color: transparent; +} + +.nautilus-window.background.csd:not(.unified) paned > separator.wide { + min-width: 12px; + box-shadow: 12px 0 #282524; + background-color: #282524; + background-image: image(#423f3e); +} + +.nautilus-window.maximized, +.nautilus-window.maximized placessidebar { + border-radius: 0; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border: none; + border-radius: 12px; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(40, 40, 40, 0.87); +} + +.nautilus-canvas-item.dim-label, +.nautilus-list-dim-label { + color: rgba(251, 241, 199, 0.7); +} + +.nemo-desktop.nemo-canvas-item, .caja-desktop.caja-canvas-item, +.nautilus-desktop.nautilus-canvas-item { + color: #fbf1c7; +} + +@keyframes nautilus-operations-button-needs-attention { + to { + background-color: alpha(currentColor, 0.08); + } +} + +.nautilus-operations-button-needs-attention { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 2 alternate; +} + +.nautilus-operations-button-needs-attention-multiple { + animation: nautilus-operations-button-needs-attention 300ms cubic-bezier(0.4, 0, 0.2, 1) 6 alternate; +} + +.path-bar-box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + border-radius: 12px; +} + +.path-bar-box button { + margin: 0; +} + +.path-bar-box.width-maximized { + background-color: rgba(251, 241, 199, 0.04); +} + +.path-bar-box.background.frame { + border-style: none; + background-color: rgba(251, 241, 199, 0.04); +} + +.path-bar-box .path-bar button label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .path-bar button label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) { + padding-left: 11px; + padding-right: 11px; + margin-left: 1px; + margin-right: 1px; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):first-child { + margin-left: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action) label:not(:only-child):last-child { + margin-right: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action).text-button.image-button image:not(:only-child) { + margin: 0; +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr), .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl) { + background-color: rgba(251, 241, 199, 0.08); +} + +.path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):last-child:dir(ltr):disabled, .path-bar-box .linked.nautilus-path-bar +button:not(.suggested-action):not(.destructive-action):first-child:dir(rtl):disabled { + background-color: transparent; + color: rgba(251, 241, 199, 0.5); +} + +.windowhandle .linked.nautilus-path-bar { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action) { + margin-top: 0; + margin-bottom: 0; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir { + color: #fbf1c7; +} + +.windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:hover, .windowhandle .linked.nautilus-path-bar button:not(.suggested-action):not(.destructive-action).current-dir:active { + background: none; + box-shadow: none; +} + +.disk-space-display.unknown { + background-color: rgba(251, 241, 199, 0.3); + color: rgba(251, 241, 199, 0.3); +} + +.disk-space-display.used { + background-color: #7daea3; + color: #7daea3; +} + +.disk-space-display.free { + background-color: rgba(251, 241, 199, 0.12); + color: rgba(251, 241, 199, 0.12); +} + +.search-information { + padding: 2px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; + color: #fbf1c7; +} + +.conflict-row:not(:selected) { + background-color: #523c1c; +} + +.nautilus-window flowboxchild .icon-item-background { + padding: 4px; + border-radius: 6px; +} + +.nautilus-window flowboxchild:selected { + background-color: transparent; +} + +.nautilus-window notebook :not(treeview).view { + border-radius: 6px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > scrolledwindow.frame { + border-style: none; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child { + margin: -6px 0 0 -6px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > label { + margin: 0 8px; +} + +dialog.background > box.dialog-vbox.vertical > grid.horizontal > box.horizontal:last-child > box > button { + border-radius: 0; +} + +.nautilus-window > popover.menu:not(:last-child) { + padding: 3px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box { + margin-top: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box { + margin-bottom: -6px; +} + +.nautilus-window > popover.menu:not(:last-child) > stack > box > box > box > box.linked { + margin-top: 1px; +} + +.nautilus-window > popover.menu:not(:last-child) separator { + margin-bottom: -2px; +} + +.nautilus-menu-sort-heading { + margin: 1px 3px; + font-weight: 500; +} + +.nautilus-menu-sort-heading:disabled { + color: rgba(251, 241, 199, 0.7); +} + +.nautilus-window paned > separator { + background-color: #282524; +} + +/********* + * gedit * + *********/ +window.org-gnome-gedit > paned.titlebar > separator { + background-color: transparent; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > box.horizontal { + margin: 4px 0; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned > box.vertical > stack > grid.horizontal > scrolledwindow { + border-bottom-left-radius: 12px; +} + +window.org-gnome-gedit > overlay > box.vertical > paned.gedit-side-panel-paned stack scrolledwindow viewport.frame list.gedit-document-panel { + background: none; +} + +.open-document-selector-path-label { + color: rgba(251, 241, 199, 0.7); + font-size: smaller; +} + +.open-document-selector-match { + background-color: #b47109; + color: #fbf1c7; +} + +.gedit-document-panel { + background-color: #282524; +} + +.gedit-document-panel row button.flat { + margin-top: 8px; + margin-bottom: 8px; +} + +.gedit-document-panel-group-row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.gedit-side-panel-paned statusbar { + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0 0 12px 12px; +} + +.gedit-search-slider { + margin: 0 6px 10px; + padding: 6px; + background-color: #242220; + border-radius: 0 0 12px 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05), 0 0 0 2px #fbf1c7; +} + +.gedit-search-slider .linked:not(.vertical) > entry .gedit-search-entry-occurrences-tag { + all: unset; + color: rgba(251, 241, 199, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) .gedit-search-entry-occurrences-tag { + margin-left: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(ltr) image.right { + margin-right: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) .gedit-search-entry-occurrences-tag { + margin-right: 6px; +} + +.gedit-search-slider .linked:not(.vertical) > entry:dir(rtl) image.left { + margin-left: 0; +} + +.gedit-search-slider .linked:not(.vertical) > entry:not(.error) { + background-color: #242220; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button { + color: rgba(251, 241, 199, 0.7); +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:hover, .gedit-search-slider .linked:not(.vertical) > entry.error ~ button:active { + color: #fbf1c7; +} + +.gedit-search-slider .linked:not(.vertical) > entry.error ~ button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +frame.gedit-map-frame > border:dir(ltr) { + border-style: none none none solid; +} + +frame.gedit-map-frame > border:dir(rtl) { + border-style: none solid none none; +} + +/********** + * Tweaks * + **********/ +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame { + background-color: #282828; + color: #fbf1c7; + border-radius: 12px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + background-color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:hover { + background-color: rgba(40, 40, 40, 0.6); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:active { + background-color: rgba(40, 40, 40, 0.87); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider:disabled { + background-color: rgba(40, 40, 40, 0.3); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(40, 40, 40, 0.38); +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(40, 40, 40, 0.3); +} + +leaflet.unfolded > box.vertical:last-child > scrolledwindow > viewport.frame, +leaflet.unfolded > box.vertical:last-child > stack > scrolledwindow > viewport.frame { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + padding: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > separator, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > separator { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row { + padding: 0; + margin: -1px; + color: #fbf1c7; + border-radius: 6px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:active, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:active, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:focus { + color: #fbf1c7; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected { + font-weight: 500; + background-color: rgba(251, 241, 199, 0.04); + border-radius: 9px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected label, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected label, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected image, +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected image { + color: #7daea3; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:hover, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:hover, window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row:selected:focus, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row:selected:focus { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list > row + row, leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list > row + row { + margin-top: 3px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + border: none; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar trough, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar trough { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar slider { + border: 4px solid transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering), +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider { + border: none; + margin: 1px; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.dragging, window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.tweak { + padding: 3px; +} + +.tweak.title:hover { + box-shadow: none; +} + +.tweak-group-startup { + border: 1px solid rgba(251, 241, 199, 0.12); +} + +.tweak-group-startup > row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +row#Focus, +row#ClickMethod, +row#PrimaryWorkspaceTweak, +row#workspaces-only-on-primary { + margin-top: 4px; +} + +leaflet.titlebar > .titlebar.tweak-titlebar-left, +leaflet.titlebar > .titlebar.tweak-titlebar-right, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-left, +hdyleaflet.titlebar > .titlebar.tweak-titlebar-right { + background-color: inherit; + box-shadow: inherit; + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +leaflet.unfolded > box.vertical:first-child > scrolledwindow > viewport.frame > list { + background-color: transparent; + margin: 0; +} + +/************************ + * Gnome Control Center * + ************************/ +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:not(:only-child) { + border-top-left-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:not(:only-child), +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:not(:only-child) { + border-top-right-radius: 12px; +} + +window.background.csd > headerbar.titlebar > leaflet > headerbar:first-child:only-child, window.background.csd > headerbar.titlebar > leaflet > headerbar:last-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:first-child:only-child, +window.background.csd > headerbar.titlebar > hdyleaflet > headerbar:last-child:only-child { + border-top-right-radius: 12px; + border-top-left-radius: 12px; +} + +window.background.csd > stack:not(.titlebar) > stack.background { + border-radius: 0 0 12px 12px; +} + +window.background.csd > leaflet > stack.background, +window.background.csd > hdyleaflet > stack.background, +window.background.csd > box.horizontal > stack.background { + background: none; +} + +window.background.csd > leaflet > stack.background frame > border, +window.background.csd > hdyleaflet > stack.background frame > border, +window.background.csd > box.horizontal > stack.background frame > border { + border: none; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame { + background-color: #282524; + border-bottom-right-radius: 12px; +} + +window.background.csd > leaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > hdyleaflet > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view, +window.background.csd > box.horizontal > stack.background > widget > box.vertical > box.vertical > scrolledwindow > viewport.frame > box.vertical.view { + background: none; +} + +window.background.csd > leaflet frame.view, +window.background.csd > hdyleaflet frame.view, +window.background.csd > box.horizontal frame.view { + border-radius: 12px; + background: none; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > leaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view > viewport.frame > stack list, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view > viewport.frame > stack list { + background-color: transparent; +} + +window.background.csd > leaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > hdyleaflet > box.vertical > scrolledwindow.view scrollbar, +window.background.csd > box.horizontal > box.vertical > scrolledwindow.view scrollbar { + margin: 6px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list { + border-top-width: 0; + border-bottom-width: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical > list > row { + border-radius: 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list { + border-top-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:first-child > list > row { + border-radius: 12px 12px 0 0; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list { + border-bottom-width: 1px; +} + +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list, +window.background.csd stack.background clamp.medium frame > box.vertical > box.vertical:last-child > list > row { + border-radius: 0 0 12px 12px; +} + +window.background.csd hdycolumn stack frame.view > stack > stack list > separator { + background-color: rgba(251, 241, 199, 0.12); +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack > box.horizontal > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list { + background: none; +} + +dialog.background.csd > box.vertical.dialog-vbox > scrolledwindow > viewport.frame > list > row:not(:hover):not(:active):not(:selected) { + background-color: transparent; +} + +/************************ + * Gnome system monitor * + ************************/ +window#gnome-system-monitor.background.csd > box.vertical > stack { + background-color: #282524; + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background.csd > box.vertical > stack > box.vertical > revealer > actionbar > revealer > box { + border-radius: 0 0 12px 12px; +} + +window#gnome-system-monitor.background:not(.csd) > box.vertical > headerbar { + box-shadow: none; +} + +/************************ + * Gnome Sound Recorder * + ************************/ +stack > grid.vertical > scrolledwindow { + border: none; + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical > scrolledwindow > viewport.frame list { + border-radius: 0 0 12px 12px; +} + +stack > grid.vertical scrolledwindow.frame.emptyGrid { + border: none; +} + +/****************** + * Gnome Contacts * + ******************/ +window.background.csd scrolledwindow.contacts-contact-form { + border-bottom-right-radius: 12px; +} + +/************************ + * Epiphany (Gnome Web) * + ************************/ +tabbox { + border: none; + background-color: rgba(251, 241, 199, 0.04); + padding: 3px; + margin: 3px; + border-radius: 12px; +} + +tabbox > tab button { + min-height: 24px; + min-width: 24px; + border-radius: 9999px; + border: none; + padding: 0; + margin-right: -6px; +} + +/***************** + * Gnome Weather * + *****************/ +#weather-page, +#weekly-forecast-frame { + border-bottom-right-radius: 12px; +} + +#weather-page-content-view { + border-bottom-right-radius: 12px; + border-bottom-left-radius: 12px; +} + +/*************** + * Gnome Music * + ***************/ +window.background.csd box.vertical > overlay > stack.background { + border-radius: 0 0 12px 12px; +} + +/**************** + * Gnome Clocks * + ****************/ +/************* + * Rhythmbox * + *************/ +window.background > box.vertical > toolbar.primary-toolbar > toolitem > box.horizontal:not(.linked) > button.toggle, +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button:not(.toggle):not(.raised):not(.flat), window.background > box.vertical > toolbar.primary-toolbar > toolitem button.flat.scale, window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + min-height: 24px; + min-width: 24px; + padding: 5px; + margin: 0; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.12); +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button { + border-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:first-child), .sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button:not(:last-child) { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):first-child { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button.image-button:not(.text-button):last-child { + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; +} + +.sidebar-paned .inline-toolbar.horizontal.sidebar-toolbar button.image-button > widget > box > image { + padding: 0; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal { + padding: 6px; + margin: -1px 0; + border-bottom: none; + border-top: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: transparent; +} + +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > .linked > button, +window.solid-csd > box.vertical > box.vertical > toolbar.horizontal > toolitem > box.horizontal > button { + margin: 6px 0; +} + +window.csd > box.vertical > box.vertical > frame, +window.solid-csd > box.vertical > box.vertical > frame { + margin: -1px 0; + padding: 0; +} + +window.csd > box.vertical > box.vertical > frame > border, +window.solid-csd > box.vertical > box.vertical > frame > border { + border: none; +} + +window.background > box.vertical > toolbar.primary-toolbar { + padding: 0 12px 0 6px; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + box-shadow: inset 0 0 0 9999px transparent; + background-color: rgba(251, 241, 199, 0.08); + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; + color: #fbf1c7; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:disabled { + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised:checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +window.background > box.vertical > toolbar.primary-toolbar > toolitem > .linked > button.image-button.raised > widget > box > image { + padding: 0 3px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + padding: 6px; + margin: -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > box, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > grid > box { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + padding: 0 6px 6px; + margin: 0 -6px -6px 0; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(251, 241, 199, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > grid > grid, +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > grid > grid { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + padding: 3px; + margin: -1px -6px -6px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > box > grid > paned > box > scrolledwindow:not(:last-child), +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > notebook > stack > grid > paned > box > scrolledwindow:not(:last-child) { + border-right: 1px solid rgba(251, 241, 199, 0.12); + margin-right: -1px; +} + +window.background > box > .sidebar-paned > paned > box > notebook > stack > box > box > paned > box:first-child > box { + padding: 0 6px 6px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +/********** + * Polari * + **********/ +.polari-room-list .sidebar { + background: none; +} + +.polari-room-list .sidebar > row.activatable:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +stack.view.polari-entry-area { + background-color: #282828; + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-bottom-right-radius: 12px; +} + +stack:disabled.view.polari-entry-area { + background-image: image(#282828); +} + +/*********** + * Builder * + ***********/ +layouttabbar { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282828; +} + +layouttabbar > box > button { + margin: 3px 0; +} + +layouttab { + margin: 0 8px; + border-style: none solid; + border-width: 1px; + border-color: rgba(40, 40, 40, 0.2); + box-shadow: inset 0 -2px #7daea3; + background-color: #282524; +} + +layouttab separator.vertical { + margin: 8px 4px; +} + +layouttab button.text-button, layouttab button.image-button, layouttab button { + margin-top: 8px; + margin-bottom: 8px; + padding: 0 4px; +} + +layout { + border: 1px solid rgba(40, 40, 40, 0.2); + -pnldockbin-handle-size: 1; +} + +entry.search-missing { + background-color: #c14a4a; + color: #fbf1c7; +} + +window.workbench treeview.image { + color: rgba(251, 241, 199, 0.7); +} + +popover.popover-selector list { + padding: 6px; +} + +popover.popover-selector list row { + border-radius: 12px; +} + +popover.popover-selector list row image:dir(ltr) { + margin-right: 6px; +} + +popover.popover-selector list row image:dir(rtl) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(ltr) { + margin-left: 6px; +} + +popover.popover-selector list row .accel:dir(rtl) { + margin-right: 6px; +} + +omnibar.linked:not(.vertical) entry { + border-radius: 12px; +} + +omnibar:not(:hover):not(:active) entry { + color: rgba(251, 241, 199, 0.7); +} + +popover.omnibar list row:not(:last-child) { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +entry.preferences-search { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: #282524; +} + +preferences stacksidebar.sidebar list { + background-color: #282524; +} + +preferences stacksidebar.sidebar:dir(ltr) list, preferences stacksidebar.sidebar:dir(rtl) list { + border-style: none; +} + +preferences > box > box:dir(ltr) { + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +preferences > box > box:dir(rtl) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +popover.messagepopover.background { + padding: 0; +} + +popover.messagepopover .popover-action-area button { + padding: 8px 16px; + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0; +} + +popover.messagepopover .popover-action-area button:first-child { + border-bottom-left-radius: 12px; +} + +popover.messagepopover .popover-action-area button:last-child { + border-bottom-right-radius: 12px; +} + +popover.messagepopover .popover-content-area { + margin: 16px; +} + +popover.transfers list { + background-color: transparent; +} + +popover.transfers list row:not(:first-child) { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +popover.transfers list row > box { + padding: 10px; +} + +dockbin { + border: 1px solid rgba(40, 40, 40, 0.2); + -pnldockbin-handle-size: 1; +} + +dockpaned { + border: 1px solid rgba(40, 40, 40, 0.2); +} + +eggsearchbar box.search-bar { + padding: 0 8px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282828; +} + +docktabstrip { + padding: 0 8px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282828; +} + +docktab { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + min-height: 24px; + min-width: 24px; + margin-bottom: -1px; + padding: 6px 6px; + border-width: 1px; + border-color: transparent; + box-shadow: inset 0 -2px transparent; + background-image: radial-gradient(circle, #7daea3 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 0% 0%; + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +docktab:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +docktab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 225ms cubic-bezier(0, 0, 0.2, 1), background-image 525ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 -2px #7daea3; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-size: 1000% 1000%; + color: #fbf1c7; +} + +dockoverlayedge { + background-color: #282828; +} + +dockoverlayedge docktabstrip { + padding: 0; + border: none; +} + +dockoverlayedge.left-edge docktab:checked { + box-shadow: inset -2px 0 #7daea3; +} + +dockoverlayedge.right-edge docktab:checked { + box-shadow: inset 2px 0 #7daea3; +} + +pillbox { + background-color: #282828; + border-radius: 12px; +} + +layoutpane entry.search { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: #282524; +} + +editortweak entry.search { + margin-bottom: -1px; + box-shadow: none; + background-color: transparent; +} + +.gb-search-entry-occurrences-tag { + box-shadow: none; + background-color: transparent; +} + +docktabstrip { + min-height: 39px; +} + +window.workbench preferences preferencesgroup list entry { + padding-top: 8px; + padding-bottom: 8px; +} + +button.run-arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.dzlmenubutton image { + min-width: 28px; +} + +button.dzlmenubutton image.arrow { + min-width: 25px; +} + +button.dzlmenubuttonitem { + color: #fbf1c7; + font-weight: normal; +} + +button.dzlmenubuttonitem:disabled { + color: rgba(251, 241, 199, 0.5); +} + +idelayoutstackheader { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +idelayoutstackheader button:checked { + color: #fbf1c7; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher { + padding: 8px 0; + background-color: #282828; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(ltr) { + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher:dir(rtl) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button { + border-radius: 0; + box-shadow: none; + background-color: transparent; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:active { + background-image: radial-gradient(circle, rgba(125, 174, 163, 0.7) 10%, transparent 0%); +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:checked { + background-color: transparent; + color: #fbf1c7; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr) { + margin-right: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(ltr):checked { + box-shadow: inset -2px 0 #7daea3; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl) { + margin-left: -1px; +} + +ideeditorutilities > dzldockpaned > box > stackswitcher button:dir(rtl):checked { + box-shadow: inset 2px 0 #7daea3; +} + +ideeditorsidebar notebook header { + background: transparent; +} + +popover.messagepopover list { + border: 1px solid rgba(251, 241, 199, 0.12); +} + +popover.messagepopover list row:not(:last-child) { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +/********** + * Photos * + **********/ +GdMainIconView.content-view { + -gdmainiconview-icon-size: 48; +} + +.documents-counter { + margin: 8px; + border-radius: 9999px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + font-weight: bold; +} + +.documents-scrolledwin.frame { + border-style: none; +} + +.documents-scrolledwin.frame frame.content-view > border { + border-style: none; +} + +.photos-fade-in { + opacity: 1; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.photos-fade-out { + opacity: 0; + transition: opacity 75ms cubic-bezier(0, 0, 0.2, 1); +} + +button.photos-filter-preview { + color: #fbf1c7; + font-weight: normal; +} + +button.photos-filter-preview:checked { + background-color: alpha(currentColor, 0.06); + color: #fbf1c7; +} + +button.photos-filter-preview:checked image { + color: #fbf1c7; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(ltr) { + border-style: none none none solid; +} + +overlay grid.horizontal > revealer > scrolledwindow.frame:dir(rtl) { + border-style: none solid none none; +} + +/********* + * Music * + *********/ +.side-panel:dir(ltr) { + border-style: solid; + border-color: rgba(251, 241, 199, 0.12); +} + +.side-panel:dir(rtl) { + border-style: solid; + border-color: rgba(251, 241, 199, 0.12); +} + +.side-panel .view { + background-image: image(#282524); +} + +.side-panel .view:hover { + background-image: image(#393531); +} + +.side-panel .view:selected { + background-image: image(#7daea3); +} + +.side-panel .view:selected:hover { + background-image: image(rgba(120, 166, 155, 0.9896)); +} + +.songs-list:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +frame.documents-dropdown { + margin: 8px; +} + +frame.documents-dropdown > border { + border: none; +} + +box.vertical > revealer > toolbar.search-bar { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; +} + +box.vertical > revealer > toolbar.search-bar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +/************* + * Documents * + *************/ +.documents-scrolledwin { + background-color: transparent; +} + +.documents-scrolledwin .content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) { + background-color: transparent; +} + +.documents-scrolledwin viewport.frame widget > frame.content-view:not(:selected):not(:hover) border { + border: none; +} + +window.background.csd > stack > box > revealer > actionbar > revealer > box { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +/******************* + * Document Viewer * + *******************/ +window.background.csd evview.view.content-view { + border-radius: 0 0 12px 12px; +} + +/********************************* + * Archive Manager (File roller) * + *********************************/ +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #282524; +} + +.background.csd > grid.horizontal > paned.horizontal > scrolledwindow > treeview.view:not(:hover):not(:selected):not(:selected):not( +:hover +):not(.progressbar):not(.expander):not(.trough):not( +.separator +) { + background-color: #282524; +} + +.background.csd > grid.horizontal > paned.horizontal > box.vertical > scrolledwindow { + border-radius: 0 0 0 12px; + background-color: #282828; +} + +/************ + * Terminal * + ************/ +terminal-window decoration { + border-radius: 12px 12px 0 0; +} + +terminal-window.background.csd, terminal-window.background.csd.maximized { + border-radius: 0; +} + +terminal-window notebook > header > box { + margin: -2px -2px -2px 1px; +} + +terminal-window notebook > header > box button.flat { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; +} + +window.background > box.vertical > box.horizontal > frame > border { + border: none; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list { + /* border-radius: $corner-radius; */ + margin: 0 6px 6px; + background-color: #282828; + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row { + padding: 0 2px; + margin: 2px 0; + border-radius: 12px; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:selected, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:hover { + color: #7daea3; +} + +window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row, window.background > box.vertical > box.horizontal > frame > scrolledwindow > viewport.frame list > row:active { + color: #fbf1c7; +} + +window.background > box.vertical > box.horizontal > stack > widget > notebook.frame { + margin: 0 6px 6px 0; +} + +.terminal-window { + background-color: #282828; +} + +.terminal-window tabbar tabbox { + background-color: #282524; + margin: 0; + border-radius: 0; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; +} + +/********* + * To Do * + *********/ +task-list-view taskrow { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 0 -8px; +} + +task-list-view taskrow:hover { + transition: none; +} + +task-list-view taskrow label { + margin: 0 8px; +} + +task-list-view taskrow image.dim-label { + min-width: 16px; +} + +task-list-view > box > revealer > box > button { + margin: -5px; +} + +task-list-view > box > revealer > box > button .dim-label { + color: inherit; +} + +tasklistview taskrow { + outline: none; +} + +tasklistview taskrow entry, tasklistview taskrow entry:focus, tasklistview taskrow entry:disabled { + box-shadow: none; +} + +tasklistview taskrow image.dim-label { + min-width: 16px; +} + +tasklistview > box > revealer > box > button { + margin: -5px; +} + +tasklistview > box > revealer > box > button .dim-label { + color: inherit; +} + +/******* + * Eog * + *******/ +#eog-thumb-nav scrolledwindow { + border-top: none; +} + +/************* + * Evolution * + *************/ +frame.taskbar > border { + border-style: solid none none; +} + +box.vertical > paned.horizontal notebook widget .frame { + border-style: none; +} + +/*********** + * Fractal * + ***********/ +.background.csd.main-window .sidebar.rooms-sidebar { + border-bottom-left-radius: 12px; +} + +/******** + * Gitg * + ********/ +frame.commit-frame > border { + border-style: solid none none; +} + +/************** + * Characters * + **************/ +box.dialog-vbox scrolledwindow.related { + border: 1px solid rgba(40, 40, 40, 0.2); +} + +list.categories { + background-image: image(#282524); +} + +/********* + * Boxes * + *********/ +.transparent-bg + stack overlay > label { + min-height: 24px; + padding: 0 4px; + border-radius: 12px; + background-color: #242220; + color: #fbf1c7; +} + +/************** + * Calculator * + **************/ +button.title label { + min-height: 34px; +} + +/********* + * Geary * + *********/ +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar, +window#GearyMainWindow.background.csd > deck > overlay > box.vertical > paned.horizontal > box.sidebar.vertical statusbar { + border-bottom-left-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer, +window#GearyMainWindow.background.csd stack#conversation_viewer { + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox, +window#GearyMainWindow.background.csd stack#conversation_viewer scrolledwindow.geary-conversation-scroller viewport.frame list.conversation-listbox { + background: none; + border-bottom-right-radius: 12px; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded { + animation: none; + background-image: none; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed actionbar > revealer > box { + border-radius: 0; +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-expanded > .geary-composer-embed headerbar { + color: #fbf1c7; + background-color: #282828; + box-shadow: none; + border-bottom: 1px solid rgba(40, 40, 40, 0.2); +} + +window.background.csd.geary-main-window stack#conversation_viewer .geary-composer-box actionbar > revealer > box, +window#GearyMainWindow.background.csd stack#conversation_viewer .geary-composer-box actionbar > revealer > box { + border-bottom-left-radius: 0; +} + +.geary-accounts-editor-pane frame:not(.geary-signature) > border, +.geary-accounts-editor-pane scrolledwindow.frame { + border: none; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout { + background-color: #282524; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar { + background-color: #282828; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > separator.sidebar:backdrop, +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > separator.sidebar:backdrop { + background-color: #282828; +} + +.geary-main-window.unified > deck > overlay > .geary-main-layout > leaflet > leaflet > box.vertical + separator.sidebar { + min-width: 1px; + background-color: rgba(251, 241, 199, 0.12); +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow { + padding: 3px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view { + border: 1px solid transparent; + border-radius: 12px; + padding: 6px; +} + +.geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:selected, .geary-main-window.unified frame.geary-conversation-frame scrolledwindow treeview.view:active { + border-radius: 12px; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.geary-main-window.unified separator.geary-sidebar-pane-separator { + min-width: 1px; + background-color: rgba(251, 241, 199, 0.12); +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable { + border: 1px solid rgba(251, 241, 199, 0.12); + border-bottom-width: 0; + background-color: #282524; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content > row.activatable:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane { + border-radius: 0 0 8px 8px; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background { + background-color: transparent; +} + +.geary-main-window.unified geary-conversation-viewer#conversation_viewer list.background.conversation-listbox.content .geary-attachment-pane actionbar.background > revealer > box { + border-radius: 0 0 6px 6px; +} + +/************** + * Extensions * + **************/ +window.background.csd stack stack stack frame > border, +window.background.csd > stack > stack > box > frame > border, +window.background.csd > stack > stack > box > box > frame > border, +window.background.csd > stack > box > stack > box > frame > border, +window.background.csd > stack > box > stack > scrolledwindow > viewport frame > border, +window.background.csd > stack > box > stack > box > scrolledwindow > viewport > frame > border, +window.background.csd > stack > grid > scrolledwindow > viewport > box > frame > border { + border: none; +} + +window.background.csd > stack > box > box > list, +window.background.csd > stack > box > stack > scrolledwindow > viewport > list { + border-bottom-left-radius: 12px; +} + +window.background.csd > stack > box > .sidebar > scrolledwindow > viewport > list { + padding: 0 0; +} + +/*********** + * Dialogs * + ***********/ +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:first-child { + border-radius: 0 0 0 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > grid.horizontal > scrolledwindow.frame > viewport.frame list:last-child { + border-radius: 0 0 12px 0; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow, +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow { + border-radius: 0 0 12px 12px; + background-color: #282524; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active), +dialog.background.csd > box.vertical.dialog-vbox > stack > stack > scrolledwindow iconview.view:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack > scrolledwindow > viewport.frame > list row.activatable:not(:hover):not(:selected):not(:active) { + background-color: transparent; +} + +dialog.background.csd > box.vertical.dialog-vbox > stack toolbar.toolbar { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd > box.vertical.dialog-vbox > notebook > stack { + border-radius: 0 0 12px 12px; +} + +dialog.background.csd stack scrolledwindow.frame { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view { + border-radius: 12px; +} + +dialog.background.csd stack scrolledwindow.frame textview.view > text { + background: none; +} + +dialog.background.csd stack scrolledwindow viewport.frame.view { + border-radius: 12px; +} + +window.background.csd.unified { + background-color: #282828; +} + +window.background.csd.unified headerbar { + box-shadow: none; +} + +window.background.csd.unified > decoration-overlay { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +window.background.csd.unified, +window.background.csd.unified > decoration, +window.background.csd.unified > decoration-overlay { + border-radius: 12px; +} + +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen > decoration-overlay { + box-shadow: none; +} + +window.background.csd.unified.tiled, +window.background.csd.unified.tiled > decoration, +window.background.csd.unified.tiled > decoration-overlay, window.background.csd.unified.tiled-top, +window.background.csd.unified.tiled-top > decoration, +window.background.csd.unified.tiled-top > decoration-overlay, window.background.csd.unified.tiled-right, +window.background.csd.unified.tiled-right > decoration, +window.background.csd.unified.tiled-right > decoration-overlay, window.background.csd.unified.tiled-bottom, +window.background.csd.unified.tiled-bottom > decoration, +window.background.csd.unified.tiled-bottom > decoration-overlay, window.background.csd.unified.tiled-left, +window.background.csd.unified.tiled-left > decoration, +window.background.csd.unified.tiled-left > decoration-overlay, window.background.csd.unified.maximized, +window.background.csd.unified.maximized > decoration, +window.background.csd.unified.maximized > decoration-overlay, window.background.csd.unified.fullscreen, +window.background.csd.unified.fullscreen > decoration, +window.background.csd.unified.fullscreen > decoration-overlay { + border-radius: 0; +} + +/********* + * Tilix * + *********/ +overlay > revealer.left > scrolledwindow.frame, overlay > revealer.right > scrolledwindow.frame { + border-style: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +overlay > revealer.left > scrolledwindow.frame { + margin-right: 32px; +} + +overlay > revealer.right > scrolledwindow.frame { + margin-left: 32px; +} + +.terminix-session-sidebar, +.tilix-session-sidebar { + background-image: image(#242220); +} + +.terminal-titlebar button { + border-radius: 0; +} + +button.image-button.session-new-button { + min-width: 30px; +} + +notebook.tilix-background tab > box > stack { + margin: -6px; +} + +button.flat.tilix-small-button { + min-height: 20px; + min-width: 16px; +} + +/************** + * Terminator * + **************/ +.terminator-terminal-window paned > separator { + background-color: #282828; +} + +.terminator-terminal-window notebook.frame { + border-style: none; +} + +/************* + * Ubitquity * + *************/ +#live_installer .menubar progressbar trough { + border-radius: 4px; + background-color: rgba(251, 241, 199, 0.12); +} + +/********* + * Meld * + ********/ +.meld-notebook, +.meld-notebook > stack { + background: none; + border-radius: 0 0 12px 12px; +} + +.meld-notebook-child { + background-color: #282524; + border-radius: 0 0 12px 12px; +} + +statusbar.meld-status-bar { + background: none; +} + +/*********** + * Eclipse * + ***********/ +window.background > box.vertical > scrolledwindow > widget toolbar { + padding: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar separator, +window.background > box.vertical > scrolledwindow > widget toolbar button { + margin: 2px; +} + +window.background > box.vertical > scrolledwindow > widget toolbar button { + border-radius: 12px; +} + +/************ + * Chromium * + ************/ +window.background.chromium { + background-color: #282524; + color: #fbf1c7; +} + +window.background.chromium headerbar.titlebar { + padding: 0 12px; + /* border-radius: $corner-radius $corner-radius 0 0; */ +} + +window.background.chromium headerbar.titlebar button.toggle { + border: none; + background-color: transparent; + background-image: none; +} + +window.background.chromium headerbar.titlebar button.toggle:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + color: #fbf1c7; +} + +window.background.chromium headerbar.titlebar button.toggle:checked, window.background.chromium headerbar.titlebar button.toggle:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); + background-image: radial-gradient(circle, alpha(currentColor, 0.12) 10%, transparent 0%); + background-size: 0% 0%; + color: #fbf1c7; +} + +window.background.chromium headerbar.titlebar button.titlebutton { + min-width: 16px; + min-height: 16px; + margin: 0; + padding: 0; + background-size: 16px 16px; + border: none; +} + +window.background.chromium button { + border-width: 1px; + border-style: solid; + border-color: #423f3e; + background-color: #282828; + color: #fbf1c7; +} + +window.background.chromium entry.chromium { + background-color: rgba(251, 241, 199, 0.06); +} + +window.background.chromium entry.chromium, window.background.chromium entry.chromium:focus { + border-image: none; + color: #fbf1c7; +} + +window.background.chromium > textview.view, +window.background.chromium textview { + background-color: rgba(251, 241, 199, 0.06); + color: #fbf1c7; +} + +window.background.chromium > menubar { + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.chromium menu { + background-color: #211f1e; + /* border: 0px solid if($variant == 'light', $solid-border, $window-border); */ + border-radius: 0; +} + +window.background.chromium menu menuitem { + border-radius: 0; + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.chromium menu menuitem:hover { + background-color: #242220; + color: #7daea3; +} + +/*********** + * Firefox * + ***********/ +#MozillaGtkWidget decoration { + border: none; +} + +#MozillaGtkWidget > widget text { + background-color: #282828; +} + +#MozillaGtkWidget > widget text:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +#MozillaGtkWidget > widget > separator { + color: #423f3e; +} + +#MozillaGtkWidget > widget > scrollbar { + background-clip: border-box; +} + +#MozillaGtkWidget > widget > frame > border { + border-color: #423f3e; +} + +#MozillaGtkWidget > widget > entry, +#MozillaGtkWidget > widget > button > button { + border: 1px solid #423f3e; + border-radius: 12px; + box-shadow: none; +} + +#MozillaGtkWidget > widget > entry:disabled, +#MozillaGtkWidget > widget > button > button:disabled { + border-color: rgba(251, 241, 199, 0.12); +} + +#MozillaGtkWidget > widget > entry { + min-height: 30px; + background-color: #282524; +} + +#MozillaGtkWidget > widget > entry:focus { + border-color: #7daea3; + box-shadow: inset 0 0 0 1px #7daea3; +} + +#MozillaGtkWidget > widget > entry:disabled { + background-color: #282524; +} + +#MozillaGtkWidget > widget > button > button { + padding: 4px 8px; + background-size: auto; +} + +#MozillaGtkWidget > widget > button > button:hover { + box-shadow: inset 0 0 0 9999px alpha(currentColor, 0.08); +} + +#MozillaGtkWidget > widget > button > button:active { + background-image: image(alpha(currentColor, 0.12)); +} + +#MozillaGtkWidget > widget > checkbutton > check, +#MozillaGtkWidget > widget > radiobutton > radio { + margin: 0; + padding: 0; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate), +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate) { + color: #504945; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):hover, #MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):active, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):hover, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):active { + color: #7c6f64; +} + +#MozillaGtkWidget > widget > checkbutton > check:not(:checked):not(:indeterminate):disabled, +#MozillaGtkWidget > widget > radiobutton > radio:not(:checked):not(:indeterminate):disabled { + color: rgba(80, 73, 69, 0.5); +} + +#MozillaGtkWidget menu { + border: none; +} + +#MozillaGtkWidget > widget > menubar { + color: rgba(251, 241, 199, 0.7); +} + +#MozillaGtkWidget > widget > menubar:hover { + color: #fbf1c7; +} + +#MozillaGtkWidget > widget > menubar:disabled { + color: rgba(251, 241, 199, 0.32); +} + +#MozillaGtkWidget > widget > frame { + color: #423f3e; +} + +#MozillaGtkWidget menu > separator { + color: #423f3e; +} + +window.background:not(.csd) > window > menu menuitem { + transition: none; +} + +/************ + * Inkscape * + ************/ +#ToolboxCommon > #AuxToolbox #StyleSwatch { + font-size: smaller; +} + +#ToolboxCommon > #AuxToolbox #Kludge { + padding: 0; +} + +#ToolboxCommon > #AuxToolbox spinbutton, +#ToolboxCommon > #AuxToolbox entry { + min-height: 32px; +} + +#ToolboxCommon > #AuxToolbox button:not(.up):not(.down) { + min-height: 24px; + min-width: 16px; + padding: 4px 8px; +} + +#ToolboxCommon > #AuxToolbox spinbutton button { + border-width: 4px; +} + +#ToolboxCommon > toolbar.vertical { + margin-top: -4px; +} + +#ToolboxCommon > toolbar.vertical button { + min-height: 24px; + min-width: 24px; + padding: 4px; +} + +#CanvasTable button { + min-height: 16px; + min-width: 16px; + padding: 0; +} + +#CanvasTable #HorizontalScrollbar { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(ltr) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +#CanvasTable #VerticalScrollbar:dir(rtl) { + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +#Canvas_and_Dock frame > border { + border: none; +} + +#Canvas_and_Dock widget > widget > button.flat { + min-height: 16px; + min-width: 16px; + padding: 4px; +} + +#Canvas_and_Dock widget > widget > box.horizontal image { + padding: 4px; +} + +#Canvas_and_Dock box.horizontal > box.vertical > button.flat { + min-height: 16px; + min-width: 24px; + padding: 8px 4px; +} + +scrolledwindow#DialogNotebook > viewport.frame > notebook.frame button.close-button image { + padding: 4px; +} + +#InKscapeCanvas { + background-color: #282524; + border-radius: 12px; +} + +/*********** + * Synapse * + ***********/ +/*************** + * Libreoffice * + ***************/ +window.background > grid +> widget +> widget +> scrolledwindow +> viewport +> grid +> box +> box +> frame +> box { + background-color: #282828; +} + +/********* + * Pamac * + *********/ +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list { + border: none; + border-radius: 0; +} + +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > scrolledwindow > viewport.frame > list > row.activatable, +window.background.csd > box.vertical > overlay > stack > box.vertical > box.horizontal > revealer > stack > box.vertical > stack > scrolledwindow > viewport.frame > list > row.activatable { + border-radius: 12px; +} + +dialog-host > floating-sheet > sheet > widget.response-area { + padding: 6px; +} + +window.background:not(.csd):not(.solid-csd) > button:not(:hover):not(:active):not(:checked):not(:disabled):not(.flat) { + /* background-color: if($variant == 'light', $grey-100, $grey-900); */ + background-color: #282828; +} + +window.background:not(.csd) > box +> widget +> widget +> widget +> widget +> widget +> widget +> widget +> scrolledwindow entry:focus { + background-color: #333333; +} + +/********* + * Unity * + *********/ +UnityDecoration { + -unitydecoration-extents: 28px 0 0 0; + -unitydecoration-input-extents: 8px; + -unitydecoration-shadow-offset-x: 0; + -unitydecoration-shadow-offset-y: 3px; + -unitydecoration-active-shadow-color: rgba(0, 0, 0, 0.48); + -unitydecoration-active-shadow-radius: 18px; + -unitydecoration-inactive-shadow-color: rgba(0, 0, 0, 0.32); + -unitydecoration-inactive-shadow-radius: 6px; + -unitydecoration-glow-size: 8px; + -unitydecoration-glow-color: #7daea3; + -unitydecoration-title-indent: 4px; + -unitydecoration-title-fade: 32px; + -unitydecoration-title-alignment: 0; +} + +UnityDecoration .top { + padding: 0 2px; + border-style: none; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #282828; + color: #fbf1c7; +} + +UnityDecoration .top:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.7); +} + +UnityDecoration .menuitem { + color: rgba(251, 241, 199, 0.7); +} + +UnityDecoration .menuitem:hover { + box-shadow: inset 0 -2px #fbf1c7; + background-color: transparent; + color: #fbf1c7; +} + +.background:not(.csd) headerbar:not(.titlebar) { + border-radius: 0; + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +.background:not(.csd) headerbar:not(.titlebar).inline-toolbar { + border-style: none; +} + +UnityPanelWidget, +.unity-panel { + background-color: #282828; + color: #fbf1c7; +} + +UnityPanelWidget:backdrop, +.unity-panel:backdrop { + color: rgba(251, 241, 199, 0.7); +} + +.unity-panel.menuitem, +.unity-panel .menuitem { + color: rgba(251, 241, 199, 0.7); +} + +.unity-panel.menubar.menuitem:hover, +.unity-panel.menubar .menuitem *:hover { + box-shadow: inset 0 -2px #fbf1c7; + background-color: transparent; + color: #fbf1c7; +} + +.menu IdoPlaybackMenuItem.menuitem:active { + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); + animation: spin 1s linear infinite; + color: #7daea3; +} + +/************** + * Mate-Panel * + **************/ +.mate-panel-menu-bar menubar, +#PanelApplet-window-menu-applet-button { + background-color: transparent; +} + +.mate-panel-menu-bar { + background-color: rgba(40, 40, 40, 0.6); + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +.mate-panel-menu-bar button { + min-height: 16px; + min-width: 16px; + padding: 0; + border-radius: 0; +} + +PanelToplevel.horizontal > grid > button { + min-width: 24px; +} + +PanelToplevel.vertical > grid > button { + min-height: 24px; +} + +PanelSeparator { + color: rgba(251, 241, 199, 0.12); +} + +MatePanelAppletFrameDBus { + border-style: solid; + border-color: rgba(251, 241, 199, 0.12); +} + +.mate-panel-menu-bar.horizontal MatePanelAppletFrameDBus { + border-width: 0 1px; +} + +.mate-panel-menu-bar.vertical MatePanelAppletFrameDBus { + border-width: 1px 0; +} + +.mate-panel-menu-bar menubar > menuitem { + color: rgba(251, 241, 199, 0.7); +} + +.mate-panel-menu-bar menubar > menuitem:hover { + color: #fbf1c7; +} + +.mate-panel-menu-bar menubar > menuitem:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.mate-panel-menu-bar.horizontal menubar > menuitem { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical menubar > menuitem { + padding: 8px 0; +} + +.mate-panel-menu-bar menubar menu > menuitem { + min-height: 28px; + padding: 0 6px; +} + +.mate-panel-menu-bar #PanelApplet button { + -gtkwidget-window-dragging: true; +} + +.mate-panel-menu-bar #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0/0 0 0px; +} + +.mate-panel-menu-bar #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2/0 0 2px; +} + +.mate-panel-menu-bar #tasklist-button image:dir(ltr), +.mate-panel-menu-bar #tasklist-button label:dir(rtl) { + padding-left: 4px; +} + +.mate-panel-menu-bar #tasklist-button label:dir(ltr), +.mate-panel-menu-bar #tasklist-button image:dir(rtl) { + padding-right: 4px; +} + +.mate-panel-menu-bar.vertical #tasklist-button { + min-height: 32px; +} + +.mate-panel-menu-bar.horizontal #showdesktop-button image { + min-width: 24px; + padding: 0 4px; +} + +.mate-panel-menu-bar.vertical #showdesktop-button image { + min-height: 24px; + padding: 4px 0; +} + +PanelApplet.wnck-applet .wnck-pager { + background-color: transparent; + color: #7daea3; +} + +PanelApplet.wnck-applet .wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +PanelApplet.wnck-applet .wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +PanelApplet.wnck-applet .wnck-pager:selected { + background-color: #7daea3; +} + +.mate-panel-menu-bar.horizontal #clock-applet-button label { + padding: 0 8px; +} + +.mate-panel-menu-bar.vertical #clock-applet-button label { + padding: 8px 0; +} + +#MatePanelPopupWindow { + border: 1px solid rgba(40, 40, 40, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +#MatePanelPopupWindow frame > border { + border-style: none; +} + +#MatePanelPopupWindow calendar { + border-style: none; +} + +#MatePanelPopupWindow calendar:not(:selected) { + background-color: transparent; +} + +#MatePanelPopupWindow calendar + box { + margin-top: -5px; + padding-top: 5px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +#MatePanelPopupWindow expander > title { + min-height: 32px; +} + +#MatePanelPopupWindow button { + padding: 4px 16px; +} + +#MatePanelPopupWindow > frame > box > box > box > widget { + color: rgba(251, 241, 199, 0.12); +} + +na-tray-applet { + -natrayapplet-icon-padding: 3px; + -natrayapplet-icon-size: 16; +} + +.mate-panel-menu-bar { + -panelmenubar-icon-visible: true; +} + +.mate-panel-applet-slider { + border: 1px solid rgba(40, 40, 40, 0.2); + border-radius: 13px; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.mate-panel-applet-slider frame > border { + border-style: none; +} + +#PanelApplet:not(:selected) > box { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +#PanelApplet:selected > box { + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +#mate-menu { + border: 1px solid rgba(40, 40, 40, 0.2); + background-color: #242220; +} + +#mate-menu button { + min-height: 24px; + min-width: 24px; + padding: 4px 0; + color: #fbf1c7; + font-weight: normal; +} + +#mate-menu button:not(.flat) { + background-color: alpha(currentColor, 0.1); +} + +#mate-menu button image, +#mate-menu button label + label { + color: rgba(251, 241, 199, 0.7); +} + +#mate-menu entry { + margin: 0 0 4px; +} + +#mate-menu entry image { + margin: 0; +} + +#mate-menu entry + button { + margin: 0 4px 4px; + padding: 5px; +} + +.brisk-menu { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.brisk-menu entry { + margin-bottom: -2px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.brisk-menu entry + box > box:dir(ltr) { + margin-right: -2px; + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +.brisk-menu entry + box > box:dir(rtl) { + margin-left: -2px; + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +.brisk-menu .categories-list { + padding-top: 4px; +} + +.brisk-menu .categories-list button { + margin: 0 4px; +} + +.brisk-menu .categories-list button:checked { + color: #7daea3; +} + +.brisk-menu .session-button { + padding: 11px; +} + +.brisk-menu .frame { + border-style: none; +} + +.brisk-menu .apps-list { + padding: 4px 0; + background-color: transparent; +} + +.brisk-menu .apps-list row { + padding: 0; +} + +.brisk-menu .apps-list row:hover { + box-shadow: none; +} + +.brisk-menu .apps-list button { + border-radius: 0; + color: #fbf1c7; + font-weight: normal; +} + +/********************* + * CAJA File manager * + *********************/ +.caja-navigation-window button.toggle.image-button { + border-radius: 12px; +} + +.caja-pathbar button { + margin: 0 -1px 0 -2px; +} + +.caja-pathbar button.slider-button { + min-width: 24px; +} + +.caja-pathbar button > widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.caja-side-pane notebook viewport.frame, +.caja-side-pane notebook widget .vertical { + background-color: #282524; +} + +.caja-side-pane notebook, +.caja-notebook { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.caja-side-pane notebook .frame, +.caja-notebook .frame { + border-style: none; +} + +.caja-canvas-item { + border-radius: 12px; +} + +.caja-desktop.view .entry, +.caja-navigation-window .view .entry { + border: none; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + background-image: none; + color: #fbf1c7; +} + +.caja-desktop.view .entry:selected, +.caja-navigation-window .view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-desktop.view .entry { + background-color: #282524; + color: #fbf1c7; + caret-color: currentColor; +} + +.caja-desktop.view .entry:selected { + background-color: alpha(currentColor, 0.06); +} + +.caja-navigation-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.caja-notebook frame > border { + border-style: none; +} + +#caja-extra-view-widget { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +#caja-extra-view-widget > box > box > label { + font-weight: bold; +} + +/********* + * Pluma * + *********/ +.pluma-window statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.pluma-window statusbar frame > border { + border-style: none; +} + +.pluma-window statusbar frame button.flat { + padding: 0 4px; + border-radius: 0; +} + +.pluma-window statusbar frame button.flat widget { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + -gtkarrow-arrow-scaling: 1; +} + +.pluma-print-preview toolbar { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.pluma-window paned.horizontal box.vertical box.horizontal button.flat { + margin: 1px; +} + +.pluma-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.pluma-window paned.horizontal box.vertical notebook.frame { + margin-top: -1px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.pluma-window paned.horizontal box.vertical notebook.frame box.vertical toolbar.horizontal { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +/********* + * Atril * + *********/ +.atril-window paned.horizontal box.vertical .frame { + border-style: none; +} + +.atril-window paned.horizontal box.vertical notebook .frame { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +/* mate-screensaver lock dialog */ +.lock-dialog { + border: 1px solid rgba(40, 40, 40, 0.2); + border-radius: 13px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.lock-dialog frame > border { + border-style: none; +} + +.lock-dialog button:not(:disabled) { + color: #7daea3; +} + +/* multimedia OSD */ +MsdOsdWindow.background.osd { + border-radius: 12px; + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; +} + +MsdOsdWindow.background.osd .trough { + border-radius: 0; + background-color: rgba(251, 241, 199, 0.12); +} + +MsdOsdWindow.background.osd .progressbar { + border-radius: 0; + background-color: #7daea3; +} + +/****************** + * Budgie Desktop * + ******************/ +.budgie-container { + background-color: transparent; +} + +.budgie-settings-window list.sidebar { + background: none; + border-radius: 0 0 0 12px; +} + +.budgie-settings-window buttonbox.inline-toolbar { + border-style: none none solid; +} + +.budgie-settings-window buttonbox.inline-toolbar button { + border-radius: 12px; +} + +.budgie-popover { + border-color: #242220; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #fbf1c7; + background-clip: border-box; + background-color: #242220; + border-radius: 12px; +} + +.budgie-popover frame.container { + padding: 6px; + border: none; +} + +.budgie-popover frame.container .container { + padding: 0; +} + +.budgie-popover list, +.budgie-popover row { + padding: 0; +} + +.budgie-popover separator { + margin: 3px 0; +} + +.budgie-popover border { + border: none; +} + +.budgie-popover list { + background-color: transparent; +} + +.budgie-popover row:hover { + box-shadow: none; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) { + background-color: rgba(251, 241, 199, 0.04); + border-right: none; + border-bottom-left-radius: 12px; +} + +.budgie-popover scrolledwindow.sidebar:not(.categories) list > row.activatable { + padding: 6px 8px; +} + +.budgie-popover treeview.view.sidebar { + border-right: none; + background: none; +} + +.budgie-popover treeview.view.sidebar:hover { + background-color: alpha(currentColor, 0.08); +} + +.budgie-popover treeview.view.sidebar:selected { + background-color: alpha(currentColor, 0.12); +} + +.budgie-popover.bottom scrolledwindow.sidebar:not(.categories) { + padding-top: 12px; + border-top-left-radius: 12px; + border-bottom-left-radius: 0; +} + +.budgie-popover > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.budgie-popover.bottom > frame.container > grid.horizontal > grid.horizontal > widget > grid.horizontal > stack { + border-top: none; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.budgie-popover.budgie-menu .container { + padding: 0; +} + +.budgie-popover.budgie-menu .sidebar, +.budgie-popover.budgie-menu scrollbar, +.budgie-popover.budgie-menu entry.search { + background-color: transparent; +} + +.budgie-popover.budgie-menu entry.search { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + border-image: none; + border-radius: 0; + box-shadow: none; + font-size: 120%; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories { + background-color: rgba(251, 241, 199, 0.04); + padding-bottom: 12px; +} + +.budgie-popover.budgie-menu scrolledwindow.sidebar.categories button.flat.radio.category-button { + border-radius: 0; +} + +.budgie-popover.budgie-menu scrolledwindow > viewport.frame > list > row.activatable > button.flat { + border-radius: 0; +} + +.budgie-popover.budgie-menu list.left-overlay-menu { + border-radius: 12px; + background-color: #282524; + padding: 6px; + margin: 6px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #fbf1c7; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable { + border-radius: 12px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable:not(:last-child) { + margin-bottom: 3px; +} + +.budgie-popover.budgie-menu list.left-overlay-menu > row.activatable button.menuitem { + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer { + border-top: 1px solid rgba(251, 241, 199, 0.12); + padding: 6px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat { + padding: 3px; + border-radius: 12px; +} + +.budgie-popover.budgie-menu .budgie-menu-footer button.flat.image-button { + border-radius: 9999px; + padding: 6px; + min-height: 16px; + min-width: 16px; + margin-left: 6px; + background-clip: border-box; +} + +.budgie-popover.user-menu list, +.budgie-popover.user-menu row { + border: none; + background: none; + box-shadow: none; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child { + margin-bottom: 0; + outline-width: 0; + border-radius: 12px; +} + +.budgie-popover.user-menu > frame.container > box.vertical row.activatable:first-child button.indicator-item { + transition: none; + animation: none; +} + +.budgie-popover.night-light-indicator .view-header { + margin: 0 6px; +} + +.budgie-popover.places-menu .name-button image:dir(ltr) { + margin-right: 3px; +} + +.budgie-popover.places-menu .name-button image:dir(rtl) { + margin-left: 3px; +} + +.budgie-popover.places-menu .unmount-button { + margin: 2px; + padding: 0; +} + +.budgie-popover.places-menu .places-list:not(.always-expand) { + margin-top: 3px; + padding-top: 3px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.budgie-popover.places-menu .alternative-label { + padding: 3px; + font-size: 15px; +} + +.budgie-popover.workspace-popover flowboxchild { + padding: 0; +} + +.workspace-switcher .workspace-layout { + border: 0 solid rgba(251, 241, 199, 0.12); +} + +.top .workspace-switcher .workspace-layout:dir(ltr), .bottom .workspace-switcher .workspace-layout:dir(ltr) { + border-left-width: 1px; +} + +.top .workspace-switcher .workspace-layout:dir(rtl), .bottom .workspace-switcher .workspace-layout:dir(rtl) { + border-right-width: 1px; +} + +.left .workspace-switcher .workspace-layout, .right .workspace-switcher .workspace-layout { + border-top-width: 1px; +} + +.workspace-switcher .workspace-item, +.workspace-switcher .workspace-add-button { + border: 0 solid rgba(251, 241, 199, 0.12); +} + +.top .workspace-switcher .workspace-item:dir(ltr), .bottom .workspace-switcher .workspace-item:dir(ltr), .top .workspace-switcher .workspace-add-button:dir(ltr), .bottom .workspace-switcher .workspace-add-button:dir(ltr) { + border-right-width: 1px; +} + +.top .workspace-switcher .workspace-item:dir(rtl), .bottom .workspace-switcher .workspace-item:dir(rtl), .top .workspace-switcher .workspace-add-button:dir(rtl), .bottom .workspace-switcher .workspace-add-button:dir(rtl) { + border-left-width: 1px; +} + +.left .workspace-switcher .workspace-item, .right .workspace-switcher .workspace-item, .left .workspace-switcher .workspace-add-button, .right .workspace-switcher .workspace-add-button { + border-bottom-width: 1px; +} + +.workspace-switcher .workspace-item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.workspace-switcher .workspace-item.current-workspace { + background-color: alpha(currentColor, 0.1); +} + +.workspace-switcher .workspace-add-button:hover { + box-shadow: none; +} + +.workspace-switcher .workspace-add-button:active { + background-image: none; +} + +.workspace-switcher .workspace-add-button:active image { + margin: 1px 0 -1px; +} + +.budgie-panel .workspace-switcher .workspace-icon-button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 12px; +} + +.budgie-panel { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(40, 40, 40, 0.6); + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +.budgie-panel.transparent { + background-color: rgba(40, 40, 40, 0.75); +} + +.budgie-panel .icon-tasklist button.launcher:checked, .budgie-panel .icon-tasklist button.launcher:active { + color: #fbf1c7; +} + +.top .budgie-panel.dock-mode { + border-radius: 0 0 12px 12px; +} + +.bottom .budgie-panel.dock-mode { + border-radius: 12px 12px 0 0; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:first-child > button.launcher { + border-top-left-radius: 12px; +} + +.bottom .budgie-panel.dock-mode .icon-tasklist > box > revealer:last-child > button.launcher { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode { + border-radius: 0 12px 12px 0; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-right-radius: 12px; +} + +.left .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-right-radius: 12px; +} + +.right .budgie-panel.dock-mode { + border-radius: 12px 0 0 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:first-child { + border-top-left-radius: 12px; +} + +.right .budgie-panel.dock-mode .icon-tasklist .launcher:last-child { + border-bottom-left-radius: 12px; +} + +.budgie-panel button { + color: rgba(251, 241, 199, 0.7); + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 0; +} + +.budgie-panel button:hover { + color: #fbf1c7; +} + +.budgie-panel button:active { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel button.budgie-menu-launcher { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel button.budgie-menu-launcher:focus { + box-shadow: none; + border: none; + color: #fbf1c7; +} + +.budgie-panel button.raven-trigger { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel.horizontal button { + padding: 0 4px; +} + +.budgie-panel.vertical button { + padding: 4px 0; +} + +.budgie-panel separator { + background-color: rgba(251, 241, 199, 0.12); +} + +.budgie-panel .alert { + color: #c14a4a; +} + +.budgie-panel > box > widget > widget > image, +.budgie-panel > box > widget > widget > stack > image, +.budgie-panel > box > widget > widget > box > image { + margin-left: 6px; + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > image + label { + margin-left: -4px; +} + +.budgie-panel > box > widget > widget > box > widget > image { + margin-left: 6px; +} + +.budgie-panel > box > widget > widget > box > stack > widget > label { + margin-right: 6px; +} + +.budgie-panel > box > widget > widget > box > widget > widget > image { + margin-left: 2px; + margin-right: 2px; +} + +.budgie-panel .budgie-clock-applet > widget > box, +.budgie-panel .budgie-calendar-applet > widget > box { + padding-left: 3px; + padding-right: 3px; +} + +.budgie-panel .titlebar:not(headerbar) { + min-height: 0; + padding: 0; + box-shadow: none; + background-color: transparent; + color: #fbf1c7; +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):hover, .budgie-panel .titlebar:not(headerbar) button:not(.suggested-action):not(.destructive-action):active { + color: #fbf1c7; +} + +.budgie-panel menubar, +.budgie-panel .menubar { + color: rgba(251, 241, 199, 0.7); + box-shadow: none; + border: none; +} + +.budgie-panel menubar > menuitem, +.budgie-panel .menubar > menuitem { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel menubar > menuitem:hover, .budgie-panel menubar > menuitem:active, +.budgie-panel .menubar > menuitem:hover, +.budgie-panel .menubar > menuitem:active { + color: #fbf1c7; +} + +.budgie-panel menubar menu separator, +.budgie-panel .menubar menu separator { + background-color: rgba(251, 241, 199, 0.12); +} + +.budgie-panel #tasklist-button { + padding: 0 4px; +} + +.budgie-panel.vertical #tasklist-button { + min-height: 32px; +} + +.budgie-panel button.flat.launcher { + padding: 0; +} + +.budgie-panel button.flat.launcher:not(:checked) { + color: rgba(251, 241, 199, 0.5); +} + +.budgie-panel button.flat.launcher:not(:checked):hover, .budgie-panel button.flat.launcher:not(:checked):active { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-panel button.flat.launcher:not(:checked):disabled { + color: rgba(251, 241, 199, 0.32); +} + +.top .budgie-panel .unpinned button.flat.launcher:checked, .top .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel .unpinned button.flat.launcher:checked, .bottom .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel .unpinned button.flat.launcher:checked, .left .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel .unpinned button.flat.launcher:checked, .right .budgie-panel .pinned button.flat.launcher.running:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +.top .budgie-panel #tasklist-button, .budgie-panel .top #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.top .budgie-panel #tasklist-button:checked, .budgie-panel .top #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(1px), currentColor 100%, transparent 0%) 2 0 0 0/2px 0 0 0; +} + +.bottom .budgie-panel #tasklist-button, .budgie-panel .bottom #tasklist-button { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.bottom .budgie-panel #tasklist-button:checked, .budgie-panel .bottom #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at center calc(100% - 1px), currentColor 100%, transparent 0%) 0 0 2 0/0 0 2px 0; +} + +.left .budgie-panel #tasklist-button, .budgie-panel .left #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.left .budgie-panel #tasklist-button:checked, .budgie-panel .left #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(1px) center, currentColor 100%, transparent 0%) 0 0 0 2/0 0 0 2px; +} + +.right .budgie-panel #tasklist-button, .budgie-panel .right #tasklist-button { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 0%, transparent 0%) 0 0 0 0/0 0 0 0; +} + +.right .budgie-panel #tasklist-button:checked, .budgie-panel .right #tasklist-button:checked { + border-image: radial-gradient(circle closest-corner at calc(100% - 1px) center, currentColor 100%, transparent 0%) 0 2 0 0/0 2px 0 0; +} + +frame.raven-frame > border { + border-style: none; +} + +.top frame.raven-frame > border { + margin-bottom: 32px; +} + +.bottom frame.raven-frame > border { + margin-top: 32px; +} + +.left frame.raven-frame > border { + margin-right: 32px; +} + +.right frame.raven-frame > border { + margin-left: 32px; +} + +.raven { + background-color: #242220; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12); +} + +.raven > box { + margin-bottom: -10px; +} + +.raven stackswitcher.linked { + margin: 6px 16px; +} + +.raven stackswitcher.linked > button:focus { + box-shadow: none; +} + +.raven .raven-header { + min-height: 34px; + padding: 3px; +} + +.raven .raven-header.top { + padding: 0; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.raven .raven-header.top stackswitcher button { + margin: -4px 0 -5px; + padding: 0 16px; + min-height: 24px; +} + +.raven .raven-header.bottom { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.raven stack .raven-header { + margin-top: -6px; +} + +.raven stack scrolledwindow .raven-header { + margin-top: -8px; +} + +.raven .raven-background { + border-style: solid none; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282524; +} + +.raven .raven-background > overlay > widget > image { + color: rgba(251, 241, 199, 0.12); +} + +.raven scrolledwindow.raven-background { + border-bottom-style: none; +} + +.raven .powerstrip button { + margin: 2px 0 1px; + padding: 11px; + border-radius: 9999px; +} + +.raven .option-subtitle { + font-size: smaller; +} + +.raven .audio-widget scale.marks-after { + padding-top: 0; + padding-bottom: 0; +} + +.raven .audio-widget scale.marks-after label { + font-size: 90%; + padding: 0; + margin: -10px 0 0 6px; +} + +.raven .audio-widget button.flat.expander-button { + margin-top: 4px; + margin-bottom: 4px; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked { + background-color: rgba(251, 241, 199, 0.06); + color: #fbf1c7; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable:selected label, .raven .audio-widget list.devices-list.sound-devices > row.activatable:checked label { + color: #fbf1c7; +} + +.raven .audio-widget list.devices-list.sound-devices > row.activatable label { + padding-left: 12px; +} + +.raven levelbar, +.raven levelbar trough, +.raven levelbar block { + border-radius: 9999px; +} + +calendar.raven-calendar { + border-style: none; + background-color: transparent; +} + +calendar.raven-calendar:selected { + border-radius: 12px; +} + +.raven-mpris { + background-color: #242220; + color: #fbf1c7; +} + +.raven-mpris label { + min-height: 24px; +} + +.raven-mpris button.image-button { + padding: 11px; +} + +image.raven-mpris { + background-color: rgba(251, 241, 199, 0.12); + color: rgba(251, 241, 199, 0.7); + border-radius: 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame { + padding: 0; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable { + margin-left: -6px; + margin-right: -3px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable .raven-notifications-group-header { + padding: 0 12px; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list { + padding: 6px; + background: none; +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable { + border: none; + padding: 6px; + padding-left: 12px; + margin: 3px; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable list > row.activatable:selected { + background-color: rgba(251, 241, 199, 0.12); +} + +.raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:selected:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:hover, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:active, .raven-notifications-view > .raven-background > viewport.frame > list > row.activatable:focus { + background: none; + box-shadow: none; +} + +.budgie-notification-window, .budgie-switcher-window, .budgie-osd-window { + background-color: transparent; +} + +.budgie-notification .notification-title, .budgie-switcher .notification-title { + font-size: 120%; +} + +.budgie-notification .notification-body, .budgie-switcher .notification-body { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-osd .budgie-osd-text { + font-size: 120%; +} + +.budgie-panel .lock-keys image:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.drop-shadow { + margin: 5px 9px; + padding: 6px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +.drop-shadow .linked > button { + border-radius: 12px; +} + +.budgie-session-dialog, +.budgie-polkit-dialog, +.budgie-run-dialog { + background-color: #242220; + border: none; + padding: 0; +} + +.budgie-session-dialog > box > grid, +.budgie-polkit-dialog > box > grid, +.budgie-run-dialog > box > grid { + padding: 24px; +} + +.budgie-session-dialog.background, .budgie-session-dialog > decoration, +.budgie-polkit-dialog.background, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog.background, +.budgie-run-dialog > decoration { + border-radius: 12px; +} + +.budgie-session-dialog > decoration, +.budgie-polkit-dialog > decoration, +.budgie-run-dialog > decoration { + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(40, 40, 40, 0.75); +} + +.budgie-session-dialog label:not(:last-child), +.budgie-session-dialog .dialog-title, +.budgie-polkit-dialog label:not(:last-child), +.budgie-polkit-dialog .dialog-title, +.budgie-run-dialog label:not(:last-child), +.budgie-run-dialog .dialog-title { + font-size: 120%; +} + +.budgie-session-dialog .linked.horizontal > button, +.budgie-polkit-dialog .linked.horizontal > button, +.budgie-run-dialog .linked.horizontal > button { + padding: 8px 16px; + border-top: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 0; +} + +.budgie-session-dialog .linked.horizontal > button:first-child, +.budgie-polkit-dialog .linked.horizontal > button:first-child, +.budgie-run-dialog .linked.horizontal > button:first-child { + border-bottom-left-radius: 12px; +} + +.budgie-session-dialog .linked.horizontal > button:last-child, +.budgie-polkit-dialog .linked.horizontal > button:last-child, +.budgie-run-dialog .linked.horizontal > button:last-child { + border-bottom-right-radius: 12px; +} + +.budgie-polkit-dialog .message { + color: rgba(251, 241, 199, 0.7); +} + +.budgie-polkit-dialog .failure { + color: #c14a4a; +} + +.budgie-polkit-dialog > box > grid { + padding-bottom: 0; +} + +.budgie-run-dialog entry.search { + font-size: 120%; + padding: 6px 14px; + border-image: none; + box-shadow: none; + background-color: transparent; +} + +.budgie-run-dialog list .dim-label { + color: #fbf1c7; +} + +.budgie-run-dialog scrolledwindow { + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +/************** + * Xfce4 Apps * + **************/ +.XfceHeading { + background-color: #282524; +} + +/*************** + * xfce4-panel * + ***************/ +.xfce4-panel.background { + border: none; + background-color: rgba(40, 40, 40, 0.6); + color: rgba(251, 241, 199, 0.7); + font-weight: 500; +} + +.xfce4-panel.background button { + min-height: 16px; + min-width: 16px; + padding: 0 6px; + border-radius: 0; +} + +.xfce4-panel.background button.flat.toggle { + padding: 0 6px; +} + +.xfce4-panel.background .tasklist button image { + padding: 4px; +} + +wnck-pager:hover { + background-color: alpha(currentColor, 0.08); +} + +wnck-pager:active { + background-color: alpha(currentColor, 0.12); +} + +wnck-pager:selected { + background-color: #7daea3; +} + +#xfce4-mpc-plugin-26 > frame > border { + border: none; +} + +#xfce-panel-button { + -gtk-icon-style: symbolic; +} + +XfdesktopIconView.view { + border-radius: 12px; + background-color: transparent; + color: #fbf1c7; +} + +XfdesktopIconView.view:active { + box-shadow: none; +} + +XfdesktopIconView.view .rubberband { + border-radius: 0; +} + +window#whiskermenu-window { + border-radius: 12px; + background-color: transparent; + border: none; +} + +window#whiskermenu-window entry.search:focus { + background-color: #282524; +} + +window#whiskermenu-window > frame > border { + border-radius: 12px; + padding: 6px 8px 6px 9px; + margin: 6px; + border: none; + background-color: #242220; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3; +} + +window#whiskermenu-window box.categories > button.radio { + padding: 3px 6px; + margin: 1px 0; +} + +window#whiskermenu-window box.categories > button.radio:hover { + background-color: rgba(251, 241, 199, 0.12); +} + +window#whiskermenu-window box.categories > button.radio:checked, window#whiskermenu-window box.categories > button.radio:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +window#whiskermenu-window box.categories > button.radio:checked:hover, window#whiskermenu-window box.categories > button.radio:active:hover { + background-image: none; +} + +window#whiskermenu-window scrolledwindow.frame { + padding: 3px; + background-color: #282524; + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view { + border-radius: 12px; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:not(:hover):not(:selected) { + background: none; +} + +window#whiskermenu-window scrolledwindow.frame treeview.view:selected:hover { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:checked, window#whiskermenu-window .title-area > .commands-area > button.flat.command-button:active { + background-color: rgba(251, 241, 199, 0.3); + color: #fbf1c7; +} + +#XfceNotifyWindow { + background-color: #282524; + border-radius: 12px; + border: 2px solid #7daea3; +} + +#XfceNotifyWindow buttonbox { + padding: 0; +} + +#XfceNotifyWindow label#summary { + font-weight: bold; +} + +dialog.xfsm-logout-dialog { + border-radius: 12px; + background-color: rgba(36, 34, 32, 0.97); + border: 2px solid #7daea3; +} + +#xfwm-tabwin { + padding: 12px; + border-radius: 12px; + -xfwmtabwinwidget-icon-size: 64px; + -xfwmtabwinwidget-preview-size: 64px; +} + +/********** + * Thunar * + **********/ +.thunar toolbar { + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.thunar .standard-view.frame { + border: none; +} + +.thunar scrolledwindow.frame.sidebar { + border-top: none; +} + +.thunar .path-bar.linked:not(.vertical) > button.path-bar-button { + margin-left: 2px; + margin-right: 2px; +} + +.thunar statusbar { + margin: 0 -10px; + padding: 0 4px; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-top: none; +} + +window.background.csd.thunar > grid.horizontal +> paned.horizontal +> scrolledwindow.frame.sidebar.shortcuts-pane { + border-bottom-left-radius: 12px; +} + +menubar.-vala-panel-appmenu-private, +menubar.-vala-panel-background { + background: none; + border: none; + box-shadow: none; + animation: none; +} + +menubar.-vala-panel-appmenu-private > menuitem, +menubar.-vala-panel-background > menuitem { + color: rgba(251, 241, 199, 0.7); + font-weight: normal; +} + +menubar.-vala-panel-appmenu-private > menuitem:hover, +menubar.-vala-panel-background > menuitem:hover { + color: #fbf1c7; + border-radius: 0; +} + +menubar.-vala-panel-appmenu-private > menuitem:disabled, +menubar.-vala-panel-background > menuitem:disabled { + color: rgba(251, 241, 199, 0.32); +} + +/************************ + * LightDM GTK+ Greeter * + ************************/ +#panel_window { + background-color: #282524; + color: #fbf1c7; +} + +#panel_window menubar, +#panel_window separator { + background-color: transparent; +} + +#panel_window separator { + padding: 0 4px; +} + +#panel_window separator:first-child { + padding: 0 8px; +} + +#panel_window menubar > menuitem { + color: rgba(251, 241, 199, 0.7); +} + +#panel_window menubar > menuitem:hover { + color: #fbf1c7; +} + +#panel_window menubar > menuitem:disabled label { + color: rgba(251, 241, 199, 0.32); +} + +#login_window, +#shutdown_dialog, +#restart_dialog { + margin: 8px; + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +#content_frame { + padding-bottom: 16px; +} + +#buttonbox_frame { + padding-top: 24px; +} + +#buttonbox_frame > box, +#buttonbox_frame > buttonbox { + margin: -16px; +} + +#buttonbox_frame button:not(:disabled) { + color: #7daea3; +} + +/******** + * Nemo * + ********/ +.nemo-window .primary-toolbar { + background-color: #282828; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.nemo-window .primary-toolbar entry { + min-height: 0; + margin: 0; +} + +.nemo-window .primary-toolbar > toolitem > .linked > button.image-button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar button.text-button { + padding-left: 8px; + padding-right: 8px; + color: rgba(251, 241, 199, 0.7); +} + +.nemo-window .primary-toolbar button.text-button:hover, .nemo-window .primary-toolbar button.text-button:active, .nemo-window .primary-toolbar button.text-button:checked { + color: #fbf1c7; +} + +.nemo-window .primary-toolbar button.text-button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +.nemo-window .primary-toolbar button.text-button:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button { + margin-left: 1px; + margin-right: 1px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button:checked { + box-shadow: none; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button { + border-radius: 6px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.nemo-window .primary-toolbar .path-bar.linked:not(.vertical) > button.slider-button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.nemo-window .primary-toolbar button:not(.text-button):not(.image-button) { + padding-left: 4px; + padding-right: 4px; +} + +.nemo-window scrolledwindow.frame { + border-style: none; +} + +.nemo-window scrolledwindow.frame .view:not(:selected) { + background-color: transparent; +} + +.nemo-window .nemo-inactive-pane .view:not(:selected) { + background-color: #282524; +} + +.nemo-window .nemo-window-pane widget.entry { + border-radius: 6px; + background-color: rgba(251, 241, 199, 0.04); +} + +.nemo-window .nemo-window-pane > notebook { + border-radius: 0; +} + +.places-treeview { + -nemoplacestreeview-disk-full-bg-color: #676458; + -nemoplacestreeview-disk-full-fg-color: #7daea3; + -nemoplacestreeview-disk-full-bar-width: 2px; + -nemoplacestreeview-disk-full-bar-radius: 0; + -nemoplacestreeview-disk-full-bottom-padding: 1px; + -nemoplacestreeview-disk-full-max-length: 80px; + padding-top: 3px; + padding-bottom: 3px; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #fbf1c7; +/* text color for entries, views and content in general */ +@define-color theme_text_color #fbf1c7; +/* widget base background color */ +@define-color theme_bg_color #282828; +/* text widgets and the like base background color */ +@define-color theme_base_color #282524; +/* base background color of selections */ +@define-color theme_selected_bg_color #7daea3; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(40, 40, 40, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #282828; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(251, 241, 199, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #282524; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #fbf1c7; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #fbf1c7; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #282828; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #282524; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #7daea3; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(40, 40, 40, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(251, 241, 199, 0.5); +/* widgets main borders color */ +@define-color borders rgba(251, 241, 199, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(251, 241, 199, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #b47109; +@define-color error_color #c14a4a; +@define-color success_color #6c782e; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #fbf1c7; +@define-color wm_unfocused_title rgba(251, 241, 199, 0.7); +@define-color wm_highlight rgba(251, 241, 199, 0.1); +@define-color wm_border #080707; +@define-color wm_focused_bg #282828; +@define-color wm_unfocused_bg #282828; +@define-color wm_button_icon #fbf1c7; +@define-color wm_button_icon alpha(black, 0.5); +@define-color wm_button_focused_bg #353432; +@define-color wm_button_unfocused_bg #353432; +@define-color wm_button_hover_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_active_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_hover_bg #fbf1c7; +@define-color wm_button_active_bg #fbf1c7; +/* FIXME this is really an API */ +@define-color content_view_bg #282524; +@define-color placeholder_text_color #bcb496; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #282524; +@define-color budgie_tasklist_indicator_color rgba(132, 128, 110, 0.7); +@define-color budgie_tasklist_indicator_color_active #7daea3; +@define-color budgie_tasklist_indicator_color_active_window rgba(102, 138, 130, 0.816); +@define-color budgie_tasklist_indicator_color_attention #b47109; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/thumbnail.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/thumbnail.png new file mode 100755 index 0000000..9e8bc77 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-3.0/thumbnail.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic.svg new file mode 100755 index 0000000..c3eedb0 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic.svg @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="20" + height="20" + version="1.1" + viewBox="0 0 20 20" + id="svg4" + sodipodi:docname="checkbox-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="true" + inkscape:snap-global="false" + inkscape:zoom="10.547676" + inkscape:cx="13.510085" + inkscape:cy="10.902876" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 16.363961,5.7576864 c -0.391736,-0.3917365 -1.022477,-0.3917368 -1.414214,0 L 8.5857865,12.121648 5.0502526,8.5861135 c -0.3917367,-0.3917368 -1.0224771,-0.3917365 -1.4142135,0 -0.3917365,0.3917362 -0.3917368,1.0224772 0,1.4142135 l 4.2426407,4.242641 c 0.024483,0.02448 0.049725,0.04625 0.075958,0.06767 0.3935113,0.321347 0.9710025,0.299581 1.3382554,-0.06767 L 16.363961,7.1718999 c 0.391737,-0.3917367 0.391736,-1.0224771 0,-1.4142135 z" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..96be359 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-checked-symbolic@2.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="40" + height="40" + version="1.1" + viewBox="0 0 40 40" + id="svg4" + sodipodi:docname="checkbox-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:snap-global="false" + inkscape:zoom="10.547676" + inkscape:cx="5.8306685" + inkscape:cy="13.273066" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 32.727894,11.515401 c -0.783472,-0.783473 -2.044954,-0.783473 -2.828428,0 L 17.171545,24.243326 10.100478,17.172255 c -0.7834739,-0.783473 -2.0449547,-0.783473 -2.8284282,1e-6 -0.7834731,0.783472 -0.7834745,2.044955 0,2.828427 l 8.4852812,8.485281 c 0.04896,0.04896 0.09952,0.09245 0.151973,0.135285 0.787025,0.642691 1.942005,0.599161 2.676511,-0.135341 L 32.727951,14.343772 c 0.783473,-0.783474 0.783472,-2.044954 0,-2.828428 z" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..f016658 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="20" + height="20" + version="1.1" + viewBox="0 0 20 20" + id="svg4" + sodipodi:docname="checkbox-mixed-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="true" + inkscape:zoom="21.095352" + inkscape:cx="7.0868692" + inkscape:cy="12.988643" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + width="20px" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="10" + height="2" + x="5" + y="9" + rx="1" + ry="1" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..1bc6987 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/checkbox-mixed-symbolic@2.svg @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="40" + height="40" + version="1.1" + viewBox="0 0 40 40" + id="svg4" + sodipodi:docname="checkbox-mixed-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="10.547676" + inkscape:cx="-0.047403807" + inkscape:cy="19.340753" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + width="20px" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="20" + height="4" + x="10" + y="18" + rx="2" + ry="2" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/close.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/close.svg new file mode 100755 index 0000000..06201c3 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/close.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + sodipodi:docname="close.svg" + id="svg824" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs5" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="11.5625" + inkscape:cx="7.3513514" + inkscape:cy="13.837838" + inkscape:window-width="1440" + inkscape:window-height="742" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg824" /> + <path + d="m 4.464745,3.96488 c -0.12775,0 -0.2555,0.0486 -0.35339,0.14649 -0.19578,0.19586 -0.19578,0.51116 0,0.70703 L 7.292955,8 l -3.1816,3.1816 c -0.19578,0.19586 -0.19578,0.51116 0,0.70703 0.19578,0.19586 0.51118,0.19586 0.70704,0 l 3.18161,-3.1816 3.1816,3.1816 c 0.19578,0.19586 0.51114,0.19586 0.70704,0 0.19578,-0.19586 0.19578,-0.51116 0,-0.70703 L 8.707045,8 l 3.1816,-3.1816 c 0.19578,-0.19586 0.19578,-0.51116 0,-0.70703 -0.19578,-0.19586 -0.51117,-0.19586 -0.70704,0 l -3.1816,3.1816 -3.18161,-3.1816 C 4.720495,4.01347 4.592755,3.96488 4.465005,3.96488 Z" + id="path2928" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/cursor-handle-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/cursor-handle-symbolic.svg new file mode 100755 index 0000000..e2a252b --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/cursor-handle-symbolic.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"> + <path d="M0 0h12A12 12 0 1 1 0 12z"/> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/maximize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/maximize.svg new file mode 100755 index 0000000..39316eb --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/maximize.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + sodipodi:docname="maximize.svg" + id="svg825" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs5" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="11.243243" + inkscape:cy="11.978378" + inkscape:window-width="1440" + inkscape:window-height="742" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg825" /> + <path + d="M 6,4 C 4.892,4 4,4.892 4,6 v 4 c 0,1.108 0.89201,2 2,2 h 4 c 1.10801,0 2,-0.892 2,-2 V 6 C 12,4.892 11.10799,4 10,4 Z m 0,1 h 4 c 0.554,0 1,0.44602 1,1 v 4 c 0,0.55398 -0.44602,1 -1,1 H 6 C 5.44603,11 5.00001,10.55398 5.00001,10 V 6 C 5.00001,5.44602 5.44604,5 6,5 Z" + id="path2930" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/minimize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/minimize.svg new file mode 100755 index 0000000..f3683b9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/minimize.svg @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + id="svg4" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + sodipodi:docname="minimize.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs5" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="5.7513514" + inkscape:cy="9.8162162" + inkscape:window-width="1440" + inkscape:window-height="742" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <rect + x="4" + y="8" + width="8" + height="1" + rx="0.5" + ry="0.5" + id="rect2932" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic.svg new file mode 100755 index 0000000..d13b029 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="20" + height="20" + version="1.1" + viewBox="0 0 20 20" + id="svg4" + sodipodi:docname="radio-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="9.6368716" + inkscape:cy="12" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="path2" + d="m 10,6 c 2.209138,0 4,1.790862 4,4 0,2.209138 -1.790862,4 -4,4 C 7.790862,14 6,12.209138 6,10 6,7.790862 7.790862,6 10,6 Z" + sodipodi:nodetypes="sssss" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic@2.svg new file mode 100755 index 0000000..ed8d87a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-checked-symbolic@2.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="40" + height="40" + version="1.1" + viewBox="0 0 40 40" + id="svg4" + sodipodi:docname="radio-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="3.7291666" + inkscape:cx="-8.4469275" + inkscape:cy="25.743017" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid825" /> + </sodipodi:namedview> + <path + id="path2" + d="m 20,12 c 4.418276,0 8,3.581724 8,8 0,4.418276 -3.581724,8 -8,8 -4.418276,0 -8,-3.581724 -8,-8 0,-4.418276 3.581724,-8 8,-8 z" + sodipodi:nodetypes="sssss" + style="stroke-width:4" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic.svg new file mode 120000 index 0000000..79b7355 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..b68859d --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..de0d789 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-after-slider-symbolic.svg @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg17" + sodipodi:docname="scale-horz-marks-after-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview19" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg17" /> + <defs + id="defs6"> + <linearGradient + id="color-primary-dark"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + <linearGradient + id="a" + x1="-3.5527e-15" + x2="24" + gradientUnits="userSpaceOnUse" + xlink:href="#color-primary-dark" /> + </defs> + <path + d="m 12,20.485281 -4.2426407,-4.24264 a 6,6 0 1 1 8.4852817,0 z" + fill="#000000" + id="path10" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..7f0235f --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-horz-marks-before-slider-symbolic.svg @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg12" + sodipodi:docname="scale-horz-marks-before-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="14.916667" + inkscape:cx="3.2178771" + inkscape:cy="15.821229" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5"> + <linearGradient + id="a" + x2="24" + gradientUnits="userSpaceOnUse"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + </defs> + <path + d="m 12,3.5147186 4.242641,4.2426407 a 6,6 0 1 1 -8.4852817,0 z" + id="path9" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic.svg new file mode 100755 index 0000000..993f308 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg12" + sodipodi:docname="scale-slider-hover-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="12" + inkscape:cy="12.226415" + inkscape:window-width="1368" + inkscape:window-height="704" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="12" + cy="12" + r="8" + id="circle9" + style="stroke-width:1.33333" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg new file mode 100755 index 0000000..740bc8b --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-hover-symbolic@2.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="48" + version="1.1" + viewBox="0 0 48 48" + id="svg12" + sodipodi:docname="scale-slider-hover-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="3.4867923" + inkscape:cy="12.226415" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="24" + cy="24" + r="16" + id="circle9" + style="stroke-width:2.66666" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic.svg new file mode 100755 index 0000000..73a1dbe --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic.svg @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg12" + sodipodi:docname="scale-slider-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="11.864151" + inkscape:cy="12.226415" + inkscape:window-width="1368" + inkscape:window-height="700" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="12" + cy="12" + r="6" + id="circle9" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic@2.svg new file mode 100755 index 0000000..bec2ee4 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-slider-symbolic@2.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="48" + height="48" + version="1.1" + viewBox="0 0 48 48" + id="svg12" + sodipodi:docname="scale-slider-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview14" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + showgrid="false" + inkscape:zoom="11.041667" + inkscape:cx="3.3056603" + inkscape:cy="12.226415" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg12" /> + <defs + id="defs5" /> + <circle + cx="24" + cy="24" + r="12" + id="circle9" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg new file mode 100755 index 0000000..37d9c04 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-after-slider-symbolic.svg @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg17" + sodipodi:docname="scale-vert-marks-after-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview19" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg17" /> + <defs + id="defs6"> + <linearGradient + id="color-primary-dark"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + <linearGradient + id="a" + x2="24" + gradientUnits="userSpaceOnUse" + xlink:href="#color-primary-dark" /> + </defs> + <path + d="m 20.485281,12 -4.24264,4.242641 a 6,6 0 1 1 0,-8.4852817 z" + fill="#000000" + id="path10" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg new file mode 100755 index 0000000..1bc5cb6 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/scale-vert-marks-before-slider-symbolic.svg @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="24" + height="24" + version="1.1" + viewBox="0 0 24 24" + id="svg17" + sodipodi:docname="scale-vert-marks-before-slider-symbolic.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview19" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="29.833333" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg17" /> + <defs + id="defs6"> + <linearGradient + id="color-primary-dark"> + <stop + stop-color="#1A73E8" + offset="1" + id="stop2" /> + </linearGradient> + <linearGradient + id="a" + x1="-2.6324e-15" + x2="24" + y1="-3.5527e-15" + y2="-3.5527e-15" + gradientUnits="userSpaceOnUse" + xlink:href="#color-primary-dark" /> + </defs> + <path + d="M 3.5147186,12 7.7573593,7.7573593 a 6,6 0 1 1 0,8.4852817 z" + fill="#000000" + id="path10" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic.svg new file mode 100755 index 0000000..caed76f --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="small-checkbox-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="true" + inkscape:snap-global="false" + inkscape:zoom="31.643028" + inkscape:cx="9.1489348" + inkscape:cy="7.3001863" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid1068" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 12.596166,4.818375 c -0.391736,-0.3917359 -1.022477,-0.3917367 -1.414214,2e-7 L 6.9393399,9.0609886 4.8180203,6.9396678 c -0.3917368,-0.3917368 -1.0224772,-0.3917365 -1.4142136,0 -0.3917366,0.3917363 -0.3917373,1.0224777 0,1.4142138 l 2.8284271,2.8284274 c 0.02448,0.02448 0.049752,0.04622 0.075986,0.06764 0.3935135,0.321347 0.9710033,0.299582 1.3382562,-0.06767 l 4.949717,-4.949718 c 0.391738,-0.3917362 0.391736,-1.0224769 0,-1.4142136 z" + sodipodi:nodetypes="cscsscsccccc" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg new file mode 100755 index 0000000..58aa5ff --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-checked-symbolic@2.svg @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="32" + height="32" + version="1.1" + viewBox="0 0 32 32" + id="svg4" + sodipodi:docname="small-checkbox-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:snap-global="false" + inkscape:zoom="11.1875" + inkscape:cx="23.106146" + inkscape:cy="24.134079" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid1068" /> + </sodipodi:namedview> + <path + id="rect340" + d="m 25.192327,9.6367502 c -0.783471,-0.783472 -2.044952,-0.783474 -2.828426,-10e-7 L 13.878679,18.121974 9.6360416,13.879333 c -0.783474,-0.783473 -2.044953,-0.783472 -2.828426,10e-7 -0.783473,0.783472 -0.783474,2.044955 1e-6,2.828427 l 5.6568514,5.656851 c 0.04896,0.04896 0.0995,0.09243 0.151974,0.135287 0.787026,0.642691 1.942006,0.599162 2.676511,-0.13534 l 9.899431,-9.899434 c 0.783476,-0.783471 0.783471,-2.044952 0,-2.8284258 z" + sodipodi:nodetypes="cscsscsccccc" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg new file mode 100755 index 0000000..0e477a9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic.svg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="small-checkbox-mixed-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="22.375" + inkscape:cx="7.1284916" + inkscape:cy="13.810056" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid967" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="8" + height="2" + x="4" + y="7" + rx="1" + ry="1" + style="stroke-width:0.894427" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg new file mode 100755 index 0000000..d0980e2 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-checkbox-mixed-symbolic@2.svg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="32" + height="32" + version="1.1" + viewBox="0 0 32 32" + id="svg4" + sodipodi:docname="small-checkbox-mixed-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="11.1875" + inkscape:cx="5.4972067" + inkscape:cy="19.843575" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1"> + <inkscape:grid + type="xygrid" + id="grid967" /> + </sodipodi:namedview> + <rect + id="rect1585" + width="16" + height="4" + x="8" + y="14" + rx="2" + ry="2" + style="stroke-width:1.78885" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic.svg new file mode 100755 index 0000000..0fdb530 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="small-radio-checked-symbolic.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="22.375" + inkscape:cx="8.5139665" + inkscape:cy="11.486034" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + <path + id="path2" + d="m 8,4 c 2.209139,0 4,1.790861 4,4 0,2.209139 -1.790861,4 -4,4 C 5.790861,12 4,10.209139 4,8 4,5.790861 5.790861,4 8,4 Z" + sodipodi:nodetypes="sssss" + style="stroke-width:2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic@2.svg new file mode 100755 index 0000000..251e2f5 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-checked-symbolic@2.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="32" + height="32" + version="1.1" + viewBox="0 0 32 32" + id="svg4" + sodipodi:docname="small-radio-checked-symbolic@2.svg" + inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="22.375" + inkscape:cx="8.5139665" + inkscape:cy="11.486034" + inkscape:window-width="1280" + inkscape:window-height="652" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + <path + id="path2" + d="m 16,8 c 4.418278,0 8,3.581722 8,8 0,4.418278 -3.581722,8 -8,8 -4.418278,0 -8,-3.581722 -8,-8 0,-4.418278 3.581722,-8 8,-8 z" + sodipodi:nodetypes="sssss" + style="stroke-width:4" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic.svg new file mode 120000 index 0000000..86dfcec --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg new file mode 120000 index 0000000..bafb558 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/small-radio-mixed-symbolic@2.svg @@ -0,0 +1 @@ +small-checkbox-mixed-symbolic@2.svg \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/unmaximize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/unmaximize.svg new file mode 100755 index 0000000..492d47a --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/assets/unmaximize.svg @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + sodipodi:docname="unmaximize.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + id="svg831" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs6" /> + <sodipodi:namedview + pagecolor="#424242" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1440" + inkscape:window-height="742" + id="namedview6" + showgrid="true" + inkscape:zoom="29.580633" + inkscape:cx="2.095966" + inkscape:cy="10.006547" + inkscape:window-x="0" + inkscape:window-y="32" + inkscape:window-maximized="1" + inkscape:pagecheckerboard="0" + inkscape:current-layer="svg831" /> + <path + d="M 6,6 C 4.892,6 4,6.892 4,8 v 2 c 0,1.108 0.892,2 2,2 h 2 c 1.108,0 2,-0.892 2,-2 V 8 C 10,6.892 9.108,6 8,6 Z m 0,1 h 2 c 0.554,0 1,0.446 1,1 v 2 c 0,0.554 -0.446,1 -1,1 H 6 C 5.446,11 5,10.554 5,10 V 8 C 5,7.446 5.446,7 6,7 Z" + id="path2896" + style="fill:#ffffff" /> + <path + d="M 8,4 C 6.892,4 6,4.892 6,6 H 7 C 7,5.446 7.446,5 8,5 h 2 c 0.554,0 1,0.446 1,1 v 2 c 0,0.554 -0.446,1 -1,1 v 1 c 1.108,0 2,-0.892 2,-2 V 6 C 12,4.892 11.108,4 10,4 Z" + opacity="0.35" + id="path2898" + style="fill:#ffffff" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk-dark.css b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk-dark.css new file mode 100755 index 0000000..ddb16b9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk-dark.css @@ -0,0 +1,8519 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #7daea3 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #7daea3 100%, transparent 100%); + } +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #282828; + color: #fbf1c7; +} + +#desktopwindow.background { + background-color: transparent; +} + +dnd { + color: #fbf1c7; +} + +.normal-icons { + -gtk-icon-size: 16px; +} + +.large-icons { + -gtk-icon-size: 32px; +} + +.aboutdialog .large-icons { + -gtk-icon-size: 128px; +} + +spinner:disabled, +arrow:disabled, +scrollbar:disabled, +check:disabled, +radio:disabled, +treeview.expander:disabled { + -gtk-icon-filter: opacity(0.5); +} + +iconview, +.view { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +iconview:disabled, +.view:disabled { + color: rgba(251, 241, 199, 0.5); +} + +iconview:selected, +.view:selected { + color: #fbf1c7; +} + +textview text { + background-color: #282524; +} + +textview border { + background-color: #282524; + color: rgba(251, 241, 199, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 6px; +} + +rubberband, .content-view rubberband, .content-view columnview.view > rubberband, +.content-view treeview.view > rubberband, +.content-view .rubberband, columnview.view > rubberband, +.content-view columnview.view > .rubberband, +treeview.view > rubberband, +.content-view treeview.view > .rubberband, gridview > rubberband, flowbox > rubberband { + border: 1px solid #7daea3; + background-color: rgba(125, 174, 163, 0.3); +} + +flowbox > flowboxchild { + padding: 4px; + border-radius: 12px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +gridview > child { + padding: 3px; +} + +gridview > child:selected { + outline-color: alpha(currentColor, 0.06); +} + +gridview > child box { + border-spacing: 8px; + margin: 12px; +} + +coverflow cover { + color: #fbf1c7; + background-color: #282524; + border: 1px solid black; +} + +label.separator { + color: rgba(251, 241, 199, 0.7); +} + +label:disabled { + opacity: 1; + color: rgba(251, 241, 199, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; + opacity: 1; +} + +label.osd { + border-radius: 12px; + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; +} + + +.dim-label, +row.expander image.expander-row-arrow, +row.property > box.header > box.title > .title, +row label.subtitle { + color: rgba(251, 241, 199, 0.7); + opacity: 1; +} + +.accent { + color: #7daea3; +} + +.success { + color: #6c782e; +} + +.warning { + color: #b47109; +} + +.error { + color: #c14a4a; +} + +.large-title { + font-weight: 300; + font-size: 24pt; +} + +.title-1 { + font-weight: 800; + font-size: 20pt; +} + +.title-2 { + font-weight: 800; + font-size: 15pt; +} + +.title-3 { + font-weight: 700; + font-size: 15pt; +} + +.title-4 { + font-weight: 700; + font-size: 13pt; +} + +.heading { + font-weight: 700; + font-size: 11pt; +} + +.body { + font-weight: 400; + font-size: 11pt; +} + +.caption, row.property > box.header > box.title > .title { + font-weight: 400; + font-size: 9pt; +} + +.caption-heading { + font-weight: 700; + font-size: 9pt; +} + +window.assistant .sidebar { + padding: 4px 0; +} + +window.assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(251, 241, 199, 0.5); + font-weight: 500; +} + +window.assistant .sidebar label.highlight { + color: #fbf1c7; +} + +.osd .scale-popup > arrow, +.osd .scale-popup > contents, .osd popover > arrow, +.osd popover > contents, popover.touch-selection > arrow, +popover.touch-selection > contents, popover.magnifier > arrow, +popover.magnifier > contents, .osd { + color: #fbf1c7; + background-color: #282524; + background-clip: padding-box; + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +.osd { + padding: 6px; + margin: 6px; +} + +.osd.circular { + border-radius: 9999px; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ + +entry headerbar popover.background entry, +headerbar popover.background entry entry, +entry { + min-height: 34px; + padding: 0 8px; + border-spacing: 6px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + + +entry headerbar popover.background entry:focus-within, +headerbar popover.background entry entry:focus-within, +entry:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #7daea3; +} + + +entry headerbar popover.background entry:drop(active), +headerbar popover.background entry entry:drop(active), +entry headerbar popover.background entry:hover:not(:focus-within), +headerbar popover.background entry entry:hover:not(:focus-within), +entry:drop(active), +entry:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + + +entry headerbar popover.background entry:disabled, +headerbar popover.background entry entry:disabled, +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + + +entry headerbar popover.background entry > text > placeholder, +headerbar popover.background entry entry > text > placeholder, +entry > text > placeholder { + color: rgba(251, 241, 199, 0.5); +} + + +entry headerbar popover.background entry > text > block-cursor, +headerbar popover.background entry entry > text > block-cursor, +entry > text > block-cursor { + color: rgba(251, 241, 199, 0.04); + background-color: #fbf1c7; +} + + +entry headerbar popover.background entry.flat:focus-within, +headerbar popover.background entry entry.flat:focus-within, +entry headerbar popover.background entry.flat:disabled, +headerbar popover.background entry entry.flat:disabled, +entry headerbar popover.background entry.flat:hover, +headerbar popover.background entry entry.flat:hover, +entry headerbar popover.background entry.flat, +headerbar popover.background entry entry.flat, +entry.flat:focus-within, +entry.flat:disabled, +entry.flat:hover, +entry.flat { + min-height: 0; + padding: 2px; + background-color: transparent; + box-shadow: none; + border-radius: 0; + outline: none; +} + + +entry headerbar popover.background entry > image, +headerbar popover.background entry entry > image, +entry > image { + color: rgba(251, 241, 199, 0.7); +} + + +entry headerbar popover.background entry > image:hover, +headerbar popover.background entry entry > image:hover, +entry headerbar popover.background entry > image:active, +headerbar popover.background entry entry > image:active, +entry > image:hover, +entry > image:active { + color: #fbf1c7; +} + + +entry headerbar popover.background entry > image:disabled, +headerbar popover.background entry entry > image:disabled, +entry > image:disabled { + color: rgba(251, 241, 199, 0.5); +} + + +entry headerbar popover.background entry > image.left, +headerbar popover.background entry entry > image.left, +entry > image.left { + margin: 0 6px 0 1px; +} + + +entry headerbar popover.background entry > image.right, +headerbar popover.background entry entry > image.right, +entry > image.right { + margin: 0 1px 0 6px; +} + + +entry headerbar popover.background entry.password image.caps-lock-indicator, +headerbar popover.background entry entry.password image.caps-lock-indicator, +entry.password image.caps-lock-indicator { + opacity: 0.35; +} + + +entry headerbar popover.background entry.error, +headerbar popover.background entry entry.error, +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + outline: none; +} + + +entry headerbar popover.background entry.error:focus-within, +headerbar popover.background entry entry.error:focus-within, +entry.error:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #c14a4a; + outline: none; +} + + +entry headerbar popover.background entry.error:drop(active), +headerbar popover.background entry entry.error:drop(active), +entry headerbar popover.background entry.error:hover:not(:focus-within), +headerbar popover.background entry entry.error:hover:not(:focus-within), +entry.error:drop(active), +entry.error:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.error:disabled, +headerbar popover.background entry entry.error:disabled, +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.error > text > selection, +headerbar popover.background entry entry.error > text > selection, +entry.error > text > selection { + background-color: rgba(193, 74, 74, 0.25); + color: #c14a4a; +} + + +entry headerbar popover.background entry.error > text > cursor-handle > contents, +headerbar popover.background entry entry.error > text > cursor-handle > contents, +entry.error > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.error > image, +headerbar popover.background entry entry.error > image, +entry.error > image { + color: rgba(193, 74, 74, 0.75); +} + + +entry headerbar popover.background entry.error > image:hover, +headerbar popover.background entry entry.error > image:hover, +entry headerbar popover.background entry.error > image:active, +headerbar popover.background entry entry.error > image:active, +entry.error > image:hover, +entry.error > image:active { + color: #c14a4a; +} + + +entry headerbar popover.background entry.error > image:disabled, +headerbar popover.background entry entry.error > image:disabled, +entry.error > image:disabled { + color: rgba(193, 74, 74, 0.35); +} + + +entry headerbar popover.background entry.warning, +headerbar popover.background entry entry.warning, +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + outline: none; +} + + +entry headerbar popover.background entry.warning:focus-within, +headerbar popover.background entry entry.warning:focus-within, +entry.warning:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #b47109; + outline: none; +} + + +entry headerbar popover.background entry.warning:drop(active), +headerbar popover.background entry entry.warning:drop(active), +entry headerbar popover.background entry.warning:hover:not(:focus-within), +headerbar popover.background entry entry.warning:hover:not(:focus-within), +entry.warning:drop(active), +entry.warning:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.warning:disabled, +headerbar popover.background entry entry.warning:disabled, +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.warning > text > selection, +headerbar popover.background entry entry.warning > text > selection, +entry.warning > text > selection { + background-color: rgba(180, 113, 9, 0.25); + color: #b47109; +} + + +entry headerbar popover.background entry.warning > text > cursor-handle > contents, +headerbar popover.background entry entry.warning > text > cursor-handle > contents, +entry.warning > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.warning > image, +headerbar popover.background entry entry.warning > image, +entry.warning > image { + color: rgba(180, 113, 9, 0.75); +} + + +entry headerbar popover.background entry.warning > image:hover, +headerbar popover.background entry entry.warning > image:hover, +entry headerbar popover.background entry.warning > image:active, +headerbar popover.background entry entry.warning > image:active, +entry.warning > image:hover, +entry.warning > image:active { + color: #b47109; +} + + +entry headerbar popover.background entry.warning > image:disabled, +headerbar popover.background entry entry.warning > image:disabled, +entry.warning > image:disabled { + color: rgba(180, 113, 9, 0.35); +} + + +entry headerbar popover.background entry.success, +headerbar popover.background entry entry.success, +entry.success { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + outline: none; +} + + +entry headerbar popover.background entry.success:focus-within, +headerbar popover.background entry entry.success:focus-within, +entry.success:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #6c782e; + outline: none; +} + + +entry headerbar popover.background entry.success:drop(active), +headerbar popover.background entry entry.success:drop(active), +entry headerbar popover.background entry.success:hover:not(:focus-within), +headerbar popover.background entry entry.success:hover:not(:focus-within), +entry.success:drop(active), +entry.success:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.success:disabled, +headerbar popover.background entry entry.success:disabled, +entry.success:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.success > text > selection, +headerbar popover.background entry entry.success > text > selection, +entry.success > text > selection { + background-color: rgba(108, 120, 46, 0.25); + color: #6c782e; +} + + +entry headerbar popover.background entry.success > text > cursor-handle > contents, +headerbar popover.background entry entry.success > text > cursor-handle > contents, +entry.success > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.success > image, +headerbar popover.background entry entry.success > image, +entry.success > image { + color: rgba(108, 120, 46, 0.75); +} + + +entry headerbar popover.background entry.success > image:hover, +headerbar popover.background entry entry.success > image:hover, +entry headerbar popover.background entry.success > image:active, +headerbar popover.background entry entry.success > image:active, +entry.success > image:hover, +entry.success > image:active { + color: #6c782e; +} + + +entry headerbar popover.background entry.success > image:disabled, +headerbar popover.background entry entry.success > image:disabled, +entry.success > image:disabled { + color: rgba(108, 120, 46, 0.35); +} + + +entry > progress, +entry progress > trough > progress { + margin: 0 -4px; + border-bottom: 2px solid #7daea3; + background-color: transparent; +} + +.osd entry > progress > trough > progress { + border-color: rgba(251, 241, 199, 0.04); +} + + +entry button.image-button { + min-height: 24px; + min-width: 24px; + padding: 0; +} + +treeview entry.flat, treeview entry { + background-color: #282524; +} + +treeview entry.flat, treeview entry.flat:focus-within, treeview entry, treeview entry:focus-within { + border-image: none; + box-shadow: none; +} + +.entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +editablelabel > stack > text { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: radial-gradient(farthest-side, #7daea3 0%, rgba(125, 174, 163, 0) 0%); + } + to { + background-image: radial-gradient(farthest-side, #7daea3 95%, rgba(125, 174, 163, 0)); + } +} + +infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button, popover.touch-selection button, popover.magnifier button, headerbar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +infobar.warning > revealer > box button:focus, popover.touch-selection button:focus, popover.magnifier button:focus, headerbar.selection-mode button:focus:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:hover, popover.touch-selection button:hover, popover.magnifier button:hover, headerbar.selection-mode button:hover:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:active, popover.touch-selection button:active, popover.magnifier button:active, headerbar.selection-mode button:active:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:checked, popover.touch-selection button:checked, popover.magnifier button:checked, headerbar.selection-mode button:checked:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +infobar.warning > revealer > box button:disabled, popover.touch-selection button:disabled, popover.magnifier button:disabled, headerbar.selection-mode button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +infobar.warning > revealer > box button:checked:disabled, popover.touch-selection button:checked:disabled, popover.magnifier button:checked:disabled, headerbar.selection-mode button:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.5); +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button, button { + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:focus:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:focus, button:focus { + background-color: alpha(currentColor, 0.08); + outline: 2px solid rgba(125, 174, 163, 0.35); + outline-offset: 0; +} + +row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:hover:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:hover, button:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; + -gtk-icon-filter: brightness(1.2); +} + +row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button.keyboard-activating:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button.keyboard-activating, button.keyboard-activating, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:active:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:active, button:active { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:disabled:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:disabled, button:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + outline-color: transparent; +} + +row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:checked, button:checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:hover:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:hover { + outline-color: transparent; + background-color: #8db8ae; + color: rgba(40, 40, 40, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:disabled:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:disabled { + outline-color: transparent; + background-color: rgba(125, 174, 163, 0.35); + color: rgba(40, 40, 40, 0.38); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button, calendar > header > button, notebook > header > tabs > arrow, popover modelbutton, .pathbar button, spinbutton > button, splitbutton.flat > button, +splitbutton.flat > menubutton > button { + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:focus:not(:hover):not(:active), calendar > header > button:focus:not(:hover):not(:active), notebook > header > tabs > arrow:focus:not(:hover):not(:active), popover modelbutton:focus:not(:hover):not(:active), .pathbar button:focus:not(:hover):not(:active), spinbutton > button:focus:not(:hover):not(:active), splitbutton.flat > button:focus:not(:hover):not(:active), +splitbutton.flat > menubutton > button:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 2px solid rgba(251, 241, 199, 0.04); + outline-offset: -2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:hover, calendar > header > button:hover, notebook > header > tabs > arrow:hover, popover modelbutton:hover, .pathbar button:hover, spinbutton > button:hover, splitbutton.flat > button:hover, +splitbutton.flat > menubutton > button:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:active, calendar > header > button:active, notebook > header > tabs > arrow:active, popover modelbutton:active, .pathbar button:active, spinbutton > button:active, splitbutton.flat > button:active, +splitbutton.flat > menubutton > button:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:disabled, calendar > header > button:disabled, notebook > header > tabs > arrow:disabled, popover modelbutton:disabled, .pathbar button:disabled, spinbutton > button:disabled, splitbutton.flat > button:disabled, +splitbutton.flat > menubutton > button:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +#NautilusPathButton, filechooser #pathbarbox > stack > box > button, window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button, .app-notification button, headerbar button:not(.suggested-action):not(.destructive-action), .toolbar button, splitbutton.suggested-action > button, +splitbutton.suggested-action > menubutton > button, splitbutton.destructive-action > button, +splitbutton.destructive-action > menubutton > button, splitbutton.opaque > button, +splitbutton.opaque > menubutton > button, menubutton.suggested-action > button, menubutton.destructive-action > button, menubutton.opaque > button, menubutton.flat > button, button.flat { + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +#NautilusPathButton:focus:not(:hover):not(:active), filechooser #pathbarbox > stack > box > button:focus:not(:hover):not(:active), window.messagedialog .response-area button:focus:not(:hover):not(:active), window.dialog.message .dialog-action-area > button:focus:not(:hover):not(:active), .app-notification button:focus:not(:hover):not(:active), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), .toolbar button:focus:not(:hover):not(:active), splitbutton.suggested-action > button:focus:not(:hover):not(:active), +splitbutton.suggested-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.destructive-action > button:focus:not(:hover):not(:active), +splitbutton.destructive-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.opaque > button:focus:not(:hover):not(:active), +splitbutton.opaque > menubutton > button:focus:not(:hover):not(:active), menubutton.suggested-action > button:focus:not(:hover):not(:active), menubutton.destructive-action > button:focus:not(:hover):not(:active), menubutton.opaque > button:focus:not(:hover):not(:active), menubutton.flat > button:focus:not(:hover):not(:active), button.flat:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 2px solid rgba(251, 241, 199, 0.04); + outline-offset: -2px; +} + +#NautilusPathButton:hover, filechooser #pathbarbox > stack > box > button:hover, window.messagedialog .response-area button:hover, window.dialog.message .dialog-action-area > button:hover, .app-notification button:hover, headerbar button:hover:not(.suggested-action):not(.destructive-action), .toolbar button:hover, splitbutton.suggested-action > button:hover, +splitbutton.suggested-action > menubutton > button:hover, splitbutton.destructive-action > button:hover, +splitbutton.destructive-action > menubutton > button:hover, splitbutton.opaque > button:hover, +splitbutton.opaque > menubutton > button:hover, menubutton.suggested-action > button:hover, menubutton.destructive-action > button:hover, menubutton.opaque > button:hover, menubutton.flat > button:hover, button.flat:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +#NautilusPathButton:active, filechooser #pathbarbox > stack > box > button:active, window.messagedialog .response-area button:active, window.dialog.message .dialog-action-area > button:active, .app-notification button:active, headerbar button:active:not(.suggested-action):not(.destructive-action), .toolbar button:active, splitbutton.suggested-action > button:active, +splitbutton.suggested-action > menubutton > button:active, splitbutton.destructive-action > button:active, +splitbutton.destructive-action > menubutton > button:active, splitbutton.opaque > button:active, +splitbutton.opaque > menubutton > button:active, menubutton.suggested-action > button:active, menubutton.destructive-action > button:active, menubutton.opaque > button:active, menubutton.flat > button:active, button.flat:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; +} + +#NautilusPathButton:disabled, filechooser #pathbarbox > stack > box > button:disabled, window.messagedialog .response-area button:disabled, window.dialog.message .dialog-action-area > button:disabled, .app-notification button:disabled, headerbar button:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:disabled, splitbutton.suggested-action > button:disabled, +splitbutton.suggested-action > menubutton > button:disabled, splitbutton.destructive-action > button:disabled, +splitbutton.destructive-action > menubutton > button:disabled, splitbutton.opaque > button:disabled, +splitbutton.opaque > menubutton > button:disabled, menubutton.suggested-action > button:disabled, menubutton.destructive-action > button:disabled, menubutton.opaque > button:disabled, menubutton.flat > button:disabled, button.flat:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +#NautilusPathButton:checked, filechooser #pathbarbox > stack > box > button:checked, window.messagedialog .response-area button:checked, window.dialog.message .dialog-action-area > button:checked, .app-notification button:checked, headerbar button:checked:not(.suggested-action):not(.destructive-action), .toolbar button:checked, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button:checked, menubutton.suggested-action > button:checked, menubutton.destructive-action > button:checked, menubutton.opaque > button:checked, menubutton.flat > button:checked, button.flat:checked { + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +#NautilusPathButton:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, window.messagedialog .response-area button:checked:disabled, window.dialog.message .dialog-action-area > button:checked:disabled, .app-notification button:checked:disabled, headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:checked:disabled, splitbutton.suggested-action > button:checked:disabled, +splitbutton.suggested-action > menubutton > button:checked:disabled, splitbutton.destructive-action > button:checked:disabled, +splitbutton.destructive-action > menubutton > button:checked:disabled, splitbutton.opaque > button:checked:disabled, +splitbutton.opaque > menubutton > button:checked:disabled, menubutton.suggested-action > button:checked:disabled, menubutton.destructive-action > button:checked:disabled, menubutton.opaque > button:checked:disabled, menubutton.flat > button:checked:disabled, button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(251, 241, 199, 0.5); +} + +button.opaque { + box-shadow: none; +} + +.osd button.opaque:focus:focus-visible { + outline-color: rgba(251, 241, 199, 0.15); +} + +button.opaque:hover { + background-image: image(alpha(currentColor, 0.1)); +} + +button.keyboard-activating.opaque, button.opaque:active { + background-image: image(rgba(0, 0, 0, 0.2)); +} + +button.opaque:checked { + background-image: image(rgba(0, 0, 0, 0.15)); +} + +button.opaque:checked:hover { + background-image: image(rgba(0, 0, 0, 0.05)); +} + +button.opaque:checked.keyboard-activating, button.opaque:checked:active { + background-image: image(rgba(0, 0, 0, 0.3)); +} + +.nautilus-window .floating-bar button, placessidebar list.navigation-sidebar > row button.sidebar-button, notebook > header > tabs > tab button.flat, popover.menu box.circular-buttons button.circular.image-button.model, spinbutton > button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + +button separator { + margin: 4px 1px; +} + +button.opaque { + background-color: #525048; + color: #fbf1c7; +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button, button.image-text-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button > box, +button.text-button.image-button > box > box, button.image-text-button > box, +button.image-text-button > box > box { + border-spacing: 4px; +} + +button.text-button.image-button > box > label, +button.text-button.image-button > box > box > label, button.image-text-button > box > label, +button.image-text-button > box > box > label { + padding-left: 2px; + padding-right: 2px; +} + +button.text-button.image-button label:first-child, button.image-text-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child, button.image-text-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child, button.image-text-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child, button.image-text-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child), button.image-text-button image:not(:only-child) { + margin: 0 4px; +} + +button.arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.arrow-button > box { + border-spacing: 4px; +} + +button.arrow-button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +button.arrow-button.text-button > box { + border-spacing: 6px; +} + +menubutton.pill > button, button.pill { + padding: 9px 30px; + border-radius: 9999px; +} + +button.card { + background-color: #282524; + background-clip: padding-box; + font-weight: inherit; + border: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; +} + +button.card:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + +button.card.keyboard-activating, button.card:active { + background-image: none; + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +button.card:checked { + background-image: none; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + border-color: #7daea3; +} + +button.card:checked:hover { + background-image: none; + outline-color: transparent; + background-color: #8db8ae; + color: rgba(40, 40, 40, 0.87); +} + +button.card:checked:disabled { + outline-color: transparent; + background-color: rgba(125, 174, 163, 0.35); + color: rgba(40, 40, 40, 0.38); +} + +button.card:checked.keyboard-activating, button.card:checked:active { + background-image: none; +} + +button.card:checked.has-open-popup { + background-image: none; +} + +button.card:drop(active) { + color: #e78a4e; + box-shadow: inset 0 0 0 1px #e78a4e; +} + +.linked:not(.vertical) > button:focus, .linked.vertical > button:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + background-color: alpha(currentColor, 0.05); +} + +.linked:not(.vertical) > button.flat:focus, .linked.vertical > button.flat:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > menubutton > button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +button.osd { + min-height: 24px; + min-width: 24px; + padding: 5px; + box-shadow: none; + background-color: rgba(0, 0, 0, 0.35); + color: #fbf1c7; + margin: 0; +} + +button.osd > image { + padding: 0; +} + +button.osd.remove-button { + padding: 0; +} + +button.osd:focus { + outline-color: transparent; +} + +button.osd:hover { + background-color: rgba(0, 0, 0, 0.45); + color: #fbf1c7; +} + +button.osd:active { + background-color: rgba(0, 0, 0, 0.65); + color: #fbf1c7; +} + +button.osd:disabled { + background-color: rgba(0, 0, 0, 0.15); + color: rgba(251, 241, 199, 0.35); +} + +button.suggested-action { + background-color: #45707a; + color: #fbf1c7; + box-shadow: none; +} + +button.suggested-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + outline-color: transparent; +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:checked { + background-color: #7c9791; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(69, 112, 122, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #45707a; +} + +button.suggested-action.flat:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +button.suggested-action.flat:checked { + background-color: rgba(69, 112, 122, 0.3); +} + +button.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; + box-shadow: none; +} + +button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + outline-color: transparent; +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:checked { + background-color: #d27c70; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(193, 74, 74, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #c14a4a; +} + +button.destructive-action.flat:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +button.destructive-action.flat:checked { + background-color: rgba(193, 74, 74, 0.3); +} + +stackswitcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +stackswitcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +stackswitcher > button.needs-attention:checked > label, +stackswitcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +button.font > box, button.file > box { + border-spacing: 6px; +} + +button.font > box > box > label, button.file > box > box > label { + font-weight: bold; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar button.star, menubutton.circular > button, button.close, button.circular { + border-radius: 9999px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque) label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child label, headerbar button.star label, menubutton.circular > button label, button.close label, button.circular label { + padding: 0; +} + +menubutton.osd { + background: none; + color: inherit; +} + +menubutton.suggested-action { + background-color: #45707a; + color: #fbf1c7; +} + +menubutton.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +menubutton.opaque { + background-color: #525048; + color: #fbf1c7; +} + +menubutton.suggested-action, menubutton.destructive-action, menubutton.opaque { + border-radius: 12px; +} + +menubutton.suggested-action.circular, menubutton.suggested-action.pill, menubutton.destructive-action.circular, menubutton.destructive-action.pill, menubutton.opaque.circular, menubutton.opaque.pill { + border-radius: 9999px; +} + +menubutton.suggested-action > button, menubutton.suggested-action > button:checked, menubutton.destructive-action > button, menubutton.destructive-action > button:checked, menubutton.opaque > button, menubutton.opaque > button:checked { + background-color: transparent; + color: inherit; +} + +menubutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +menubutton arrow { + min-height: 16px; + min-width: 16px; +} + +menubutton arrow.none { + -gtk-icon-source: -gtk-icontheme("open-menu-symbolic"); +} + +menubutton arrow.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menubutton arrow.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menubutton arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +menubutton arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +splitbutton { + border-radius: 12px; +} + +splitbutton, splitbutton > separator { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + transition-property: background; +} + +splitbutton > separator { + margin-top: 6px; + margin-bottom: 6px; + background: none; +} + +splitbutton > menubutton > button { + padding: 5px 9px; +} + +splitbutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +splitbutton.text-button.image-button > button, splitbutton.image-text-button > button { + padding-left: 9px; + padding-right: 9px; +} + +splitbutton.text-button.image-button > button > box, splitbutton.image-text-button > button > box { + border-spacing: 6px; +} + +splitbutton > button:dir(ltr), +splitbutton > menubutton > button:dir(rtl) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: -1px; +} + +splitbutton > button:dir(rtl), +splitbutton > menubutton > button:dir(ltr) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin-left: -1px; +} + +splitbutton.flat > separator { + background: rgba(251, 241, 199, 0.12); +} + +splitbutton.flat:hover, splitbutton.flat:active, splitbutton.flat:checked { + background: alpha(currentColor, 0.07); +} + +splitbutton.flat:hover > separator, splitbutton.flat:active > separator, splitbutton.flat:checked > separator { + background: none; +} + +splitbutton.flat:focus-within:focus-visible > separator { + background: none; +} + +splitbutton.flat > button, +splitbutton.flat > menubutton > button { + border-radius: 12px; +} + +splitbutton.suggested-action { + background-color: #45707a; + color: #fbf1c7; +} + +splitbutton.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +splitbutton.opaque { + background-color: #525048; + color: #fbf1c7; +} + +splitbutton.suggested-action > button, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button, +splitbutton.opaque > menubutton > button:checked { + color: inherit; + background-color: transparent; +} + +splitbutton.suggested-action > menubutton > button:dir(ltr), splitbutton.destructive-action > menubutton > button:dir(ltr), splitbutton.opaque > menubutton > button:dir(ltr) { + box-shadow: inset 1px 0 rgba(251, 241, 199, 0.12); +} + +splitbutton.suggested-action > menubutton > button:dir(rtl), splitbutton.destructive-action > menubutton > button:dir(rtl), splitbutton.opaque > menubutton > button:dir(rtl) { + box-shadow: inset -1px 0 rgba(251, 241, 199, 0.12); +} + +splitbutton > menubutton > button > arrow.none { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +buttoncontent { + border-spacing: 6px; +} + +buttoncontent > label { + font-weight: bold; +} + +buttoncontent > label:dir(ltr) { + padding-right: 2px; +} + +buttoncontent > label:dir(rtl) { + padding-left: 2px; +} + +.arrow-button > box > buttoncontent > label:dir(ltr), splitbutton > button > buttoncontent > label:dir(ltr) { + padding-right: 0; +} + +.arrow-button > box > buttoncontent > label:dir(rtl), splitbutton > button > buttoncontent > label:dir(rtl) { + padding-left: 0; +} + +stacksidebar row.needs-attention > label, stackswitcher > button.needs-attention > label, +stackswitcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar row.needs-attention > label:dir(rtl), stackswitcher > button.needs-attention > label:dir(rtl), +stackswitcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +.linked:not(.vertical) > entry, .linked:not(.vertical) > button, .linked:not(.vertical) > button.image-button { + border-radius: 0; +} + +.linked:not(.vertical) > entry:first-child, .linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > entry:last-child, .linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > entry:only-child, .linked:not(.vertical) > button:only-child { + border-radius: 12px; +} + +.linked.vertical > entry, .linked.vertical > button, .linked.vertical > button.image-button { + border-radius: 0; +} + +.linked.vertical > entry:first-child, .linked.vertical > button:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > entry:last-child, .linked.vertical > button:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > entry:only-child, .linked.vertical > button:only-child { + border-radius: 12px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + + +list > row button.image-button:not(.flat) { + background-color: transparent; + box-shadow: none; + border: none; +} + + +list > row button.image-button:not(.flat):hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + + +list > row button.image-button:not(.flat):active, +list > row button.image-button:not(.flat):checked { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + + +list > row button.image-button:not(.flat).suggested-action { + background-color: #45707a; + color: #fbf1c7; +} + + +list > row button.image-button:not(.flat).destructive-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +/********* + * Links * + *********/ +link { + color: #83b193; +} + +link:visited { + color: #ab62b1; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #83b193; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #ab62b1; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton { + border-radius: 9px; + padding: 0; + border-spacing: 0; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #7daea3; +} + +spinbutton:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton > text { + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + margin: 0; +} + +spinbutton > button { + border: none; +} + +spinbutton > button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: none; +} + +spinbutton:not(.vertical) > text { + min-width: 30px; + padding-left: 12px; +} + +spinbutton:not(.vertical) > button { + padding: 0; + margin: 6px; +} + +spinbutton:not(.vertical) > button.up:dir(ltr), spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 3px; +} + +spinbutton:not(.vertical) > button.up:dir(rtl), spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 3px; +} + +cell.activatable spinbutton:not(.vertical) { + margin: 3px 0; +} + +cell.activatable spinbutton:not(.vertical) > button { + margin: 0; + padding: 0; + min-height: 24px; + border-radius: 0; +} + +cell.activatable spinbutton:not(.vertical) > button:last-child { + border-radius: 0 12px 12px 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(ltr), cell.activatable spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(rtl), cell.activatable spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 0; +} + +spinbutton.vertical > text { + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical > button { + padding: 0; + margin: 6px 8px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #e78a4e; + box-shadow: inset 0 0 0 2px #e78a4e; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #fbf1c7; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top, combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +.toolbar { + padding: 6px; + /* background-color: $background; */ + border-spacing: 6px; +} + +.osd .toolbar { + background-color: transparent; +} + +.app-notification, .toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 18px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; + color: #fbf1c7; +} + +.app-notification:backdrop, .toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +.left.app-notification, .right.app-notification, .top.app-notification, .bottom.app-notification, .toolbar.osd.left, .toolbar.osd.right, .toolbar.osd.top, .toolbar.osd.bottom { + border-radius: 0; +} + +.bottom.app-notification, .toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +.toolbar.horizontal > separator { + margin: 2px; +} + +.toolbar.vertical > separator { + margin: 2px; +} + +.toolbar entry, +.toolbar spinbutton, +.toolbar splitbutton, +.toolbar separator:not(.sidebar), +.toolbar button, +.toolbar menubutton, +.toolbar scalebutton { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar menubutton > button, +.toolbar splitbutton > button, +.toolbar splitbutton > menubutton, +.toolbar scalebutton > button { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar switch { + margin-top: 4px; + margin-bottom: 4px; +} + +.toolbar spinbutton entry, +.toolbar spinbutton button { + margin: 0; +} + +.toolbar popover.menu separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +searchbar > revealer > box { + padding: 6px; + border-spacing: 0; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282828; + background-clip: border-box; + box-shadow: none; +} + +searchbar > revealer > box entry, +searchbar > revealer > box button, +searchbar > revealer > box menubutton { + margin: 0; +} + +/*************** + * Header bars * + ***************/ +headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); + border: none; +} + +headerbar button:hover:not(.suggested-action):not(.destructive-action), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), headerbar button:active:not(.suggested-action):not(.destructive-action), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(251, 241, 199, 0.5); +} + +headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.5); +} + +headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +headerbar entry { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.7); +} + +headerbar entry:hover, headerbar entry:focus-within { + color: #fbf1c7; +} + +headerbar entry:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +headerbar entry > text > placeholder { + color: rgba(251, 241, 199, 0.5); +} + +headerbar entry > text > block-cursor { + color: rgba(251, 241, 199, 0.04); + background-color: #fbf1c7; +} + +headerbar entry > image { + color: rgba(251, 241, 199, 0.7); +} + +headerbar entry > image:hover, headerbar entry > image:active { + color: #fbf1c7; +} + +headerbar entry > image:disabled { + color: rgba(251, 241, 199, 0.5); +} + +headerbar { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: transparent; + color: #fbf1c7; + min-height: 46px; + border: none; + box-shadow: none; + padding: 0; + margin: 0; +} + +headerbar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +headerbar:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.7); + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +headerbar:backdrop:disabled { + color: rgba(251, 241, 199, 0.32); +} + +headerbar.flat, headerbar.flat:backdrop { + background: none; + box-shadow: none; + transition: none; +} + +headerbar .title { + padding-left: 6px; + padding-right: 6px; + margin: 0 -13px; + font-weight: bold; +} + +headerbar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +headerbar .subtitle, +headerbar .dim-label, +headerbar row.expander image.expander-row-arrow, +row.expander headerbar image.expander-row-arrow, +headerbar row.property > box.header > box.title > .title, +headerbar row label.subtitle, +row headerbar label.subtitle { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(251, 241, 199, 0.7); +} + +headerbar .subtitle:backdrop, +headerbar .dim-label:backdrop, +headerbar row.expander image.expander-row-arrow:backdrop, +row.expander headerbar image.expander-row-arrow:backdrop, +headerbar row.property > box.header > box.title > .title:backdrop, +headerbar row label.subtitle:backdrop, +row headerbar label.subtitle:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +headerbar .titlebar { + background-color: transparent; + box-shadow: none; +} + +headerbar headerbar + separator { + background-color: rgba(251, 241, 199, 0.12); +} + +headerbar > windowhandle > box { + padding: 0 6px; +} + +headerbar > windowhandle > box, +headerbar > windowhandle > box > box.start, +headerbar > windowhandle > box > box.end { + border-spacing: 6px; +} + +headerbar entry, +headerbar spinbutton, +headerbar splitbutton, +headerbar button, +headerbar menubutton, +headerbar stackswitcher, +headerbar separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar menubutton > button, +headerbar spinbutton > button, +headerbar splitbutton > button, +headerbar splitbutton > menubutton, +headerbar .linked > menubutton, +headerbar entry > menubutton { + margin-top: 0; + margin-bottom: 0; +} + +headerbar button.suggested-action:disabled, +headerbar button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + opacity: 1; +} + +headerbar button.star { + min-height: 24px; + min-width: 24px; + padding: 5px; +} + +headerbar .linked:not(.vertical) > entry:not(:only-child) { + border-radius: 12px; +} + +headerbar .entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar popover.background button.suggested-action:disabled, +headerbar popover.background button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +headerbar popover.background entry, +headerbar popover.background spinbutton, +headerbar popover.background button, +headerbar popover.background menubutton, +headerbar popover.background stackswitcher { + margin-top: 0; + margin-bottom: 0; +} + +headerbar separator:not(.sidebar) { + background-color: rgba(251, 241, 199, 0.12); +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +headerbar.selection-mode:backdrop { + color: rgba(40, 40, 40, 0.6); +} + +headerbar.selection-mode .subtitle:link { + color: rgba(40, 40, 40, 0.87); +} + +headerbar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +headerbar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +headerbar.default-decoration { + min-height: 34px; + padding: 0; + margin: 0; + border: none; + outline: none; +} + +headerbar.default-decoration windowcontrols > button { + min-width: 16px; + min-height: 16px; + margin: 0 4px; + padding: 0; + /* @if $window_button == 'mac' { */ + /* min-width: 16px; */ + /* min-height: 16px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } @else { */ + /* min-width: 22px; */ + /* min-height: 22px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } */ +} + +headerbar.default-decoration windowcontrols menubutton button { + min-height: 20px; + min-width: 20px; + margin: 0; + padding: 4px; +} + +.maximized headerbar, .fullscreen headerbar, .tiled headerbar, .tiled-top headerbar, .tiled-right headerbar, .tiled-bottom headerbar, .tiled-left headerbar { + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.maximized headerbar.default-decoration, .fullscreen headerbar.default-decoration, .tiled headerbar.default-decoration, .tiled-top headerbar.default-decoration, .tiled-right headerbar.default-decoration, .tiled-bottom headerbar.default-decoration, .tiled-left headerbar.default-decoration { + box-shadow: none; +} + +.solid-csd headerbar:dir(rtl), .solid-csd headerbar:dir(ltr) { + border-radius: 0; + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.titlebar:not(headerbar) { + box-shadow: none; +} + +window.devel headerbar { + background: #282828 cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, linear-gradient(to right, transparent 65%, rgba(125, 174, 163, 0.1)), linear-gradient(to top, #303030 3px, #353535); +} + +window.devel headerbar:backdrop { + background: #282828 cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, image(#282828); + /* background-color would flash */ +} + +/************ + * Pathbars * + ************/ +.pathbar { + background-color: alpha(currentColor, 0.08); + border-radius: 12px; + padding: 0; +} + +.pathbar button { + margin: 0; +} + +headerbar .pathbar button { + margin: 0; +} + +/************** + * Tree Views * + **************/ +columnview.view, +treeview.view { + border-left-color: #423f3e; + border-top-color: #423f3e; +} + +columnview.view:hover, columnview.view:selected, +treeview.view:hover, +treeview.view:selected { + border-radius: 0; +} + +columnview.view:focus, +treeview.view:focus { + box-shadow: none; + outline: none; +} + +columnview.view.separator, +treeview.view.separator { + min-height: 5px; + color: rgba(251, 241, 199, 0.12); +} + +columnview.view:drop(active), +treeview.view:drop(active) { + box-shadow: none; +} + +columnview.view:drop(active).after, +treeview.view:drop(active).after { + border-top-style: none; +} + +columnview.view:drop(active).before, +treeview.view:drop(active).before { + border-bottom-style: none; +} + +columnview.view > dndtarget:drop(active), +treeview.view > dndtarget:drop(active) { + border-style: solid none; + border-width: 1px; + border-color: alpha(currentColor, 0.06); +} + +columnview.view > dndtarget:drop(active).after, +treeview.view > dndtarget:drop(active).after { + border-top-style: none; +} + +columnview.view > dndtarget:drop(active).before, +treeview.view > dndtarget:drop(active).before { + border-bottom-style: none; +} + +columnview.view.expander, +treeview.view.expander { + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + color: rgba(251, 241, 199, 0.7); +} + +columnview.view.expander:dir(rtl), +treeview.view.expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +columnview.view.expander:hover, +treeview.view.expander:hover { + color: #fbf1c7; +} + +columnview.view.expander:selected, +treeview.view.expander:selected { + color: #fbf1c7; +} + +columnview.view.expander:selected:hover, +treeview.view.expander:selected:hover { + color: #fbf1c7; +} + +columnview.view.expander:checked, +treeview.view.expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +columnview.view.expander:disabled, +treeview.view.expander:disabled { + color: rgba(251, 241, 199, 0.32); +} + +columnview.view.progressbar, +treeview.view.progressbar { + border-bottom: 6px solid #7daea3; + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.progressbar:selected:hover, +treeview.view.progressbar:selected:hover { + box-shadow: none; +} + +columnview.view.trough, +treeview.view.trough { + border-bottom: 6px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.trough:selected:hover, +treeview.view.trough:selected:hover { + box-shadow: none; +} + +columnview.view > header > button, +treeview.view > header > button { + padding: 2px 6px; + border-style: none solid solid none; + border-width: 0 1px 0 0; + border-color: transparent; + border-radius: 0; + background-clip: border-box; +} + +columnview.view > header > button:not(:focus):not(:hover):not(:active), +treeview.view > header > button:not(:focus):not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +columnview.view > header > button, columnview.view > header > button:disabled, +treeview.view > header > button, +treeview.view > header > button:disabled { + background-color: transparent; +} + +columnview.view > header > button:last-child, +treeview.view > header > button:last-child { + border-right-style: none; +} + +columnview.view button.dnd, +columnview.view header.button.dnd, +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #282524; + background-clip: border-box; + color: #7daea3; +} + +columnview.view acceleditor > label, +treeview.view acceleditor > label { + background-color: #7daea3; +} + +stack.view treeview.view { + min-height: 34px; +} + +/********* + * Menus * + *********/ +menubar { + padding: 0; + background-color: #282828; + color: #fbf1c7; +} + +menubar:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.7); +} + +.csd menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + padding: 4px 8px; + color: rgba(251, 241, 199, 0.7); +} + +menubar > item:selected { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +menubar > item:disabled { + color: rgba(251, 241, 199, 0.32); +} + +menubar > item label:disabled { + color: inherit; +} + +menubar > item popover.menu popover.menu { + margin-left: 9px; +} + +menubar > item popover.menu.background popover.menu.background > contents { + margin: 0; + border-radius: 12px; +} + +/********************** + * Popover Base Menus * + **********************/ +popover.menu box.inline-buttons { + color: #fbf1c7; + padding: 0 6px; +} + +popover.menu box.inline-buttons button.image-button.model { + min-height: 28px; + min-width: 28px; + padding: 0; + border: none; + outline: none; + transition: none; +} + +popover.menu box.inline-buttons button.image-button.model:selected { + background: image(alpha(currentColor, 0.06)); +} + +popover.menu box.circular-buttons { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model:focus { + background-color: alpha(currentColor, 0.06); +} + +popover.menu arrow.left, +popover.menu radio.left, +popover.menu check.left { + margin-left: 0; + margin-right: 0; +} + +popover.menu arrow.right, +popover.menu radio.right, +popover.menu check.right { + margin-left: 0; + margin-right: 0; +} + +popover.menu label.title { + font-weight: bold; + padding: 4px 26px; +} + +/************ + * Popovers * + ************/ +popover.background { + font: initial; +} + +popover.background, popover.background:backdrop { + background-color: transparent; +} + +popover > arrow, +popover > contents { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + background-color: #141617; + border-radius: 12px; + color: #fbf1c7; + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +popover > arrow { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +popover > contents > list, +popover > contents > .view, +popover > contents > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover > contents separator { + background-color: rgba(251, 241, 199, 0.12); + margin: 15px 10px; +} + +popover > contents list separator { + margin: 0; +} + +popover > contents list > row { + border-radius: 12px; +} + +popover > contents stack > box { + padding: 0; +} + +popover > contents > box > button { + margin: 0; +} + +popover .view:not(:selected), +popover toolbar { + background-color: #141617; +} + +popover button, +popover entry, +popover combobox { + border-radius: 12px; +} + +popover .linked > button:not(.radio) { + border-radius: 0; +} + +popover .linked > button:not(.radio):first-child { + border-radius: 12px 0 0 12px; +} + +popover .linked > button:not(.radio):last-child { + border-radius: 0 12px 12px 0; +} + +popover .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.menu button, +popover button.model { + min-height: 32px; + padding: 0 8px; +} + +popover modelbutton { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 22px; + min-width: 56px; + padding: 3px 9px; + color: #fbf1c7; + font: initial; + border-radius: 12px; +} + +popover modelbutton:hover { + transition: none; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +popover modelbutton:hover accelerator { + color: #7daea3; +} + +popover modelbutton:hover accelerator:disabled { + color: rgba(251, 241, 199, 0.5); +} + +popover modelbutton:focus:not(:hover) { + transition: none; + box-shadow: none; + outline: none; +} + +popover modelbutton:disabled { + color: rgba(251, 241, 199, 0.5); +} + +popover modelbutton accelerator { + color: rgba(251, 241, 199, 0.5); + margin-left: 30px; +} + +popover modelbutton accelerator:disabled { + color: rgba(251, 241, 199, 0.12); +} + +popover modelbutton arrow.left { + -gtk-icon-source: -gtk-icontheme("go-previous-symbolic"); +} + +popover modelbutton arrow.right { + -gtk-icon-source: -gtk-icontheme("go-next-symbolic"); +} + +.osd popover, popover.touch-selection, popover.magnifier { + background-color: transparent; +} + +magnifier { + background-color: #282524; +} + +/************* + * Notebooks * + *************/ +notebook > header > tabs > tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +notebook > header > tabs > tab:hover:not(:checked):not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +notebook > header > tabs > tab:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +notebook > header > tabs > tab:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; + background-color: #282524; + color: #fbf1c7; + box-shadow: none; +} + +notebook > header > tabs > tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +notebook > header > tabs > tab:checked:disabled { + color: rgba(251, 241, 199, 0.5); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: rgba(251, 241, 199, 0.04); +} + +notebook, notebook.frame { + background-color: #282524; + background-color: rgba(251, 241, 199, 0.04); + border-radius: 15px; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(251, 241, 199, 0.04); + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header > tabs > tab { + margin: 3px; +} + +notebook > header > tabs > tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header > tabs > tab > box:drop(active) { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +notebook > header > tabs > tab button.flat:last-child { + margin-left: 6px; + margin-right: -3px; +} + +notebook > header > tabs > tab button.flat:first-child { + margin-left: -3px; + margin-right: 6px; +} + +notebook > header > tabs > tab button.close-button { + min-width: 24px; + min-height: 24px; +} + +notebook > header.top > tabs, notebook > header.bottom > tabs { + padding-left: 0; + padding-right: 0; +} + +notebook > header.top > tabs:not(:only-child):first-child, notebook > header.bottom > tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top > tabs:not(:only-child):last-child, notebook > header.bottom > tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top > tabs > tab:not(:last-child), notebook > header.bottom > tabs > tab:not(:last-child) { + margin-right: 0; +} + +notebook > header.top > tabs tab.reorderable-page, notebook > header.bottom > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left > tabs, notebook > header.right > tabs { + padding-top: 0; + padding-bottom: 0; +} + +notebook > header.left > tabs:not(:only-child):first-child, notebook > header.right > tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left > tabs:not(:only-child):last-child, notebook > header.right > tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left > tabs > tab:not(:last-child), notebook > header.right > tabs > tab:not(:last-child) { + margin-bottom: 0; +} + +notebook > header.left > tabs tab.reorderable-page, notebook > header.right > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > menubutton > button.image-button { + padding: 3px; + min-width: 24px; + min-height: 24px; + margin: 0 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +tabbar tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(251, 241, 199, 0.7); +} + +tabbar tab:hover:not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +tabbar tab:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +tabbar tab:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; + box-shadow: none; + color: #fbf1c7; +} + +tabbar tab:selected:not(:active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbar tab:selected:not(:active):disabled { + color: rgba(251, 241, 199, 0.5); +} + +tabbar > revealer > box { + box-shadow: none; +} + +tabbar .box { + background-color: #282828; + background-image: none; + padding: 0; + margin: 0; + border-radius: 0; + min-height: 34px; + border: none; + /* box-shadow: inset 0 -1px $border; */ +} + +tabbar .box:backdrop { + background-color: #282828; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabbar .box:backdrop > scrolledwindow, +tabbar .box:backdrop > .start-action, +tabbar .box:backdrop > .end-action { + filter: none; + transition: none; +} + +tabbar tabbox { + padding: 0; + margin: 0; + min-height: 34px; +} + +tabbar tabbox > background { + background: none; +} + +tabbar tabbox > separator { + margin: 9px 0; + transition: opacity 150ms ease-in-out; +} + +tabbar tabbox > separator.hidden { + opacity: 0; +} + +tabbar tabbox > tabboxchild { + padding: 0; + margin: 0; +} + +tabbar tab { + padding: 6px; + margin: 6px 2px; +} + +tabbar tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#7daea3, 0.4) 10%, alpha(#7daea3, 0) 30%); +} + +tabbar tab.needs-attention:hover { + background-image: image(alpha(currentColor, 0.03)), radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#7daea3, 0.4) 10%, alpha(#7daea3, 0) 30%); +} + +tabbar tabbox.single-tab tab, tabbar tabbox.single-tab tab:hover, tabbar tabbox.single-tab tab:active { + background: none; +} + +tabbar undershoot { + transition: background 150ms ease-in-out; +} + +tabbar undershoot.left { + background: linear-gradient(to right, #282524, rgba(0, 0, 0, 0) 20px); +} + +tabbar undershoot.right { + background: linear-gradient(to left, #282524, rgba(0, 0, 0, 0) 20px); +} + +tabbar .needs-attention-left undershoot.left { + background: linear-gradient(to right, alpha(#7daea3, 0.5), alpha(#7daea3, 0.3) 1px, alpha(#7daea3, 0) 20px); +} + +tabbar .needs-attention-right undershoot.right { + background: linear-gradient(to left, alpha(#7daea3, 0.5), alpha(#7daea3, 0.3) 1px, alpha(#7daea3, 0) 20px); +} + +tabbar .start-action, +tabbar .end-action { + padding: 6px 5px; +} + +tabbar .start-action:dir(ltr), +tabbar .end-action:dir(rtl) { + padding-right: 0; +} + +tabbar .start-action:dir(rtl), +tabbar .end-action:dir(ltr) { + padding-left: 0; +} + +tabbar.inline .box { + background-color: transparent; + color: inherit; + box-shadow: none; + padding-bottom: 0; +} + +tabbar.inline .box:backdrop { + background-color: transparent; + transition: none; +} + +tabbar.inline .box:backdrop > scrolledwindow, +tabbar.inline .box:backdrop > .start-action, +tabbar.inline .box:backdrop > .end-action { + filter: none; + transition: none; +} + +dnd tab { + min-height: 24px; + background-color: #282828; + color: #fbf1c7; + box-shadow: 0 1px 5px 1px rgba(0, 0, 0, 0.09), 0 2px 14px 3px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.05); + outline: 1px solid rgba(40, 40, 40, 0.75); + outline-offset: -1px; + margin: 24px; +} + +dnd tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#7daea3, 0.4) 10%, alpha(#7daea3, 0) 30%); +} + +tabbar tab, +dnd tab { + padding: 6px; +} + +tabbar tab button.image-button, +dnd tab button.image-button { + padding: 0; + margin: 0; + min-width: 24px; + min-height: 24px; + border-radius: 9999px; + color: rgba(251, 241, 199, 0.7); +} + +tabbar tab button.image-button:hover, tabbar tab button.image-button:active, +dnd tab button.image-button:hover, +dnd tab button.image-button:active { + color: #fbf1c7; +} + +tabbar tab button.image-button:disabled, +dnd tab button.image-button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +tabbar tab indicator, +dnd tab indicator { + min-height: 2px; + border-radius: 2px; + background: alpha(#7daea3, 0.5); + transform: translateY(4px); +} + +tabthumbnail { + border-radius: 12px; + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabthumbnail > box { + margin: 6px; +} + +tabthumbnail:drop(active) { + box-shadow: inset 0 0 0 2px alpha(#e78a4e, 0.4); + background-color: alpha(#e78a4e, 0.1); +} + +tabthumbnail .needs-attention:dir(ltr) { + transform: translate(8px, -8px); +} + +tabthumbnail .needs-attention:dir(rtl) { + transform: translate(-8px, -8px); +} + +tabthumbnail .needs-attention > widget { + background: #7daea3; + min-width: 12px; + min-height: 12px; + border-radius: 9px; + margin: 3px; + box-shadow: 0 1px 2px alpha(#7daea3, 0.4); +} + +tabthumbnail .card { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +tabthumbnail .card picture { + outline: 1px solid rgba(251, 241, 199, 0.12); + outline-offset: -1px; + border-radius: 12px; +} + +tabthumbnail.pinned .card { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +tabthumbnail .icon-title-box { + border-spacing: 6px; +} + +tabthumbnail .tab-unpin-icon { + margin: 6px; + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular { + margin: 6px; + background-color: rgba(251, 241, 199, 0.04); + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular:hover { + background-color: alpha(currentColor, 0.08); +} + +tabthumbnail button.circular:active { + background-color: alpha(currentColor, 0.12); +} + +taboverview > .overview .new-tab-button { + margin: 18px; +} + +tabview:drop(active), +tabbox:drop(active), +tabgrid:drop(active) { + box-shadow: none; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); + outline: none; +} + +scrollbar, +scrollbar button { + border: none; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar > range > trough { + background: none; + padding: 0; + margin: 0; + border: none; + outline: none; + transition: none; +} + +scrollbar > range > trough > slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 9999px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(251, 241, 199, 0.5); +} + +scrollbar > range > trough > slider:hover { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar > range > trough > slider:active { + background-color: rgba(251, 241, 199, 0.7); +} + +scrollbar > range > trough > slider:disabled { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar > range.fine-tune > trough > slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.overlay-indicator { + background: none; + color: inherit; + box-shadow: none; + padding: 0; +} + +scrollbar.overlay-indicator > range > trough { + outline: none; + background-color: rgba(251, 241, 199, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator > range > trough > slider { + outline: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; + border-color: transparent; + background-color: transparent; + box-shadow: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough { + background-color: transparent; + border: none; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough > slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical > range > trough > slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.vertical > range > trough > slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + padding: 0; + border: none; + border-radius: 9999px; + background-color: rgba(251, 241, 199, 0.5); + background-clip: border-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #7daea3; +} + +switch:disabled { + opacity: 0.5; +} + +switch > slider { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 0 0 0 transparent, 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #fbf1c7; + border: none; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12), 0 3px 3px -2px transparent, 0 2px 3px -1px transparent, 0 1px 4px 0 transparent; +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; + border-spacing: 3px; +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + border: none; + color: transparent; + background-color: rgba(251, 241, 199, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.04); + background-color: rgba(251, 241, 199, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(251, 241, 199, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(40, 40, 40, 0.6); + background-color: #7daea3; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.15); + background-color: #9cc2b9; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.2); + background-color: #7daea3; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(40, 40, 40, 0.6); + background-color: rgba(125, 174, 163, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu radio { + transition: none; + margin: 0; + padding: 0; +} + +popover.menu check:dir(ltr), popover.menu radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +popover.menu check:dir(rtl), popover.menu radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu check:hover, popover.menu check:disabled, popover.menu check:checked:hover, popover.menu check:indeterminate:hover, popover.menu radio, popover.menu radio:hover, popover.menu radio:disabled, popover.menu radio:checked:hover, popover.menu radio:indeterminate:hover { + box-shadow: none; +} + + +check { + -gtk-icon-size: 20px; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/checkbox-mixed-symbolic@2.svg"))); +} + + +radio { + -gtk-icon-size: 20px; +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/radio-mixed-symbolic@2.svg"))); +} + + +popover.menu check { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-checked-symbolic@2.svg"))); +} + + +popover.menu check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-mixed-symbolic@2.svg"))); +} + + +popover.menu radio { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/small-radio-checked-symbolic@2.svg"))); +} + + +popover.menu radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view radio, +treeview.view check, +columnview.view radio, +columnview.view check { + padding: 0; + margin: 0; + transition: none; +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover, +columnview.view radio, +columnview.view radio:hover, +columnview.view radio:disabled, +columnview.view radio:checked:hover, +columnview.view radio:indeterminate:hover, +columnview.view check, +columnview.view check:hover, +columnview.view check:disabled, +columnview.view check:checked:hover, +columnview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view:hover check, +treeview.view:hover radio, treeview.view:selected check, +treeview.view:selected radio, treeview.view:focus check, +treeview.view:focus radio, +columnview.view:hover check, +columnview.view:hover radio, +columnview.view:selected check, +columnview.view:selected radio, +columnview.view:focus check, +columnview.view:focus radio { + box-shadow: none; +} + +treeview.view:hover check:checked, +treeview.view:hover radio:checked, treeview.view:selected check:checked, +treeview.view:selected radio:checked, treeview.view:focus check:checked, +treeview.view:focus radio:checked, +columnview.view:hover check:checked, +columnview.view:hover radio:checked, +columnview.view:selected check:checked, +columnview.view:selected radio:checked, +columnview.view:focus check:checked, +columnview.view:focus radio:checked { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +checkbutton.selection-mode { + border-radius: 9999px; +} + +checkbutton.selection-mode check, +checkbutton.selection-mode radio { + padding: 6px; + border-radius: 9999px; +} + +checkbutton.selection-mode check:checked, checkbutton.selection-mode check:indeterminate, +checkbutton.selection-mode radio:checked, +checkbutton.selection-mode radio:indeterminate { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +checkbutton.selection-mode label:dir(ltr) { + margin-right: 6px; +} + +checkbutton.selection-mode label:dir(rtl) { + margin-left: 6px; +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale > trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(251, 241, 199, 0.3); +} + +scale > trough:disabled { + background-color: rgba(251, 241, 199, 0.12); +} + +scale > trough > highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#7daea3); +} + +scale > trough > highlight:disabled { + background-color: #282828; + background-image: image(rgba(251, 241, 199, 0.32)); +} + +scale > trough > fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.3); +} + +scale > trough > fill:disabled { + background-color: transparent; +} + +scale > trough > slider { + min-height: 18px; + min-width: 18px; + margin: -8px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #7daea3; + background-color: #282524; + box-shadow: inset 0 0 0 2px #7daea3; +} + +scale > trough > slider:hover { + box-shadow: inset 0 0 0 2px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale > trough > slider:active { + box-shadow: inset 0 0 0 4px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale > trough > slider:disabled { + box-shadow: inset 0 0 0 2px rgba(251, 241, 199, 0.32); +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune > trough > slider { + margin: -7px; +} + +scale > marks, +scale > value { + color: rgba(251, 241, 199, 0.7); +} + +scale indicator { + background-color: rgba(251, 241, 199, 0.3); + color: transparent; +} + +scale.marks-before:not(.marks-after) > trough > slider, scale.marks-after:not(.marks-before) > trough > slider { + transform: rotate(45deg); + border-bottom-right-radius: 0; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal > trough > slider:dir(ltr), scale.color.horizontal > trough > slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) > trough > slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(251, 241, 199, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #7daea3; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; + box-shadow: none; + margin: 0; + padding: 0; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #7daea3; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #b47109; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #7daea3; +} + +levelbar block.full { + background-color: #6c782e; +} + +levelbar block.empty { + background-color: rgba(251, 241, 199, 0.12); +} + +/**************** + * Print dialog * +*****************/ +window.dialog.print drawing { + color: #fbf1c7; + background: none; + border: none; + padding: 0; +} + +window.dialog.print drawing paper { + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; + color: #fbf1c7; +} + +window.dialog.print .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame, +.frame { + border: 1px solid rgba(251, 241, 199, 0.12); +} + +frame > list, +.frame > list { + border: none; +} + +frame.view, +.frame.view { + border-radius: 12px; +} + +frame.flat, +.frame.flat { + border-style: none; +} + +frame { + border-radius: 12px; +} + +frame > label { + margin: 4px; +} + +frame.flat > border, statusbar frame > border { + border: none; +} + +actionbar { + box-shadow: none; +} + +actionbar > revealer > box { + padding: 6px; + border-spacing: 6px; + box-shadow: none; + /* background-color: $base; */ + background-color: rgba(251, 241, 199, 0.04); + background-clip: border-box; + border: none; + color: #fbf1c7; +} + +actionbar > revealer > box button, +actionbar > revealer > box entry, +actionbar > revealer > box menubutton, +actionbar > revealer > box menubutton > button, +actionbar > revealer > box splitbutton, +actionbar > revealer > box splitbutton > button, +actionbar > revealer > box spinbutton { + margin: 0; +} + +statusbar { + padding: 6px 18px; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +scrolledwindow > overshoot.top { + background-image: radial-gradient(farthest-side at top, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at top, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: top; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.bottom { + background-image: radial-gradient(farthest-side at bottom, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at bottom, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.left { + background-image: radial-gradient(farthest-side at left, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at left, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: left; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.right { + background-image: radial-gradient(farthest-side at right, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at right, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: right; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow.undershoot-top > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 0px 0px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow > undershoot { + background-image: none; + box-shadow: none; + border: none; +} + +separator { + min-width: 1px; + min-height: 1px; + background-color: transparent; +} + +stacksidebar + separator.vertical, +stacksidebar separator.horizontal, button.font separator, button.file separator, separator.spacer, separator.sidebar { + min-width: 0; + min-height: 0; + background-color: transparent; + background-image: none; +} + +/********* + * Lists * + *********/ +list.content, +list.boxed-list { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); +} + +listview, +list { + border-color: rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); + background-clip: padding-box; +} + +listview > row, +list > row { + padding: 6px; + background-clip: padding-box; +} + +listview > row.expander, +list > row.expander { + padding: 0px; +} + +listview > row.expander .row-header, +list > row.expander .row-header { + padding: 2px; +} + +listview.horizontal row.separator:not(:last-child), listview.separators.horizontal > row:not(.separator):not(:last-child), +list.horizontal row.separator:not(:last-child), +list.separators.horizontal > row:not(.separator):not(:last-child) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +listview:not(.horizontal) row.separator:not(:last-child), listview.separators:not(.horizontal) > row:not(.separator):not(:last-child), +list:not(.horizontal) row.separator:not(:last-child), +list.separators:not(.horizontal) > row:not(.separator):not(:last-child) { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +list.frame { + border-radius: 12px; +} + +listview.view { + color: #fbf1c7; + background-color: transparent; +} + +popover.menu listview.view { + padding: 0; + border-radius: 12px; +} + +popover.menu listview.view > row { + margin-left: 0; + margin-right: 0; + border-radius: 12px; +} + +row { + color: rgba(251, 241, 199, 0.7); + background-clip: padding-box; +} + +.nautilus-window .nautilus-grid-view child.activatable, +.nautilus-window .nautilus-list-view child.activatable, columnview.view > header > button, +treeview.view > header > button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), font-weight 0; + outline: none; + box-shadow: none; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.nautilus-window .nautilus-grid-view child.activatable:focus, +.nautilus-window .nautilus-list-view child.activatable:focus, columnview.view > header > button:focus, +treeview.view > header > button:focus, row.activatable:focus { + color: #fbf1c7; + background-color: transparent; + box-shadow: none; + outline: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:hover, +.nautilus-window .nautilus-list-view child.activatable:hover, columnview.view > header > button:hover, +treeview.view > header > button:hover, .nautilus-window .nautilus-grid-view child.has-open-popup.activatable, +.nautilus-window .nautilus-list-view child.has-open-popup.activatable, columnview.view > header > button.has-open-popup, +treeview.view > header > button.has-open-popup, row.activatable:hover, row.activatable.has-open-popup { + color: #fbf1c7; + background-color: alpha(currentColor, 0.05); + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:active, +.nautilus-window .nautilus-list-view child.activatable:active, columnview.view > header > button:active, +treeview.view > header > button:active, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, font-weight 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; + background-color: alpha(currentColor, 0.05); + color: #fbf1c7; + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:selected, +.nautilus-window .nautilus-list-view child.activatable:selected, columnview.view > header > button:selected, +treeview.view > header > button:selected, row.activatable:selected { + background-color: alpha(currentColor, 0.06); +} + +.nautilus-window .nautilus-grid-view child.activatable:selected:hover, +.nautilus-window .nautilus-list-view child.activatable:selected:hover, columnview.view > header > button:selected:hover, +treeview.view > header > button:selected:hover, row.activatable:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +button row.activatable:focus, button row.activatable:hover, button row.activatable:active { + box-shadow: none; + background: none; +} + +button:checked row.activatable { + color: rgba(40, 40, 40, 0.87); +} + +row:selected { + background-color: alpha(currentColor, 0.06); + color: #fbf1c7; + box-shadow: none; +} + +row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus, row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus:hover, row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.rich-list { + /* rich lists usually containing other widgets than just labels/text */ +} + +.rich-list > row { + padding: 9px 12px; + min-height: 32px; + /* should be tall even when only containing a label */ +} + +.rich-list > row:last-child { + border-bottom: none; +} + +.rich-list > row > box { + border-spacing: 12px; +} + +row label.subtitle { + font-size: smaller; +} + +row > box.header { + margin-left: 12px; + margin-right: 12px; + border-spacing: 6px; + min-height: 50px; +} + +row > box.header > .icon:disabled { + filter: opacity(0.45); +} + +row > box.header > box.title { + margin-top: 6px; + margin-bottom: 6px; + border-spacing: 3px; + padding: 0; +} + +row > box.header > box.title, +row > box.header > box.title > .title, +row > box.header > box.title > .subtitle { + padding: 0; + font-weight: inherit; +} + +row > box.header > .prefixes, +row > box.header > .suffixes { + border-spacing: 6px; +} + +row > box.header > .icon:dir(ltr), +row > box.header > .prefixes:dir(ltr) { + margin-right: 6px; +} + +row > box.header > .icon:dir(rtl), +row > box.header > .prefixes:dir(rtl) { + margin-left: 6px; +} + +row.property > box.header > box.title > .subtitle { + font-size: inherit; + opacity: 1; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry:disabled text { + opacity: 0.45; +} + +row.entry:disabled .dim-label, row.entry:disabled row.expander image.expander-row-arrow, row.expander row.entry:disabled image.expander-row-arrow, row.entry:disabled row.property > box.header > box.title > .title, +row.entry:disabled .subtitle { + opacity: 1; +} + +row.entry .edit-icon, +row.entry .indicator { + min-width: 24px; + min-height: 24px; + padding: 5px; +} + +row.entry .edit-icon:disabled { + opacity: 0.5; +} + +row.entry .indicator { + opacity: 0.65; +} + +row.entry.monospace { + font-family: inherit; +} + +row.entry.monospace text { + font-family: monospace; +} + +row.spin:not(:selected).activatable.focused:hover, row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.spin spinbutton { + background: none; + border-spacing: 6px; + box-shadow: none; +} + +row.spin spinbutton, row.spin spinbutton:focus { + outline: none; +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child { + min-width: 30px; + min-height: 30px; + margin: 10px 2px; + border: none; +} + +row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child:disabled { + filter: none; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active, +row.spin:not(:selected).activatable.focused:hover, +row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry.error text > selection:focus-within, +row.spin.error text > selection:focus-within { + background-color: alpha(#c14a4a, 0.2); +} + +row.entry.error text > cursor-handle > contents, +row.spin.error text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.error .dim-label, row.entry.error row.expander image.expander-row-arrow, row.expander row.entry.error image.expander-row-arrow, row.entry.error row.property > box.header > box.title > .title, +row.entry.error .subtitle, +row.spin.error .dim-label, +row.spin.error row.expander image.expander-row-arrow, +row.expander row.spin.error image.expander-row-arrow, +row.spin.error row.property > box.header > box.title > .title, +row.spin.error .subtitle { + opacity: 1; +} + +row.entry.error .suggested-action, +row.spin.error .suggested-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +row.entry.warning text > selection:focus-within, +row.spin.warning text > selection:focus-within { + background-color: alpha(#b47109, 0.2); +} + +row.entry.warning text > cursor-handle > contents, +row.spin.warning text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.warning .dim-label, row.entry.warning row.expander image.expander-row-arrow, row.expander row.entry.warning image.expander-row-arrow, row.entry.warning row.property > box.header > box.title > .title, +row.entry.warning .subtitle, +row.spin.warning .dim-label, +row.spin.warning row.expander image.expander-row-arrow, +row.expander row.spin.warning image.expander-row-arrow, +row.spin.warning row.property > box.header > box.title > .title, +row.spin.warning .subtitle { + opacity: 1; +} + +row.entry.warning .suggested-action, +row.spin.warning .suggested-action { + background-color: #b47109; + color: #fbf1c7; +} + +row.entry.success text > selection:focus-within, +row.spin.success text > selection:focus-within { + background-color: alpha(#6c782e, 0.2); +} + +row.entry.success text > cursor-handle > contents, +row.spin.success text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.success .dim-label, row.entry.success row.expander image.expander-row-arrow, row.expander row.entry.success image.expander-row-arrow, row.entry.success row.property > box.header > box.title > .title, +row.entry.success .subtitle, +row.spin.success .dim-label, +row.spin.success row.expander image.expander-row-arrow, +row.expander row.spin.success image.expander-row-arrow, +row.spin.success row.property > box.header > box.title > .title, +row.spin.success .subtitle { + opacity: 1; +} + +row.entry.success .suggested-action, +row.spin.success .suggested-action { + background-color: #6c782e; + color: #fbf1c7; +} + +row.combo image.dropdown-arrow:disabled { + filter: opacity(0.45); +} + +row.combo listview.inline { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +row.combo listview.inline, row.combo listview.inline:disabled { + background: none; + color: inherit; +} + +row.combo popover > contents { + min-width: 120px; +} + +row.combo popover > contents .combo-searchbar { + margin: 6px; +} + +row.combo popover > contents .combo-searchbar + scrolledwindow > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(251, 241, 199, 0.12), 0.75), transparent 4px); +} + +list.content > row, list.content > row.expander row.header, +list.boxed-list > row, +list.boxed-list > row.expander row.header, row.expander list.nested > row { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +list.content > row:not(:selected).activatable:hover, list.content > row.expander row.header:not(:selected).activatable:hover, +list.boxed-list > row:not(:selected).activatable:hover, +list.boxed-list > row.expander row.header:not(:selected).activatable:hover, row.expander list.nested > row:not(:selected).activatable:hover { + background-color: alpha(currentColor, 0.08); +} + +list.content > row:not(:selected).activatable:active, list.content > row.expander row.header:not(:selected).activatable:active, +list.boxed-list > row:not(:selected).activatable:active, +list.boxed-list > row.expander row.header:not(:selected).activatable:active, row.expander list.nested > row:not(:selected).activatable:active { + background-color: alpha(currentColor, 0.12); +} + +list.content > row:not(:selected).activatable.has-open-popup, list.content > row.expander row.header:not(:selected).activatable.has-open-popup, +list.boxed-list > row:not(:selected).activatable.has-open-popup, +list.boxed-list > row.expander row.header:not(:selected).activatable.has-open-popup, row.expander list.nested > row:not(:selected).activatable.has-open-popup { + background-color: alpha(currentColor, 0.03); +} + +row.expander { + background: none; + padding: 0px; +} + +row.expander > box > list { + background: none; + color: inherit; +} + +row.expander list.nested { + color: inherit; +} + +row.expander image.expander-row-arrow { + transition: -gtk-icon-transform 200ms cubic-bezier(0, 0, 0.2, 1); +} + +row.expander image.expander-row-arrow:dir(ltr) { + margin-left: 6px; +} + +row.expander image.expander-row-arrow:dir(rtl) { + margin-right: 6px; +} + +row.expander image.expander-row-arrow:dir(ltr) { + -gtk-icon-transform: rotate(0.5turn); +} + +row.expander image.expander-row-arrow:dir(rtl) { + -gtk-icon-transform: rotate(-0.5turn); +} + +row.expander image.expander-row-arrow:disabled { + filter: opacity(0.45); +} + +row.expander:checked image.expander-row-arrow { + -gtk-icon-transform: rotate(0turn); + opacity: 1; +} + +row.expander:checked image.expander-row-arrow:not(:disabled) { + color: #7daea3; +} + +.osd row.expander:checked image.expander-row-arrow:not(:disabled) { + color: inherit; +} + +list.content > row.expander, +list.boxed-list > row.expander { + border: none; +} + +list.content > row:first-child, list.content > row:first-child.expander row.header, +list.boxed-list > row:first-child, +list.boxed-list > row:first-child.expander row.header { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +list.content > row:last-child, list.content > row:last-child.expander:not(:checked), list.content > row:last-child.expander:not(:checked) row.header, list.content > row:last-child.expander:checked list.nested, list.content > row:last-child.expander:checked list.nested > row:last-child, +list.boxed-list > row:last-child, +list.boxed-list > row:last-child.expander:not(:checked), +list.boxed-list > row:last-child.expander:not(:checked) row.header, +list.boxed-list > row:last-child.expander:checked list.nested, +list.boxed-list > row:last-child.expander:checked list.nested > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; + border-bottom-width: 0; +} + +columnview > listview > row { + padding: 0; +} + +columnview > listview > row > cell { + padding: 8px 6px; +} + +columnview > listview > row > cell:not(:first-child) { + border-left: 1px solid transparent; +} + +columnview.column-separators > listview > row > cell { + border-left-color: rgba(251, 241, 199, 0.12); +} + +columnview.data-table > listview > row > cell { + padding-top: 2px; + padding-bottom: 2px; +} + +treeexpander { + border-spacing: 6px; +} + +columnview row:not(:selected) cell editablelabel:not(.editing):focus-within { + outline: 2px solid alpha(currentColor, 0.06); +} + +columnview row:not(:selected) cell editablelabel.editing:focus-within { + outline: 2px solid #7daea3; +} + +columnview row:not(:selected) cell editablelabel.editing text selection { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 6px; + border-spacing: 0; + padding: 0; + border: none; + background-image: none; +} + +.app-notification button.text-button:not(:disabled) { + color: #7daea3; +} + +.app-notification > box > label { + margin-left: 9px; +} + +.app-notification.frame, +.app-notification border { + border: none; +} + +/************* + * Expanders * + *************/ +expander { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + color: rgba(251, 241, 199, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +expander:hover, expander:active { + color: #fbf1c7; +} + +expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +expander:disabled { + color: rgba(251, 241, 199, 0.32); +} + +expander-widget > box > title { + border-radius: 12px; +} + +expander-widget > box > title:hover > expander { + color: rgba(251, 241, 199, 0.7); +} + +.navigation-sidebar:not(decoration):not(window):drop(active):focus, .navigation-sidebar:not(decoration):not(window):drop(active), +placessidebar:not(decoration):not(window):drop(active):focus, +placessidebar:not(decoration):not(window):drop(active), +stackswitcher:not(decoration):not(window):drop(active):focus, +stackswitcher:not(decoration):not(window):drop(active), +expander-widget:not(decoration):not(window):drop(active):focus, +expander-widget:not(decoration):not(window):drop(active) { + box-shadow: none; +} + +/************ + * Calendar * + ************/ +calendar { + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 12px; + color: #fbf1c7; +} + +calendar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +calendar:selected { + border-radius: 12px; +} + +calendar > header { + padding: 3px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +calendar > header > button { + min-height: 24px; +} + +calendar > grid { + margin: 3px; +} + +calendar > grid > label { + border-radius: 12px; + margin: 0; +} + +calendar > grid > label.today:selected { + box-shadow: none; +} + +calendar > grid > label:focus { + outline-style: none; +} + +calendar > grid > label.day-number { + padding: 6px; +} + +calendar > grid > label.day-number.other-month { + color: alpha(currentColor, 0.3); +} + +/*********** + * Dialogs * + ***********/ +window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button { + border-radius: 9px; + min-height: 28px; + padding: 6px 12px; + margin: 0; + border: none; +} + +window.dialog.message.background { + background-color: #282828; +} + +window.dialog.message box.dialog-vbox.vertical { + margin-top: 6px; +} + +window.dialog.message box.dialog-vbox.vertical > box > box > box > label.title { + font-weight: 800; + font-size: 15pt; +} + +window.dialog.message .titlebar { + min-height: 24px; + border-style: none; + /* box-shadow: inset 0 1px highlight($surface); */ + background-color: #282828; + color: #fbf1c7; +} + +window.dialog.message .titlebar:backdrop { + background-color: #242220; + color: rgba(251, 241, 199, 0.7); +} + +window.dialog.message .dialog-action-area { + padding: 18px; + border-spacing: 18px; +} + +window.dialog.message .dialog-action-area > button { + background-color: rgba(251, 241, 199, 0.08); + border: 0 solid transparent; + outline: 0 solid transparent; +} + +window.dialog.message .dialog-action-area > button:not(:last-child):hover { + background-color: rgba(251, 241, 199, 0.1); +} + +window.dialog.message .dialog-action-area > button.suggested-action:not(:disabled) { + background-color: #365860; + color: #fbf1c7; +} + +window.dialog.message .dialog-action-area > button.destructive-action:not(:disabled) { + background-color: #a13737; + color: #fbf1c7; +} + +window.aboutdialog.background.csd scrolledwindow.frame, +window.aboutdialog.background.csd scrolledwindow.frame > viewport.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view > text { + border-radius: 12px; +} + +/******************** + * AdwMessageDialog * + ********************/ +window.messagedialog { + background-color: #242220; + color: #fbf1c7; + padding: 6px; +} + +window.messagedialog .message-area { + padding: 24px 30px; + border-spacing: 10px; +} + +window.messagedialog .response-area { + border-spacing: 6px; +} + +window.messagedialog .response-area button.suggested { + background-color: #365860; + color: #fbf1c7; + /* color: $primary; */ +} + +window.messagedialog .response-area button.destructive { + background-color: #a13737; + color: #fbf1c7; + /* color: $destructive; */ +} + +window.messagedialog .response-area separator { + background: none; + margin: 3px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; + background-color: #282524; +} + +.sidebar listview.view, +.sidebar list { + background-color: transparent; + color: inherit; +} + +stacksidebar.sidebar:dir(ltr), stacksidebar.sidebar.left, stacksidebar.sidebar.left:dir(rtl) { + box-shadow: inset -1px 0 rgba(251, 241, 199, 0.12); +} + +stacksidebar.sidebar:dir(rtl), stacksidebar.sidebar.right, stacksidebar.sidebar.right:dir(ltr) { + box-shadow: inset 1px 0 rgba(251, 241, 199, 0.12); +} + +.sidebar-pane stacksidebar.sidebar, leaflet.unfolded > box > stacksidebar.sidebar { + box-shadow: none; +} + +stacksidebar list { + padding: 6px; + background-color: #282524; +} + +stacksidebar row { + min-height: 24px; + padding: 6px; + border-radius: 12px; +} + +stacksidebar row:selected { + font-weight: 500; +} + +stacksidebar row + row { + margin-top: 4px; +} + +stacksidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +separator.sidebar { + background-color: rgba(251, 241, 199, 0.12); + border-right: none; +} + +separator.sidebar.selection-mode, .selection-mode separator.sidebar { + background-color: rgba(255, 255, 255, 0.12); +} + +/********************** + * Navigation Sidebar * + **********************/ +.navigation-sidebar { + padding: 2px 4px; + border-right: none; +} + +.navigation-sidebar, .navigation-sidebar.view, .navigation-sidebar.background { + background-color: transparent; + color: inherit; +} + +.navigation-sidebar > separator { + background-color: rgba(251, 241, 199, 0.12); + margin: 10px 15px; +} + +.navigation-sidebar row.activatable label.dim-label { + color: rgba(251, 241, 199, 0.32); +} + +.navigation-sidebar > row { + min-height: 24px; + /* padding: 0 $space-size 0 $space-size; */ + padding: 0 6px; + margin: 0; + border-radius: 9px; +} + +.navigation-sidebar > row:hover, .navigation-sidebar > row:focus-visible:focus-within { + background-color: alpha(currentColor, 0.08); + color: #7daea3; +} + +.navigation-sidebar > row:active { + background-color: alpha(currentColor, 0.12); +} + +.navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + box-shadow: none; +} + +.navigation-sidebar > row:selected label, +.navigation-sidebar > row:selected image { + color: #7daea3; + font-weight: 700; +} + +.navigation-sidebar > row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +.navigation-sidebar > row:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.navigation-sidebar > row:not(:first-child) { + margin-top: 3px; +} + +/**************** + * File chooser * + ****************/ +filechooser paned > separator { + background: rgba(251, 241, 199, 0.12); +} + +filechooser paned > box #pathbarbox.view, +filechooser paned > box stack.view, +filechooser paned > box columnview.view, +filechooser paned > box gridview.view { + background-color: transparent; + color: #fbf1c7; +} + +filechooser .dialog-action-box { + border: none; +} + +filechooser #pathbarbox { + border: none; + background-color: transparent; +} + +filechooser stack.view frame > border { + border: none; +} + +filechooserbutton > button > box { + border-spacing: 6px; +} + +filechooserbutton:drop(active) { + box-shadow: none; + border-color: transparent; +} + +filechooser child.activatable filelistcell.dim-label { + color: rgba(251, 241, 199, 0.7); +} + +placessidebar { + background-color: transparent; +} + +placessidebar > viewport.frame { + border-style: none; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon { + color: inherit; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label { + color: inherit; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button { + /* @extend %button-on-indicator; */ +} + +placessidebar list.navigation-sidebar > row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row { + color: #7daea3; +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row image.sidebar-icon { + color: #7daea3; +} + +placessidebar list.navigation-sidebar > row:drop(active) { + background-color: alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + border-spacing: 6px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(#423f3e); + background-size: 1px 1px; + background-clip: content-box; + box-shadow: none; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #282828; + background-image: image(#423f3e), image(#423f3e); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************ + * GtkVideo * + ************/ +video { + background: black; + border-radius: 12px; +} + +video image.osd { + min-width: 64px; + min-height: 64px; + border-radius: 9999px; + border: none; +} + +/************** + * GtkInfoBar * + **************/ +infobar > revealer > box { + padding: 6px; + border-spacing: 12px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #282524; + color: #fbf1c7; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #7daea3; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action > revealer > box *:link, infobar.action:backdrop > revealer > box *:link, infobar.question > revealer > box *:link, infobar.question:backdrop > revealer > box *:link { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #6da498; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #b47109; + color: #fbf1c7; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.warning > revealer > box *:link, infobar.warning:backdrop > revealer > box *:link { + color: #fbf1c7; +} + +infobar.warning:hover > revealer > box { + background-color: #9c6208; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #c14a4a; + color: #fbf1c7; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.error > revealer > box *:link, infobar.error:backdrop > revealer > box *:link { + color: #fbf1c7; +} + +infobar.error:hover > revealer > box { + background-color: #b43e3e; +} + +/************ + * Tooltips * + ************/ +tooltip { + padding: 6px 12px; + box-shadow: none; + border: none; +} + +tooltip.background { + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05); + border-radius: 12px; + margin: 2px 6px 8px 6px; +} + +tooltip > box { + border-spacing: 6px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #fbf1c7; +} + +colorswatch.light { + color: rgba(40, 40, 40, 0.87); +} + +colorchooser colorswatch:hover { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 0 0 2px #7daea3; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; + color: #fbf1c7; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(251, 241, 199, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(251, 241, 199, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #282828; +} + +/********************** + * Window Decorations * + **********************/ +window { + border: none; +} + +window.csd { + border-radius: 12px; + margin: 0; + transition: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +window.csd:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +window.csd.maximized, window.csd.fullscreen, window.csd.tiled, window.csd.tiled-top, window.csd.tiled-right, window.csd.tiled-bottom, window.csd.tiled-left { + border-radius: 0; + transition: none; +} + +window.csd.maximized, window.csd.fullscreen { + box-shadow: none; + outline: none; +} + +window.solid-csd { + margin: 0; + padding: 2px; + border-radius: 0; + background-color: #282828; + border: 1px solid #423f3e; +} + +window.solid-csd:backdrop { + background-color: #282828; +} + +window.ssd { + box-shadow: 0 0 0 1px rgba(251, 241, 199, 0.12); +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + padding: 9px 0; + margin-left: 0px; + margin-right: 0px; + /* min-height: 22px; */ + /* min-width: 22px; */ + /* padding: ($medium-size - 22px) / 2 0; */ + /* margin-left: $space-size - 7px; */ + /* margin-right: $space-size - 7px; */ +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + background: none; + box-shadow: none; +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:not(.suggested-action):not(.destructive-action) > image { + padding: 1px; + background-color: alpha(currentColor, 0.1); +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.15); +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.2); +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) > image { + background-color: #282524; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: rgba(251, 241, 199, 0.3); +} + +/* $window-space: if($window_button == 'mac', $space-size * 1.5, $space-size); */ +windowcontrols { + border-spacing: 6px; +} + +windowcontrols:not(.empty).start:dir(ltr), windowcontrols:not(.empty).end:dir(rtl) { + margin-right: 6px; + margin-left: 6px; +} + +windowcontrols:not(.empty).start:dir(rtl), windowcontrols:not(.empty).end:dir(ltr) { + margin-left: 6px; + margin-right: 6px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) > image { + border-radius: 100%; + padding: 0; +} + + +.view:selected, iconview:selected, gridview > child:selected, columnview.view:selected, +treeview.view:selected, calendar:selected, calendar > grid > label.day-number:selected { + background-color: alpha(currentColor, 0.06); +} + +flowbox > flowboxchild:selected, calendar > grid > label.today { + color: #7daea3; + background-color: rgba(125, 174, 163, 0.2); +} + +textview text selection:focus, textview text selection, label > selection, +entry > text > selection, spinbutton > text > selection, +entry headerbar popover.background entry > text > selection, +headerbar popover.background entry entry > text > selection, calendar > grid > label.today:selected { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #7daea3; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; +} + +shortcuts-section { + margin: 20px; +} + +.shortcuts-search-results { + margin: 20px; + border-spacing: 24px; +} + +shortcut { + border-spacing: 6px; +} + +shortcut > .keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(251, 241, 199, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(251, 241, 199, 0.12); + background-color: #242220; + color: #fbf1c7; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #7daea3; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0 2px; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/************* + * App Icons * + *************/ +.lowres-icon { + -gtk-icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.icon-dropshadow { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 1px 6px rgba(0, 0, 0, 0.1); +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker > contents { + padding: 0; +} + +.emoji-searchbar { + padding: 6px; + border-spacing: 6px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background: none; +} + +.emoji-searchbar entry text { + background: none; + box-shadow: none; +} + +.emoji-toolbar { + padding: 0; + border-spacing: 3px; + border-top: 1px solid rgba(251, 241, 199, 0.12); + background: none; +} + +button.emoji-section { + margin: 0; + padding: 6px; + border-radius: 12px; +} + +button.emoji-section:checked { + color: #7daea3; +} + +popover.emoji-picker emoji { + font-size: x-large; + padding: 6px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker emoji:focus, popover.emoji-picker emoji:hover { + background: alpha(currentColor, 0.08); +} + +emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +emoji-completion-row > box { + border-spacing: 6px; + padding: 2px 6px; +} + +emoji-completion-row:focus, emoji-completion-row:hover, +emoji-completion-row emoji:hover, +emoji-completion-row emoji:focus { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +popover.entry-completion > contents { + padding: 0; +} + +.nautilus-window.view { + background-color: #282828; +} + +.nautilus-window .sidebar-pane, +.nautilus-window .content-pane { + background-color: #282828; + color: #fbf1c7; +} + +.nautilus-window .sidebar-pane:backdrop, +.nautilus-window .content-pane:backdrop { + background-color: #282828; + transition: none; +} + +.nautilus-window .sidebar-pane:dir(ltr), +.nautilus-window .sidebar-pane:dir(ltr) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(rtl), +.nautilus-window .sidebar-pane.end:dir(rtl) banner > revealer > widget { + box-shadow: none; + border-right: none; +} + +.nautilus-window .sidebar-pane:dir(rtl), +.nautilus-window .sidebar-pane:dir(rtl) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(ltr), +.nautilus-window .sidebar-pane.end:dir(ltr) banner > revealer > widget { + box-shadow: none; + border-left: none; +} + +.nautilus-window placesview label { + color: rgba(251, 241, 199, 0.7); +} + +.nautilus-window flap > separator { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view .view, +.nautilus-window .nautilus-list-view .view { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell { + padding: 0; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell > widget#NautilusViewCell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell > widget#NautilusViewCell { + padding: 3px 9px; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable:nth-child(odd):not(:disabled), +.nautilus-window .nautilus-list-view listview.view > row.activatable:nth-child(odd):not(:disabled) { + background-image: image(alpha(currentColor, 0.03)); +} + +.nautilus-window .nautilus-grid-view gridview.view, +.nautilus-window .nautilus-list-view gridview.view { + margin: 10px 5px; + padding: 10px 5px; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border-style: none; + border-radius: 9px; + background-color: rgba(40, 37, 36, 0.95); + color: #7daea3; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(40, 40, 40, 0.87); +} + +.nautilus-window banner > revealer > widget { + background-color: rgba(40, 37, 36, 0.4); + color: #fbf1c7; + border-radius: 9px; + margin: 9px; +} + +.nautilus-window banner > revealer > widget button { + background-color: rgba(125, 174, 163, 0.3); + color: rgba(40, 40, 40, 0.87); +} + +.nautilus-window banner > revealer > widget button:hover { + background-color: rgba(125, 174, 163, 0.6); +} + +#NautilusQueryEditor > menubutton > button.image-button { + min-width: 24px; + min-height: 24px; + padding: 3px; + margin-right: -5px; +} + +#NautilusQueryEditor > menubutton > button.image-button:checked image { + color: rgba(40, 40, 40, 0.87); +} + +#NautilusQueryEditor > text, +#NautilusQueryEditor > box, +#NautilusQueryEditor > menubutton { + margin: 3px 0; +} + +#NautilusQueryEditorTag { + background-color: rgba(251, 241, 199, 0.12); +} + +#NautilusQueryEditorTag > button.image-button { + margin: 0; + padding: 0; +} + +#NautilusPathBar { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +#NautilusPathButton { + margin: 0 3px; + border-radius: 12px; +} + +#NautilusPathButton.current-dir { + color: #7daea3; +} + +#NautilusPathButton.current-dir:hover, #NautilusPathButton.current-dir:active { + background: none; + box-shadow: none; +} + +#NautilusPathButton:first-child { + margin-left: 0; +} + +#NautilusViewCell clamp box { + margin: 0; + border-spacing: 0; +} + +#NautilusFileChooser gridview.view { + background-color: transparent; + margin: 10px 5px; + padding: 10px 5px; +} + +#NautilusFileChooser columnview.view, +row.activatable > cell { + background-color: transparent; + padding: 1px 10px; +} + +#NautilusProgressIndicator popover label { + color: rgba(251, 241, 199, 0.7); +} + +#NautilusProgressIndicator popover image { + color: rgba(251, 241, 199, 0.7); +} + +/* Nautilus Progress Indicator */ +windowhandle box.vertical box.toolbar { + background-color: #282828; + border: none; + outline: none; +} + +windowhandle box.toolbar menubutton button.toggle { + background-color: #282828; + border: none; + outline: none; +} + +window.dialog > box > stack > box > box > notebook.frame { + border-width: 0 0 0 1px; + border-radius: 0; +} + +.display-container.card { + background-color: #282524; +} + +.small .display-container.card { + border-radius: 0; + box-shadow: none; + border-width: 0 0 1px 0; +} + +.display-container .history-view { + background-color: transparent; +} + +.display-container #displayitem { + padding: 0 12px 8px 0; + font-size: 1.4em; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.math-buttons button { + font-size: 1.1em; + padding: 2px 6px; +} + +.math-buttons button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +leaflet button.number-button { + background-color: rgba(251, 241, 199, 0.1); +} + +leaflet button.number-button:hover { + background-color: rgba(251, 241, 199, 0.2); +} + +leaflet button.number-button:active { + background-color: rgba(251, 241, 199, 0.3); +} + +label.primary-label, label.month-name, label.secondary-label { + font-size: 16pt; + font-weight: bold; + padding: 12px; +} + +label.primary-label, label.month-name { + color: #7daea3; +} + +label.secondary-label { + color: rgba(251, 241, 199, 0.5); +} + +toastoverlay datechooser.view, +toastoverlay agenda-view.view, +toastoverlay agenda-view.view list, +toastoverlay stack.view { + background-color: transparent; +} + +calendar-view { + font-size: 10pt; +} + +calendar-view:selected { + color: #7daea3; + font-weight: bold; +} + +calendar-view.header, +label.header { + font-size: 10pt; + font-weight: bold; + color: rgba(251, 241, 199, 0.5); +} + +calendar-view.current, +weekgrid.current { + background-color: alpha(#7daea3, 0.3); +} + +popover.events { + background-color: #242220; + padding: 0; +} + +popover.events box { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +popover.events list { + background-color: #282524; + border-radius: 12px; +} + +popover.events scrolledwindow { + border-width: 0; +} + +popover.events button { + border-radius: 12px; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-style: solid none none; + box-shadow: none; +} + +event { + margin: 1px; + font-size: 0.9rem; +} + +event widget.content { + margin: 4px; +} + +event.timed, event:not(.slanted):not(.slanted-start):not(.slanted-end) { + border-radius: 12px; +} + +event.timed widget.edge { + border-radius: 6px; + min-width: 5px; +} + +event.slanted-start, event.slanted-end:dir(rtl) { + padding-left: 16px; + border-radius: 0 6px 6px 0; +} + +event.slanted-end, event.slanted-start:dir(rtl) { + padding-right: 16px; + border-radius: 6px 0 0 6px; +} + +event:not(.timed).color-dark { + color: white; + outline-color: rgba(0, 0, 0, 0.3); +} + +event.timed, event:not(.timed).color-light { + color: alpha(black, 0.75); + outline-color: rgba(255, 255, 255, 0.5); +} + +popover.event-popover, +popover.event-popover > contents { + padding: 0; +} + +.search-viewport { + background-color: #282524; +} + +.calendar-list { + background-color: transparent; +} + +.calendar-list > list { + border-radius: 4px; +} + +menubutton.flat.sources-button { + margin-top: 0; + margin-bottom: 0; + border-radius: 0; + border-top-style: none; + border-bottom-style: none; +} + +menubutton.flat.sources-button:hover:not(:backdrop) { + background-image: none; + text-shadow: none; +} + +menubutton.flat.sources-button > button { + border-radius: 0 0 12px 12px; +} + +.calendar-color-image { + -gtk-icon-filter: none; +} + +image.calendar-color-image, +button:active:not(:backdrop) .calendar-color-image, +button:checked:not(:backdrop) .calendar-color-image, +.calendars-list .calendar-color-image:not(:backdrop):not(:disabled), +.calendar-list .calendar-color-image:not(:backdrop):not(:disabled), +.sources-button:not(:backdrop):not(:disabled) .calendar-color-image { + -gtk-icon-shadow: 0 1px alpha(black, 0.1); +} + +datechooser { + padding: 6px; +} + +datechooser .current-week { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; + border-radius: 12px; +} + +datechooser navigator { + margin-right: 6px; + margin-left: 6px; + margin-bottom: 6px; +} + +datechooser navigator label { + font-weight: bold; +} + +datechooser navigator button.flat, +datechooser navigator button.image-button { + min-height: 34px; + min-width: 34px; + padding: 0; +} + +datechooser .weeknum, +datechooser .weekday { + color: rgba(251, 241, 199, 0.5); + font-size: smaller; +} + +datechooser button.day { + font-size: 10pt; + font-weight: normal; + margin: 3px; + padding: 0; + min-height: 34px; + min-width: 34px; + transition: none; +} + +datechooser button.day dot { + background-color: #fbf1c7; + border-radius: 50%; + min-height: 3px; + min-width: 3px; +} + +datechooser button.day:selected, datechooser button.day.today:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + font-weight: bold; +} + +datechooser button.day:selected dot, datechooser button.day.today:selected dot { + background-color: rgba(40, 40, 40, 0.87); +} + +datechooser button.day.today { + color: #7daea3; +} + +datechooser button.day.today dot { + background-color: #7daea3; +} + +datechooser button.day.other-month:not(:hover), datechooser button.day.other-month:backdrop { + color: rgba(251, 241, 199, 0.32); +} + +datechooser button.day.other-month:not(:hover) dot, datechooser button.day.other-month:backdrop dot { + background-color: rgba(251, 241, 199, 0.32); +} + +datechooser button.day.other-month:hover:not(:backdrop) { + color: rgba(251, 241, 199, 0.5); +} + +datechooser button.day.other-month:hover:not(:backdrop) dot { + background-color: rgba(251, 241, 199, 0.5); +} + +.week-header { + padding: 0; +} + +.week-header > box:first-child { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.week-header .week-number { + font-size: 16pt; + font-weight: bold; + padding: 12px 12px 18px 12px; + color: rgba(251, 241, 199, 0.3); +} + +.week-header.week-temperature { + font-size: 10pt; + font-weight: bold; + color: rgba(251, 241, 199, 0.5); +} + +.week-header.lines { + color: rgba(251, 241, 199, 0.12); +} + +weekhourbar > label { + font-size: 10pt; + padding: 4px 6px; +} + +.week-view .lines { + color: rgba(251, 241, 199, 0.12); +} + +weekgrid > widget.now-strip { + background-color: alpha(#7daea3, 0.8); + margin: 0 0 0 1px; + min-height: 3px; +} + +weekgrid:selected, weekgrid.dnd, +.week-header:selected, +.week-header.dnd { + background-color: alpha(#7daea3, 0.25); +} + +monthcell { + border: solid 1px rgba(251, 241, 199, 0.12); + border-width: 1px 0 0 1px; + background-color: transparent; + transition: background-color 200ms; +} + +monthcell:hover:not(.out-of-month):not(.today) { + background-color: #282524; + transition: background-color 200ms; + color: #fbf1c7; +} + +monthcell:selected { + background-color: alpha(#7daea3, 0.1); +} + +monthcell:selected:hover { + background-color: alpha(#7daea3, 0.2); +} + +monthcell:selected label.day-label { + font-weight: bold; +} + +monthcell:nth-child(7n + 1) { + border-left-width: 0; +} + +monthcell.today { + background-color: alpha(#7daea3, 0.2); +} + +monthcell.today:hover { + background-color: alpha(#7daea3, 0.3); + color: #7daea3; +} + +monthcell.today:selected { + background-color: alpha(#7daea3, 0.25); +} + +monthcell.today:selected:hover { + background-color: alpha(#7daea3, 0.35); +} + +monthcell label { + color: #fbf1c7; + font-size: 0.9rem; +} + +monthcell label.day-label { + font-size: 1rem; +} + +monthcell.out-of-month { + background-color: rgba(251, 241, 199, 0.04); +} + +monthcell.out-of-month label { + color: rgba(251, 241, 199, 0.7); +} + +monthcell button { + padding: 0 6px; + border-radius: 0; + border-bottom: none; + border-right: none; +} + +monthpopover > box { + margin: 0; + padding: 0; + background-color: transparent; +} + +.notes-section box > textview { + border-radius: 12px; + padding: 6px; +} + +.notes-section box > textview > text { + background: none; +} + +agenda-view list.background > row { + padding: 2px 12px; +} + +agenda-view list.background > label { + padding: 6px 12px; +} + +label.no-events { + font-style: italic; +} + +searchbutton > popover > arrow { + background: none; + border: none; +} + +menubutton stack > box { + border-spacing: 6px; +} + +#TweakPreferencesPage.tweak-group label.subtitle { + color: rgba(251, 241, 199, 0.32); +} + +#TweakPreferencesPage label.dim-label { + color: rgba(251, 241, 199, 0.32); +} + +.sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow .dim-label, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row label.subtitle, row .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow label.subtitle, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.expander image.expander-row-arrow, row.expander .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow image.expander-row-arrow { + color: rgba(40, 40, 40, 0.38); +} + +.details-page { + margin: 24px 0px; +} + +.installed-overlay-box { + font-size: smaller; + background-color: #7daea3; + border-radius: 0; + color: rgba(40, 40, 40, 0.87); + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); +} + +screenshot-carousel box.frame { + border-width: 1px 0; + border-radius: 0; +} + +screenshot-carousel button, +.featured-carousel button { + margin: 12px; +} + +carousel.card { + border: none; + background-color: rgba(251, 241, 199, 0.04); +} + +.smaller { + font-size: smaller; +} + +.screenshot-image-main .image1, +.screenshot-image-main .image2 { + margin-top: 6px; + margin-bottom: 12px; + margin-left: 6px; + margin-right: 6px; +} + +.app-tile-label { + font-size: 105%; +} + +gs-summary-tile image.loading-icon { + background-color: rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.review-row > box { + margin: 12px; + border-spacing: 3px; +} + +.review-row textview { + background: none; +} + +.review-row .edit-icon { + min-width: 24px; + min-height: 24px; + padding: 6px; +} + +.review-textbox { + padding: 6px; +} + +.origin-rounded-box { + background-color: rgba(251, 241, 199, 0.12); + border-radius: 9999px; + padding: 4px; +} + +.origin-beta { + color: #b47109; +} + +.origin-button > button { + padding: 3px 9px; +} + +clamp.medium .category-tile:not(.category-tile-iconless) { + font-size: large; +} + +clamp.large .category-tile:not(.category-tile-iconless) { + font-size: larger; +} + +flowboxchild.card:not(.category-tile) { + padding: 0; + box-shadow: none; + border: none; + background-color: transparent; + background-image: none; +} + +.category-tile.card { + padding: 21px; + border: none; + border-radius: 12px; + min-width: 140px; + font-weight: 900; + font-size: larger; +} + +.category-tile.card:not(.category-tile-iconless), .category-tile.card:not(.category-tile-iconless):active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + animation: none; +} + +.category-tile.card.category-tile-iconless { + padding: 9px 15px; + min-width: 130px; + font-size: 105%; + font-weight: normal; +} + +.category-tile.card.category-create { + background: linear-gradient(180deg, #ce8cd7 0%, #2861c6 100%); + color: white; +} + +.category-tile.card.category-create:hover { + background: linear-gradient(180deg, shade(#ce8cd7, 1.07) 0%, shade(#2861c6, 1.1) 100%); + color: white; +} + +.category-tile.card.category-create:active { + background: linear-gradient(180deg, shade(#ce8cd7, 0.95) 0%, shade(#2861c6, 0.95) 100%); + color: white; +} + +.category-tile.card.category-develop { + background-color: #5e5c64; + color: white; +} + +.category-tile.card.category-develop:hover { + background-color: shade(#5e5c64, 1.2); + color: white; +} + +.category-tile.card.category-develop:active { + background-color: shade(#5e5c64, 0.95); + color: white; +} + +.category-tile.card.category-learn { + background: linear-gradient(180deg, #2ec27e 30%, #27a66c 100%); + color: white; +} + +.category-tile.card.category-learn:hover { + background: linear-gradient(180deg, shade(#2ec27e, 1.06) 30%, shade(#27a66c, 1.06) 100%); + color: white; +} + +.category-tile.card.category-learn:active { + background: linear-gradient(180deg, shade(#2ec27e, 0.95) 30%, shade(#27a66c, 0.95) 100%); + color: white; +} + +.category-tile.card.category-play { + background: linear-gradient(75deg, #f9e2a7 0%, #eb5ec3 50%, #6d53e0 100%); + color: #393484; +} + +.category-tile.card.category-play:hover { + background: linear-gradient(75deg, shade(#f9e2a7, 1.07) 0%, shade(#eb5ec3, 1.07) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-play:active { + background: linear-gradient(75deg, shade(#f9e2a7, 0.97) 0%, shade(#eb5ec3, 0.95) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-socialize { + background: linear-gradient(90deg, #ef4e9b 0%, #f77466 100%); + color: rgba(251, 241, 199, 0.7); +} + +.category-tile.card.category-socialize:hover { + background: linear-gradient(90deg, shade(#ef4e9b, 1.08) 0%, shade(#f77466, 1.08) 100%); +} + +.category-tile.card.category-socialize:active { + background: linear-gradient(90deg, shade(#ef4e9b, 0.95) 0%, shade(#f77466, 0.95) 100%); +} + +.category-tile.card.category-work { + padding: 1px; + /* FIXME: work around https://gitlab.gnome.org/GNOME/gtk/-/issues/4324 */ + color: #1c71d8; + background-color: #fdf8d7; + background-image: linear-gradient(rgba(251, 241, 199, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(251, 241, 199, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.category-tile.card.category-work:hover { + color: #1c71d8; + background-color: #fefcef; + background-image: linear-gradient(rgba(251, 241, 199, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(251, 241, 199, 0.12) 1px, transparent 1px); +} + +.category-tile.card.category-work:active { + color: #1c71d8; + background-color: #fcf4bf; + background-image: linear-gradient(rgba(251, 241, 199, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(251, 241, 199, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.featured-tile { + padding: 0; + box-shadow: none; + color: #fbf1c7; +} + +.featured-tile label.title-1 { + margin-top: 6px; + margin-bottom: 6px; +} + +.featured-tile.narrow label.title-1 { + font-size: 16pt; +} + +.application-details-infobar, .application-details-infobar.info { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; + border: 1px solid rgba(251, 241, 199, 0.12); +} + +.application-details-infobar.warning { + background-color: #b47109; + color: #fbf1c7; + border: 1px solid rgba(251, 241, 199, 0.12); +} + +.card.info { + background-color: #292929; + color: #fbf1c7; +} + +.card.warning { + background-color: #292928; + color: #fbf1c7; +} + +.infobox { + border-spacing: 6px; + padding: 12px; +} + +@keyframes install-progress-unknown-move { + 0% { + background-position: 0%; + } + 50% { + background-position: 100%; + } + 100% { + background-position: 0%; + } +} + +.application-details-description .button { + padding-left: 24px; + padding-right: 24px; +} + +.install-progress { + background-image: linear-gradient(to top, #7daea3 2px, alpha(#7daea3, 0) 2px); + background-repeat: no-repeat; + background-position: 0 bottom; + background-size: 0; + transition: none; +} + +.install-progress:dir(rtl) { + background-position: 100% bottom; +} + +.review-row > * { + margin: 12px; +} + +.review-row button { + font-size: smaller; +} + +.review-row .vote-buttons button { + margin-right: -1px; +} + +.review-row .vote-buttons button:not(:first-child) { + border-image: linear-gradient(to top, rgba(251, 241, 199, 0.12), rgba(251, 241, 199, 0.12)) 0 0 0 1/5px 0 5px 1px; +} + +.review-row .vote-buttons button:hover, +.review-row .vote-buttons button:active, +.review-row .vote-buttons button:hover + button, +.review-row .vote-buttons button:active + button { + border-image: none; +} + +review-bar { + color: rgba(251, 241, 199, 0.5); + background-image: none; + background-color: rgba(251, 241, 199, 0.3); +} + +.review-histogram star-image { + color: rgba(251, 241, 199, 0.5); +} + +.version-arrow-label { + font-size: x-small; +} + +.overview-more-button { + font-size: smaller; + padding: 0 16px; +} + +.app-row-origin-text { + font-size: smaller; +} + +.app-listbox-header { + padding: 6px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.image-list { + background-color: transparent; +} + +box.star { + background-color: transparent; + background-image: none; +} + +button.star { + outline-offset: 0; + background-color: transparent; + background-image: none; + border-image: none; + border-radius: 0; + border-width: 0; + padding: 0; + box-shadow: none; + outline-offset: -1px; +} + +flowboxchild { + padding: 0px; +} + +star-image > image.starred { + color: #d8a657; + transition-duration: 200ms; +} + +star-image > image.starred:hover { + color: #b47109; +} + +star-image > image.non-starred { + opacity: 0.2; + transition-duration: 200ms; +} + +star-image > image.non-starred:hover { + color: #d8a657; + opacity: 0.7; +} + +.dimmer-label { + opacity: 0.25; +} + +.update-failed-details { + font-family: Monospace; + font-size: smaller; + padding: 16px; +} + +.upgrade-banner { + padding: 0px; + border-radius: 12px; + border: none; +} + +.upgrade-banner-background { + background: linear-gradient(to bottom, #6c782e, #45707a); + color: white; +} + +.upgrade-buttons #button_upgrades_install, +.upgrade-buttons #button_upgrades_install_cancel { + padding-left: 16px; + padding-right: 16px; +} + +scrolledwindow.list-page > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +.update-preferences preferencesgroup > box > box { + margin-top: 18px; +} + +.section > label:not(:first-child) { + margin-top: 6px; +} + +.section > box:not(:first-child) { + margin-top: 12px; +} + +clamp.status-page { + margin: 36px 12px; +} + +clamp.status-page .iconbox { + min-height: 128px; + min-width: 128px; +} + +clamp.status-page .icon { + color: rgba(251, 241, 199, 0.5); + min-height: 32px; + min-width: 32px; +} + +clamp.status-page .icon:not(:last-child) { + margin-bottom: 36px; +} + +clamp.status-page .title:not(:last-child) { + margin-bottom: 12px; +} + +app-context-bar .context-tile { + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: transparent; + border-radius: 0; + padding: 24px 12px 21px 12px; + outline-offset: 5px; + transition-property: outline, outline-offset, background-image; + border-bottom: none; + border-right: none; +} + +app-context-bar .context-tile:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); +} + +app-context-bar .context-tile.keyboard-activating, app-context-bar .context-tile:active { + background-color: alpha(currentColor, 0.12); +} + +app-context-bar .context-tile:focus:focus-visible { + outline-offset: -1px; +} + +app-context-bar.horizontal box:first-child .context-tile:first-child, app-context-bar.vertical .context-tile:first-child { + border-left: none; +} + +app-context-bar.horizontal .context-tile, app-context-bar.vertical box:first-child .context-tile { + border-top: none; +} + +app-context-bar > box:not(:first-child) > button.flat { + border-radius: 0; +} + +app-context-bar > box:not(:first-child) > button.flat:last-child { + border-radius: 0 12px 12px 0; +} + +app-context-bar > box:first-child > button.flat { + border-radius: 0; +} + +app-context-bar > box:first-child > button.flat:first-child { + border-radius: 12px 0 0 12px; +} + +app-context-bar > box > button.flat { + border-left-color: rgba(251, 241, 199, 0.12); +} + +.context-tile-lozenge { + min-height: 28px; + min-width: 28px; + padding: 6px; + font-size: 18px; + font-weight: bold; + border-radius: 9999px; +} + +.context-tile-lozenge.large { + font-size: 24px; + padding: 16px; + min-width: 24px; + /* 60px minus the left and right padding */ + min-height: 24px; + /* 60px minus the top and bottom padding */ +} + +.context-tile-lozenge.wide-image image { + margin-top: -28px; + margin-bottom: -28px; +} + +.context-tile-lozenge image { + -gtk-icon-style: symbolic; +} + +.context-tile-lozenge.grey { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.context-tile-lozenge.green, .context-tile-lozenge.details-rating-0 { + color: #3a4119; + background-color: rgba(108, 120, 46, 0.15); +} + +.context-tile-lozenge.blue, .context-tile-lozenge.details-rating-5 { + color: #45707a; + background-color: rgba(69, 112, 122, 0.15); +} + +.context-tile-lozenge.yellow, .context-tile-lozenge.details-rating-12 { + color: #6b4305; + background-color: rgba(180, 113, 9, 0.15); +} + +.context-tile-lozenge.details-rating-15 { + color: #c35e0a; + background-color: rgba(195, 94, 10, 0.15); +} + +.context-tile-lozenge.red, .context-tile-lozenge.details-rating-18 { + color: #8e3131; + background-color: rgba(193, 74, 74, 0.15); +} + +.eol-red { + font-weight: bold; + color: #c14a4a; +} + +window.narrow .app-title { + font-size: 16pt; +} + +window.narrow .app-developer { + font-size: small; +} + +.install-progress-label { + font-size: smaller; + font-feature-settings: 'tnum'; +} + +scrolledwindow.fake-adw-status-page > viewport > box { + margin: 36px 12px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp:not(:last-child) +> box { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .icon:not(:last-child) { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .title:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.icon-dropshadow image.icon { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 -1px rgba(0, 0, 0, 0.05), 1px 0 rgba(0, 0, 0, 0.1), 0 1px rgba(0, 0, 0, 0.3), -1px 0 rgba(0, 0, 0, 0.1); +} + +window.info scrollbar.vertical { + margin-top: 48px; + background: none; + box-shadow: none; +} + +window.info scrollbar.vertical trough { + margin-top: 0; +} + +row.app > box.header { + margin-left: 12px; + margin-right: 12px; +} + +row.app > box.header { + border-spacing: 12px; +} + +row.app > box.header > image { + margin-top: 12px; + margin-bottom: 12px; +} + +row.app label.warning { + color: #c14a4a; +} + +@keyframes pre-delay { + from { + opacity: 0; + } + to { + opacity: 0; + } +} + +@keyframes fade-in { + from { + filter: opacity(0%); + } +} + +/* Give a fade-in animation to spinners. */ +spinner.fade-in:checked { + animation: pre-delay 0.5s linear 1, fade-in 1s linear 1, spin 1s linear infinite; + animation-delay: 0s, 0.5s, 0.5s; +} + +window > contents > leaflet > box > stack.background { + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, transparent 46px, #282828 46px, #282828); +} + +@define-color weather_temp_chart_fill_color rgba(180, 113, 9, 0.5); +@define-color weather_temp_chart_stroke_color #835307; +@define-color weather_thermometer_warm_color #b47109; +@define-color weather_thermometer_cold_color #45707a; +#places-label { + font-weight: bold; +} + +#temperature-label { + font-size: 32pt; + font-weight: 900; + margin-left: 9px; +} + +#conditions-grid *:backdrop { + color: rgba(251, 241, 199, 0.7); +} + +.content-view.cell { + font-weight: bold; +} + +#locationEntry { + margin: 6px; +} + +.weather-popover { + margin-top: 6px; +} + +.forecast-card { + transition: border-radius 100ms ease-out; + border-radius: 12px; +} + +.forecast-card separator { + background-color: #282828; +} + +#daily-forecast-box > separator:last-child { + background-color: transparent; + min-width: 0; +} + +#conditions-grid, +#attributionGrid { + margin-left: 18px; + margin-right: 18px; +} + +#weather-page .small .forecast-card { + margin-left: 0; + margin-right: 0; + border-radius: 0; + border-width: 1px 0; +} + +.forecast-temperature-label { + font-weight: bold; + color: #ae7b03; +} + +WeatherThermometer { + margin-bottom: 12px; +} + +WeatherThermometer > label.high { + font-weight: bold; + color: #b47109; +} + +WeatherThermometer > label.low { + font-weight: bold; + color: #45707a; +} + +.forecast-button { + margin: 0 12px; +} + +.forecast-graphic { + margin: 18px; +} + +button.osd.circular { + border-radius: 9999px; + min-width: 24px; + min-height: 24px; +} + +button.osd.circular > image { + padding: 0; +} + +scrolledwindow.inline list, +scrolledwindow.inline listview { + background: none; + color: inherit; +} + +scrolledwindow.inline undershoot.top { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.12); +} + +.search-view { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.search-view menubutton button:focus:focus-visible { + outline-color: rgba(255, 255, 255, 0.3); +} + +image.circular { + min-width: 34px; + min-height: 34px; + padding: 0; + border-radius: 9999px; +} + +#gnome-system-monitor.background.csd { + background-color: #282828; +} + +.large-button { + padding: 6px; +} + +.alarm-time { + font-size: 2.5em; + font-weight: 300; +} + +.clocks-ampm-toggle-button, +.clocks-secondary-standalone-label { + font-size: 18pt; +} + +.clocks-standalone-label, +.clocks-ringing-label { + font-size: 6em; + font-weight: 300; +} + +.clocks-ringing-title { + font-size: 1.5em; + font-weight: bold; +} + +.clocks-alarm-setup-time { + font-size: 32pt; +} + +.clocks-timer-label, +.clocks-spinbutton { + font-size: 48pt; +} + +.timer-panel .timer-header { + font-size: 20pt; + font-weight: 300; +} + +.timer-countdown { + font-size: 40pt; + font-weight: 300; +} + +/* Stopwatch Panel */ +.lap-time { + font-weight: bold; +} + +.stopped-stopwatch label, +.running-stopwatch label, +.paused-stopwatch label { + font-size: 70px; + font-weight: lighter; +} + +.stopped-stopwatch .seconds-label { + font-weight: 300; +} + +.running-stopwatch .seconds-label, +.running-stopwatch .miliseconds-label { + color: #7daea3; +} + +.stopped-stopwatch .miliseconds-label, +.running-stopwatch .miliseconds-label, +.paused-stopwatch .miliseconds-label { + font-size: 50px; +} + +.running-stopwatch .seconds-label, +.paused-stopwatch .seconds-label { + font-weight: 300; +} + +.clock-location { + font-weight: bolder; +} + +.hidden { + opacity: 0; +} + +.clock-time { + font-size: 2em; + padding: 0.2em 0.5em; + border-radius: 1em; +} + +.none .clock-time { + background: alpha(currentColor, 0.2); +} + +.night .clock-time { + color: #7daea3; + background-color: alpha(#45707a, 0.25); +} + +.naut .clock-time, +.astro .clock-time { + color: #e78a4e; + background-color: alpha(#c35e0a, 0.25); +} + +.civil .clock-time, +.day .clock-time { + color: #d8a657; + background: alpha(#b47109, 0.25); +} + +headerbar splitbutton notification button { + margin: 0; + min-height: 24px; + min-width: 24px; + padding: 0; +} + +popover.background.global-search > arrow, +popover.background.global-search > contents { + padding: 0; +} + +panelframeswitcher { + padding: 3px; +} + +.frameheader.header { + min-height: 24px; + background-color: #282524; +} + +.frameheader.header > button { + border: none; + margin: 0; + padding: 3px; +} + +.frameheader.header tabbar.inline > revealer > box { + min-height: 24px; +} + +.frameheader.header tabbar.inline > revealer > box .start-action { + padding: 0; + border: none; +} + +.frameheader.header tabbar.inline > revealer > box .end-action { + padding: 0; + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +.frameheader.header tabbar.inline > revealer > box tabbox { + border: none; + background: none; +} + +panelstatusbar > menubutton > button, +panelstatusbar > paneltogglebutton button { + border-radius: 0; +} + +.style-variant { + padding: 0 12px; +} + +.style-variant button.toggle { + padding: 0; +} + +.style-variant button.toggle, .style-variant button.toggle:hover, .style-variant button.toggle:focus, .style-variant button.toggle:active, .style-variant button.toggle:checked { + background: none; + outline: none; + border: none; + box-shadow: none; +} + +.style-variant button.toggle > stylevariantpreview > .wallpaper { + border-radius: 12px; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; + box-shadow: none; +} + +.style-variant button.toggle:hover > stylevariantpreview > .wallpaper { + outline-color: rgba(251, 241, 199, 0.04); +} + +.style-variant button.toggle:active > stylevariantpreview > .wallpaper { + outline-color: rgba(251, 241, 199, 0.3); +} + +.style-variant button.toggle:checked > stylevariantpreview > .wallpaper { + outline-color: #7daea3; +} + +playlistview scrollbar.overlay-indicator.dragging, playlistview scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +playlistview queuerow picture.cover, +playlistview queuerow image.card { + border: none; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list { + border: none; + border-radius: 0; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:first-child, window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:last-child { + border-radius: 0; +} + +/* Tagger */ +list.music-list { + margin: -40px 0; + background-color: transparent; +} + +/* Nicotine+ */ +notebook scrolledwindow treeview.treeview-spacing { + background-color: #282828; +} + +.account-switcher-row label { + color: #fbf1c7; +} + +.account-switcher-row label.dim-label { + color: rgba(251, 241, 199, 0.7); +} + +window.background.chromium { + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.chromium headerbar.header-bar.titlebar { + padding: 0 12px; + background-color: #282828; + color: #fbf1c7; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px 0 rgba(251, 241, 199, 0.1); +} + +window.background.chromium headerbar.header-bar.titlebar:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.5); +} + +window.background.chromium headerbar.header-bar.titlebar button.titlebutton { + margin: 0 0px; +} + +.nautilus-window placessidebar > scrolledwindow { + background-color: #282828; + color: #fbf1c7; + border-radius: 0; + /* margin: 0 6px 0 0; */ +} + +.nautilus-window placessidebar > scrolledwindow .dim-label, .nautilus-window placessidebar > scrolledwindow row label.subtitle, row .nautilus-window placessidebar > scrolledwindow label.subtitle, .nautilus-window placessidebar > scrolledwindow row.property > box.header > box.title > .title, .nautilus-window placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander .nautilus-window placessidebar > scrolledwindow image.expander-row-arrow { + color: rgba(40, 40, 40, 0.38); +} + +.nautilus-window .nautilus-grid-view, +.nautilus-window .nautilus-list-view { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 0 6px 6px 6px; +} + +calendar-view { + margin: 6px; +} + +.sidebar-pane .sidebar > scrolledwindow, +.sidebar-pane toolbarview > scrolledwindow, +.sidebar-pane navigation-view-page stack > scrolledwindow, .sidebar-pane, filechooser paned > box, placessidebar > scrolledwindow, agenda-view list.background, .tweak-titlebar-left, .tweak-titlebar-left:backdrop, leaflet.unfolded > box > scrolledwindow, leaflet.unfolded .contacts-contact-list > scrolledwindow, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow { + background-color: #141617; + background-color: #282828; + color: #fbf1c7; + border-radius: 0; + margin: 0; +} + +.sidebar-pane .sidebar > scrolledwindow .dim-label, +.sidebar-pane toolbarview > scrolledwindow .dim-label, +.sidebar-pane navigation-view-page stack > scrolledwindow .dim-label, .sidebar-pane .dim-label, filechooser paned > box .dim-label, placessidebar > scrolledwindow .dim-label, agenda-view list.background .dim-label, .tweak-titlebar-left .dim-label, leaflet.unfolded > box > scrolledwindow .dim-label, leaflet.unfolded .contacts-contact-list > scrolledwindow .dim-label, .sidebar-pane row label.subtitle, row .sidebar-pane label.subtitle, filechooser paned > box row label.subtitle, row filechooser paned > box label.subtitle, placessidebar > scrolledwindow row label.subtitle, row placessidebar > scrolledwindow label.subtitle, agenda-view list.background row label.subtitle, row agenda-view list.background label.subtitle, .tweak-titlebar-left row label.subtitle, row .tweak-titlebar-left label.subtitle, leaflet.unfolded > box > scrolledwindow row label.subtitle, row leaflet.unfolded > box > scrolledwindow label.subtitle, leaflet.unfolded .contacts-contact-list > scrolledwindow row label.subtitle, row leaflet.unfolded .contacts-contact-list > scrolledwindow label.subtitle, .sidebar-pane row.property > box.header > box.title > .title, placessidebar > scrolledwindow row.property > box.header > box.title > .title, agenda-view list.background row.property > box.header > box.title > .title, .tweak-titlebar-left row.property > box.header > box.title > .title, leaflet.unfolded > box > scrolledwindow row.property > box.header > box.title > .title, leaflet.unfolded .contacts-contact-list > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane row.expander image.expander-row-arrow, row.expander .sidebar-pane image.expander-row-arrow, filechooser paned > box row.expander image.expander-row-arrow, row.expander filechooser paned > box image.expander-row-arrow, placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander placessidebar > scrolledwindow image.expander-row-arrow, agenda-view list.background row.expander image.expander-row-arrow, row.expander agenda-view list.background image.expander-row-arrow, .tweak-titlebar-left row.expander image.expander-row-arrow, row.expander .tweak-titlebar-left image.expander-row-arrow, leaflet.unfolded > box > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded > box > scrolledwindow image.expander-row-arrow, leaflet.unfolded .contacts-contact-list > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded .contacts-contact-list > scrolledwindow image.expander-row-arrow { + color: rgba(40, 40, 40, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider, placessidebar > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar > range > trough > slider { + background-color: rgba(251, 241, 199, 0.5); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:hover, placessidebar > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:hover { + background-color: rgba(251, 241, 199, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:active, placessidebar > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:active { + background-color: rgba(251, 241, 199, 0.7); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:disabled, placessidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:disabled { + background-color: rgba(251, 241, 199, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(40, 40, 40, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(40, 40, 40, 0.3); +} + +placessidebar list.navigation-sidebar, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar { + padding: 6px 0 6px 6px; + background: none; + color: rgba(251, 241, 199, 0.7); +} + +placessidebar list.navigation-sidebar > separator, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > separator, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > separator { + background-color: rgba(251, 241, 199, 0.12); + margin: 10px 15px; +} + +placessidebar list.navigation-sidebar > row, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row { + color: rgba(40, 40, 40, 0.6); + border-radius: 9px; + color: #fbf1c7; + padding: 6px 0; +} + +placessidebar list.navigation-sidebar > row:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:hover, placessidebar list.navigation-sidebar > row:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:active, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:active, placessidebar list.navigation-sidebar > row:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:focus { + color: #accbc4; +} + +placessidebar list.navigation-sidebar > row:selected, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + color: #7daea3; + font-weight: 500; +} + +placessidebar list.navigation-sidebar > row:selected:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:hover, placessidebar list.navigation-sidebar > row:selected:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:focus { + color: #9cc2b9; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.top, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.top, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.top, filechooser paned > box scrolledwindow scrollbar.top, placessidebar > scrolledwindow > scrollbar.top, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.top, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.top, leaflet.unfolded > box > scrolledwindow > scrollbar.top, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.top, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.top { + border-bottom: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.bottom, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.bottom, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.bottom, filechooser paned > box scrolledwindow scrollbar.bottom, placessidebar > scrolledwindow > scrollbar.bottom, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.bottom, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.bottom, leaflet.unfolded > box > scrolledwindow > scrollbar.bottom, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.bottom, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.bottom { + border-top: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.left, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.left, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.left, filechooser paned > box scrolledwindow scrollbar.left, placessidebar > scrolledwindow > scrollbar.left, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.left, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.left, leaflet.unfolded > box > scrolledwindow > scrollbar.left, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.left, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.left { + border-right: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.right, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.right, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.right, filechooser paned > box scrolledwindow scrollbar.right, placessidebar > scrolledwindow > scrollbar.right, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.right, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.right, leaflet.unfolded > box > scrolledwindow > scrollbar.right, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.right, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.right { + border-left: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.dragging, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.dragging, placessidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.dragging, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.dragging, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.dragging, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.hovering, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.hovering, placessidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.hovering, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.hovering, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.hovering, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.hovering, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-top > undershoot.top, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-top > undershoot.top { + border-radius: 12px 12px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-bottom > undershoot.bottom, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 12px 12px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +avatar { + border-radius: 9999px; + font-weight: bold; +} + +avatar.color1 { + background-image: linear-gradient(#83b6ec, #337fdc); + color: #cfe1f5; +} + +avatar.color2 { + background-image: linear-gradient(#7ad9f1, #0f9ac8); + color: #caeaf2; +} + +avatar.color3 { + background-image: linear-gradient(#8de6b1, #29ae74); + color: #cef8d8; +} + +avatar.color4 { + background-image: linear-gradient(#b5e98a, #6ab85b); + color: #e6f9d7; +} + +avatar.color5 { + background-image: linear-gradient(#f8e359, #d29d09); + color: #f9f4e1; +} + +avatar.color6 { + background-image: linear-gradient(#ffcb62, #d68400); + color: #ffead1; +} + +avatar.color7 { + background-image: linear-gradient(#ffa95a, #ed5b00); + color: #ffe5c5; +} + +avatar.color8 { + background-image: linear-gradient(#f78773, #e62d42); + color: #f8d2ce; +} + +avatar.color9 { + background-image: linear-gradient(#e973ab, #e33b6a); + color: #fac7de; +} + +avatar.color10 { + background-image: linear-gradient(#cb78d4, #9945b5); + color: #e7c2e8; +} + +avatar.color11 { + background-image: linear-gradient(#9e91e8, #7a59ca); + color: #d5d2f5; +} + +avatar.color12 { + background-image: linear-gradient(#e3cf9c, #b08952); + color: #f2eade; +} + +avatar.color13 { + background-image: linear-gradient(#be916d, #785336); + color: #e5d6ca; +} + +avatar.color14 { + background-image: linear-gradient(#c0bfbc, #6e6d71); + color: #d8d7d3; +} + +avatar.contrasted { + color: #fbf1c7; +} + +avatar.image { + background: none; +} + +.card { + border-radius: 12px; + border: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; + color: rgba(251, 241, 199, 0.7); + box-shadow: none; + outline: none; + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +.card.activatable { + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.04); +} + +.card.activatable:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + +.card.activatable:active { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +toast { + margin: 12px; + margin-bottom: 24px; + border-radius: 9999px; + border-spacing: 6px; + padding: 6px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; + color: #fbf1c7; + border: none; +} + +toast:dir(ltr) { + padding-left: 12px; +} + +toast:dir(rtl) { + padding-right: 12px; +} + +toast > label { + margin: 0 6px; +} + +viewswitcher { + min-height: 0; + padding: 3px; + margin: 6px 0; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + border: none; +} + +viewswitcher.wide { + margin-top: 6px; + margin-bottom: 6px; +} + +viewswitcher.wide button.toggle { + margin: 0; + border-radius: 9px; +} + +viewswitcher.narrow button.toggle { + border-radius: 0; + margin: 0; +} + +viewswitcher.narrow button.toggle:focus-within, viewswitcher.narrow button.toggle:focus { + box-shadow: none; +} + +viewswitcher button.toggle { + font-weight: bold; + padding: 0; +} + +viewswitcher button.toggle > stack > box.narrow { + font-size: 0.75rem; + padding-top: 6px; + padding-bottom: 4px; + border-spacing: 4px; +} + +viewswitcher button.toggle > stack > box.narrow > stack > label { + padding-left: 6px; + padding-right: 6px; +} + +viewswitcher button.toggle > stack > box.wide { + padding: 2px 12px; + border-spacing: 6px; +} + +viewswitcherbar actionbar > revealer > box { + padding: 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle { + border-radius: 12px; + margin: 3px 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 5px; + padding-bottom: 1px; + border-spacing: 0; +} + +viewswitchertitle { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher { + margin-left: 12px; + margin-right: 12px; +} + +viewswitchertitle viewswitcher.narrow { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 0; + padding-bottom: 0; + border-spacing: 0; +} + +viewswitchertitle viewswitcher.wide { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle windowtitle { + margin-top: 0; + margin-bottom: 0; +} + +indicatorbin > indicator, +indicatorbin > mask { + min-width: 6px; + min-height: 6px; + border-radius: 9999px; +} + +indicatorbin > indicator { + margin: 1px; + background-color: alpha(currentColor, 0.4); +} + +indicatorbin > indicator > label { + font-size: 0.6rem; + font-weight: bold; + padding: 1px 4px; + color: #fbf1c7; +} + +indicatorbin > mask { + padding: 1px; + background: black; +} + +indicatorbin.needs-attention > indicator { + background-color: #7daea3; +} + +indicatorbin.needs-attention > indicator > label { + color: rgba(40, 40, 40, 0.87); +} + +preferencespage > scrolledwindow > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +preferencesgroup > box background-preview widget.sidebar, +preferencesgroup > box widget.header-bar:not(.editable-area) { + background-color: #0d0907; +} + +preferencesgroup > box, +preferencesgroup > box .labels { + border-spacing: 6px; +} + +preferencesgroup > box > box.header:not(.single-line) { + margin-bottom: 6px; +} + +preferencesgroup > box > box.single-line { + min-height: 34px; +} + +preferencesgroup > box button.background-preview-button.toggle { + padding: 0; + background: none; + box-shadow: none; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; +} + +preferencesgroup > box button.background-preview-button.toggle, +preferencesgroup > box button.background-preview-button.toggle > background-preview { + border-radius: 12px; +} + +preferencesgroup > box button.background-preview-button.toggle:hover { + outline-color: rgba(251, 241, 199, 0.04); +} + +preferencesgroup > box button.background-preview-button.toggle:active { + outline-color: rgba(251, 241, 199, 0.3); +} + +preferencesgroup > box button.background-preview-button.toggle:checked { + outline-color: #7daea3; +} + +preferencesgroup > box .cutout-button { + background-color: #282524; +} + +preferencesgroup > box button.accent-button { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; + background: var(--accent-bg-color); + outline: none; + background-clip: content-box; + box-shadow: none; +} + +preferencesgroup > box button.accent-button:hover { + box-shadow: 0 0 0 3px alpha(currentColor, 0.08); +} + +preferencesgroup > box button.accent-button:checked { + box-shadow: 0 0 0 3px #7daea3; +} + +preferencesgroup > box button.accent-button.blue, preferencesgroup > box button.accent-button.teal, preferencesgroup > box button.accent-button.green, preferencesgroup > box button.accent-button.yellow, preferencesgroup > box button.accent-button.orange, preferencesgroup > box button.accent-button.red, preferencesgroup > box button.accent-button.pink, preferencesgroup > box button.accent-button.purple, preferencesgroup > box button.accent-button.slate { + --accent-color: oklab( + from var(--accent-bg-color) var(--standalone-color-oklab) + ); +} + +preferencesgroup > box button.accent-button.blue { + --accent-bg-color: var(--accent-blue); +} + +preferencesgroup > box button.accent-button.teal { + --accent-bg-color: var(--accent-teal); +} + +preferencesgroup > box button.accent-button.green { + --accent-bg-color: var(--accent-green); +} + +preferencesgroup > box button.accent-button.yellow { + --accent-bg-color: var(--accent-yellow); +} + +preferencesgroup > box button.accent-button.orange { + --accent-bg-color: var(--accent-orange); +} + +preferencesgroup > box button.accent-button.red { + --accent-bg-color: var(--accent-red); +} + +preferencesgroup > box button.accent-button.pink { + --accent-bg-color: var(--accent-pink); +} + +preferencesgroup > box button.accent-button.purple { + --accent-bg-color: var(--accent-purple); +} + +preferencesgroup > box button.accent-button.slate { + --accent-bg-color: var(--accent-slate); +} + +preferencesgroup > box box > list.boxed-list-separate { + background-color: transparent; + border-radius: 12px; + border: 1px solid rgba(251, 241, 199, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row { + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px 12px 0 0; + margin-top: 0px; + margin-bottom: 0px; +} + +preferencesgroup > box box > list.boxed-list-separate row:first-child { + border-radius: 12px 12px 0 0; + box-shadow: 0 1px rgba(251, 241, 199, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row:last-child { + border-radius: 0 0 12px 12px; +} + +preferencesgroup > box box > list.boxed-list-separate row:hover, preferencesgroup > box box > list.boxed-list-separate row:focus { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); +} + +window.about .main-page > viewport > clamp > box { + margin: 12px; + border-spacing: 6px; +} + +window.about .main-page > viewport > clamp > box > box { + margin-top: 18px; + border-spacing: 18px; + margin-bottom: 6px; +} + +window.about .main-page .app-version { + padding: 3px 18px; + color: #7daea3; + border-radius: 12px; + margin-top: 3px; +} + +window.about .subpage > viewport > clamp > box { + margin: 18px 12px; + border-spacing: 18px; +} + +window.about .subpage > clamp > textview { + background: none; + color: inherit; +} + +statuspage > scrolledwindow > viewport > box { + margin: 36px 12px; + border-spacing: 36px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box { + border-spacing: 12px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 128px; + color: alpha(currentColor, 0.55); +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:disabled { + opacity: 0.35; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box { + margin: 24px 12px; + border-spacing: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 96px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .title { + font-size: 18pt; +} + +flap > dimming, +leaflet > dimming, +navigation-view > dimming, +overlay-split-view > dimming { + background-color: rgba(40, 40, 40, 0.2); + background-image: none; +} + +flap > border, +leaflet > border, +navigation-view > border, +overlay-split-view > border { + background-color: transparent; + background-image: none; +} + +flap > shadow, +leaflet > shadow, +navigation-view > shadow, +overlay-split-view > shadow { + min-width: 56px; + min-height: 56px; +} + +flap > shadow.left, +leaflet > shadow.left, +navigation-view > shadow.left, +overlay-split-view > shadow.left { + background-image: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +flap > shadow.right, +leaflet > shadow.right, +navigation-view > shadow.right, +overlay-split-view > shadow.right { + background-image: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +flap > shadow.up, +leaflet > shadow.up, +navigation-view > shadow.up, +overlay-split-view > shadow.up { + background-image: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +flap > shadow.down, +leaflet > shadow.down, +navigation-view > shadow.down, +overlay-split-view > shadow.down { + background-image: linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +.sidebar-pane { + color: #fbf1c7; + border-top-left-radius: 12px; +} + +.sidebar-pane .sidebar-pane { + background-color: transparent; + color: inherit; +} + +.sidebar-pane headerbar, +.sidebar-pane .navigation-sidebar, +.sidebar-pane searchbar > revealer > box { + background-color: transparent; + box-shadow: none; + border: none; +} + +.sidebar-pane .navigation-sidebar { + padding: 2px 4px; + background: none; + color: rgba(251, 241, 199, 0.7); +} + +.sidebar-pane:dir(ltr), +.sidebar-pane:dir(ltr) banner > revealer > widget, .sidebar-pane.end:dir(rtl), +.sidebar-pane.end:dir(rtl) banner > revealer > widget { + /* box-shadow: inset 0 1px highlight($base-alt); */ + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +/* Middle pane in three-pane setups */ +.content-pane .sidebar-pane, +.sidebar-pane .content-pane { + background-color: transparent; + color: #fbf1c7; +} + +.content-pane .sidebar-pane:backdrop, +.sidebar-pane .content-pane:backdrop { + background-color: transparent; + transition: none; +} + +.content-pane { + background-color: #282828; + color: #fbf1c7; + border-top-right-radius: 12px; + /* box-shadow: inset 0 1px highlight($background); */ +} + +.content-pane headerbar, .content-pane headerbar:backdrop { + background-color: transparent; + box-shadow: none; + border: none; +} + +.maximized .content-pane, .fullscreen .content-pane, .tiled .content-pane, .tiled-top .content-pane, .tiled-right .content-pane, .tiled-bottom .content-pane, .tiled-left .content-pane { + border-radius: 0; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +.top-bar { + box-shadow: none; + background: none; + border: none; +} + +.top-bar headerbar, .top-bar headerbar:backdrop { + background-color: transparent; + box-shadow: none; +} + +.top-bar .collapse-spacing { + padding: 0; +} + +themeselector, +panelthemeselector { + margin: 9px; +} + +themeselector checkbutton, +panelthemeselector checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.12); +} + +themeselector checkbutton.follow:checked, themeselector checkbutton.light:checked, themeselector checkbutton.dark:checked, +panelthemeselector checkbutton.follow:checked, +panelthemeselector checkbutton.light:checked, +panelthemeselector checkbutton.dark:checked { + box-shadow: inset 0 0 0 2px #7daea3; +} + +themeselector checkbutton.follow, +panelthemeselector checkbutton.follow { + background-image: linear-gradient(to bottom right, #f9f5d7 50%, #211f1e 50%); +} + +themeselector checkbutton.light, +panelthemeselector checkbutton.light { + background-color: #f9f5d7; +} + +themeselector checkbutton.dark, +panelthemeselector checkbutton.dark { + background-color: #211f1e; +} + +themeselector checkbutton.theme-selector radio, +panelthemeselector checkbutton.theme-selector radio { + -gtk-icon-source: none; + border: none; + background: none; + box-shadow: none; + min-height: 20px; + min-width: 20px; + padding: 0; +} + +themeselector checkbutton.theme-selector radio:hover, themeselector checkbutton.theme-selector radio:active, themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:hover, +panelthemeselector checkbutton.theme-selector radio:active, +panelthemeselector checkbutton.theme-selector radio:checked { + background-color: transparent; +} + +themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked { + -gtk-icon-size: 20px; + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +themeselector checkbutton.theme-selector radio:checked, themeselector checkbutton.theme-selector radio:checked:hover, themeselector checkbutton.theme-selector radio:checked:active, +panelthemeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked:hover, +panelthemeselector checkbutton.theme-selector radio:checked:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher { + padding: 6px; +} + +themeswitcher .check { + min-height: 20px; + min-width: 20px; + background: none; + padding: 0; + margin: 0; + border-radius: 9999px; + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +themeswitcher .check, themeswitcher .check:hover, themeswitcher .check:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.12); +} + +themeswitcher checkbutton:checked { + box-shadow: inset 0 0 0 2px #7daea3; +} + +themeswitcher checkbutton radio, themeswitcher checkbutton radio:hover, themeswitcher checkbutton radio:active, themeswitcher checkbutton radio:checked, themeswitcher checkbutton radio:checked:hover, themeswitcher checkbutton radio:checked:active { + background-color: transparent; + border: none; + background: none; + box-shadow: none; + color: transparent; + -gtk-icon-source: none; + -gtk-icon-size: 0; +} + +themeswitcher checkbutton.system { + background: linear-gradient(-45deg, #282828 50%, #fbf1c7 50%); +} + +themeswitcher checkbutton.light { + color: alpha(black, 0.8); + background-color: #fbf1c7; +} + +themeswitcher checkbutton.dark { + color: #fbf1c7; + background-color: #282828; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #fbf1c7; +/* text color for entries, views and content in general */ +@define-color theme_text_color #fbf1c7; +/* widget base background color */ +@define-color theme_bg_color #282828; +/* text widgets and the like base background color */ +@define-color theme_base_color #282524; +/* base background color of selections */ +@define-color theme_selected_bg_color #7daea3; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(40, 40, 40, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #282828; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(251, 241, 199, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #282524; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #fbf1c7; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #fbf1c7; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #282828; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #282524; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #7daea3; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(40, 40, 40, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(251, 241, 199, 0.5); +/* widgets main borders color */ +@define-color borders rgba(251, 241, 199, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(251, 241, 199, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #b47109; +@define-color error_color #c14a4a; +@define-color success_color #6c782e; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #fbf1c7; +@define-color wm_unfocused_title rgba(251, 241, 199, 0.7); +@define-color wm_highlight rgba(251, 241, 199, 0.1); +@define-color wm_border #080707; +@define-color wm_focused_bg #282828; +@define-color wm_unfocused_bg #282828; +@define-color wm_button_icon #fbf1c7; +@define-color wm_button_icon alpha(black, 0.5); +@define-color wm_button_focused_bg #353432; +@define-color wm_button_unfocused_bg #353432; +@define-color wm_button_hover_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_active_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_hover_bg #fbf1c7; +@define-color wm_button_active_bg #fbf1c7; +/* FIXME this is really an API */ +@define-color content_view_bg #282524; +@define-color placeholder_text_color #bcb496; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #282524; +@define-color budgie_tasklist_indicator_color rgba(132, 128, 110, 0.7); +@define-color budgie_tasklist_indicator_color_active #7daea3; +@define-color budgie_tasklist_indicator_color_active_window rgba(102, 138, 130, 0.816); +@define-color budgie_tasklist_indicator_color_attention #b47109; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; +@define-color blue_1 #99c1f1; +@define-color blue_2 #62a0ea; +@define-color blue_3 #3584e4; +@define-color blue_4 #1c71d8; +@define-color blue_5 #1a5fb4; +@define-color green_1 #8ff0a4; +@define-color green_2 #57e389; +@define-color green_3 #33d17a; +@define-color green_4 #2ec27e; +@define-color green_5 #26a269; +@define-color yellow_1 #f9f06b; +@define-color yellow_2 #f8e45c; +@define-color yellow_3 #f6d32d; +@define-color yellow_4 #f5c211; +@define-color yellow_5 #e5a50a; +@define-color orange_1 #ffbe6f; +@define-color orange_2 #ffa348; +@define-color orange_3 #ff7800; +@define-color orange_4 #e66100; +@define-color orange_5 #c64600; +@define-color red_1 #f66151; +@define-color red_2 #ed333b; +@define-color red_3 #e01b24; +@define-color red_4 #c01c28; +@define-color red_5 #a51d2d; +@define-color purple_1 #dc8add; +@define-color purple_2 #c061cb; +@define-color purple_3 #9141ac; +@define-color purple_4 #813d9c; +@define-color purple_5 #613583; +@define-color brown_1 #cdab8f; +@define-color brown_2 #b5835a; +@define-color brown_3 #986a44; +@define-color brown_4 #865e3c; +@define-color brown_5 #63452c; +@define-color light_1 #ffffff; +@define-color light_2 #f6f5f4; +@define-color light_3 #deddda; +@define-color light_4 #c0bfbc; +@define-color light_5 #9a9996; +@define-color dark_1 #77767b; +@define-color dark_2 #5e5c64; +@define-color dark_3 #3d3846; +@define-color dark_4 #241f31; +@define-color dark_5 #000000; +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +@define-color accent_bg_color #7daea3; +@define-color accent_fg_color rgba(40, 40, 40, 0.87); +@define-color accent_color #7daea3; +@define-color destructive_bg_color #c14a4a; +@define-color destructive_fg_color #fbf1c7; +@define-color destructive_color #c14a4a; +@define-color success_bg_color #6c782e; +@define-color success_fg_color #fbf1c7; +@define-color success_color #6c782e; +@define-color warning_bg_color #b47109; +@define-color warning_fg_color #fbf1c7; +@define-color warning_color #b47109; +@define-color error_bg_color #c14a4a; +@define-color error_fg_color #fbf1c7; +@define-color error_color #c14a4a; +@define-color window_bg_color #282828; +@define-color window_fg_color #fbf1c7; +@define-color view_bg_color #282524; +@define-color view_fg_color #fbf1c7; +@define-color headerbar_bg_color #282828; +@define-color headerbar_fg_color #fbf1c7; +@define-color headerbar_border_color rgba(251, 241, 199, 0.12); +@define-color headerbar_backdrop_color #282828; +@define-color headerbar_shade_color rgba(251, 241, 199, 0.12); +@define-color card_bg_color #282524; +@define-color card_fg_color #fbf1c7; +@define-color card_shade_color rgba(251, 241, 199, 0.12); +@define-color dialog_bg_color #282524; +@define-color dialog_fg_color #fbf1c7; +@define-color popover_bg_color #242220; +@define-color popover_fg_color #fbf1c7; +@define-color shade_color rgba(251, 241, 199, 0.12); +@define-color scrollbar_outline_color rgba(251, 241, 199, 0.12); diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk.css b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk.css new file mode 100755 index 0000000..ddb16b9 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/gtk.css @@ -0,0 +1,8519 @@ +@keyframes ripple { + to { + background-size: 1000% 1000%; + } +} + +@keyframes ripple-on-slider { + to { + background-size: auto, 1000% 1000%; + } +} + +@keyframes ripple-on-headerbar { + from { + background-image: radial-gradient(circle, #7daea3 0%, transparent 0%); + } + to { + background-image: radial-gradient(circle, #7daea3 100%, transparent 100%); + } +} + +/*************** + * Base States * + ***************/ +.background { + background-color: #282828; + color: #fbf1c7; +} + +#desktopwindow.background { + background-color: transparent; +} + +dnd { + color: #fbf1c7; +} + +.normal-icons { + -gtk-icon-size: 16px; +} + +.large-icons { + -gtk-icon-size: 32px; +} + +.aboutdialog .large-icons { + -gtk-icon-size: 128px; +} + +spinner:disabled, +arrow:disabled, +scrollbar:disabled, +check:disabled, +radio:disabled, +treeview.expander:disabled { + -gtk-icon-filter: opacity(0.5); +} + +iconview, +.view { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +iconview:disabled, +.view:disabled { + color: rgba(251, 241, 199, 0.5); +} + +iconview:selected, +.view:selected { + color: #fbf1c7; +} + +textview text { + background-color: #282524; +} + +textview border { + background-color: #282524; + color: rgba(251, 241, 199, 0.7); +} + +iconview:hover, iconview:selected { + border-radius: 6px; +} + +rubberband, .content-view rubberband, .content-view columnview.view > rubberband, +.content-view treeview.view > rubberband, +.content-view .rubberband, columnview.view > rubberband, +.content-view columnview.view > .rubberband, +treeview.view > rubberband, +.content-view treeview.view > .rubberband, gridview > rubberband, flowbox > rubberband { + border: 1px solid #7daea3; + background-color: rgba(125, 174, 163, 0.3); +} + +flowbox > flowboxchild { + padding: 4px; + border-radius: 12px; +} + +.content-view .tile:selected { + background-color: transparent; +} + +gridview > child { + padding: 3px; +} + +gridview > child:selected { + outline-color: alpha(currentColor, 0.06); +} + +gridview > child box { + border-spacing: 8px; + margin: 12px; +} + +coverflow cover { + color: #fbf1c7; + background-color: #282524; + border: 1px solid black; +} + +label.separator { + color: rgba(251, 241, 199, 0.7); +} + +label:disabled { + opacity: 1; + color: rgba(251, 241, 199, 0.5); +} + +headerbar label:disabled, tab label:disabled, button label:disabled { + color: inherit; + opacity: 1; +} + +label.osd { + border-radius: 12px; + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; +} + + +.dim-label, +row.expander image.expander-row-arrow, +row.property > box.header > box.title > .title, +row label.subtitle { + color: rgba(251, 241, 199, 0.7); + opacity: 1; +} + +.accent { + color: #7daea3; +} + +.success { + color: #6c782e; +} + +.warning { + color: #b47109; +} + +.error { + color: #c14a4a; +} + +.large-title { + font-weight: 300; + font-size: 24pt; +} + +.title-1 { + font-weight: 800; + font-size: 20pt; +} + +.title-2 { + font-weight: 800; + font-size: 15pt; +} + +.title-3 { + font-weight: 700; + font-size: 15pt; +} + +.title-4 { + font-weight: 700; + font-size: 13pt; +} + +.heading { + font-weight: 700; + font-size: 11pt; +} + +.body { + font-weight: 400; + font-size: 11pt; +} + +.caption, row.property > box.header > box.title > .title { + font-weight: 400; + font-size: 9pt; +} + +.caption-heading { + font-weight: 700; + font-size: 9pt; +} + +window.assistant .sidebar { + padding: 4px 0; +} + +window.assistant .sidebar label { + min-height: 34px; + padding: 0 12px; + color: rgba(251, 241, 199, 0.5); + font-weight: 500; +} + +window.assistant .sidebar label.highlight { + color: #fbf1c7; +} + +.osd .scale-popup > arrow, +.osd .scale-popup > contents, .osd popover > arrow, +.osd popover > contents, popover.touch-selection > arrow, +popover.touch-selection > contents, popover.magnifier > arrow, +popover.magnifier > contents, .osd { + color: #fbf1c7; + background-color: #282524; + background-clip: padding-box; + border-radius: 12px; + border: none; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +.osd { + padding: 6px; + margin: 6px; +} + +.osd.circular { + border-radius: 9999px; +} + +/********************* + * Spinner Animation * + *********************/ +@keyframes spin { + to { + transform: rotate(1turn); + } +} + +spinner { + background: none; + opacity: 0; + -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); +} + +spinner:checked { + opacity: 1; + animation: spin 1s linear infinite; +} + +spinner:checked:disabled { + opacity: 0.5; +} + +/**************** + * Text Entries * + ****************/ + +entry headerbar popover.background entry, +headerbar popover.background entry entry, +entry { + min-height: 34px; + padding: 0 8px; + border-spacing: 6px; + border-radius: 12px; + caret-color: currentColor; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + + +entry headerbar popover.background entry:focus-within, +headerbar popover.background entry entry:focus-within, +entry:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #7daea3; +} + + +entry headerbar popover.background entry:drop(active), +headerbar popover.background entry entry:drop(active), +entry headerbar popover.background entry:hover:not(:focus-within), +headerbar popover.background entry entry:hover:not(:focus-within), +entry:drop(active), +entry:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); +} + + +entry headerbar popover.background entry:disabled, +headerbar popover.background entry entry:disabled, +entry:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + + +entry headerbar popover.background entry > text > placeholder, +headerbar popover.background entry entry > text > placeholder, +entry > text > placeholder { + color: rgba(251, 241, 199, 0.5); +} + + +entry headerbar popover.background entry > text > block-cursor, +headerbar popover.background entry entry > text > block-cursor, +entry > text > block-cursor { + color: rgba(251, 241, 199, 0.04); + background-color: #fbf1c7; +} + + +entry headerbar popover.background entry.flat:focus-within, +headerbar popover.background entry entry.flat:focus-within, +entry headerbar popover.background entry.flat:disabled, +headerbar popover.background entry entry.flat:disabled, +entry headerbar popover.background entry.flat:hover, +headerbar popover.background entry entry.flat:hover, +entry headerbar popover.background entry.flat, +headerbar popover.background entry entry.flat, +entry.flat:focus-within, +entry.flat:disabled, +entry.flat:hover, +entry.flat { + min-height: 0; + padding: 2px; + background-color: transparent; + box-shadow: none; + border-radius: 0; + outline: none; +} + + +entry headerbar popover.background entry > image, +headerbar popover.background entry entry > image, +entry > image { + color: rgba(251, 241, 199, 0.7); +} + + +entry headerbar popover.background entry > image:hover, +headerbar popover.background entry entry > image:hover, +entry headerbar popover.background entry > image:active, +headerbar popover.background entry entry > image:active, +entry > image:hover, +entry > image:active { + color: #fbf1c7; +} + + +entry headerbar popover.background entry > image:disabled, +headerbar popover.background entry entry > image:disabled, +entry > image:disabled { + color: rgba(251, 241, 199, 0.5); +} + + +entry headerbar popover.background entry > image.left, +headerbar popover.background entry entry > image.left, +entry > image.left { + margin: 0 6px 0 1px; +} + + +entry headerbar popover.background entry > image.right, +headerbar popover.background entry entry > image.right, +entry > image.right { + margin: 0 1px 0 6px; +} + + +entry headerbar popover.background entry.password image.caps-lock-indicator, +headerbar popover.background entry entry.password image.caps-lock-indicator, +entry.password image.caps-lock-indicator { + opacity: 0.35; +} + + +entry headerbar popover.background entry.error, +headerbar popover.background entry entry.error, +entry.error { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + outline: none; +} + + +entry headerbar popover.background entry.error:focus-within, +headerbar popover.background entry entry.error:focus-within, +entry.error:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #c14a4a; + outline: none; +} + + +entry headerbar popover.background entry.error:drop(active), +headerbar popover.background entry entry.error:drop(active), +entry headerbar popover.background entry.error:hover:not(:focus-within), +headerbar popover.background entry entry.error:hover:not(:focus-within), +entry.error:drop(active), +entry.error:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.error:disabled, +headerbar popover.background entry entry.error:disabled, +entry.error:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.error > text > selection, +headerbar popover.background entry entry.error > text > selection, +entry.error > text > selection { + background-color: rgba(193, 74, 74, 0.25); + color: #c14a4a; +} + + +entry headerbar popover.background entry.error > text > cursor-handle > contents, +headerbar popover.background entry entry.error > text > cursor-handle > contents, +entry.error > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.error > image, +headerbar popover.background entry entry.error > image, +entry.error > image { + color: rgba(193, 74, 74, 0.75); +} + + +entry headerbar popover.background entry.error > image:hover, +headerbar popover.background entry entry.error > image:hover, +entry headerbar popover.background entry.error > image:active, +headerbar popover.background entry entry.error > image:active, +entry.error > image:hover, +entry.error > image:active { + color: #c14a4a; +} + + +entry headerbar popover.background entry.error > image:disabled, +headerbar popover.background entry entry.error > image:disabled, +entry.error > image:disabled { + color: rgba(193, 74, 74, 0.35); +} + + +entry headerbar popover.background entry.warning, +headerbar popover.background entry entry.warning, +entry.warning { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + outline: none; +} + + +entry headerbar popover.background entry.warning:focus-within, +headerbar popover.background entry entry.warning:focus-within, +entry.warning:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #b47109; + outline: none; +} + + +entry headerbar popover.background entry.warning:drop(active), +headerbar popover.background entry entry.warning:drop(active), +entry headerbar popover.background entry.warning:hover:not(:focus-within), +headerbar popover.background entry entry.warning:hover:not(:focus-within), +entry.warning:drop(active), +entry.warning:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.warning:disabled, +headerbar popover.background entry entry.warning:disabled, +entry.warning:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.warning > text > selection, +headerbar popover.background entry entry.warning > text > selection, +entry.warning > text > selection { + background-color: rgba(180, 113, 9, 0.25); + color: #b47109; +} + + +entry headerbar popover.background entry.warning > text > cursor-handle > contents, +headerbar popover.background entry entry.warning > text > cursor-handle > contents, +entry.warning > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.warning > image, +headerbar popover.background entry entry.warning > image, +entry.warning > image { + color: rgba(180, 113, 9, 0.75); +} + + +entry headerbar popover.background entry.warning > image:hover, +headerbar popover.background entry entry.warning > image:hover, +entry headerbar popover.background entry.warning > image:active, +headerbar popover.background entry entry.warning > image:active, +entry.warning > image:hover, +entry.warning > image:active { + color: #b47109; +} + + +entry headerbar popover.background entry.warning > image:disabled, +headerbar popover.background entry entry.warning > image:disabled, +entry.warning > image:disabled { + color: rgba(180, 113, 9, 0.35); +} + + +entry headerbar popover.background entry.success, +headerbar popover.background entry entry.success, +entry.success { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + outline: none; +} + + +entry headerbar popover.background entry.success:focus-within, +headerbar popover.background entry entry.success:focus-within, +entry.success:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #6c782e; + outline: none; +} + + +entry headerbar popover.background entry.success:drop(active), +headerbar popover.background entry entry.success:drop(active), +entry headerbar popover.background entry.success:hover:not(:focus-within), +headerbar popover.background entry entry.success:hover:not(:focus-within), +entry.success:drop(active), +entry.success:hover:not(:focus-within) { + background-color: alpha(currentColor, 0.08); + box-shadow: inset 0 0 0 2px alpha(currentColor, 0.08); + outline: none; +} + + +entry headerbar popover.background entry.success:disabled, +headerbar popover.background entry entry.success:disabled, +entry.success:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); + outline: none; +} + + +entry headerbar popover.background entry.success > text > selection, +headerbar popover.background entry entry.success > text > selection, +entry.success > text > selection { + background-color: rgba(108, 120, 46, 0.25); + color: #6c782e; +} + + +entry headerbar popover.background entry.success > text > cursor-handle > contents, +headerbar popover.background entry entry.success > text > cursor-handle > contents, +entry.success > text > cursor-handle > contents { + background-color: currentColor; +} + + +entry headerbar popover.background entry.success > image, +headerbar popover.background entry entry.success > image, +entry.success > image { + color: rgba(108, 120, 46, 0.75); +} + + +entry headerbar popover.background entry.success > image:hover, +headerbar popover.background entry entry.success > image:hover, +entry headerbar popover.background entry.success > image:active, +headerbar popover.background entry entry.success > image:active, +entry.success > image:hover, +entry.success > image:active { + color: #6c782e; +} + + +entry headerbar popover.background entry.success > image:disabled, +headerbar popover.background entry entry.success > image:disabled, +entry.success > image:disabled { + color: rgba(108, 120, 46, 0.35); +} + + +entry > progress, +entry progress > trough > progress { + margin: 0 -4px; + border-bottom: 2px solid #7daea3; + background-color: transparent; +} + +.osd entry > progress > trough > progress { + border-color: rgba(251, 241, 199, 0.04); +} + + +entry button.image-button { + min-height: 24px; + min-width: 24px; + padding: 0; +} + +treeview entry.flat, treeview entry { + background-color: #282524; +} + +treeview entry.flat, treeview entry.flat:focus-within, treeview entry, treeview entry:focus-within { + border-image: none; + box-shadow: none; +} + +.entry-tag { + margin: 2px; + border-radius: 9999px; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +.entry-tag:hover { + background-image: image(alpha(currentColor, 0.08)); +} + +:dir(ltr) .entry-tag { + margin-left: 4px; + margin-right: 0; + padding-left: 12px; + padding-right: 8px; +} + +:dir(rtl) .entry-tag { + margin-left: 0; + margin-right: 4px; + padding-left: 8px; + padding-right: 12px; +} + +.entry-tag.button { + box-shadow: none; + background-color: transparent; +} + +.entry-tag.button:not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +editablelabel > stack > text { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +/*********** + * Buttons * + ***********/ +@keyframes needs-attention { + from { + background-image: radial-gradient(farthest-side, #7daea3 0%, rgba(125, 174, 163, 0) 0%); + } + to { + background-image: radial-gradient(farthest-side, #7daea3 95%, rgba(125, 174, 163, 0)); + } +} + +infobar.warning > revealer > box button, infobar.warning:backdrop > revealer > box button, popover.touch-selection button, popover.magnifier button, headerbar.selection-mode button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +infobar.warning > revealer > box button:focus, popover.touch-selection button:focus, popover.magnifier button:focus, headerbar.selection-mode button:focus:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:hover, popover.touch-selection button:hover, popover.magnifier button:hover, headerbar.selection-mode button:hover:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:active, popover.touch-selection button:active, popover.magnifier button:active, headerbar.selection-mode button:active:not(.suggested-action):not(.destructive-action), infobar.warning > revealer > box button:checked, popover.touch-selection button:checked, popover.magnifier button:checked, headerbar.selection-mode button:checked:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +infobar.warning > revealer > box button:disabled, popover.touch-selection button:disabled, popover.magnifier button:disabled, headerbar.selection-mode button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +infobar.warning > revealer > box button:checked:disabled, popover.touch-selection button:checked:disabled, popover.magnifier button:checked:disabled, headerbar.selection-mode button:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.5); +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button, button { + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:focus:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:focus:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:focus, button:focus { + background-color: alpha(currentColor, 0.08); + outline: 2px solid rgba(125, 174, 163, 0.35); + outline-offset: 0; +} + +row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:hover:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:hover, button:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; + -gtk-icon-filter: brightness(1.2); +} + +row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.keyboard-activating.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.keyboard-activating.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button.keyboard-activating:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button.keyboard-activating, button.keyboard-activating, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:active:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:active:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:active, button:active { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:disabled:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:disabled, button:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + outline-color: transparent; +} + +row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr), row.spin spinbutton > button.image-button.up:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:not(.suggested-action):not(.destructive-action):not(.flat), .toolbar .linked button:checked, button:checked { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:hover:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:hover:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:hover { + outline-color: transparent; + background-color: #8db8ae; + color: rgba(40, 40, 40, 0.87); +} + +row.spin spinbutton > button.image-button.up:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:checked:disabled:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar popover.background button:checked:disabled:not(.suggested-action):not(.destructive-action):not(.flat), button:checked:disabled { + outline-color: transparent; + background-color: rgba(125, 174, 163, 0.35); + color: rgba(40, 40, 40, 0.38); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button, calendar > header > button, notebook > header > tabs > arrow, popover modelbutton, .pathbar button, spinbutton > button, splitbutton.flat > button, +splitbutton.flat > menubutton > button { + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:focus:not(:hover):not(:active), calendar > header > button:focus:not(:hover):not(:active), notebook > header > tabs > arrow:focus:not(:hover):not(:active), popover modelbutton:focus:not(:hover):not(:active), .pathbar button:focus:not(:hover):not(:active), spinbutton > button:focus:not(:hover):not(:active), splitbutton.flat > button:focus:not(:hover):not(:active), +splitbutton.flat > menubutton > button:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 2px solid rgba(251, 241, 199, 0.04); + outline-offset: -2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:hover, calendar > header > button:hover, notebook > header > tabs > arrow:hover, popover modelbutton:hover, .pathbar button:hover, spinbutton > button:hover, splitbutton.flat > button:hover, +splitbutton.flat > menubutton > button:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:active, calendar > header > button:active, notebook > header > tabs > arrow:active, popover modelbutton:active, .pathbar button:active, spinbutton > button:active, splitbutton.flat > button:active, +splitbutton.flat > menubutton > button:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button:disabled, calendar > header > button:disabled, notebook > header > tabs > arrow:disabled, popover modelbutton:disabled, .pathbar button:disabled, spinbutton > button:disabled, splitbutton.flat > button:disabled, +splitbutton.flat > menubutton > button:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +#NautilusPathButton, filechooser #pathbarbox > stack > box > button, window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button, .app-notification button, headerbar button:not(.suggested-action):not(.destructive-action), .toolbar button, splitbutton.suggested-action > button, +splitbutton.suggested-action > menubutton > button, splitbutton.destructive-action > button, +splitbutton.destructive-action > menubutton > button, splitbutton.opaque > button, +splitbutton.opaque > menubutton > button, menubutton.suggested-action > button, menubutton.destructive-action > button, menubutton.opaque > button, menubutton.flat > button, button.flat { + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +#NautilusPathButton:focus:not(:hover):not(:active), filechooser #pathbarbox > stack > box > button:focus:not(:hover):not(:active), window.messagedialog .response-area button:focus:not(:hover):not(:active), window.dialog.message .dialog-action-area > button:focus:not(:hover):not(:active), .app-notification button:focus:not(:hover):not(:active), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), .toolbar button:focus:not(:hover):not(:active), splitbutton.suggested-action > button:focus:not(:hover):not(:active), +splitbutton.suggested-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.destructive-action > button:focus:not(:hover):not(:active), +splitbutton.destructive-action > menubutton > button:focus:not(:hover):not(:active), splitbutton.opaque > button:focus:not(:hover):not(:active), +splitbutton.opaque > menubutton > button:focus:not(:hover):not(:active), menubutton.suggested-action > button:focus:not(:hover):not(:active), menubutton.destructive-action > button:focus:not(:hover):not(:active), menubutton.opaque > button:focus:not(:hover):not(:active), menubutton.flat > button:focus:not(:hover):not(:active), button.flat:focus:not(:hover):not(:active) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 2px solid rgba(251, 241, 199, 0.04); + outline-offset: -2px; +} + +#NautilusPathButton:hover, filechooser #pathbarbox > stack > box > button:hover, window.messagedialog .response-area button:hover, window.dialog.message .dialog-action-area > button:hover, .app-notification button:hover, headerbar button:hover:not(.suggested-action):not(.destructive-action), .toolbar button:hover, splitbutton.suggested-action > button:hover, +splitbutton.suggested-action > menubutton > button:hover, splitbutton.destructive-action > button:hover, +splitbutton.destructive-action > menubutton > button:hover, splitbutton.opaque > button:hover, +splitbutton.opaque > menubutton > button:hover, menubutton.suggested-action > button:hover, menubutton.destructive-action > button:hover, menubutton.opaque > button:hover, menubutton.flat > button:hover, button.flat:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +#NautilusPathButton:active, filechooser #pathbarbox > stack > box > button:active, window.messagedialog .response-area button:active, window.dialog.message .dialog-action-area > button:active, .app-notification button:active, headerbar button:active:not(.suggested-action):not(.destructive-action), .toolbar button:active, splitbutton.suggested-action > button:active, +splitbutton.suggested-action > menubutton > button:active, splitbutton.destructive-action > button:active, +splitbutton.destructive-action > menubutton > button:active, splitbutton.opaque > button:active, +splitbutton.opaque > menubutton > button:active, menubutton.suggested-action > button:active, menubutton.destructive-action > button:active, menubutton.opaque > button:active, menubutton.flat > button:active, button.flat:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; +} + +#NautilusPathButton:disabled, filechooser #pathbarbox > stack > box > button:disabled, window.messagedialog .response-area button:disabled, window.dialog.message .dialog-action-area > button:disabled, .app-notification button:disabled, headerbar button:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:disabled, splitbutton.suggested-action > button:disabled, +splitbutton.suggested-action > menubutton > button:disabled, splitbutton.destructive-action > button:disabled, +splitbutton.destructive-action > menubutton > button:disabled, splitbutton.opaque > button:disabled, +splitbutton.opaque > menubutton > button:disabled, menubutton.suggested-action > button:disabled, menubutton.destructive-action > button:disabled, menubutton.opaque > button:disabled, menubutton.flat > button:disabled, button.flat:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +#NautilusPathButton:checked, filechooser #pathbarbox > stack > box > button:checked, window.messagedialog .response-area button:checked, window.dialog.message .dialog-action-area > button:checked, .app-notification button:checked, headerbar button:checked:not(.suggested-action):not(.destructive-action), .toolbar button:checked, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button:checked, menubutton.suggested-action > button:checked, menubutton.destructive-action > button:checked, menubutton.opaque > button:checked, menubutton.flat > button:checked, button.flat:checked { + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +#NautilusPathButton:checked:disabled, filechooser #pathbarbox > stack > box > button:checked:disabled, window.messagedialog .response-area button:checked:disabled, window.dialog.message .dialog-action-area > button:checked:disabled, .app-notification button:checked:disabled, headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action), .toolbar button:checked:disabled, splitbutton.suggested-action > button:checked:disabled, +splitbutton.suggested-action > menubutton > button:checked:disabled, splitbutton.destructive-action > button:checked:disabled, +splitbutton.destructive-action > menubutton > button:checked:disabled, splitbutton.opaque > button:checked:disabled, +splitbutton.opaque > menubutton > button:checked:disabled, menubutton.suggested-action > button:checked:disabled, menubutton.destructive-action > button:checked:disabled, menubutton.opaque > button:checked:disabled, menubutton.flat > button:checked:disabled, button.flat:checked:disabled { + background-color: alpha(currentColor, 0.1); + color: rgba(251, 241, 199, 0.5); +} + +button.opaque { + box-shadow: none; +} + +.osd button.opaque:focus:focus-visible { + outline-color: rgba(251, 241, 199, 0.15); +} + +button.opaque:hover { + background-image: image(alpha(currentColor, 0.1)); +} + +button.keyboard-activating.opaque, button.opaque:active { + background-image: image(rgba(0, 0, 0, 0.2)); +} + +button.opaque:checked { + background-image: image(rgba(0, 0, 0, 0.15)); +} + +button.opaque:checked:hover { + background-image: image(rgba(0, 0, 0, 0.05)); +} + +button.opaque:checked.keyboard-activating, button.opaque:checked:active { + background-image: image(rgba(0, 0, 0, 0.3)); +} + +.nautilus-window .floating-bar button, placessidebar list.navigation-sidebar > row button.sidebar-button, notebook > header > tabs > tab button.flat, popover.menu box.circular-buttons button.circular.image-button.model, spinbutton > button { + min-height: 24px; + min-width: 24px; + padding: 0; + border-radius: 9999px; +} + +button { + min-height: 24px; + min-width: 16px; + padding: 5px 9px; + border-radius: 12px; + font-weight: 500; +} + +button:drop(active) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + +button separator { + margin: 4px 1px; +} + +button.opaque { + background-color: #525048; + color: #fbf1c7; +} + +button.text-button { + min-width: 32px; + padding-left: 16px; + padding-right: 16px; +} + +button.image-button { + min-width: 24px; + padding: 5px; +} + +button.text-button.image-button, button.image-text-button { + min-width: 24px; + padding: 5px; + border-radius: 12px; +} + +button.text-button.image-button > box, +button.text-button.image-button > box > box, button.image-text-button > box, +button.image-text-button > box > box { + border-spacing: 4px; +} + +button.text-button.image-button > box > label, +button.text-button.image-button > box > box > label, button.image-text-button > box > label, +button.image-text-button > box > box > label { + padding-left: 2px; + padding-right: 2px; +} + +button.text-button.image-button label:first-child, button.image-text-button label:first-child { + margin-left: 11px; +} + +button.text-button.image-button label:last-child, button.image-text-button label:last-child { + margin-right: 11px; +} + +button.text-button.image-button.flat label:first-child, button.image-text-button.flat label:first-child { + margin-left: 7px; +} + +button.text-button.image-button.flat label:last-child, button.image-text-button.flat label:last-child { + margin-right: 7px; +} + +button.text-button.image-button image:not(:only-child), button.image-text-button image:not(:only-child) { + margin: 0 4px; +} + +button.arrow-button { + padding-left: 9px; + padding-right: 9px; +} + +button.arrow-button > box { + border-spacing: 4px; +} + +button.arrow-button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +button.arrow-button.text-button > box { + border-spacing: 6px; +} + +menubutton.pill > button, button.pill { + padding: 9px 30px; + border-radius: 9999px; +} + +button.card { + background-color: #282524; + background-clip: padding-box; + font-weight: inherit; + border: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; +} + +button.card:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + +button.card.keyboard-activating, button.card:active { + background-image: none; + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +button.card:checked { + background-image: none; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + border-color: #7daea3; +} + +button.card:checked:hover { + background-image: none; + outline-color: transparent; + background-color: #8db8ae; + color: rgba(40, 40, 40, 0.87); +} + +button.card:checked:disabled { + outline-color: transparent; + background-color: rgba(125, 174, 163, 0.35); + color: rgba(40, 40, 40, 0.38); +} + +button.card:checked.keyboard-activating, button.card:checked:active { + background-image: none; +} + +button.card:checked.has-open-popup { + background-image: none; +} + +button.card:drop(active) { + color: #e78a4e; + box-shadow: inset 0 0 0 1px #e78a4e; +} + +.linked:not(.vertical) > button:focus, .linked.vertical > button:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > button.flat:not(:only-child), .linked.vertical > button.flat:not(:only-child) { + background-color: alpha(currentColor, 0.05); +} + +.linked:not(.vertical) > button.flat:focus, .linked.vertical > button.flat:focus { + box-shadow: none; + outline: none; +} + +.linked:not(.vertical) > menubutton > button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +button.osd { + min-height: 24px; + min-width: 24px; + padding: 5px; + box-shadow: none; + background-color: rgba(0, 0, 0, 0.35); + color: #fbf1c7; + margin: 0; +} + +button.osd > image { + padding: 0; +} + +button.osd.remove-button { + padding: 0; +} + +button.osd:focus { + outline-color: transparent; +} + +button.osd:hover { + background-color: rgba(0, 0, 0, 0.45); + color: #fbf1c7; +} + +button.osd:active { + background-color: rgba(0, 0, 0, 0.65); + color: #fbf1c7; +} + +button.osd:disabled { + background-color: rgba(0, 0, 0, 0.15); + color: rgba(251, 241, 199, 0.35); +} + +button.suggested-action { + background-color: #45707a; + color: #fbf1c7; + box-shadow: none; +} + +button.suggested-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + outline-color: transparent; +} + +button.suggested-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:checked { + background-color: #7c9791; +} + +button.suggested-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.suggested-action:focus { + box-shadow: 0 0 0 2px rgba(69, 112, 122, 0.35); +} + +button.suggested-action.flat { + background-color: transparent; + color: #45707a; +} + +button.suggested-action.flat:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +button.suggested-action.flat:checked { + background-color: rgba(69, 112, 122, 0.3); +} + +button.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; + box-shadow: none; +} + +button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + outline-color: transparent; +} + +button.destructive-action:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 2px 2.4px -1px rgba(0, 0, 0, 0.1), 0 4px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 6px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:checked { + background-color: #d27c70; +} + +button.destructive-action:checked:hover { + box-shadow: inset 0 0 0 9999px transparent, 0 3px 3px -3px rgba(0, 0, 0, 0.15), 0 2px 3px -1px rgba(0, 0, 0, 0.12), 0 2px 5px 0 rgba(0, 0, 0, 0.06); +} + +button.destructive-action:focus { + box-shadow: 0 0 0 2px rgba(193, 74, 74, 0.35); +} + +button.destructive-action.flat { + background-color: transparent; + color: #c14a4a; +} + +button.destructive-action.flat:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +button.destructive-action.flat:checked { + background-color: rgba(193, 74, 74, 0.3); +} + +stackswitcher > button > label { + margin: 0 -6px; + padding: 0 6px; +} + +stackswitcher > button > image { + margin: -3px -6px; + padding: 3px 6px; +} + +stackswitcher > button.needs-attention:checked > label, +stackswitcher > button.needs-attention:checked > image { + animation: none; + background-image: none; +} + +button.font > box, button.file > box { + border-spacing: 6px; +} + +button.font > box > box > label, button.file > box > box > label { + font-weight: bold; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action), filechooser #pathbarbox > stack > box > button, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child, headerbar button.star, menubutton.circular > button, button.close, button.circular { + border-radius: 9999px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) label, filechooser #pathbarbox > stack > box > button label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child label, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque) label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child label, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child label, headerbar button.star label, menubutton.circular > button label, button.close label, button.circular label { + padding: 0; +} + +menubutton.osd { + background: none; + color: inherit; +} + +menubutton.suggested-action { + background-color: #45707a; + color: #fbf1c7; +} + +menubutton.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +menubutton.opaque { + background-color: #525048; + color: #fbf1c7; +} + +menubutton.suggested-action, menubutton.destructive-action, menubutton.opaque { + border-radius: 12px; +} + +menubutton.suggested-action.circular, menubutton.suggested-action.pill, menubutton.destructive-action.circular, menubutton.destructive-action.pill, menubutton.opaque.circular, menubutton.opaque.pill { + border-radius: 9999px; +} + +menubutton.suggested-action > button, menubutton.suggested-action > button:checked, menubutton.destructive-action > button, menubutton.destructive-action > button:checked, menubutton.opaque > button, menubutton.opaque > button:checked { + background-color: transparent; + color: inherit; +} + +menubutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +menubutton arrow { + min-height: 16px; + min-width: 16px; +} + +menubutton arrow.none { + -gtk-icon-source: -gtk-icontheme("open-menu-symbolic"); +} + +menubutton arrow.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +menubutton arrow.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +menubutton arrow.left { + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +menubutton arrow.right { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +splitbutton { + border-radius: 12px; +} + +splitbutton, splitbutton > separator { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + transition-property: background; +} + +splitbutton > separator { + margin-top: 6px; + margin-bottom: 6px; + background: none; +} + +splitbutton > menubutton > button { + padding: 5px 9px; +} + +splitbutton.image-button > button { + min-width: 24px; + padding-left: 6px; + padding-right: 6px; +} + +splitbutton.text-button.image-button > button, splitbutton.image-text-button > button { + padding-left: 9px; + padding-right: 9px; +} + +splitbutton.text-button.image-button > button > box, splitbutton.image-text-button > button > box { + border-spacing: 6px; +} + +splitbutton > button:dir(ltr), +splitbutton > menubutton > button:dir(rtl) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: -1px; +} + +splitbutton > button:dir(rtl), +splitbutton > menubutton > button:dir(ltr) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin-left: -1px; +} + +splitbutton.flat > separator { + background: rgba(251, 241, 199, 0.12); +} + +splitbutton.flat:hover, splitbutton.flat:active, splitbutton.flat:checked { + background: alpha(currentColor, 0.07); +} + +splitbutton.flat:hover > separator, splitbutton.flat:active > separator, splitbutton.flat:checked > separator { + background: none; +} + +splitbutton.flat:focus-within:focus-visible > separator { + background: none; +} + +splitbutton.flat > button, +splitbutton.flat > menubutton > button { + border-radius: 12px; +} + +splitbutton.suggested-action { + background-color: #45707a; + color: #fbf1c7; +} + +splitbutton.destructive-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +splitbutton.opaque { + background-color: #525048; + color: #fbf1c7; +} + +splitbutton.suggested-action > button, splitbutton.suggested-action > button:checked, +splitbutton.suggested-action > menubutton > button, +splitbutton.suggested-action > menubutton > button:checked, splitbutton.destructive-action > button, splitbutton.destructive-action > button:checked, +splitbutton.destructive-action > menubutton > button, +splitbutton.destructive-action > menubutton > button:checked, splitbutton.opaque > button, splitbutton.opaque > button:checked, +splitbutton.opaque > menubutton > button, +splitbutton.opaque > menubutton > button:checked { + color: inherit; + background-color: transparent; +} + +splitbutton.suggested-action > menubutton > button:dir(ltr), splitbutton.destructive-action > menubutton > button:dir(ltr), splitbutton.opaque > menubutton > button:dir(ltr) { + box-shadow: inset 1px 0 rgba(251, 241, 199, 0.12); +} + +splitbutton.suggested-action > menubutton > button:dir(rtl), splitbutton.destructive-action > menubutton > button:dir(rtl), splitbutton.opaque > menubutton > button:dir(rtl) { + box-shadow: inset -1px 0 rgba(251, 241, 199, 0.12); +} + +splitbutton > menubutton > button > arrow.none { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +buttoncontent { + border-spacing: 6px; +} + +buttoncontent > label { + font-weight: bold; +} + +buttoncontent > label:dir(ltr) { + padding-right: 2px; +} + +buttoncontent > label:dir(rtl) { + padding-left: 2px; +} + +.arrow-button > box > buttoncontent > label:dir(ltr), splitbutton > button > buttoncontent > label:dir(ltr) { + padding-right: 0; +} + +.arrow-button > box > buttoncontent > label:dir(rtl), splitbutton > button > buttoncontent > label:dir(rtl) { + padding-left: 0; +} + +stacksidebar row.needs-attention > label, stackswitcher > button.needs-attention > label, +stackswitcher > button.needs-attention > image { + animation: needs-attention 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-repeat: no-repeat; + background-position: right 3px; + background-size: 6px 6px; +} + +stacksidebar row.needs-attention > label:dir(rtl), stackswitcher > button.needs-attention > label:dir(rtl), +stackswitcher > button.needs-attention > image:dir(rtl) { + background-position: left 3px; +} + +.linked:not(.vertical) > entry, .linked:not(.vertical) > button, .linked:not(.vertical) > button.image-button { + border-radius: 0; +} + +.linked:not(.vertical) > entry:first-child, .linked:not(.vertical) > button:first-child { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +.linked:not(.vertical) > entry:last-child, .linked:not(.vertical) > button:last-child { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked:not(.vertical) > entry:only-child, .linked:not(.vertical) > button:only-child { + border-radius: 12px; +} + +.linked.vertical > entry, .linked.vertical > button, .linked.vertical > button.image-button { + border-radius: 0; +} + +.linked.vertical > entry:first-child, .linked.vertical > button:first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +.linked.vertical > entry:last-child, .linked.vertical > button:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +.linked.vertical > entry:only-child, .linked.vertical > button:only-child { + border-radius: 12px; +} + +button.color { + min-height: 24px; + min-width: 24px; + padding: 6px; +} + + +list > row button.image-button:not(.flat) { + background-color: transparent; + box-shadow: none; + border: none; +} + + +list > row button.image-button:not(.flat):hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + + +list > row button.image-button:not(.flat):active, +list > row button.image-button:not(.flat):checked { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + + +list > row button.image-button:not(.flat).suggested-action { + background-color: #45707a; + color: #fbf1c7; +} + + +list > row button.image-button:not(.flat).destructive-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +/********* + * Links * + *********/ +link { + color: #83b193; +} + +link:visited { + color: #ab62b1; +} + +button.link:link, button.link:link:focus, button.link:link:hover, button.link:link:active { + color: #83b193; +} + +button.link:visited, button.link:visited:focus, button.link:visited:hover, button.link:visited:active { + color: #ab62b1; +} + +button.link > label { + text-decoration-line: underline; +} + +/***************** + * GtkSpinButton * + *****************/ +spinbutton { + border-radius: 9px; + padding: 0; + border-spacing: 0; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 300ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; +} + +spinbutton:focus-within { + background-color: rgba(251, 241, 199, 0.08); + box-shadow: inset 0 0 0 2px #7daea3; +} + +spinbutton:disabled { + box-shadow: inset 0 0 0 2px transparent; + background-color: rgba(251, 241, 199, 0.08); + color: rgba(251, 241, 199, 0.5); +} + +spinbutton > text { + border-image: none; + border-radius: 0; + box-shadow: none; + background-color: transparent; + margin: 0; +} + +spinbutton > button { + border: none; +} + +spinbutton > button:focus:not(:hover):not(:active):not(:disabled) { + box-shadow: none; +} + +spinbutton:not(.vertical) > text { + min-width: 30px; + padding-left: 12px; +} + +spinbutton:not(.vertical) > button { + padding: 0; + margin: 6px; +} + +spinbutton:not(.vertical) > button.up:dir(ltr), spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 3px; +} + +spinbutton:not(.vertical) > button.up:dir(rtl), spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 3px; +} + +cell.activatable spinbutton:not(.vertical) { + margin: 3px 0; +} + +cell.activatable spinbutton:not(.vertical) > button { + margin: 0; + padding: 0; + min-height: 24px; + border-radius: 0; +} + +cell.activatable spinbutton:not(.vertical) > button:last-child { + border-radius: 0 12px 12px 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(ltr), cell.activatable spinbutton:not(.vertical) > button.down:dir(rtl) { + margin-left: 0; +} + +cell.activatable spinbutton:not(.vertical) > button.up:dir(rtl), cell.activatable spinbutton:not(.vertical) > button.down:dir(ltr) { + margin-right: 0; +} + +spinbutton.vertical > text { + min-height: 34px; + min-width: 40px; + padding: 0; +} + +spinbutton.vertical > button { + padding: 0; + margin: 6px 8px; +} + +/************* + * dropdowns * + *************/ +dropdown button.toggle, combobox button.toggle { + border-radius: 0 9px 9px 0; +} + +dropdown > button > box, combobox > button > box { + border-spacing: 6px; +} + +dropdown > button > box > stack > row.activatable:hover, combobox > button > box > stack > row.activatable:hover, dropdown > button > box > stack > row.activatable:active, combobox > button > box > stack > row.activatable:active { + background: none; +} + +dropdown arrow, combobox arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); + min-height: 16px; + min-width: 16px; +} + +dropdown:drop(active), combobox:drop(active) { + box-shadow: none; +} + +dropdown:drop(active) button.combo, combobox:drop(active) button.combo { + color: #e78a4e; + box-shadow: inset 0 0 0 2px #e78a4e; +} + +dropdown popover.menu, combobox popover.menu { + padding: 6px 0 0; +} + +dropdown popover.menu listview > row, combobox popover.menu listview > row { + min-width: 0; + padding: 6px; +} + +dropdown popover.menu listview > row:selected, combobox popover.menu listview > row:selected { + color: #fbf1c7; + background-color: alpha(currentColor, 0.06); +} + +dropdown popover.menu .dropdown-searchbar, combobox popover.menu .dropdown-searchbar { + padding: 6px; +} + +dropdown popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top, combobox popover.menu .dropdown-searchbar + scrolledwindow:not(.undershoot-top) > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +/************** + * ComboBoxes * + **************/ +/************ + * Toolbars * + ************/ +.toolbar { + padding: 6px; + /* background-color: $background; */ + border-spacing: 6px; +} + +.osd .toolbar { + background-color: transparent; +} + +.app-notification, .toolbar.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + border-radius: 18px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; + color: #fbf1c7; +} + +.app-notification:backdrop, .toolbar.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +.left.app-notification, .right.app-notification, .top.app-notification, .bottom.app-notification, .toolbar.osd.left, .toolbar.osd.right, .toolbar.osd.top, .toolbar.osd.bottom { + border-radius: 0; +} + +.bottom.app-notification, .toolbar.osd.bottom { + box-shadow: none; + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.2) 50%, rgba(0, 0, 0, 0.4)); +} + +.toolbar.horizontal > separator { + margin: 2px; +} + +.toolbar.vertical > separator { + margin: 2px; +} + +.toolbar entry, +.toolbar spinbutton, +.toolbar splitbutton, +.toolbar separator:not(.sidebar), +.toolbar button, +.toolbar menubutton, +.toolbar scalebutton { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar menubutton > button, +.toolbar splitbutton > button, +.toolbar splitbutton > menubutton, +.toolbar scalebutton > button { + margin-top: 0; + margin-bottom: 0; +} + +.toolbar switch { + margin-top: 4px; + margin-bottom: 4px; +} + +.toolbar spinbutton entry, +.toolbar spinbutton button { + margin: 0; +} + +.toolbar popover.menu separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +searchbar > revealer > box { + padding: 6px; + border-spacing: 0; + border-style: solid; + border-width: 0 0 1px; + border-color: rgba(251, 241, 199, 0.12); + background-color: #282828; + background-clip: border-box; + box-shadow: none; +} + +searchbar > revealer > box entry, +searchbar > revealer > box button, +searchbar > revealer > box menubutton { + margin: 0; +} + +/*************** + * Header bars * + ***************/ +headerbar button:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); + border: none; +} + +headerbar button:hover:not(.suggested-action):not(.destructive-action), headerbar button:focus:not(:hover):not(:active):not(.suggested-action):not(.destructive-action), headerbar button:active:not(.suggested-action):not(.destructive-action), headerbar button:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +headerbar button:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +headerbar button:checked:disabled:not(.suggested-action):not(.destructive-action) { + background-color: transparent; + color: rgba(251, 241, 199, 0.5); +} + +headerbar button:backdrop:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.5); +} + +headerbar button:backdrop:focus:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:hover:not(.suggested-action):not(.destructive-action), headerbar button:backdrop:active:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +headerbar button:backdrop:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +headerbar button:backdrop:checked:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +headerbar button:backdrop:checked:disabled:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.32); +} + +headerbar entry { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.7); +} + +headerbar entry:hover, headerbar entry:focus-within { + color: #fbf1c7; +} + +headerbar entry:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +headerbar entry > text > placeholder { + color: rgba(251, 241, 199, 0.5); +} + +headerbar entry > text > block-cursor { + color: rgba(251, 241, 199, 0.04); + background-color: #fbf1c7; +} + +headerbar entry > image { + color: rgba(251, 241, 199, 0.7); +} + +headerbar entry > image:hover, headerbar entry > image:active { + color: #fbf1c7; +} + +headerbar entry > image:disabled { + color: rgba(251, 241, 199, 0.5); +} + +headerbar { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1), color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: transparent; + color: #fbf1c7; + min-height: 46px; + border: none; + box-shadow: none; + padding: 0; + margin: 0; +} + +headerbar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +headerbar:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.7); + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +headerbar:backdrop:disabled { + color: rgba(251, 241, 199, 0.32); +} + +headerbar.flat, headerbar.flat:backdrop { + background: none; + box-shadow: none; + transition: none; +} + +headerbar .title { + padding-left: 6px; + padding-right: 6px; + margin: 0 -13px; + font-weight: bold; +} + +headerbar .subtitle { + padding: 0 12px; + font-size: smaller; +} + +headerbar .subtitle, +headerbar .dim-label, +headerbar row.expander image.expander-row-arrow, +row.expander headerbar image.expander-row-arrow, +headerbar row.property > box.header > box.title > .title, +headerbar row label.subtitle, +row headerbar label.subtitle { + transition: color 75ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(251, 241, 199, 0.7); +} + +headerbar .subtitle:backdrop, +headerbar .dim-label:backdrop, +headerbar row.expander image.expander-row-arrow:backdrop, +row.expander headerbar image.expander-row-arrow:backdrop, +headerbar row.property > box.header > box.title > .title:backdrop, +headerbar row label.subtitle:backdrop, +row headerbar label.subtitle:backdrop { + color: rgba(251, 241, 199, 0.5); +} + +headerbar .titlebar { + background-color: transparent; + box-shadow: none; +} + +headerbar headerbar + separator { + background-color: rgba(251, 241, 199, 0.12); +} + +headerbar > windowhandle > box { + padding: 0 6px; +} + +headerbar > windowhandle > box, +headerbar > windowhandle > box > box.start, +headerbar > windowhandle > box > box.end { + border-spacing: 6px; +} + +headerbar entry, +headerbar spinbutton, +headerbar splitbutton, +headerbar button, +headerbar menubutton, +headerbar stackswitcher, +headerbar separator:not(.sidebar) { + margin-top: 6px; + margin-bottom: 6px; +} + +headerbar menubutton > button, +headerbar spinbutton > button, +headerbar splitbutton > button, +headerbar splitbutton > menubutton, +headerbar .linked > menubutton, +headerbar entry > menubutton { + margin-top: 0; + margin-bottom: 0; +} + +headerbar button.suggested-action:disabled, +headerbar button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); + opacity: 1; +} + +headerbar button.star { + min-height: 24px; + min-width: 24px; + padding: 5px; +} + +headerbar .linked:not(.vertical) > entry:not(:only-child) { + border-radius: 12px; +} + +headerbar .entry-tag { + margin-top: 5px; + margin-bottom: 5px; +} + +headerbar popover.background button.suggested-action:disabled, +headerbar popover.background button.destructive-action:disabled { + background-color: rgba(251, 241, 199, 0.04); + color: rgba(251, 241, 199, 0.5); +} + +headerbar popover.background entry, +headerbar popover.background spinbutton, +headerbar popover.background button, +headerbar popover.background menubutton, +headerbar popover.background stackswitcher { + margin-top: 0; + margin-bottom: 0; +} + +headerbar separator:not(.sidebar) { + background-color: rgba(251, 241, 199, 0.12); +} + +headerbar switch { + margin-top: 11px; + margin-bottom: 11px; +} + +headerbar.selection-mode { + transition: background-color 0.1ms 225ms, color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +headerbar.selection-mode:backdrop { + color: rgba(40, 40, 40, 0.6); +} + +headerbar.selection-mode .subtitle:link { + color: rgba(40, 40, 40, 0.87); +} + +headerbar.selection-mode .selection-menu { + padding-left: 16px; + padding-right: 16px; +} + +headerbar.selection-mode .selection-menu .arrow { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +headerbar.default-decoration { + min-height: 34px; + padding: 0; + margin: 0; + border: none; + outline: none; +} + +headerbar.default-decoration windowcontrols > button { + min-width: 16px; + min-height: 16px; + margin: 0 4px; + padding: 0; + /* @if $window_button == 'mac' { */ + /* min-width: 16px; */ + /* min-height: 16px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } @else { */ + /* min-width: 22px; */ + /* min-height: 22px; */ + /* margin: 0 $space-size - 2px; */ + /* padding: 0; */ + /* } */ +} + +headerbar.default-decoration windowcontrols menubutton button { + min-height: 20px; + min-width: 20px; + margin: 0; + padding: 4px; +} + +.maximized headerbar, .fullscreen headerbar, .tiled headerbar, .tiled-top headerbar, .tiled-right headerbar, .tiled-bottom headerbar, .tiled-left headerbar { + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.maximized headerbar.default-decoration, .fullscreen headerbar.default-decoration, .tiled headerbar.default-decoration, .tiled-top headerbar.default-decoration, .tiled-right headerbar.default-decoration, .tiled-bottom headerbar.default-decoration, .tiled-left headerbar.default-decoration { + box-shadow: none; +} + +.solid-csd headerbar:dir(rtl), .solid-csd headerbar:dir(ltr) { + border-radius: 0; + box-shadow: inset 0 -1px rgba(251, 241, 199, 0.12); +} + +.titlebar:not(headerbar) { + box-shadow: none; +} + +window.devel headerbar { + background: #282828 cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, linear-gradient(to right, transparent 65%, rgba(125, 174, 163, 0.1)), linear-gradient(to top, #303030 3px, #353535); +} + +window.devel headerbar:backdrop { + background: #282828 cross-fade(10% -gtk-icontheme("system-run-symbolic"), image(transparent)) 90% 0/256px 256px no-repeat, image(#282828); + /* background-color would flash */ +} + +/************ + * Pathbars * + ************/ +.pathbar { + background-color: alpha(currentColor, 0.08); + border-radius: 12px; + padding: 0; +} + +.pathbar button { + margin: 0; +} + +headerbar .pathbar button { + margin: 0; +} + +/************** + * Tree Views * + **************/ +columnview.view, +treeview.view { + border-left-color: #423f3e; + border-top-color: #423f3e; +} + +columnview.view:hover, columnview.view:selected, +treeview.view:hover, +treeview.view:selected { + border-radius: 0; +} + +columnview.view:focus, +treeview.view:focus { + box-shadow: none; + outline: none; +} + +columnview.view.separator, +treeview.view.separator { + min-height: 5px; + color: rgba(251, 241, 199, 0.12); +} + +columnview.view:drop(active), +treeview.view:drop(active) { + box-shadow: none; +} + +columnview.view:drop(active).after, +treeview.view:drop(active).after { + border-top-style: none; +} + +columnview.view:drop(active).before, +treeview.view:drop(active).before { + border-bottom-style: none; +} + +columnview.view > dndtarget:drop(active), +treeview.view > dndtarget:drop(active) { + border-style: solid none; + border-width: 1px; + border-color: alpha(currentColor, 0.06); +} + +columnview.view > dndtarget:drop(active).after, +treeview.view > dndtarget:drop(active).after { + border-top-style: none; +} + +columnview.view > dndtarget:drop(active).before, +treeview.view > dndtarget:drop(active).before { + border-bottom-style: none; +} + +columnview.view.expander, +treeview.view.expander { + min-width: 16px; + min-height: 16px; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); + color: rgba(251, 241, 199, 0.7); +} + +columnview.view.expander:dir(rtl), +treeview.view.expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +columnview.view.expander:hover, +treeview.view.expander:hover { + color: #fbf1c7; +} + +columnview.view.expander:selected, +treeview.view.expander:selected { + color: #fbf1c7; +} + +columnview.view.expander:selected:hover, +treeview.view.expander:selected:hover { + color: #fbf1c7; +} + +columnview.view.expander:checked, +treeview.view.expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +columnview.view.expander:disabled, +treeview.view.expander:disabled { + color: rgba(251, 241, 199, 0.32); +} + +columnview.view.progressbar, +treeview.view.progressbar { + border-bottom: 6px solid #7daea3; + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.progressbar:selected:hover, +treeview.view.progressbar:selected:hover { + box-shadow: none; +} + +columnview.view.trough, +treeview.view.trough { + border-bottom: 6px solid rgba(251, 241, 199, 0.12); + box-shadow: none; + background-color: transparent; + background-image: none; +} + +columnview.view.trough:selected:hover, +treeview.view.trough:selected:hover { + box-shadow: none; +} + +columnview.view > header > button, +treeview.view > header > button { + padding: 2px 6px; + border-style: none solid solid none; + border-width: 0 1px 0 0; + border-color: transparent; + border-radius: 0; + background-clip: border-box; +} + +columnview.view > header > button:not(:focus):not(:hover):not(:active), +treeview.view > header > button:not(:focus):not(:hover):not(:active) { + color: rgba(251, 241, 199, 0.7); +} + +columnview.view > header > button, columnview.view > header > button:disabled, +treeview.view > header > button, +treeview.view > header > button:disabled { + background-color: transparent; +} + +columnview.view > header > button:last-child, +treeview.view > header > button:last-child { + border-right-style: none; +} + +columnview.view button.dnd, +columnview.view header.button.dnd, +treeview.view button.dnd, +treeview.view header.button.dnd { + padding: 2px 6px; + border-style: none solid solid; + border-width: 1px; + border-color: rgba(251, 241, 199, 0.12); + border-radius: 0; + box-shadow: none; + background-color: #282524; + background-clip: border-box; + color: #7daea3; +} + +columnview.view acceleditor > label, +treeview.view acceleditor > label { + background-color: #7daea3; +} + +stack.view treeview.view { + min-height: 34px; +} + +/********* + * Menus * + *********/ +menubar { + padding: 0; + background-color: #282828; + color: #fbf1c7; +} + +menubar:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.7); +} + +.csd menubar { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); +} + +menubar > item { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 20px; + padding: 4px 8px; + color: rgba(251, 241, 199, 0.7); +} + +menubar > item:selected { + transition: none; + background-color: alpha(currentColor, 0.1); + color: #fbf1c7; +} + +menubar > item:disabled { + color: rgba(251, 241, 199, 0.32); +} + +menubar > item label:disabled { + color: inherit; +} + +menubar > item popover.menu popover.menu { + margin-left: 9px; +} + +menubar > item popover.menu.background popover.menu.background > contents { + margin: 0; + border-radius: 12px; +} + +/********************** + * Popover Base Menus * + **********************/ +popover.menu box.inline-buttons { + color: #fbf1c7; + padding: 0 6px; +} + +popover.menu box.inline-buttons button.image-button.model { + min-height: 28px; + min-width: 28px; + padding: 0; + border: none; + outline: none; + transition: none; +} + +popover.menu box.inline-buttons button.image-button.model:selected { + background: image(alpha(currentColor, 0.06)); +} + +popover.menu box.circular-buttons { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model { + padding: 6px; +} + +popover.menu box.circular-buttons button.circular.image-button.model:focus { + background-color: alpha(currentColor, 0.06); +} + +popover.menu arrow.left, +popover.menu radio.left, +popover.menu check.left { + margin-left: 0; + margin-right: 0; +} + +popover.menu arrow.right, +popover.menu radio.right, +popover.menu check.right { + margin-left: 0; + margin-right: 0; +} + +popover.menu label.title { + font-weight: bold; + padding: 4px 26px; +} + +/************ + * Popovers * + ************/ +popover.background { + font: initial; +} + +popover.background, popover.background:backdrop { + background-color: transparent; +} + +popover > arrow, +popover > contents { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + padding: 6px; + background-color: #141617; + border-radius: 12px; + color: #fbf1c7; + border: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +popover > arrow { + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +popover > contents > list, +popover > contents > .view, +popover > contents > toolbar { + border-style: none; + box-shadow: none; + background-color: transparent; +} + +popover > contents separator { + background-color: rgba(251, 241, 199, 0.12); + margin: 15px 10px; +} + +popover > contents list separator { + margin: 0; +} + +popover > contents list > row { + border-radius: 12px; +} + +popover > contents stack > box { + padding: 0; +} + +popover > contents > box > button { + margin: 0; +} + +popover .view:not(:selected), +popover toolbar { + background-color: #141617; +} + +popover button, +popover entry, +popover combobox { + border-radius: 12px; +} + +popover .linked > button:not(.radio) { + border-radius: 0; +} + +popover .linked > button:not(.radio):first-child { + border-radius: 12px 0 0 12px; +} + +popover .linked > button:not(.radio):last-child { + border-radius: 0 12px 12px 0; +} + +popover .linked > button:not(.radio):only-child { + border-radius: 12px; +} + +popover.menu button, +popover button.model { + min-height: 32px; + padding: 0 8px; +} + +popover modelbutton { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + min-height: 22px; + min-width: 56px; + padding: 3px 9px; + color: #fbf1c7; + font: initial; + border-radius: 12px; +} + +popover modelbutton:hover { + transition: none; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +popover modelbutton:hover accelerator { + color: #7daea3; +} + +popover modelbutton:hover accelerator:disabled { + color: rgba(251, 241, 199, 0.5); +} + +popover modelbutton:focus:not(:hover) { + transition: none; + box-shadow: none; + outline: none; +} + +popover modelbutton:disabled { + color: rgba(251, 241, 199, 0.5); +} + +popover modelbutton accelerator { + color: rgba(251, 241, 199, 0.5); + margin-left: 30px; +} + +popover modelbutton accelerator:disabled { + color: rgba(251, 241, 199, 0.12); +} + +popover modelbutton arrow.left { + -gtk-icon-source: -gtk-icontheme("go-previous-symbolic"); +} + +popover modelbutton arrow.right { + -gtk-icon-source: -gtk-icontheme("go-next-symbolic"); +} + +.osd popover, popover.touch-selection, popover.magnifier { + background-color: transparent; +} + +magnifier { + background-color: #282524; +} + +/************* + * Notebooks * + *************/ +notebook > header > tabs > tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); +} + +notebook > header > tabs > tab:hover:not(:checked):not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +notebook > header > tabs > tab:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; +} + +notebook > header > tabs > tab:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; + background-color: #282524; + color: #fbf1c7; + box-shadow: none; +} + +notebook > header > tabs > tab:checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +notebook > header > tabs > tab:checked:disabled { + color: rgba(251, 241, 199, 0.5); +} + +frame > paned > notebook > header, notebook.frame > header { + background-color: rgba(251, 241, 199, 0.04); +} + +notebook, notebook.frame { + background-color: #282524; + background-color: rgba(251, 241, 199, 0.04); + border-radius: 15px; +} + +notebook.frame frame > border { + border: none; + border-radius: 9px; +} + +notebook.frame frame > list row.activatable { + border-radius: 12px; +} + +notebook > header { + border: none; + background-color: rgba(251, 241, 199, 0.04); + margin: 3px; + border-radius: 12px; +} + +notebook > header.top > tabs > arrow { + border-top-style: none; +} + +notebook > header.bottom > tabs > arrow { + border-bottom-style: none; +} + +notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow { + padding-left: 4px; + padding-right: 4px; +} + +notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down { + margin-left: 0; + -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); +} + +notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up { + margin-right: 0; + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +notebook > header.left > tabs > arrow { + border-left-style: none; +} + +notebook > header.right > tabs > arrow { + border-right-style: none; +} + +notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow { + padding-top: 4px; + padding-bottom: 4px; +} + +notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down { + margin-top: 0; + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up { + margin-bottom: 0; + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +notebook > header > tabs > arrow { + min-height: 16px; + min-width: 16px; + border-radius: 12px; +} + +notebook > header > tabs > tab { + margin: 3px; +} + +notebook > header > tabs > tab > box { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + margin: -6px -12px; + padding: 6px 12px; +} + +notebook > header > tabs > tab > box:drop(active) { + background-color: rgba(251, 241, 199, 0.12); + color: #fbf1c7; +} + +notebook > header > tabs > tab button.flat:last-child { + margin-left: 6px; + margin-right: -3px; +} + +notebook > header > tabs > tab button.flat:first-child { + margin-left: -3px; + margin-right: 6px; +} + +notebook > header > tabs > tab button.close-button { + min-width: 24px; + min-height: 24px; +} + +notebook > header.top > tabs, notebook > header.bottom > tabs { + padding-left: 0; + padding-right: 0; +} + +notebook > header.top > tabs:not(:only-child):first-child, notebook > header.bottom > tabs:not(:only-child):first-child { + margin-left: 0; +} + +notebook > header.top > tabs:not(:only-child):last-child, notebook > header.bottom > tabs:not(:only-child):last-child { + margin-right: 0; +} + +notebook > header.top > tabs > tab:not(:last-child), notebook > header.bottom > tabs > tab:not(:last-child) { + margin-right: 0; +} + +notebook > header.top > tabs tab.reorderable-page, notebook > header.bottom > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header.left > tabs, notebook > header.right > tabs { + padding-top: 0; + padding-bottom: 0; +} + +notebook > header.left > tabs:not(:only-child):first-child, notebook > header.right > tabs:not(:only-child):first-child { + margin-top: 0; +} + +notebook > header.left > tabs:not(:only-child):last-child, notebook > header.right > tabs:not(:only-child):last-child { + margin-bottom: 0; +} + +notebook > header.left > tabs > tab:not(:last-child), notebook > header.right > tabs > tab:not(:last-child) { + margin-bottom: 0; +} + +notebook > header.left > tabs tab.reorderable-page, notebook > header.right > tabs tab.reorderable-page { + border-style: solid; +} + +notebook > header > menubutton > button.image-button { + padding: 3px; + min-width: 24px; + min-height: 24px; + margin: 0 3px; +} + +notebook > stack:not(:only-child) { + background-color: transparent; + border-radius: 12px; +} + +tabbar tab { + min-height: 24px; + min-width: 24px; + padding: 3px 6px; + border: none; + background-clip: padding-box; + font-weight: 500; + border-radius: 9px; + background-color: transparent; + color: rgba(251, 241, 199, 0.7); + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + color: rgba(251, 241, 199, 0.7); +} + +tabbar tab:hover:not(:selected) { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + box-shadow: none; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; +} + +tabbar tab:disabled { + color: rgba(251, 241, 199, 0.32); + background-color: transparent; + color: rgba(251, 241, 199, 0.32); +} + +tabbar tab:active { + background-color: alpha(currentColor, 0.12); + color: #fbf1c7; + box-shadow: none; + color: #fbf1c7; +} + +tabbar tab:selected:not(:active) { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: rgba(251, 241, 199, 0.04); + color: #7daea3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +tabbar tab:selected:not(:active):disabled { + color: rgba(251, 241, 199, 0.5); +} + +tabbar > revealer > box { + box-shadow: none; +} + +tabbar .box { + background-color: #282828; + background-image: none; + padding: 0; + margin: 0; + border-radius: 0; + min-height: 34px; + border: none; + /* box-shadow: inset 0 -1px $border; */ +} + +tabbar .box:backdrop { + background-color: #282828; + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabbar .box:backdrop > scrolledwindow, +tabbar .box:backdrop > .start-action, +tabbar .box:backdrop > .end-action { + filter: none; + transition: none; +} + +tabbar tabbox { + padding: 0; + margin: 0; + min-height: 34px; +} + +tabbar tabbox > background { + background: none; +} + +tabbar tabbox > separator { + margin: 9px 0; + transition: opacity 150ms ease-in-out; +} + +tabbar tabbox > separator.hidden { + opacity: 0; +} + +tabbar tabbox > tabboxchild { + padding: 0; + margin: 0; +} + +tabbar tab { + padding: 6px; + margin: 6px 2px; +} + +tabbar tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#7daea3, 0.4) 10%, alpha(#7daea3, 0) 30%); +} + +tabbar tab.needs-attention:hover { + background-image: image(alpha(currentColor, 0.03)), radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#7daea3, 0.4) 10%, alpha(#7daea3, 0) 30%); +} + +tabbar tabbox.single-tab tab, tabbar tabbox.single-tab tab:hover, tabbar tabbox.single-tab tab:active { + background: none; +} + +tabbar undershoot { + transition: background 150ms ease-in-out; +} + +tabbar undershoot.left { + background: linear-gradient(to right, #282524, rgba(0, 0, 0, 0) 20px); +} + +tabbar undershoot.right { + background: linear-gradient(to left, #282524, rgba(0, 0, 0, 0) 20px); +} + +tabbar .needs-attention-left undershoot.left { + background: linear-gradient(to right, alpha(#7daea3, 0.5), alpha(#7daea3, 0.3) 1px, alpha(#7daea3, 0) 20px); +} + +tabbar .needs-attention-right undershoot.right { + background: linear-gradient(to left, alpha(#7daea3, 0.5), alpha(#7daea3, 0.3) 1px, alpha(#7daea3, 0) 20px); +} + +tabbar .start-action, +tabbar .end-action { + padding: 6px 5px; +} + +tabbar .start-action:dir(ltr), +tabbar .end-action:dir(rtl) { + padding-right: 0; +} + +tabbar .start-action:dir(rtl), +tabbar .end-action:dir(ltr) { + padding-left: 0; +} + +tabbar.inline .box { + background-color: transparent; + color: inherit; + box-shadow: none; + padding-bottom: 0; +} + +tabbar.inline .box:backdrop { + background-color: transparent; + transition: none; +} + +tabbar.inline .box:backdrop > scrolledwindow, +tabbar.inline .box:backdrop > .start-action, +tabbar.inline .box:backdrop > .end-action { + filter: none; + transition: none; +} + +dnd tab { + min-height: 24px; + background-color: #282828; + color: #fbf1c7; + box-shadow: 0 1px 5px 1px rgba(0, 0, 0, 0.09), 0 2px 14px 3px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.05); + outline: 1px solid rgba(40, 40, 40, 0.75); + outline-offset: -1px; + margin: 24px; +} + +dnd tab.needs-attention { + background-image: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.8), alpha(#7daea3, 0.4) 10%, alpha(#7daea3, 0) 30%); +} + +tabbar tab, +dnd tab { + padding: 6px; +} + +tabbar tab button.image-button, +dnd tab button.image-button { + padding: 0; + margin: 0; + min-width: 24px; + min-height: 24px; + border-radius: 9999px; + color: rgba(251, 241, 199, 0.7); +} + +tabbar tab button.image-button:hover, tabbar tab button.image-button:active, +dnd tab button.image-button:hover, +dnd tab button.image-button:active { + color: #fbf1c7; +} + +tabbar tab button.image-button:disabled, +dnd tab button.image-button:disabled { + color: rgba(251, 241, 199, 0.32); +} + +tabbar tab indicator, +dnd tab indicator { + min-height: 2px; + border-radius: 2px; + background: alpha(#7daea3, 0.5); + transform: translateY(4px); +} + +tabthumbnail { + border-radius: 12px; + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); +} + +tabthumbnail > box { + margin: 6px; +} + +tabthumbnail:drop(active) { + box-shadow: inset 0 0 0 2px alpha(#e78a4e, 0.4); + background-color: alpha(#e78a4e, 0.1); +} + +tabthumbnail .needs-attention:dir(ltr) { + transform: translate(8px, -8px); +} + +tabthumbnail .needs-attention:dir(rtl) { + transform: translate(-8px, -8px); +} + +tabthumbnail .needs-attention > widget { + background: #7daea3; + min-width: 12px; + min-height: 12px; + border-radius: 9px; + margin: 3px; + box-shadow: 0 1px 2px alpha(#7daea3, 0.4); +} + +tabthumbnail .card { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +tabthumbnail .card picture { + outline: 1px solid rgba(251, 241, 199, 0.12); + outline-offset: -1px; + border-radius: 12px; +} + +tabthumbnail.pinned .card { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +tabthumbnail .icon-title-box { + border-spacing: 6px; +} + +tabthumbnail .tab-unpin-icon { + margin: 6px; + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular { + margin: 6px; + background-color: rgba(251, 241, 199, 0.04); + min-width: 24px; + min-height: 24px; +} + +tabthumbnail button.circular:hover { + background-color: alpha(currentColor, 0.08); +} + +tabthumbnail button.circular:active { + background-color: alpha(currentColor, 0.12); +} + +taboverview > .overview .new-tab-button { + margin: 18px; +} + +tabview:drop(active), +tabbox:drop(active), +tabgrid:drop(active) { + box-shadow: none; +} + +/************** + * Scrollbars * + **************/ +scrollbar { + background-color: transparent; + transition: 300ms cubic-bezier(0, 0, 0.2, 1); + outline: none; +} + +scrollbar, +scrollbar button { + border: none; +} + +scrollbar.vertical button.down { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +scrollbar.vertical button.up { + -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); +} + +scrollbar.horizontal button.down { + -gtk-icon-source: -gtk-icontheme("pan-right-symbolic"); +} + +scrollbar.horizontal button.up { + -gtk-icon-source: -gtk-icontheme("pan-left-symbolic"); +} + +scrollbar > range > trough { + background: none; + padding: 0; + margin: 0; + border: none; + outline: none; + transition: none; +} + +scrollbar > range > trough > slider { + min-width: 6px; + min-height: 6px; + margin: 0; + border: none; + border-radius: 9999px; + background-clip: padding-box; + box-shadow: none; + outline: none; + transition: all 200ms linear; + background-color: rgba(251, 241, 199, 0.5); +} + +scrollbar > range > trough > slider:hover { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar > range > trough > slider:active { + background-color: rgba(251, 241, 199, 0.7); +} + +scrollbar > range > trough > slider:disabled { + background-color: rgba(251, 241, 199, 0.32); +} + +scrollbar > range.fine-tune > trough > slider { + min-width: 4px; + min-height: 4px; +} + +scrollbar.overlay-indicator { + background: none; + color: inherit; + box-shadow: none; + padding: 0; +} + +scrollbar.overlay-indicator > range > trough { + outline: none; + background-color: rgba(251, 241, 199, 0.12); + border-radius: 9999px; + margin: 6px; +} + +scrollbar.overlay-indicator > range > trough > slider { + outline: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + opacity: 0.5; + border-color: transparent; + background-color: transparent; + box-shadow: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough { + background-color: transparent; + border: none; + margin: 6px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering) > range > trough > slider { + margin: 0; + min-width: 4px; + min-height: 4px; + border: none; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.overlay-indicator:not(.dragging):not(.hovering).vertical > range > trough > slider { + min-height: 40px; +} + +scrollbar.overlay-indicator.dragging, scrollbar.overlay-indicator.hovering { + opacity: 1; +} + +scrollbar.horizontal > range > trough > slider { + min-width: 40px; +} + +scrollbar.vertical > range > trough > slider { + min-height: 40px; +} + +/********** + * Switch * + **********/ +switch { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + margin: 6px 0; + padding: 0; + border: none; + border-radius: 9999px; + background-color: rgba(251, 241, 199, 0.5); + background-clip: border-box; + font-size: 0; + color: transparent; +} + +switch:checked { + background-color: #7daea3; +} + +switch:disabled { + opacity: 0.5; +} + +switch > slider { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 18px; + min-height: 18px; + margin: 3px; + border-radius: 9999px; + outline: none; + box-shadow: 0 0 0 0 transparent, 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); + background-color: #fbf1c7; + border: none; +} + +switch:focus slider, switch:hover slider, switch:focus:hover slider { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12), 0 3px 3px -2px transparent, 0 2px 3px -1px transparent, 0 1px 4px 0 transparent; +} + +/************************* + * Check and Radio items * + *************************/ +checkbutton, +radiobutton { + outline: none; + border-spacing: 3px; +} + +check, +radio { + min-height: 20px; + min-width: 20px; + margin: 3px; + padding: 0; + border-radius: 9999px; + border: none; + color: transparent; + background-color: rgba(251, 241, 199, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0, 0, 0.2, 1); +} + +check:hover, +radio:hover { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.04); + background-color: rgba(251, 241, 199, 0.15); +} + +check:active, +radio:active { + box-shadow: 0 0 0 6px rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.2); +} + +check:disabled, +radio:disabled { + background-color: rgba(251, 241, 199, 0.04); +} + +check:checked, check:indeterminate, +radio:checked, +radio:indeterminate { + color: rgba(40, 40, 40, 0.6); + background-color: #7daea3; +} + +check:checked:hover, check:indeterminate:hover, +radio:checked:hover, +radio:indeterminate:hover { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.15); + background-color: #9cc2b9; +} + +check:checked:active, check:indeterminate:active, +radio:checked:active, +radio:indeterminate:active { + box-shadow: 0 0 0 6px rgba(125, 174, 163, 0.2); + background-color: #7daea3; +} + +check:checked:disabled, check:indeterminate:disabled, +radio:checked:disabled, +radio:indeterminate:disabled { + color: rgba(40, 40, 40, 0.6); + background-color: rgba(125, 174, 163, 0.35); +} + +popover modelbutton.flat check, popover modelbutton.flat check:focus, popover modelbutton.flat check:hover, popover modelbutton.flat check:focus:hover, popover modelbutton.flat check:active, popover modelbutton.flat check:disabled, popover modelbutton.flat radio, popover modelbutton.flat radio:focus, popover modelbutton.flat radio:hover, popover modelbutton.flat radio:focus:hover, popover modelbutton.flat radio:active, popover modelbutton.flat radio:disabled { + transition: none; + box-shadow: none; + background-image: none; +} + +popover modelbutton.flat check.left:dir(rtl), popover modelbutton.flat radio.left:dir(rtl) { + margin-left: -3px; + margin-right: 6px; +} + +popover modelbutton.flat check.right:dir(ltr), popover modelbutton.flat radio.right:dir(ltr) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu radio { + transition: none; + margin: 0; + padding: 0; +} + +popover.menu check:dir(ltr), popover.menu radio:dir(ltr) { + margin-right: 6px; + margin-left: -3px; +} + +popover.menu check:dir(rtl), popover.menu radio:dir(rtl) { + margin-left: 6px; + margin-right: -3px; +} + +popover.menu check, popover.menu check:hover, popover.menu check:disabled, popover.menu check:checked:hover, popover.menu check:indeterminate:hover, popover.menu radio, popover.menu radio:hover, popover.menu radio:disabled, popover.menu radio:checked:hover, popover.menu radio:indeterminate:hover { + box-shadow: none; +} + + +check { + -gtk-icon-size: 20px; +} + + +check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); +} + + +check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/checkbox-mixed-symbolic@2.svg"))); +} + + +radio { + -gtk-icon-size: 20px; +} + + +radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-checked-symbolic.svg")), -gtk-recolor(url("assets/radio-checked-symbolic@2.svg"))); +} + + +radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/radio-mixed-symbolic@2.svg"))); +} + + +popover.menu check { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu check:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-checked-symbolic@2.svg"))); +} + + +popover.menu check:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-checkbox-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-checkbox-mixed-symbolic@2.svg"))); +} + + +popover.menu radio { + min-height: 16px; + min-width: 16px; + -gtk-icon-size: 16px; +} + + +popover.menu radio:checked { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-checked-symbolic.svg")), -gtk-recolor(url("assets/small-radio-checked-symbolic@2.svg"))); +} + + +popover.menu radio:indeterminate { + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/small-radio-mixed-symbolic.svg")), -gtk-recolor(url("assets/small-radio-mixed-symbolic@2.svg"))); +} + +check:not(:checked):active { + -gtk-icon-transform: rotate(90deg); +} + +treeview.view radio, +treeview.view check, +columnview.view radio, +columnview.view check { + padding: 0; + margin: 0; + transition: none; +} + +treeview.view radio, treeview.view radio:hover, treeview.view radio:disabled, treeview.view radio:checked:hover, treeview.view radio:indeterminate:hover, +treeview.view check, +treeview.view check:hover, +treeview.view check:disabled, +treeview.view check:checked:hover, +treeview.view check:indeterminate:hover, +columnview.view radio, +columnview.view radio:hover, +columnview.view radio:disabled, +columnview.view radio:checked:hover, +columnview.view radio:indeterminate:hover, +columnview.view check, +columnview.view check:hover, +columnview.view check:disabled, +columnview.view check:checked:hover, +columnview.view check:indeterminate:hover { + box-shadow: none; +} + +treeview.view:hover check, +treeview.view:hover radio, treeview.view:selected check, +treeview.view:selected radio, treeview.view:focus check, +treeview.view:focus radio, +columnview.view:hover check, +columnview.view:hover radio, +columnview.view:selected check, +columnview.view:selected radio, +columnview.view:focus check, +columnview.view:focus radio { + box-shadow: none; +} + +treeview.view:hover check:checked, +treeview.view:hover radio:checked, treeview.view:selected check:checked, +treeview.view:selected radio:checked, treeview.view:focus check:checked, +treeview.view:focus radio:checked, +columnview.view:hover check:checked, +columnview.view:hover radio:checked, +columnview.view:selected check:checked, +columnview.view:selected radio:checked, +columnview.view:focus check:checked, +columnview.view:focus radio:checked { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +checkbutton.selection-mode { + border-radius: 9999px; +} + +checkbutton.selection-mode check, +checkbutton.selection-mode radio { + padding: 6px; + border-radius: 9999px; +} + +checkbutton.selection-mode check:checked, checkbutton.selection-mode check:indeterminate, +checkbutton.selection-mode radio:checked, +checkbutton.selection-mode radio:indeterminate { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +checkbutton.selection-mode label:dir(ltr) { + margin-right: 6px; +} + +checkbutton.selection-mode label:dir(rtl) { + margin-left: 6px; +} + +/************ + * GtkScale * + ************/ +scale { + min-height: 2px; + min-width: 2px; +} + +scale.horizontal { + padding: 16px 12px; +} + +scale.vertical { + padding: 12px 16px; +} + +scale > trough { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + outline: none; + background-color: rgba(251, 241, 199, 0.3); +} + +scale > trough:disabled { + background-color: rgba(251, 241, 199, 0.12); +} + +scale > trough > highlight { + transition: background-image 75ms cubic-bezier(0, 0, 0.2, 1); + background-image: image(#7daea3); +} + +scale > trough > highlight:disabled { + background-color: #282828; + background-image: image(rgba(251, 241, 199, 0.32)); +} + +scale > trough > fill { + transition: background-color 75ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.3); +} + +scale > trough > fill:disabled { + background-color: transparent; +} + +scale > trough > slider { + min-height: 18px; + min-width: 18px; + margin: -8px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 9999px; + color: #7daea3; + background-color: #282524; + box-shadow: inset 0 0 0 2px #7daea3; +} + +scale > trough > slider:hover { + box-shadow: inset 0 0 0 2px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale > trough > slider:active { + box-shadow: inset 0 0 0 4px #7daea3, 0 0 0 8px rgba(251, 241, 199, 0.12); +} + +scale > trough > slider:disabled { + box-shadow: inset 0 0 0 2px rgba(251, 241, 199, 0.32); +} + +scale.fine-tune.horizontal { + min-height: 4px; + padding-top: 15px; + padding-bottom: 15px; +} + +scale.fine-tune.vertical { + min-width: 4px; + padding-left: 15px; + padding-right: 15px; +} + +scale.fine-tune > trough > slider { + margin: -7px; +} + +scale > marks, +scale > value { + color: rgba(251, 241, 199, 0.7); +} + +scale indicator { + background-color: rgba(251, 241, 199, 0.3); + color: transparent; +} + +scale.marks-before:not(.marks-after) > trough > slider, scale.marks-after:not(.marks-before) > trough > slider { + transform: rotate(45deg); + border-bottom-right-radius: 0; +} + +scale.horizontal indicator { + min-height: 8px; + min-width: 1px; +} + +scale.vertical indicator { + min-height: 1px; + min-width: 8px; +} + +scale.color { + min-height: 0; + min-width: 0; +} + +scale.color.horizontal { + padding: 0 0 12px 0; +} + +scale.color.horizontal > trough > slider:dir(ltr), scale.color.horizontal > trough > slider:dir(rtl) { + margin-bottom: -13.5px; + margin-top: 11.5px; +} + +scale.color.vertical:dir(ltr) { + padding: 0 0 0 12px; +} + +scale.color.vertical:dir(ltr) slider { + margin-left: -13.5px; + margin-right: 11.5px; +} + +scale.color.vertical:dir(rtl) { + padding: 0 12px 0 0; +} + +scale.color.vertical:dir(rtl) > trough > slider { + margin-right: -13.5px; + margin-left: 11.5px; +} + +/***************** + * Progress bars * + *****************/ +progressbar { + color: rgba(251, 241, 199, 0.7); + font-size: smaller; +} + +progressbar.horizontal trough, +progressbar.horizontal progress { + min-height: 6px; +} + +progressbar.vertical trough, +progressbar.vertical progress { + min-width: 6px; +} + +progressbar trough { + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.12); +} + +progressbar progress { + border-radius: 12px; + background-color: #7daea3; +} + +progressbar.osd { + min-width: 6px; + min-height: 6px; + background-color: transparent; + box-shadow: none; + margin: 0; + padding: 0; +} + +progressbar.osd trough { + background-color: transparent; +} + +progressbar.osd progress { + background-color: #7daea3; +} + +progressbar trough.empty progress { + all: unset; +} + +/************* + * Level Bar * + *************/ +levelbar.horizontal block { + min-height: 6px; +} + +levelbar.horizontal.discrete block { + min-width: 34px; +} + +levelbar.horizontal.discrete block:not(:last-child) { + margin-right: 2px; +} + +levelbar.vertical block { + min-width: 6px; +} + +levelbar.vertical.discrete block { + min-height: 34px; +} + +levelbar.vertical.discrete block:not(:last-child) { + margin-bottom: 2px; +} + +levelbar trough { + border-radius: 12px; +} + +levelbar block.low { + background-color: #b47109; +} + +levelbar block.high, levelbar block:not(.empty) { + background-color: #7daea3; +} + +levelbar block.full { + background-color: #6c782e; +} + +levelbar block.empty { + background-color: rgba(251, 241, 199, 0.12); +} + +/**************** + * Print dialog * +*****************/ +window.dialog.print drawing { + color: #fbf1c7; + background: none; + border: none; + padding: 0; +} + +window.dialog.print drawing paper { + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: #282524; + color: #fbf1c7; +} + +window.dialog.print .dialog-action-box { + margin: 12px; +} + +/********** + * Frames * + **********/ +frame, +.frame { + border: 1px solid rgba(251, 241, 199, 0.12); +} + +frame > list, +.frame > list { + border: none; +} + +frame.view, +.frame.view { + border-radius: 12px; +} + +frame.flat, +.frame.flat { + border-style: none; +} + +frame { + border-radius: 12px; +} + +frame > label { + margin: 4px; +} + +frame.flat > border, statusbar frame > border { + border: none; +} + +actionbar { + box-shadow: none; +} + +actionbar > revealer > box { + padding: 6px; + border-spacing: 6px; + box-shadow: none; + /* background-color: $base; */ + background-color: rgba(251, 241, 199, 0.04); + background-clip: border-box; + border: none; + color: #fbf1c7; +} + +actionbar > revealer > box button, +actionbar > revealer > box entry, +actionbar > revealer > box menubutton, +actionbar > revealer > box menubutton > button, +actionbar > revealer > box splitbutton, +actionbar > revealer > box splitbutton > button, +actionbar > revealer > box spinbutton { + margin: 0; +} + +statusbar { + padding: 6px 18px; +} + +scrolledwindow viewport.frame { + border: none; +} + +stack scrolledwindow.frame viewport.frame list { + border: none; +} + +scrolledwindow > overshoot.top { + background-image: radial-gradient(farthest-side at top, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at top, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: top; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.bottom { + background-image: radial-gradient(farthest-side at bottom, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at bottom, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 100% 3%, 100% 50%; + background-repeat: no-repeat; + background-position: bottom; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.left { + background-image: radial-gradient(farthest-side at left, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at left, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: left; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow > overshoot.right { + background-image: radial-gradient(farthest-side at right, alpha(currentColor, 0.12) 85%, alpha(currentColor, 0)), radial-gradient(farthest-side at right, alpha(currentColor, 0.05), alpha(currentColor, 0)); + background-size: 3% 100%, 50% 100%; + background-repeat: no-repeat; + background-position: right; + background-color: transparent; + border: none; + box-shadow: none; +} + +scrolledwindow.undershoot-top > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 0px 0px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 0px 0px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 0px 0 0 0px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +scrolledwindow > undershoot { + background-image: none; + box-shadow: none; + border: none; +} + +separator { + min-width: 1px; + min-height: 1px; + background-color: transparent; +} + +stacksidebar + separator.vertical, +stacksidebar separator.horizontal, button.font separator, button.file separator, separator.spacer, separator.sidebar { + min-width: 0; + min-height: 0; + background-color: transparent; + background-image: none; +} + +/********* + * Lists * + *********/ +list.content, +list.boxed-list { + border-radius: 13px; + box-shadow: none; + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); +} + +listview, +list { + border-color: rgba(251, 241, 199, 0.12); + background-color: rgba(251, 241, 199, 0.04); + background-clip: padding-box; +} + +listview > row, +list > row { + padding: 6px; + background-clip: padding-box; +} + +listview > row.expander, +list > row.expander { + padding: 0px; +} + +listview > row.expander .row-header, +list > row.expander .row-header { + padding: 2px; +} + +listview.horizontal row.separator:not(:last-child), listview.separators.horizontal > row:not(.separator):not(:last-child), +list.horizontal row.separator:not(:last-child), +list.separators.horizontal > row:not(.separator):not(:last-child) { + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +listview:not(.horizontal) row.separator:not(:last-child), listview.separators:not(.horizontal) > row:not(.separator):not(:last-child), +list:not(.horizontal) row.separator:not(:last-child), +list.separators:not(.horizontal) > row:not(.separator):not(:last-child) { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +list.frame { + border-radius: 12px; +} + +listview.view { + color: #fbf1c7; + background-color: transparent; +} + +popover.menu listview.view { + padding: 0; + border-radius: 12px; +} + +popover.menu listview.view > row { + margin-left: 0; + margin-right: 0; + border-radius: 12px; +} + +row { + color: rgba(251, 241, 199, 0.7); + background-clip: padding-box; +} + +.nautilus-window .nautilus-grid-view child.activatable, +.nautilus-window .nautilus-list-view child.activatable, columnview.view > header > button, +treeview.view > header > button, row.activatable { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), font-weight 0; + outline: none; + box-shadow: none; + background-color: transparent; + background-image: radial-gradient(circle, transparent 10%, transparent 0%); + background-repeat: no-repeat; + background-position: center; + background-size: 1000% 1000%; +} + +.nautilus-window .nautilus-grid-view child.activatable:focus, +.nautilus-window .nautilus-list-view child.activatable:focus, columnview.view > header > button:focus, +treeview.view > header > button:focus, row.activatable:focus { + color: #fbf1c7; + background-color: transparent; + box-shadow: none; + outline: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:hover, +.nautilus-window .nautilus-list-view child.activatable:hover, columnview.view > header > button:hover, +treeview.view > header > button:hover, .nautilus-window .nautilus-grid-view child.has-open-popup.activatable, +.nautilus-window .nautilus-list-view child.has-open-popup.activatable, columnview.view > header > button.has-open-popup, +treeview.view > header > button.has-open-popup, row.activatable:hover, row.activatable.has-open-popup { + color: #fbf1c7; + background-color: alpha(currentColor, 0.05); + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:active, +.nautilus-window .nautilus-list-view child.activatable:active, columnview.view > header > button:active, +treeview.view > header > button:active, row.activatable:active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, font-weight 0ms; + animation: ripple 225ms cubic-bezier(0, 0, 0.2, 1) forwards; + background-image: radial-gradient(circle, alpha(currentColor, 0.05) 10%, transparent 0%); + background-size: 0% 0%; + background-color: alpha(currentColor, 0.05); + color: #fbf1c7; + box-shadow: none; +} + +.nautilus-window .nautilus-grid-view child.activatable:selected, +.nautilus-window .nautilus-list-view child.activatable:selected, columnview.view > header > button:selected, +treeview.view > header > button:selected, row.activatable:selected { + background-color: alpha(currentColor, 0.06); +} + +.nautilus-window .nautilus-grid-view child.activatable:selected:hover, +.nautilus-window .nautilus-list-view child.activatable:selected:hover, columnview.view > header > button:selected:hover, +treeview.view > header > button:selected:hover, row.activatable:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +button row.activatable:focus, button row.activatable:hover, button row.activatable:active { + box-shadow: none; + background: none; +} + +button:checked row.activatable { + color: rgba(40, 40, 40, 0.87); +} + +row:selected { + background-color: alpha(currentColor, 0.06); + color: #fbf1c7; + box-shadow: none; +} + +row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus, row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +row:selected:focus:hover, row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +row:selected button image, +row:selected button label { + color: inherit; +} + +row:selected:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.rich-list { + /* rich lists usually containing other widgets than just labels/text */ +} + +.rich-list > row { + padding: 9px 12px; + min-height: 32px; + /* should be tall even when only containing a label */ +} + +.rich-list > row:last-child { + border-bottom: none; +} + +.rich-list > row > box { + border-spacing: 12px; +} + +row label.subtitle { + font-size: smaller; +} + +row > box.header { + margin-left: 12px; + margin-right: 12px; + border-spacing: 6px; + min-height: 50px; +} + +row > box.header > .icon:disabled { + filter: opacity(0.45); +} + +row > box.header > box.title { + margin-top: 6px; + margin-bottom: 6px; + border-spacing: 3px; + padding: 0; +} + +row > box.header > box.title, +row > box.header > box.title > .title, +row > box.header > box.title > .subtitle { + padding: 0; + font-weight: inherit; +} + +row > box.header > .prefixes, +row > box.header > .suffixes { + border-spacing: 6px; +} + +row > box.header > .icon:dir(ltr), +row > box.header > .prefixes:dir(ltr) { + margin-right: 6px; +} + +row > box.header > .icon:dir(rtl), +row > box.header > .prefixes:dir(rtl) { + margin-left: 6px; +} + +row.property > box.header > box.title > .subtitle { + font-size: inherit; + opacity: 1; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry:disabled text { + opacity: 0.45; +} + +row.entry:disabled .dim-label, row.entry:disabled row.expander image.expander-row-arrow, row.expander row.entry:disabled image.expander-row-arrow, row.entry:disabled row.property > box.header > box.title > .title, +row.entry:disabled .subtitle { + opacity: 1; +} + +row.entry .edit-icon, +row.entry .indicator { + min-width: 24px; + min-height: 24px; + padding: 5px; +} + +row.entry .edit-icon:disabled { + opacity: 0.5; +} + +row.entry .indicator { + opacity: 0.65; +} + +row.entry.monospace { + font-family: inherit; +} + +row.entry.monospace text { + font-family: monospace; +} + +row.spin:not(:selected).activatable.focused:hover, row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.spin spinbutton { + background: none; + border-spacing: 6px; + box-shadow: none; +} + +row.spin spinbutton, row.spin spinbutton:focus { + outline: none; +} + +row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child, row.spin spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque), +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child, +row.spin spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child { + min-width: 30px; + min-height: 30px; + margin: 10px 2px; + border: none; +} + +row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(ltr):last-child:disabled, row.spin:disabled spinbutton > button.image-button.up:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):last-child:dir(rtl):first-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(ltr):last-child:disabled, +row.spin:disabled spinbutton > button.image-button.down:not(.flat):not(.raised):not( +.suggested-action +):not(.destructive-action):not(.opaque):dir(rtl):first-child:disabled { + filter: none; +} + +row.entry:not(:selected).activatable.focused:hover, row.entry:not(:selected).activatable.focused:active, +row.spin:not(:selected).activatable.focused:hover, +row.spin:not(:selected).activatable.focused:active { + background-color: transparent; +} + +row.entry.error text > selection:focus-within, +row.spin.error text > selection:focus-within { + background-color: alpha(#c14a4a, 0.2); +} + +row.entry.error text > cursor-handle > contents, +row.spin.error text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.error .dim-label, row.entry.error row.expander image.expander-row-arrow, row.expander row.entry.error image.expander-row-arrow, row.entry.error row.property > box.header > box.title > .title, +row.entry.error .subtitle, +row.spin.error .dim-label, +row.spin.error row.expander image.expander-row-arrow, +row.expander row.spin.error image.expander-row-arrow, +row.spin.error row.property > box.header > box.title > .title, +row.spin.error .subtitle { + opacity: 1; +} + +row.entry.error .suggested-action, +row.spin.error .suggested-action { + background-color: #c14a4a; + color: #fbf1c7; +} + +row.entry.warning text > selection:focus-within, +row.spin.warning text > selection:focus-within { + background-color: alpha(#b47109, 0.2); +} + +row.entry.warning text > cursor-handle > contents, +row.spin.warning text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.warning .dim-label, row.entry.warning row.expander image.expander-row-arrow, row.expander row.entry.warning image.expander-row-arrow, row.entry.warning row.property > box.header > box.title > .title, +row.entry.warning .subtitle, +row.spin.warning .dim-label, +row.spin.warning row.expander image.expander-row-arrow, +row.expander row.spin.warning image.expander-row-arrow, +row.spin.warning row.property > box.header > box.title > .title, +row.spin.warning .subtitle { + opacity: 1; +} + +row.entry.warning .suggested-action, +row.spin.warning .suggested-action { + background-color: #b47109; + color: #fbf1c7; +} + +row.entry.success text > selection:focus-within, +row.spin.success text > selection:focus-within { + background-color: alpha(#6c782e, 0.2); +} + +row.entry.success text > cursor-handle > contents, +row.spin.success text > cursor-handle > contents { + background-color: currentColor; +} + +row.entry.success .dim-label, row.entry.success row.expander image.expander-row-arrow, row.expander row.entry.success image.expander-row-arrow, row.entry.success row.property > box.header > box.title > .title, +row.entry.success .subtitle, +row.spin.success .dim-label, +row.spin.success row.expander image.expander-row-arrow, +row.expander row.spin.success image.expander-row-arrow, +row.spin.success row.property > box.header > box.title > .title, +row.spin.success .subtitle { + opacity: 1; +} + +row.entry.success .suggested-action, +row.spin.success .suggested-action { + background-color: #6c782e; + color: #fbf1c7; +} + +row.combo image.dropdown-arrow:disabled { + filter: opacity(0.45); +} + +row.combo listview.inline { + background: none; + border: none; + box-shadow: none; + color: inherit; +} + +row.combo listview.inline, row.combo listview.inline:disabled { + background: none; + color: inherit; +} + +row.combo popover > contents { + min-width: 120px; +} + +row.combo popover > contents .combo-searchbar { + margin: 6px; +} + +row.combo popover > contents .combo-searchbar + scrolledwindow > undershoot.top { + border-radius: 0px 0px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(251, 241, 199, 0.12), 0.75), transparent 4px); +} + +list.content > row, list.content > row.expander row.header, +list.boxed-list > row, +list.boxed-list > row.expander row.header, row.expander list.nested > row { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +list.content > row:not(:selected).activatable:hover, list.content > row.expander row.header:not(:selected).activatable:hover, +list.boxed-list > row:not(:selected).activatable:hover, +list.boxed-list > row.expander row.header:not(:selected).activatable:hover, row.expander list.nested > row:not(:selected).activatable:hover { + background-color: alpha(currentColor, 0.08); +} + +list.content > row:not(:selected).activatable:active, list.content > row.expander row.header:not(:selected).activatable:active, +list.boxed-list > row:not(:selected).activatable:active, +list.boxed-list > row.expander row.header:not(:selected).activatable:active, row.expander list.nested > row:not(:selected).activatable:active { + background-color: alpha(currentColor, 0.12); +} + +list.content > row:not(:selected).activatable.has-open-popup, list.content > row.expander row.header:not(:selected).activatable.has-open-popup, +list.boxed-list > row:not(:selected).activatable.has-open-popup, +list.boxed-list > row.expander row.header:not(:selected).activatable.has-open-popup, row.expander list.nested > row:not(:selected).activatable.has-open-popup { + background-color: alpha(currentColor, 0.03); +} + +row.expander { + background: none; + padding: 0px; +} + +row.expander > box > list { + background: none; + color: inherit; +} + +row.expander list.nested { + color: inherit; +} + +row.expander image.expander-row-arrow { + transition: -gtk-icon-transform 200ms cubic-bezier(0, 0, 0.2, 1); +} + +row.expander image.expander-row-arrow:dir(ltr) { + margin-left: 6px; +} + +row.expander image.expander-row-arrow:dir(rtl) { + margin-right: 6px; +} + +row.expander image.expander-row-arrow:dir(ltr) { + -gtk-icon-transform: rotate(0.5turn); +} + +row.expander image.expander-row-arrow:dir(rtl) { + -gtk-icon-transform: rotate(-0.5turn); +} + +row.expander image.expander-row-arrow:disabled { + filter: opacity(0.45); +} + +row.expander:checked image.expander-row-arrow { + -gtk-icon-transform: rotate(0turn); + opacity: 1; +} + +row.expander:checked image.expander-row-arrow:not(:disabled) { + color: #7daea3; +} + +.osd row.expander:checked image.expander-row-arrow:not(:disabled) { + color: inherit; +} + +list.content > row.expander, +list.boxed-list > row.expander { + border: none; +} + +list.content > row:first-child, list.content > row:first-child.expander row.header, +list.boxed-list > row:first-child, +list.boxed-list > row:first-child.expander row.header { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +list.content > row:last-child, list.content > row:last-child.expander:not(:checked), list.content > row:last-child.expander:not(:checked) row.header, list.content > row:last-child.expander:checked list.nested, list.content > row:last-child.expander:checked list.nested > row:last-child, +list.boxed-list > row:last-child, +list.boxed-list > row:last-child.expander:not(:checked), +list.boxed-list > row:last-child.expander:not(:checked) row.header, +list.boxed-list > row:last-child.expander:checked list.nested, +list.boxed-list > row:last-child.expander:checked list.nested > row:last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; + border-bottom-width: 0; +} + +columnview > listview > row { + padding: 0; +} + +columnview > listview > row > cell { + padding: 8px 6px; +} + +columnview > listview > row > cell:not(:first-child) { + border-left: 1px solid transparent; +} + +columnview.column-separators > listview > row > cell { + border-left-color: rgba(251, 241, 199, 0.12); +} + +columnview.data-table > listview > row > cell { + padding-top: 2px; + padding-bottom: 2px; +} + +treeexpander { + border-spacing: 6px; +} + +columnview row:not(:selected) cell editablelabel:not(.editing):focus-within { + outline: 2px solid alpha(currentColor, 0.06); +} + +columnview row:not(:selected) cell editablelabel.editing:focus-within { + outline: 2px solid #7daea3; +} + +columnview row:not(:selected) cell editablelabel.editing text selection { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +/********************* + * App Notifications * + *********************/ +.app-notification { + margin: 6px; + border-spacing: 0; + padding: 0; + border: none; + background-image: none; +} + +.app-notification button.text-button:not(:disabled) { + color: #7daea3; +} + +.app-notification > box > label { + margin-left: 9px; +} + +.app-notification.frame, +.app-notification border { + border: none; +} + +/************* + * Expanders * + *************/ +expander { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + min-width: 16px; + min-height: 16px; + color: rgba(251, 241, 199, 0.7); + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); +} + +expander:dir(rtl) { + -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); +} + +expander:hover, expander:active { + color: #fbf1c7; +} + +expander:checked { + -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); +} + +expander:disabled { + color: rgba(251, 241, 199, 0.32); +} + +expander-widget > box > title { + border-radius: 12px; +} + +expander-widget > box > title:hover > expander { + color: rgba(251, 241, 199, 0.7); +} + +.navigation-sidebar:not(decoration):not(window):drop(active):focus, .navigation-sidebar:not(decoration):not(window):drop(active), +placessidebar:not(decoration):not(window):drop(active):focus, +placessidebar:not(decoration):not(window):drop(active), +stackswitcher:not(decoration):not(window):drop(active):focus, +stackswitcher:not(decoration):not(window):drop(active), +expander-widget:not(decoration):not(window):drop(active):focus, +expander-widget:not(decoration):not(window):drop(active) { + box-shadow: none; +} + +/************ + * Calendar * + ************/ +calendar { + padding: 0; + border: 1px solid rgba(251, 241, 199, 0.12); + border-radius: 12px; + color: #fbf1c7; +} + +calendar:disabled { + color: rgba(251, 241, 199, 0.5); +} + +calendar:selected { + border-radius: 12px; +} + +calendar > header { + padding: 3px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +calendar > header > button { + min-height: 24px; +} + +calendar > grid { + margin: 3px; +} + +calendar > grid > label { + border-radius: 12px; + margin: 0; +} + +calendar > grid > label.today:selected { + box-shadow: none; +} + +calendar > grid > label:focus { + outline-style: none; +} + +calendar > grid > label.day-number { + padding: 6px; +} + +calendar > grid > label.day-number.other-month { + color: alpha(currentColor, 0.3); +} + +/*********** + * Dialogs * + ***********/ +window.messagedialog .response-area button, window.dialog.message .dialog-action-area > button { + border-radius: 9px; + min-height: 28px; + padding: 6px 12px; + margin: 0; + border: none; +} + +window.dialog.message.background { + background-color: #282828; +} + +window.dialog.message box.dialog-vbox.vertical { + margin-top: 6px; +} + +window.dialog.message box.dialog-vbox.vertical > box > box > box > label.title { + font-weight: 800; + font-size: 15pt; +} + +window.dialog.message .titlebar { + min-height: 24px; + border-style: none; + /* box-shadow: inset 0 1px highlight($surface); */ + background-color: #282828; + color: #fbf1c7; +} + +window.dialog.message .titlebar:backdrop { + background-color: #242220; + color: rgba(251, 241, 199, 0.7); +} + +window.dialog.message .dialog-action-area { + padding: 18px; + border-spacing: 18px; +} + +window.dialog.message .dialog-action-area > button { + background-color: rgba(251, 241, 199, 0.08); + border: 0 solid transparent; + outline: 0 solid transparent; +} + +window.dialog.message .dialog-action-area > button:not(:last-child):hover { + background-color: rgba(251, 241, 199, 0.1); +} + +window.dialog.message .dialog-action-area > button.suggested-action:not(:disabled) { + background-color: #365860; + color: #fbf1c7; +} + +window.dialog.message .dialog-action-area > button.destructive-action:not(:disabled) { + background-color: #a13737; + color: #fbf1c7; +} + +window.aboutdialog.background.csd scrolledwindow.frame, +window.aboutdialog.background.csd scrolledwindow.frame > viewport.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view, +window.aboutdialog.background.csd scrolledwindow.frame > textview.view > text { + border-radius: 12px; +} + +/******************** + * AdwMessageDialog * + ********************/ +window.messagedialog { + background-color: #242220; + color: #fbf1c7; + padding: 6px; +} + +window.messagedialog .message-area { + padding: 24px 30px; + border-spacing: 10px; +} + +window.messagedialog .response-area { + border-spacing: 6px; +} + +window.messagedialog .response-area button.suggested { + background-color: #365860; + color: #fbf1c7; + /* color: $primary; */ +} + +window.messagedialog .response-area button.destructive { + background-color: #a13737; + color: #fbf1c7; + /* color: $destructive; */ +} + +window.messagedialog .response-area separator { + background: none; + margin: 3px; +} + +/*********** + * Sidebar * + ***********/ +.sidebar { + border-style: none; + background-color: #282524; +} + +.sidebar listview.view, +.sidebar list { + background-color: transparent; + color: inherit; +} + +stacksidebar.sidebar:dir(ltr), stacksidebar.sidebar.left, stacksidebar.sidebar.left:dir(rtl) { + box-shadow: inset -1px 0 rgba(251, 241, 199, 0.12); +} + +stacksidebar.sidebar:dir(rtl), stacksidebar.sidebar.right, stacksidebar.sidebar.right:dir(ltr) { + box-shadow: inset 1px 0 rgba(251, 241, 199, 0.12); +} + +.sidebar-pane stacksidebar.sidebar, leaflet.unfolded > box > stacksidebar.sidebar { + box-shadow: none; +} + +stacksidebar list { + padding: 6px; + background-color: #282524; +} + +stacksidebar row { + min-height: 24px; + padding: 6px; + border-radius: 12px; +} + +stacksidebar row:selected { + font-weight: 500; +} + +stacksidebar row + row { + margin-top: 4px; +} + +stacksidebar row > label { + padding-left: 6px; + padding-right: 6px; + color: inherit; +} + +separator.sidebar { + background-color: rgba(251, 241, 199, 0.12); + border-right: none; +} + +separator.sidebar.selection-mode, .selection-mode separator.sidebar { + background-color: rgba(255, 255, 255, 0.12); +} + +/********************** + * Navigation Sidebar * + **********************/ +.navigation-sidebar { + padding: 2px 4px; + border-right: none; +} + +.navigation-sidebar, .navigation-sidebar.view, .navigation-sidebar.background { + background-color: transparent; + color: inherit; +} + +.navigation-sidebar > separator { + background-color: rgba(251, 241, 199, 0.12); + margin: 10px 15px; +} + +.navigation-sidebar row.activatable label.dim-label { + color: rgba(251, 241, 199, 0.32); +} + +.navigation-sidebar > row { + min-height: 24px; + /* padding: 0 $space-size 0 $space-size; */ + padding: 0 6px; + margin: 0; + border-radius: 9px; +} + +.navigation-sidebar > row:hover, .navigation-sidebar > row:focus-visible:focus-within { + background-color: alpha(currentColor, 0.08); + color: #7daea3; +} + +.navigation-sidebar > row:active { + background-color: alpha(currentColor, 0.12); +} + +.navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + box-shadow: none; +} + +.navigation-sidebar > row:selected label, +.navigation-sidebar > row:selected image { + color: #7daea3; + font-weight: 700; +} + +.navigation-sidebar > row:selected:hover { + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within { + outline: none; + background-color: alpha(currentColor, 0.08); +} + +.navigation-sidebar > row:selected:focus-visible:focus-within:hover { + background-color: alpha(currentColor, 0.16); +} + +.navigation-sidebar > row:disabled { + color: rgba(251, 241, 199, 0.5); +} + +.navigation-sidebar > row:not(:first-child) { + margin-top: 3px; +} + +/**************** + * File chooser * + ****************/ +filechooser paned > separator { + background: rgba(251, 241, 199, 0.12); +} + +filechooser paned > box #pathbarbox.view, +filechooser paned > box stack.view, +filechooser paned > box columnview.view, +filechooser paned > box gridview.view { + background-color: transparent; + color: #fbf1c7; +} + +filechooser .dialog-action-box { + border: none; +} + +filechooser #pathbarbox { + border: none; + background-color: transparent; +} + +filechooser stack.view frame > border { + border: none; +} + +filechooserbutton > button > box { + border-spacing: 6px; +} + +filechooserbutton:drop(active) { + box-shadow: none; + border-color: transparent; +} + +filechooser child.activatable filelistcell.dim-label { + color: rgba(251, 241, 199, 0.7); +} + +placessidebar { + background-color: transparent; +} + +placessidebar > viewport.frame { + border-style: none; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon { + color: inherit; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(ltr) { + padding-right: 8px; +} + +placessidebar list.navigation-sidebar > row image.sidebar-icon:dir(rtl) { + padding-left: 8px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label { + color: inherit; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(ltr) { + padding-right: 2px; +} + +placessidebar list.navigation-sidebar > row label.sidebar-label:dir(rtl) { + padding-left: 2px; +} + +placessidebar list.navigation-sidebar > row button.sidebar-button { + /* @extend %button-on-indicator; */ +} + +placessidebar list.navigation-sidebar > row.sidebar-placeholder-row { + background-color: alpha(currentColor, 0.08); +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row { + color: #7daea3; +} + +placessidebar list.navigation-sidebar > row.sidebar-new-bookmark-row image.sidebar-icon { + color: #7daea3; +} + +placessidebar list.navigation-sidebar > row:drop(active) { + background-color: alpha(currentColor, 0.08); +} + +placesview .server-list-button > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(0turn); +} + +placesview .server-list-button:checked > image { + transition: 200ms cubic-bezier(0, 0, 0.2, 1); + -gtk-icon-transform: rotate(-0.5turn); +} + +placesview > actionbar > revealer > box > label { + border-spacing: 6px; +} + +/********* + * Paned * + *********/ +paned > separator { + min-width: 1px; + min-height: 1px; + -gtk-icon-source: none; + border-style: none; + background-color: transparent; + background-image: image(#423f3e); + background-size: 1px 1px; + background-clip: content-box; + box-shadow: none; +} + +paned > separator.wide { + min-width: 6px; + min-height: 6px; + background-color: #282828; + background-image: image(#423f3e), image(#423f3e); + background-size: 1px 1px, 1px 1px; +} + +paned.horizontal > separator { + background-repeat: repeat-y; +} + +paned.horizontal > separator:dir(ltr) { + margin: 0 -8px 0 0; + padding: 0 8px 0 0; + background-position: left; +} + +paned.horizontal > separator:dir(rtl) { + margin: 0 0 0 -8px; + padding: 0 0 0 8px; + background-position: right; +} + +paned.horizontal > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-y, repeat-y; + background-position: left, right; +} + +paned.vertical > separator { + margin: 0 0 -8px 0; + padding: 0 0 8px 0; + background-repeat: repeat-x; + background-position: top; +} + +paned.vertical > separator.wide { + margin: 0; + padding: 0; + background-repeat: repeat-x, repeat-x; + background-position: bottom, top; +} + +/************ + * GtkVideo * + ************/ +video { + background: black; + border-radius: 12px; +} + +video image.osd { + min-width: 64px; + min-height: 64px; + border-radius: 9999px; + border: none; +} + +/************** + * GtkInfoBar * + **************/ +infobar > revealer > box { + padding: 6px; + border-spacing: 12px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + box-shadow: none; +} + +infobar.info > revealer > box, infobar.info:hover > revealer > box, infobar.info:backdrop > revealer > box { + background-color: #282524; + color: #fbf1c7; +} + +infobar.info > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:hover > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +), infobar.info:backdrop > revealer > box button.text-button:not(:disabled):not(.suggested-action):not( +.destructive-action +) { + color: #7daea3; +} + +infobar.action > revealer > box, infobar.action:backdrop > revealer > box, infobar.question > revealer > box, infobar.question:backdrop > revealer > box { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +infobar.action > revealer > box button, infobar.action > revealer > box button:hover, infobar.action > revealer > box button:focus, infobar.action > revealer > box button:active, infobar.action > revealer > box button:checked, infobar.action > revealer > box button.text-button:not(:disabled), infobar.action:backdrop > revealer > box button, infobar.action:backdrop > revealer > box button:hover, infobar.action:backdrop > revealer > box button:focus, infobar.action:backdrop > revealer > box button:active, infobar.action:backdrop > revealer > box button:checked, infobar.action:backdrop > revealer > box button.text-button:not(:disabled), infobar.question > revealer > box button, infobar.question > revealer > box button:hover, infobar.question > revealer > box button:focus, infobar.question > revealer > box button:active, infobar.question > revealer > box button:checked, infobar.question > revealer > box button.text-button:not(:disabled), infobar.question:backdrop > revealer > box button, infobar.question:backdrop > revealer > box button:hover, infobar.question:backdrop > revealer > box button:focus, infobar.question:backdrop > revealer > box button:active, infobar.question:backdrop > revealer > box button:checked, infobar.question:backdrop > revealer > box button.text-button:not(:disabled) { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action > revealer > box *:link, infobar.action:backdrop > revealer > box *:link, infobar.question > revealer > box *:link, infobar.question:backdrop > revealer > box *:link { + color: rgba(40, 40, 40, 0.87); +} + +infobar.action:hover > revealer > box, infobar.question:hover > revealer > box { + background-color: #6da498; +} + +infobar.warning > revealer > box, infobar.warning:backdrop > revealer > box { + background-color: #b47109; + color: #fbf1c7; +} + +infobar.warning > revealer > box button, infobar.warning > revealer > box button:hover, infobar.warning > revealer > box button:focus, infobar.warning > revealer > box button:active, infobar.warning > revealer > box button:checked, infobar.warning > revealer > box button.text-button:not(:disabled), infobar.warning:backdrop > revealer > box button, infobar.warning:backdrop > revealer > box button:hover, infobar.warning:backdrop > revealer > box button:focus, infobar.warning:backdrop > revealer > box button:active, infobar.warning:backdrop > revealer > box button:checked, infobar.warning:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.warning > revealer > box *:link, infobar.warning:backdrop > revealer > box *:link { + color: #fbf1c7; +} + +infobar.warning:hover > revealer > box { + background-color: #9c6208; +} + +infobar.error > revealer > box, infobar.error:backdrop > revealer > box { + background-color: #c14a4a; + color: #fbf1c7; +} + +infobar.error > revealer > box button, infobar.error > revealer > box button:hover, infobar.error > revealer > box button:focus, infobar.error > revealer > box button:active, infobar.error > revealer > box button:checked, infobar.error > revealer > box button.text-button:not(:disabled), infobar.error:backdrop > revealer > box button, infobar.error:backdrop > revealer > box button:hover, infobar.error:backdrop > revealer > box button:focus, infobar.error:backdrop > revealer > box button:active, infobar.error:backdrop > revealer > box button:checked, infobar.error:backdrop > revealer > box button.text-button:not(:disabled) { + color: #fbf1c7; +} + +infobar.error > revealer > box *:link, infobar.error:backdrop > revealer > box *:link { + color: #fbf1c7; +} + +infobar.error:hover > revealer > box { + background-color: #b43e3e; +} + +/************ + * Tooltips * + ************/ +tooltip { + padding: 6px 12px; + box-shadow: none; + border: none; +} + +tooltip.background { + background-color: rgba(32, 32, 32, 0.9); + color: #fbf1c7; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.05), 0 4px 6px 0 rgba(0, 0, 0, 0.06), 0 1px 10px 0 rgba(0, 0, 0, 0.05); + border-radius: 12px; + margin: 2px 6px 8px 6px; +} + +tooltip > box { + border-spacing: 6px; +} + +/***************** + * Color Chooser * + *****************/ +colorswatch.top { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.top overlay { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +colorswatch.bottom { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.bottom overlay { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.left, colorswatch:first-child:not(.top) { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.left overlay, colorswatch:first-child:not(.top) overlay { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +} + +colorswatch.right, colorswatch:last-child:not(.bottom) { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.right overlay, colorswatch:last-child:not(.bottom) overlay { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +} + +colorswatch.dark { + color: #fbf1c7; +} + +colorswatch.light { + color: rgba(40, 40, 40, 0.87); +} + +colorchooser colorswatch:hover { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 0 0 2px #7daea3; +} + +colorswatch#add-color-button { + border-radius: 12px 0 0 12px; + color: #fbf1c7; +} + +colorswatch#add-color-button:only-child { + border-radius: 12px; +} + +colorswatch#add-color-button overlay { + background-color: rgba(251, 241, 199, 0.04); +} + +colorswatch#add-color-button overlay:hover { + background-color: rgba(251, 241, 199, 0.12); + box-shadow: none; +} + +colorswatch#add-color-button overlay:active { + background-color: rgba(251, 241, 199, 0.3); +} + +colorswatch:disabled { + opacity: 0.5; +} + +colorswatch:disabled overlay { + box-shadow: none; +} + +colorswatch#editor-color-sample { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay { + border-radius: 12px; +} + +colorswatch#editor-color-sample overlay:hover { + box-shadow: 0 2px 3px -2px rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 2px -1px rgba(0, 0, 0, 0.17); +} + +colorchooser .popover.osd { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.15), 0 4px 3px 0 rgba(0, 0, 0, 0.18), 0 1px 6px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; +} + +colorchooser .popover.osd:backdrop { + box-shadow: 0 3px 2px -3px rgba(0, 0, 0, 0.2), 0 2px 2px -1px rgba(0, 0, 0, 0.24), 0 1px 3px 0 rgba(0, 0, 0, 0.12), inset 0 1px rgba(251, 241, 199, 0.1); +} + +/******** + * Misc * + ********/ +.content-view { + background-color: #282828; +} + +/********************** + * Window Decorations * + **********************/ +window { + border: none; +} + +window.csd { + border-radius: 12px; + margin: 0; + transition: none; + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +window.csd:backdrop { + transition: box-shadow 75ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 8px 6px -5px rgba(0, 0, 0, 0.2), 0 16px 15px 2px rgba(0, 0, 0, 0.14), 0 6px 18px 5px rgba(0, 0, 0, 0.12), 0 0 0 2px #7daea3, 0 0 36px transparent; +} + +window.csd.maximized, window.csd.fullscreen, window.csd.tiled, window.csd.tiled-top, window.csd.tiled-right, window.csd.tiled-bottom, window.csd.tiled-left { + border-radius: 0; + transition: none; +} + +window.csd.maximized, window.csd.fullscreen { + box-shadow: none; + outline: none; +} + +window.solid-csd { + margin: 0; + padding: 2px; + border-radius: 0; + background-color: #282828; + border: 1px solid #423f3e; +} + +window.solid-csd:backdrop { + background-color: #282828; +} + +window.ssd { + box-shadow: 0 0 0 1px rgba(251, 241, 199, 0.12); +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) { + min-height: 16px; + min-width: 16px; + padding: 9px 0; + margin-left: 0px; + margin-right: 0px; + /* min-height: 22px; */ + /* min-width: 22px; */ + /* padding: ($medium-size - 22px) / 2 0; */ + /* margin-left: $space-size - 7px; */ + /* margin-right: $space-size - 7px; */ +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + color: rgba(251, 241, 199, 0.7); +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:not(.suggested-action):not(.destructive-action) { + background: none; + box-shadow: none; +} + +windowcontrols > button.minimize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:not(.suggested-action):not(.destructive-action) > image { + padding: 1px; + background-color: alpha(currentColor, 0.1); +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +windowcontrols > button.minimize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.15); +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +windowcontrols > button.minimize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:active:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:active:not(.suggested-action):not(.destructive-action) > image { + background-color: alpha(currentColor, 0.2); +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) { + color: transparent; +} + +windowcontrols > button.minimize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:not(.suggested-action):not(.destructive-action) > image { + background-color: #282524; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action), windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) { + color: #fbf1c7; +} + +windowcontrols > button.minimize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.maximize:backdrop:hover:not(.suggested-action):not(.destructive-action) > image, windowcontrols > button.close:backdrop:hover:not(.suggested-action):not(.destructive-action) > image { + background-color: rgba(251, 241, 199, 0.3); +} + +/* $window-space: if($window_button == 'mac', $space-size * 1.5, $space-size); */ +windowcontrols { + border-spacing: 6px; +} + +windowcontrols:not(.empty).start:dir(ltr), windowcontrols:not(.empty).end:dir(rtl) { + margin-right: 6px; + margin-left: 6px; +} + +windowcontrols:not(.empty).start:dir(rtl), windowcontrols:not(.empty).end:dir(ltr) { + margin-left: 6px; + margin-right: 6px; +} + +windowcontrols > button:not(.suggested-action):not(.destructive-action) > image { + border-radius: 100%; + padding: 0; +} + + +.view:selected, iconview:selected, gridview > child:selected, columnview.view:selected, +treeview.view:selected, calendar:selected, calendar > grid > label.day-number:selected { + background-color: alpha(currentColor, 0.06); +} + +flowbox > flowboxchild:selected, calendar > grid > label.today { + color: #7daea3; + background-color: rgba(125, 174, 163, 0.2); +} + +textview text selection:focus, textview text selection, label > selection, +entry > text > selection, spinbutton > text > selection, +entry headerbar popover.background entry > text > selection, +headerbar popover.background entry entry > text > selection, calendar > grid > label.today:selected { + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +/********************** + * Touch Copy & Paste * + **********************/ +cursor-handle { + color: #7daea3; + -gtk-icon-source: -gtk-recolor(url("assets/cursor-handle-symbolic.svg")); +} + +cursor-handle.insertion-cursor:dir(ltr), cursor-handle.insertion-cursor:dir(rtl) { + padding-top: 6px; +} + +shortcuts-section { + margin: 20px; +} + +.shortcuts-search-results { + margin: 20px; + border-spacing: 24px; +} + +shortcut { + border-spacing: 6px; +} + +shortcut > .keycap { + min-width: 12px; + min-height: 26px; + margin-top: 2px; + padding-bottom: 2px; + padding-left: 8px; + padding-right: 8px; + border: solid 1px rgba(251, 241, 199, 0.12); + border-radius: 13px; + box-shadow: inset 0 -2px rgba(251, 241, 199, 0.12); + background-color: #242220; + color: #fbf1c7; + font-size: smaller; +} + +:not(decoration):not(window):drop(active) { + caret-color: #7daea3; +} + +/**************** + * Stackswitcher * + ****************/ +stackswitcher { + min-height: 0; + padding: 3px; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + border: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action) { + margin: 0 2px; + background-color: transparent; + border-radius: 9px; + padding: 2px 9px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action).text-button { + min-width: 100px; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):focus:not(:hover):not(:checked) { + box-shadow: none; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):hover { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):active { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +stackswitcher.linked:not(.vertical) > button:not(.suggested-action):not(.destructive-action):checked { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), border-image 225ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, background-color 0ms; + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +stackswitcher button.text-button { + min-width: 100px; +} + +stackswitcher button.circular, +stackswitcher button.text-button.circular { + min-width: 34px; + min-height: 34px; + padding: 0; +} + +/************* + * App Icons * + *************/ +.lowres-icon { + -gtk-icon-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.icon-dropshadow { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 1px 6px rgba(0, 0, 0, 0.1); +} + +/********* + * Emoji * + *********/ +popover.emoji-picker { + padding: 0; +} + +popover.emoji-picker > contents { + padding: 0; +} + +.emoji-searchbar { + padding: 6px; + border-spacing: 6px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); + background: none; +} + +.emoji-searchbar entry text { + background: none; + box-shadow: none; +} + +.emoji-toolbar { + padding: 0; + border-spacing: 3px; + border-top: 1px solid rgba(251, 241, 199, 0.12); + background: none; +} + +button.emoji-section { + margin: 0; + padding: 6px; + border-radius: 12px; +} + +button.emoji-section:checked { + color: #7daea3; +} + +popover.emoji-picker emoji { + font-size: x-large; + padding: 6px; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + border-radius: 12px; +} + +popover.emoji-picker emoji:focus, popover.emoji-picker emoji:hover { + background: alpha(currentColor, 0.08); +} + +emoji-completion-row { + min-height: 28px; + padding: 0 12px; +} + +emoji-completion-row > box { + border-spacing: 6px; + padding: 2px 6px; +} + +emoji-completion-row:focus, emoji-completion-row:hover, +emoji-completion-row emoji:hover, +emoji-completion-row emoji:focus { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; +} + +popover.entry-completion > contents { + padding: 0; +} + +.nautilus-window.view { + background-color: #282828; +} + +.nautilus-window .sidebar-pane, +.nautilus-window .content-pane { + background-color: #282828; + color: #fbf1c7; +} + +.nautilus-window .sidebar-pane:backdrop, +.nautilus-window .content-pane:backdrop { + background-color: #282828; + transition: none; +} + +.nautilus-window .sidebar-pane:dir(ltr), +.nautilus-window .sidebar-pane:dir(ltr) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(rtl), +.nautilus-window .sidebar-pane.end:dir(rtl) banner > revealer > widget { + box-shadow: none; + border-right: none; +} + +.nautilus-window .sidebar-pane:dir(rtl), +.nautilus-window .sidebar-pane:dir(rtl) banner > revealer > widget, .nautilus-window .sidebar-pane.end:dir(ltr), +.nautilus-window .sidebar-pane.end:dir(ltr) banner > revealer > widget { + box-shadow: none; + border-left: none; +} + +.nautilus-window placesview label { + color: rgba(251, 241, 199, 0.7); +} + +.nautilus-window flap > separator { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view .view, +.nautilus-window .nautilus-list-view .view { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell { + padding: 0; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable > cell > widget#NautilusViewCell, +.nautilus-window .nautilus-list-view listview.view > row.activatable > cell > widget#NautilusViewCell { + padding: 3px 9px; +} + +.nautilus-window .nautilus-grid-view listview.view > row.activatable:nth-child(odd):not(:disabled), +.nautilus-window .nautilus-list-view listview.view > row.activatable:nth-child(odd):not(:disabled) { + background-image: image(alpha(currentColor, 0.03)); +} + +.nautilus-window .nautilus-grid-view gridview.view, +.nautilus-window .nautilus-list-view gridview.view { + margin: 10px 5px; + padding: 10px 5px; +} + +.nautilus-window .floating-bar { + min-height: 32px; + padding: 0; + margin: 6px; + border-style: none; + border-radius: 9px; + background-color: rgba(40, 37, 36, 0.95); + color: #7daea3; + box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.05), 0 2px 3px -1px rgba(0, 0, 0, 0.06), 0 1px 4px 0 rgba(0, 0, 0, 0.05); +} + +.nautilus-window .floating-bar button { + margin: 4px; + color: rgba(40, 40, 40, 0.87); +} + +.nautilus-window banner > revealer > widget { + background-color: rgba(40, 37, 36, 0.4); + color: #fbf1c7; + border-radius: 9px; + margin: 9px; +} + +.nautilus-window banner > revealer > widget button { + background-color: rgba(125, 174, 163, 0.3); + color: rgba(40, 40, 40, 0.87); +} + +.nautilus-window banner > revealer > widget button:hover { + background-color: rgba(125, 174, 163, 0.6); +} + +#NautilusQueryEditor > menubutton > button.image-button { + min-width: 24px; + min-height: 24px; + padding: 3px; + margin-right: -5px; +} + +#NautilusQueryEditor > menubutton > button.image-button:checked image { + color: rgba(40, 40, 40, 0.87); +} + +#NautilusQueryEditor > text, +#NautilusQueryEditor > box, +#NautilusQueryEditor > menubutton { + margin: 3px 0; +} + +#NautilusQueryEditorTag { + background-color: rgba(251, 241, 199, 0.12); +} + +#NautilusQueryEditorTag > button.image-button { + margin: 0; + padding: 0; +} + +#NautilusPathBar { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 6px 0; +} + +#NautilusPathButton { + margin: 0 3px; + border-radius: 12px; +} + +#NautilusPathButton.current-dir { + color: #7daea3; +} + +#NautilusPathButton.current-dir:hover, #NautilusPathButton.current-dir:active { + background: none; + box-shadow: none; +} + +#NautilusPathButton:first-child { + margin-left: 0; +} + +#NautilusViewCell clamp box { + margin: 0; + border-spacing: 0; +} + +#NautilusFileChooser gridview.view { + background-color: transparent; + margin: 10px 5px; + padding: 10px 5px; +} + +#NautilusFileChooser columnview.view, +row.activatable > cell { + background-color: transparent; + padding: 1px 10px; +} + +#NautilusProgressIndicator popover label { + color: rgba(251, 241, 199, 0.7); +} + +#NautilusProgressIndicator popover image { + color: rgba(251, 241, 199, 0.7); +} + +/* Nautilus Progress Indicator */ +windowhandle box.vertical box.toolbar { + background-color: #282828; + border: none; + outline: none; +} + +windowhandle box.toolbar menubutton button.toggle { + background-color: #282828; + border: none; + outline: none; +} + +window.dialog > box > stack > box > box > notebook.frame { + border-width: 0 0 0 1px; + border-radius: 0; +} + +.display-container.card { + background-color: #282524; +} + +.small .display-container.card { + border-radius: 0; + box-shadow: none; + border-width: 0 0 1px 0; +} + +.display-container .history-view { + background-color: transparent; +} + +.display-container #displayitem { + padding: 0 12px 8px 0; + font-size: 1.4em; + border-top: 1px solid rgba(251, 241, 199, 0.12); +} + +.math-buttons button { + font-size: 1.1em; + padding: 2px 6px; +} + +.math-buttons button.text-button { + padding-left: 16px; + padding-right: 16px; +} + +leaflet button.number-button { + background-color: rgba(251, 241, 199, 0.1); +} + +leaflet button.number-button:hover { + background-color: rgba(251, 241, 199, 0.2); +} + +leaflet button.number-button:active { + background-color: rgba(251, 241, 199, 0.3); +} + +label.primary-label, label.month-name, label.secondary-label { + font-size: 16pt; + font-weight: bold; + padding: 12px; +} + +label.primary-label, label.month-name { + color: #7daea3; +} + +label.secondary-label { + color: rgba(251, 241, 199, 0.5); +} + +toastoverlay datechooser.view, +toastoverlay agenda-view.view, +toastoverlay agenda-view.view list, +toastoverlay stack.view { + background-color: transparent; +} + +calendar-view { + font-size: 10pt; +} + +calendar-view:selected { + color: #7daea3; + font-weight: bold; +} + +calendar-view.header, +label.header { + font-size: 10pt; + font-weight: bold; + color: rgba(251, 241, 199, 0.5); +} + +calendar-view.current, +weekgrid.current { + background-color: alpha(#7daea3, 0.3); +} + +popover.events { + background-color: #242220; + padding: 0; +} + +popover.events box { + border-top-left-radius: 12px; + border-top-right-radius: 12px; +} + +popover.events list { + background-color: #282524; + border-radius: 12px; +} + +popover.events scrolledwindow { + border-width: 0; +} + +popover.events button { + border-radius: 12px; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-style: solid none none; + box-shadow: none; +} + +event { + margin: 1px; + font-size: 0.9rem; +} + +event widget.content { + margin: 4px; +} + +event.timed, event:not(.slanted):not(.slanted-start):not(.slanted-end) { + border-radius: 12px; +} + +event.timed widget.edge { + border-radius: 6px; + min-width: 5px; +} + +event.slanted-start, event.slanted-end:dir(rtl) { + padding-left: 16px; + border-radius: 0 6px 6px 0; +} + +event.slanted-end, event.slanted-start:dir(rtl) { + padding-right: 16px; + border-radius: 6px 0 0 6px; +} + +event:not(.timed).color-dark { + color: white; + outline-color: rgba(0, 0, 0, 0.3); +} + +event.timed, event:not(.timed).color-light { + color: alpha(black, 0.75); + outline-color: rgba(255, 255, 255, 0.5); +} + +popover.event-popover, +popover.event-popover > contents { + padding: 0; +} + +.search-viewport { + background-color: #282524; +} + +.calendar-list { + background-color: transparent; +} + +.calendar-list > list { + border-radius: 4px; +} + +menubutton.flat.sources-button { + margin-top: 0; + margin-bottom: 0; + border-radius: 0; + border-top-style: none; + border-bottom-style: none; +} + +menubutton.flat.sources-button:hover:not(:backdrop) { + background-image: none; + text-shadow: none; +} + +menubutton.flat.sources-button > button { + border-radius: 0 0 12px 12px; +} + +.calendar-color-image { + -gtk-icon-filter: none; +} + +image.calendar-color-image, +button:active:not(:backdrop) .calendar-color-image, +button:checked:not(:backdrop) .calendar-color-image, +.calendars-list .calendar-color-image:not(:backdrop):not(:disabled), +.calendar-list .calendar-color-image:not(:backdrop):not(:disabled), +.sources-button:not(:backdrop):not(:disabled) .calendar-color-image { + -gtk-icon-shadow: 0 1px alpha(black, 0.1); +} + +datechooser { + padding: 6px; +} + +datechooser .current-week { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; + border-radius: 12px; +} + +datechooser navigator { + margin-right: 6px; + margin-left: 6px; + margin-bottom: 6px; +} + +datechooser navigator label { + font-weight: bold; +} + +datechooser navigator button.flat, +datechooser navigator button.image-button { + min-height: 34px; + min-width: 34px; + padding: 0; +} + +datechooser .weeknum, +datechooser .weekday { + color: rgba(251, 241, 199, 0.5); + font-size: smaller; +} + +datechooser button.day { + font-size: 10pt; + font-weight: normal; + margin: 3px; + padding: 0; + min-height: 34px; + min-width: 34px; + transition: none; +} + +datechooser button.day dot { + background-color: #fbf1c7; + border-radius: 50%; + min-height: 3px; + min-width: 3px; +} + +datechooser button.day:selected, datechooser button.day.today:selected { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); + font-weight: bold; +} + +datechooser button.day:selected dot, datechooser button.day.today:selected dot { + background-color: rgba(40, 40, 40, 0.87); +} + +datechooser button.day.today { + color: #7daea3; +} + +datechooser button.day.today dot { + background-color: #7daea3; +} + +datechooser button.day.other-month:not(:hover), datechooser button.day.other-month:backdrop { + color: rgba(251, 241, 199, 0.32); +} + +datechooser button.day.other-month:not(:hover) dot, datechooser button.day.other-month:backdrop dot { + background-color: rgba(251, 241, 199, 0.32); +} + +datechooser button.day.other-month:hover:not(:backdrop) { + color: rgba(251, 241, 199, 0.5); +} + +datechooser button.day.other-month:hover:not(:backdrop) dot { + background-color: rgba(251, 241, 199, 0.5); +} + +.week-header { + padding: 0; +} + +.week-header > box:first-child { + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.week-header .week-number { + font-size: 16pt; + font-weight: bold; + padding: 12px 12px 18px 12px; + color: rgba(251, 241, 199, 0.3); +} + +.week-header.week-temperature { + font-size: 10pt; + font-weight: bold; + color: rgba(251, 241, 199, 0.5); +} + +.week-header.lines { + color: rgba(251, 241, 199, 0.12); +} + +weekhourbar > label { + font-size: 10pt; + padding: 4px 6px; +} + +.week-view .lines { + color: rgba(251, 241, 199, 0.12); +} + +weekgrid > widget.now-strip { + background-color: alpha(#7daea3, 0.8); + margin: 0 0 0 1px; + min-height: 3px; +} + +weekgrid:selected, weekgrid.dnd, +.week-header:selected, +.week-header.dnd { + background-color: alpha(#7daea3, 0.25); +} + +monthcell { + border: solid 1px rgba(251, 241, 199, 0.12); + border-width: 1px 0 0 1px; + background-color: transparent; + transition: background-color 200ms; +} + +monthcell:hover:not(.out-of-month):not(.today) { + background-color: #282524; + transition: background-color 200ms; + color: #fbf1c7; +} + +monthcell:selected { + background-color: alpha(#7daea3, 0.1); +} + +monthcell:selected:hover { + background-color: alpha(#7daea3, 0.2); +} + +monthcell:selected label.day-label { + font-weight: bold; +} + +monthcell:nth-child(7n + 1) { + border-left-width: 0; +} + +monthcell.today { + background-color: alpha(#7daea3, 0.2); +} + +monthcell.today:hover { + background-color: alpha(#7daea3, 0.3); + color: #7daea3; +} + +monthcell.today:selected { + background-color: alpha(#7daea3, 0.25); +} + +monthcell.today:selected:hover { + background-color: alpha(#7daea3, 0.35); +} + +monthcell label { + color: #fbf1c7; + font-size: 0.9rem; +} + +monthcell label.day-label { + font-size: 1rem; +} + +monthcell.out-of-month { + background-color: rgba(251, 241, 199, 0.04); +} + +monthcell.out-of-month label { + color: rgba(251, 241, 199, 0.7); +} + +monthcell button { + padding: 0 6px; + border-radius: 0; + border-bottom: none; + border-right: none; +} + +monthpopover > box { + margin: 0; + padding: 0; + background-color: transparent; +} + +.notes-section box > textview { + border-radius: 12px; + padding: 6px; +} + +.notes-section box > textview > text { + background: none; +} + +agenda-view list.background > row { + padding: 2px 12px; +} + +agenda-view list.background > label { + padding: 6px 12px; +} + +label.no-events { + font-style: italic; +} + +searchbutton > popover > arrow { + background: none; + border: none; +} + +menubutton stack > box { + border-spacing: 6px; +} + +#TweakPreferencesPage.tweak-group label.subtitle { + color: rgba(251, 241, 199, 0.32); +} + +#TweakPreferencesPage label.dim-label { + color: rgba(251, 241, 199, 0.32); +} + +.sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow .dim-label, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row label.subtitle, row .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow label.subtitle, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow row.expander image.expander-row-arrow, row.expander .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow image.expander-row-arrow { + color: rgba(40, 40, 40, 0.38); +} + +.details-page { + margin: 24px 0px; +} + +.installed-overlay-box { + font-size: smaller; + background-color: #7daea3; + border-radius: 0; + color: rgba(40, 40, 40, 0.87); + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); +} + +screenshot-carousel box.frame { + border-width: 1px 0; + border-radius: 0; +} + +screenshot-carousel button, +.featured-carousel button { + margin: 12px; +} + +carousel.card { + border: none; + background-color: rgba(251, 241, 199, 0.04); +} + +.smaller { + font-size: smaller; +} + +.screenshot-image-main .image1, +.screenshot-image-main .image2 { + margin-top: 6px; + margin-bottom: 12px; + margin-left: 6px; + margin-right: 6px; +} + +.app-tile-label { + font-size: 105%; +} + +gs-summary-tile image.loading-icon { + background-color: rgba(251, 241, 199, 0.12); + border-radius: 12px; +} + +.review-row > box { + margin: 12px; + border-spacing: 3px; +} + +.review-row textview { + background: none; +} + +.review-row .edit-icon { + min-width: 24px; + min-height: 24px; + padding: 6px; +} + +.review-textbox { + padding: 6px; +} + +.origin-rounded-box { + background-color: rgba(251, 241, 199, 0.12); + border-radius: 9999px; + padding: 4px; +} + +.origin-beta { + color: #b47109; +} + +.origin-button > button { + padding: 3px 9px; +} + +clamp.medium .category-tile:not(.category-tile-iconless) { + font-size: large; +} + +clamp.large .category-tile:not(.category-tile-iconless) { + font-size: larger; +} + +flowboxchild.card:not(.category-tile) { + padding: 0; + box-shadow: none; + border: none; + background-color: transparent; + background-image: none; +} + +.category-tile.card { + padding: 21px; + border: none; + border-radius: 12px; + min-width: 140px; + font-weight: 900; + font-size: larger; +} + +.category-tile.card:not(.category-tile-iconless), .category-tile.card:not(.category-tile-iconless):active { + transition: all 75ms cubic-bezier(0, 0, 0.2, 1); + animation: none; +} + +.category-tile.card.category-tile-iconless { + padding: 9px 15px; + min-width: 130px; + font-size: 105%; + font-weight: normal; +} + +.category-tile.card.category-create { + background: linear-gradient(180deg, #ce8cd7 0%, #2861c6 100%); + color: white; +} + +.category-tile.card.category-create:hover { + background: linear-gradient(180deg, shade(#ce8cd7, 1.07) 0%, shade(#2861c6, 1.1) 100%); + color: white; +} + +.category-tile.card.category-create:active { + background: linear-gradient(180deg, shade(#ce8cd7, 0.95) 0%, shade(#2861c6, 0.95) 100%); + color: white; +} + +.category-tile.card.category-develop { + background-color: #5e5c64; + color: white; +} + +.category-tile.card.category-develop:hover { + background-color: shade(#5e5c64, 1.2); + color: white; +} + +.category-tile.card.category-develop:active { + background-color: shade(#5e5c64, 0.95); + color: white; +} + +.category-tile.card.category-learn { + background: linear-gradient(180deg, #2ec27e 30%, #27a66c 100%); + color: white; +} + +.category-tile.card.category-learn:hover { + background: linear-gradient(180deg, shade(#2ec27e, 1.06) 30%, shade(#27a66c, 1.06) 100%); + color: white; +} + +.category-tile.card.category-learn:active { + background: linear-gradient(180deg, shade(#2ec27e, 0.95) 30%, shade(#27a66c, 0.95) 100%); + color: white; +} + +.category-tile.card.category-play { + background: linear-gradient(75deg, #f9e2a7 0%, #eb5ec3 50%, #6d53e0 100%); + color: #393484; +} + +.category-tile.card.category-play:hover { + background: linear-gradient(75deg, shade(#f9e2a7, 1.07) 0%, shade(#eb5ec3, 1.07) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-play:active { + background: linear-gradient(75deg, shade(#f9e2a7, 0.97) 0%, shade(#eb5ec3, 0.95) 50%, shade(#6d53e0, 1.07) 100%); + color: #393484; +} + +.category-tile.card.category-socialize { + background: linear-gradient(90deg, #ef4e9b 0%, #f77466 100%); + color: rgba(251, 241, 199, 0.7); +} + +.category-tile.card.category-socialize:hover { + background: linear-gradient(90deg, shade(#ef4e9b, 1.08) 0%, shade(#f77466, 1.08) 100%); +} + +.category-tile.card.category-socialize:active { + background: linear-gradient(90deg, shade(#ef4e9b, 0.95) 0%, shade(#f77466, 0.95) 100%); +} + +.category-tile.card.category-work { + padding: 1px; + /* FIXME: work around https://gitlab.gnome.org/GNOME/gtk/-/issues/4324 */ + color: #1c71d8; + background-color: #fdf8d7; + background-image: linear-gradient(rgba(251, 241, 199, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(251, 241, 199, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.category-tile.card.category-work:hover { + color: #1c71d8; + background-color: #fefcef; + background-image: linear-gradient(rgba(251, 241, 199, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(251, 241, 199, 0.12) 1px, transparent 1px); +} + +.category-tile.card.category-work:active { + color: #1c71d8; + background-color: #fcf4bf; + background-image: linear-gradient(rgba(251, 241, 199, 0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(251, 241, 199, 0.12) 1px, transparent 1px); + background-size: 10px 10px, 10px 10px; + background-position: -1px -4px, center -1px; + background-repeat: repeat; +} + +.featured-tile { + padding: 0; + box-shadow: none; + color: #fbf1c7; +} + +.featured-tile label.title-1 { + margin-top: 6px; + margin-bottom: 6px; +} + +.featured-tile.narrow label.title-1 { + font-size: 16pt; +} + +.application-details-infobar, .application-details-infobar.info { + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; + border: 1px solid rgba(251, 241, 199, 0.12); +} + +.application-details-infobar.warning { + background-color: #b47109; + color: #fbf1c7; + border: 1px solid rgba(251, 241, 199, 0.12); +} + +.card.info { + background-color: #292929; + color: #fbf1c7; +} + +.card.warning { + background-color: #292928; + color: #fbf1c7; +} + +.infobox { + border-spacing: 6px; + padding: 12px; +} + +@keyframes install-progress-unknown-move { + 0% { + background-position: 0%; + } + 50% { + background-position: 100%; + } + 100% { + background-position: 0%; + } +} + +.application-details-description .button { + padding-left: 24px; + padding-right: 24px; +} + +.install-progress { + background-image: linear-gradient(to top, #7daea3 2px, alpha(#7daea3, 0) 2px); + background-repeat: no-repeat; + background-position: 0 bottom; + background-size: 0; + transition: none; +} + +.install-progress:dir(rtl) { + background-position: 100% bottom; +} + +.review-row > * { + margin: 12px; +} + +.review-row button { + font-size: smaller; +} + +.review-row .vote-buttons button { + margin-right: -1px; +} + +.review-row .vote-buttons button:not(:first-child) { + border-image: linear-gradient(to top, rgba(251, 241, 199, 0.12), rgba(251, 241, 199, 0.12)) 0 0 0 1/5px 0 5px 1px; +} + +.review-row .vote-buttons button:hover, +.review-row .vote-buttons button:active, +.review-row .vote-buttons button:hover + button, +.review-row .vote-buttons button:active + button { + border-image: none; +} + +review-bar { + color: rgba(251, 241, 199, 0.5); + background-image: none; + background-color: rgba(251, 241, 199, 0.3); +} + +.review-histogram star-image { + color: rgba(251, 241, 199, 0.5); +} + +.version-arrow-label { + font-size: x-small; +} + +.overview-more-button { + font-size: smaller; + padding: 0 16px; +} + +.app-row-origin-text { + font-size: smaller; +} + +.app-listbox-header { + padding: 6px; + border-bottom: 1px solid rgba(251, 241, 199, 0.12); +} + +.image-list { + background-color: transparent; +} + +box.star { + background-color: transparent; + background-image: none; +} + +button.star { + outline-offset: 0; + background-color: transparent; + background-image: none; + border-image: none; + border-radius: 0; + border-width: 0; + padding: 0; + box-shadow: none; + outline-offset: -1px; +} + +flowboxchild { + padding: 0px; +} + +star-image > image.starred { + color: #d8a657; + transition-duration: 200ms; +} + +star-image > image.starred:hover { + color: #b47109; +} + +star-image > image.non-starred { + opacity: 0.2; + transition-duration: 200ms; +} + +star-image > image.non-starred:hover { + color: #d8a657; + opacity: 0.7; +} + +.dimmer-label { + opacity: 0.25; +} + +.update-failed-details { + font-family: Monospace; + font-size: smaller; + padding: 16px; +} + +.upgrade-banner { + padding: 0px; + border-radius: 12px; + border: none; +} + +.upgrade-banner-background { + background: linear-gradient(to bottom, #6c782e, #45707a); + color: white; +} + +.upgrade-buttons #button_upgrades_install, +.upgrade-buttons #button_upgrades_install_cancel { + padding-left: 16px; + padding-right: 16px; +} + +scrolledwindow.list-page > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +.update-preferences preferencesgroup > box > box { + margin-top: 18px; +} + +.section > label:not(:first-child) { + margin-top: 6px; +} + +.section > box:not(:first-child) { + margin-top: 12px; +} + +clamp.status-page { + margin: 36px 12px; +} + +clamp.status-page .iconbox { + min-height: 128px; + min-width: 128px; +} + +clamp.status-page .icon { + color: rgba(251, 241, 199, 0.5); + min-height: 32px; + min-width: 32px; +} + +clamp.status-page .icon:not(:last-child) { + margin-bottom: 36px; +} + +clamp.status-page .title:not(:last-child) { + margin-bottom: 12px; +} + +app-context-bar .context-tile { + border: 1px solid rgba(251, 241, 199, 0.12); + background-color: transparent; + border-radius: 0; + padding: 24px 12px 21px 12px; + outline-offset: 5px; + transition-property: outline, outline-offset, background-image; + border-bottom: none; + border-right: none; +} + +app-context-bar .context-tile:hover { + background-image: none; + background-color: alpha(currentColor, 0.08); +} + +app-context-bar .context-tile.keyboard-activating, app-context-bar .context-tile:active { + background-color: alpha(currentColor, 0.12); +} + +app-context-bar .context-tile:focus:focus-visible { + outline-offset: -1px; +} + +app-context-bar.horizontal box:first-child .context-tile:first-child, app-context-bar.vertical .context-tile:first-child { + border-left: none; +} + +app-context-bar.horizontal .context-tile, app-context-bar.vertical box:first-child .context-tile { + border-top: none; +} + +app-context-bar > box:not(:first-child) > button.flat { + border-radius: 0; +} + +app-context-bar > box:not(:first-child) > button.flat:last-child { + border-radius: 0 12px 12px 0; +} + +app-context-bar > box:first-child > button.flat { + border-radius: 0; +} + +app-context-bar > box:first-child > button.flat:first-child { + border-radius: 12px 0 0 12px; +} + +app-context-bar > box > button.flat { + border-left-color: rgba(251, 241, 199, 0.12); +} + +.context-tile-lozenge { + min-height: 28px; + min-width: 28px; + padding: 6px; + font-size: 18px; + font-weight: bold; + border-radius: 9999px; +} + +.context-tile-lozenge.large { + font-size: 24px; + padding: 16px; + min-width: 24px; + /* 60px minus the left and right padding */ + min-height: 24px; + /* 60px minus the top and bottom padding */ +} + +.context-tile-lozenge.wide-image image { + margin-top: -28px; + margin-bottom: -28px; +} + +.context-tile-lozenge image { + -gtk-icon-style: symbolic; +} + +.context-tile-lozenge.grey { + color: #fbf1c7; + background-color: rgba(251, 241, 199, 0.12); +} + +.context-tile-lozenge.green, .context-tile-lozenge.details-rating-0 { + color: #3a4119; + background-color: rgba(108, 120, 46, 0.15); +} + +.context-tile-lozenge.blue, .context-tile-lozenge.details-rating-5 { + color: #45707a; + background-color: rgba(69, 112, 122, 0.15); +} + +.context-tile-lozenge.yellow, .context-tile-lozenge.details-rating-12 { + color: #6b4305; + background-color: rgba(180, 113, 9, 0.15); +} + +.context-tile-lozenge.details-rating-15 { + color: #c35e0a; + background-color: rgba(195, 94, 10, 0.15); +} + +.context-tile-lozenge.red, .context-tile-lozenge.details-rating-18 { + color: #8e3131; + background-color: rgba(193, 74, 74, 0.15); +} + +.eol-red { + font-weight: bold; + color: #c14a4a; +} + +window.narrow .app-title { + font-size: 16pt; +} + +window.narrow .app-developer { + font-size: small; +} + +.install-progress-label { + font-size: smaller; + font-feature-settings: 'tnum'; +} + +scrolledwindow.fake-adw-status-page > viewport > box { + margin: 36px 12px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp:not(:last-child) +> box { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .icon:not(:last-child) { + margin-bottom: 36px; +} + +scrolledwindow.fake-adw-status-page +> viewport +> box +> clamp +> box +> .title:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.icon-dropshadow image.icon { + -gtk-icon-shadow: 0 1px 12px rgba(0, 0, 0, 0.05), 0 -1px rgba(0, 0, 0, 0.05), 1px 0 rgba(0, 0, 0, 0.1), 0 1px rgba(0, 0, 0, 0.3), -1px 0 rgba(0, 0, 0, 0.1); +} + +window.info scrollbar.vertical { + margin-top: 48px; + background: none; + box-shadow: none; +} + +window.info scrollbar.vertical trough { + margin-top: 0; +} + +row.app > box.header { + margin-left: 12px; + margin-right: 12px; +} + +row.app > box.header { + border-spacing: 12px; +} + +row.app > box.header > image { + margin-top: 12px; + margin-bottom: 12px; +} + +row.app label.warning { + color: #c14a4a; +} + +@keyframes pre-delay { + from { + opacity: 0; + } + to { + opacity: 0; + } +} + +@keyframes fade-in { + from { + filter: opacity(0%); + } +} + +/* Give a fade-in animation to spinners. */ +spinner.fade-in:checked { + animation: pre-delay 0.5s linear 1, fade-in 1s linear 1, spin 1s linear infinite; + animation-delay: 0s, 0.5s, 0.5s; +} + +window > contents > leaflet > box > stack.background { + background-color: transparent; + background-image: linear-gradient(to bottom, transparent, transparent 46px, #282828 46px, #282828); +} + +@define-color weather_temp_chart_fill_color rgba(180, 113, 9, 0.5); +@define-color weather_temp_chart_stroke_color #835307; +@define-color weather_thermometer_warm_color #b47109; +@define-color weather_thermometer_cold_color #45707a; +#places-label { + font-weight: bold; +} + +#temperature-label { + font-size: 32pt; + font-weight: 900; + margin-left: 9px; +} + +#conditions-grid *:backdrop { + color: rgba(251, 241, 199, 0.7); +} + +.content-view.cell { + font-weight: bold; +} + +#locationEntry { + margin: 6px; +} + +.weather-popover { + margin-top: 6px; +} + +.forecast-card { + transition: border-radius 100ms ease-out; + border-radius: 12px; +} + +.forecast-card separator { + background-color: #282828; +} + +#daily-forecast-box > separator:last-child { + background-color: transparent; + min-width: 0; +} + +#conditions-grid, +#attributionGrid { + margin-left: 18px; + margin-right: 18px; +} + +#weather-page .small .forecast-card { + margin-left: 0; + margin-right: 0; + border-radius: 0; + border-width: 1px 0; +} + +.forecast-temperature-label { + font-weight: bold; + color: #ae7b03; +} + +WeatherThermometer { + margin-bottom: 12px; +} + +WeatherThermometer > label.high { + font-weight: bold; + color: #b47109; +} + +WeatherThermometer > label.low { + font-weight: bold; + color: #45707a; +} + +.forecast-button { + margin: 0 12px; +} + +.forecast-graphic { + margin: 18px; +} + +button.osd.circular { + border-radius: 9999px; + min-width: 24px; + min-height: 24px; +} + +button.osd.circular > image { + padding: 0; +} + +scrolledwindow.inline list, +scrolledwindow.inline listview { + background: none; + color: inherit; +} + +scrolledwindow.inline undershoot.top { + box-shadow: inset 0 1px rgba(251, 241, 199, 0.12); +} + +.search-view { + background-color: #7daea3; + color: rgba(40, 40, 40, 0.87); +} + +.search-view menubutton button:focus:focus-visible { + outline-color: rgba(255, 255, 255, 0.3); +} + +image.circular { + min-width: 34px; + min-height: 34px; + padding: 0; + border-radius: 9999px; +} + +#gnome-system-monitor.background.csd { + background-color: #282828; +} + +.large-button { + padding: 6px; +} + +.alarm-time { + font-size: 2.5em; + font-weight: 300; +} + +.clocks-ampm-toggle-button, +.clocks-secondary-standalone-label { + font-size: 18pt; +} + +.clocks-standalone-label, +.clocks-ringing-label { + font-size: 6em; + font-weight: 300; +} + +.clocks-ringing-title { + font-size: 1.5em; + font-weight: bold; +} + +.clocks-alarm-setup-time { + font-size: 32pt; +} + +.clocks-timer-label, +.clocks-spinbutton { + font-size: 48pt; +} + +.timer-panel .timer-header { + font-size: 20pt; + font-weight: 300; +} + +.timer-countdown { + font-size: 40pt; + font-weight: 300; +} + +/* Stopwatch Panel */ +.lap-time { + font-weight: bold; +} + +.stopped-stopwatch label, +.running-stopwatch label, +.paused-stopwatch label { + font-size: 70px; + font-weight: lighter; +} + +.stopped-stopwatch .seconds-label { + font-weight: 300; +} + +.running-stopwatch .seconds-label, +.running-stopwatch .miliseconds-label { + color: #7daea3; +} + +.stopped-stopwatch .miliseconds-label, +.running-stopwatch .miliseconds-label, +.paused-stopwatch .miliseconds-label { + font-size: 50px; +} + +.running-stopwatch .seconds-label, +.paused-stopwatch .seconds-label { + font-weight: 300; +} + +.clock-location { + font-weight: bolder; +} + +.hidden { + opacity: 0; +} + +.clock-time { + font-size: 2em; + padding: 0.2em 0.5em; + border-radius: 1em; +} + +.none .clock-time { + background: alpha(currentColor, 0.2); +} + +.night .clock-time { + color: #7daea3; + background-color: alpha(#45707a, 0.25); +} + +.naut .clock-time, +.astro .clock-time { + color: #e78a4e; + background-color: alpha(#c35e0a, 0.25); +} + +.civil .clock-time, +.day .clock-time { + color: #d8a657; + background: alpha(#b47109, 0.25); +} + +headerbar splitbutton notification button { + margin: 0; + min-height: 24px; + min-width: 24px; + padding: 0; +} + +popover.background.global-search > arrow, +popover.background.global-search > contents { + padding: 0; +} + +panelframeswitcher { + padding: 3px; +} + +.frameheader.header { + min-height: 24px; + background-color: #282524; +} + +.frameheader.header > button { + border: none; + margin: 0; + padding: 3px; +} + +.frameheader.header tabbar.inline > revealer > box { + min-height: 24px; +} + +.frameheader.header tabbar.inline > revealer > box .start-action { + padding: 0; + border: none; +} + +.frameheader.header tabbar.inline > revealer > box .end-action { + padding: 0; + border-left: 1px solid rgba(251, 241, 199, 0.12); +} + +.frameheader.header tabbar.inline > revealer > box tabbox { + border: none; + background: none; +} + +panelstatusbar > menubutton > button, +panelstatusbar > paneltogglebutton button { + border-radius: 0; +} + +.style-variant { + padding: 0 12px; +} + +.style-variant button.toggle { + padding: 0; +} + +.style-variant button.toggle, .style-variant button.toggle:hover, .style-variant button.toggle:focus, .style-variant button.toggle:active, .style-variant button.toggle:checked { + background: none; + outline: none; + border: none; + box-shadow: none; +} + +.style-variant button.toggle > stylevariantpreview > .wallpaper { + border-radius: 12px; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; + box-shadow: none; +} + +.style-variant button.toggle:hover > stylevariantpreview > .wallpaper { + outline-color: rgba(251, 241, 199, 0.04); +} + +.style-variant button.toggle:active > stylevariantpreview > .wallpaper { + outline-color: rgba(251, 241, 199, 0.3); +} + +.style-variant button.toggle:checked > stylevariantpreview > .wallpaper { + outline-color: #7daea3; +} + +playlistview scrollbar.overlay-indicator.dragging, playlistview scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +playlistview queuerow picture.cover, +playlistview queuerow image.card { + border: none; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list { + border: none; + border-radius: 0; +} + +window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:first-child, window.dialog > .dialog-vbox > box > scrolledwindow > viewport > widget > list.boxed-list > row:last-child { + border-radius: 0; +} + +/* Tagger */ +list.music-list { + margin: -40px 0; + background-color: transparent; +} + +/* Nicotine+ */ +notebook scrolledwindow treeview.treeview-spacing { + background-color: #282828; +} + +.account-switcher-row label { + color: #fbf1c7; +} + +.account-switcher-row label.dim-label { + color: rgba(251, 241, 199, 0.7); +} + +window.background.chromium { + background-color: rgba(251, 241, 199, 0.04); +} + +window.background.chromium headerbar.header-bar.titlebar { + padding: 0 12px; + background-color: #282828; + color: #fbf1c7; + border-radius: 12px 12px 0 0; + box-shadow: inset 0 1px 0 rgba(251, 241, 199, 0.1); +} + +window.background.chromium headerbar.header-bar.titlebar:backdrop { + background-color: #282828; + color: rgba(251, 241, 199, 0.5); +} + +window.background.chromium headerbar.header-bar.titlebar button.titlebutton { + margin: 0 0px; +} + +.nautilus-window placessidebar > scrolledwindow { + background-color: #282828; + color: #fbf1c7; + border-radius: 0; + /* margin: 0 6px 0 0; */ +} + +.nautilus-window placessidebar > scrolledwindow .dim-label, .nautilus-window placessidebar > scrolledwindow row label.subtitle, row .nautilus-window placessidebar > scrolledwindow label.subtitle, .nautilus-window placessidebar > scrolledwindow row.property > box.header > box.title > .title, .nautilus-window placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander .nautilus-window placessidebar > scrolledwindow image.expander-row-arrow { + color: rgba(40, 40, 40, 0.38); +} + +.nautilus-window .nautilus-grid-view, +.nautilus-window .nautilus-list-view { + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px; + margin: 0 6px 6px 6px; +} + +calendar-view { + margin: 6px; +} + +.sidebar-pane .sidebar > scrolledwindow, +.sidebar-pane toolbarview > scrolledwindow, +.sidebar-pane navigation-view-page stack > scrolledwindow, .sidebar-pane, filechooser paned > box, placessidebar > scrolledwindow, agenda-view list.background, .tweak-titlebar-left, .tweak-titlebar-left:backdrop, leaflet.unfolded > box > scrolledwindow, leaflet.unfolded .contacts-contact-list > scrolledwindow, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow { + background-color: #141617; + background-color: #282828; + color: #fbf1c7; + border-radius: 0; + margin: 0; +} + +.sidebar-pane .sidebar > scrolledwindow .dim-label, +.sidebar-pane toolbarview > scrolledwindow .dim-label, +.sidebar-pane navigation-view-page stack > scrolledwindow .dim-label, .sidebar-pane .dim-label, filechooser paned > box .dim-label, placessidebar > scrolledwindow .dim-label, agenda-view list.background .dim-label, .tweak-titlebar-left .dim-label, leaflet.unfolded > box > scrolledwindow .dim-label, leaflet.unfolded .contacts-contact-list > scrolledwindow .dim-label, .sidebar-pane row label.subtitle, row .sidebar-pane label.subtitle, filechooser paned > box row label.subtitle, row filechooser paned > box label.subtitle, placessidebar > scrolledwindow row label.subtitle, row placessidebar > scrolledwindow label.subtitle, agenda-view list.background row label.subtitle, row agenda-view list.background label.subtitle, .tweak-titlebar-left row label.subtitle, row .tweak-titlebar-left label.subtitle, leaflet.unfolded > box > scrolledwindow row label.subtitle, row leaflet.unfolded > box > scrolledwindow label.subtitle, leaflet.unfolded .contacts-contact-list > scrolledwindow row label.subtitle, row leaflet.unfolded .contacts-contact-list > scrolledwindow label.subtitle, .sidebar-pane row.property > box.header > box.title > .title, placessidebar > scrolledwindow row.property > box.header > box.title > .title, agenda-view list.background row.property > box.header > box.title > .title, .tweak-titlebar-left row.property > box.header > box.title > .title, leaflet.unfolded > box > scrolledwindow row.property > box.header > box.title > .title, leaflet.unfolded .contacts-contact-list > scrolledwindow row.property > box.header > box.title > .title, .sidebar-pane row.expander image.expander-row-arrow, row.expander .sidebar-pane image.expander-row-arrow, filechooser paned > box row.expander image.expander-row-arrow, row.expander filechooser paned > box image.expander-row-arrow, placessidebar > scrolledwindow row.expander image.expander-row-arrow, row.expander placessidebar > scrolledwindow image.expander-row-arrow, agenda-view list.background row.expander image.expander-row-arrow, row.expander agenda-view list.background image.expander-row-arrow, .tweak-titlebar-left row.expander image.expander-row-arrow, row.expander .tweak-titlebar-left image.expander-row-arrow, leaflet.unfolded > box > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded > box > scrolledwindow image.expander-row-arrow, leaflet.unfolded .contacts-contact-list > scrolledwindow row.expander image.expander-row-arrow, row.expander leaflet.unfolded .contacts-contact-list > scrolledwindow image.expander-row-arrow { + color: rgba(40, 40, 40, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider, placessidebar > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar > range > trough > slider { + background-color: rgba(251, 241, 199, 0.5); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:hover, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:hover, placessidebar > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:hover { + background-color: rgba(251, 241, 199, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:active, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:active, placessidebar > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:active { + background-color: rgba(251, 241, 199, 0.7); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar > range > trough > slider:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar > range > trough > slider:disabled, placessidebar > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar > range > trough > slider:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar > range > trough > slider:disabled { + background-color: rgba(251, 241, 199, 0.32); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + background-color: rgba(40, 40, 40, 0.38); +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button:disabled { + background-color: rgba(40, 40, 40, 0.3); +} + +placessidebar list.navigation-sidebar, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar { + padding: 6px 0 6px 6px; + background: none; + color: rgba(251, 241, 199, 0.7); +} + +placessidebar list.navigation-sidebar > separator, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > separator, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > separator { + background-color: rgba(251, 241, 199, 0.12); + margin: 10px 15px; +} + +placessidebar list.navigation-sidebar > row, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row { + color: rgba(40, 40, 40, 0.6); + border-radius: 9px; + color: #fbf1c7; + padding: 6px 0; +} + +placessidebar list.navigation-sidebar > row:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:hover, placessidebar list.navigation-sidebar > row:active, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:active, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:active, placessidebar list.navigation-sidebar > row:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:focus { + color: #accbc4; +} + +placessidebar list.navigation-sidebar > row:selected, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected { + background-color: alpha(currentColor, 0.08); + color: #7daea3; + font-weight: 500; +} + +placessidebar list.navigation-sidebar > row:selected:hover, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:hover, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:hover, placessidebar list.navigation-sidebar > row:selected:focus, leaflet.unfolded .contacts-contact-list > scrolledwindow > viewport > .navigation-sidebar > row:selected:focus, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > .navigation-sidebar > row:selected:focus { + color: #9cc2b9; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.top, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.top, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.top, filechooser paned > box scrolledwindow scrollbar.top, placessidebar > scrolledwindow > scrollbar.top, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.top, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.top, leaflet.unfolded > box > scrolledwindow > scrollbar.top, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.top, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.top { + border-bottom: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.bottom, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.bottom, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.bottom, filechooser paned > box scrolledwindow scrollbar.bottom, placessidebar > scrolledwindow > scrollbar.bottom, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.bottom, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.bottom, leaflet.unfolded > box > scrolledwindow > scrollbar.bottom, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.bottom, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.bottom { + border-top: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.left, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.left, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.left, filechooser paned > box scrolledwindow scrollbar.left, placessidebar > scrolledwindow > scrollbar.left, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.left, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.left, leaflet.unfolded > box > scrolledwindow > scrollbar.left, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.left, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.left { + border-right: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.right, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.right, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.right, filechooser paned > box scrolledwindow scrollbar.right, placessidebar > scrolledwindow > scrollbar.right, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.right, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.right, leaflet.unfolded > box > scrolledwindow > scrollbar.right, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.right, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.right { + border-left: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering), .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) { + border-color: transparent; + background-color: transparent; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, filechooser paned > box scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, placessidebar > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator:not(.dragging):not(.hovering) button { + border: none; +} + +.sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.dragging, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.dragging, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.dragging, placessidebar > scrolledwindow > scrollbar.overlay-indicator.dragging, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.dragging, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.dragging, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.dragging, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.dragging, .sidebar-pane .sidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane toolbarview > scrolledwindow > scrollbar.overlay-indicator.hovering, +.sidebar-pane navigation-view-page stack > scrolledwindow > scrollbar.overlay-indicator.hovering, filechooser paned > box scrolledwindow scrollbar.overlay-indicator.hovering, placessidebar > scrolledwindow > scrollbar.overlay-indicator.hovering, .nautilus-window .nautilus-grid-view scrolledwindow scrollbar.overlay-indicator.hovering, +.nautilus-window .nautilus-list-view scrolledwindow scrollbar.overlay-indicator.hovering, leaflet.unfolded > box > scrolledwindow > scrollbar.overlay-indicator.hovering, leaflet.unfolded .contacts-contact-list > scrolledwindow > scrollbar.overlay-indicator.hovering, .sidebar-pane toolbarview > stack > box > widget > widget > scrolledwindow > scrollbar.overlay-indicator.hovering { + background-color: transparent; +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-top > undershoot.top, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-top > undershoot.top { + border-radius: 12px 12px 0 0; + box-shadow: none; + background: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-bottom > undershoot.bottom, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-bottom > undershoot.bottom { + border-radius: 0 0 12px 12px; + box-shadow: none; + background: linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(ltr) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-start:dir(rtl) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(ltr) > undershoot.right { + border-radius: 0 12px 12px 0; + box-shadow: none; + background: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +.nautilus-window .nautilus-grid-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left, +.nautilus-window .nautilus-list-view scrolledwindow.undershoot-end:dir(rtl) > undershoot.left { + border-radius: 12px 0 0 12px; + box-shadow: none; + background: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.75), transparent 4px); +} + +avatar { + border-radius: 9999px; + font-weight: bold; +} + +avatar.color1 { + background-image: linear-gradient(#83b6ec, #337fdc); + color: #cfe1f5; +} + +avatar.color2 { + background-image: linear-gradient(#7ad9f1, #0f9ac8); + color: #caeaf2; +} + +avatar.color3 { + background-image: linear-gradient(#8de6b1, #29ae74); + color: #cef8d8; +} + +avatar.color4 { + background-image: linear-gradient(#b5e98a, #6ab85b); + color: #e6f9d7; +} + +avatar.color5 { + background-image: linear-gradient(#f8e359, #d29d09); + color: #f9f4e1; +} + +avatar.color6 { + background-image: linear-gradient(#ffcb62, #d68400); + color: #ffead1; +} + +avatar.color7 { + background-image: linear-gradient(#ffa95a, #ed5b00); + color: #ffe5c5; +} + +avatar.color8 { + background-image: linear-gradient(#f78773, #e62d42); + color: #f8d2ce; +} + +avatar.color9 { + background-image: linear-gradient(#e973ab, #e33b6a); + color: #fac7de; +} + +avatar.color10 { + background-image: linear-gradient(#cb78d4, #9945b5); + color: #e7c2e8; +} + +avatar.color11 { + background-image: linear-gradient(#9e91e8, #7a59ca); + color: #d5d2f5; +} + +avatar.color12 { + background-image: linear-gradient(#e3cf9c, #b08952); + color: #f2eade; +} + +avatar.color13 { + background-image: linear-gradient(#be916d, #785336); + color: #e5d6ca; +} + +avatar.color14 { + background-image: linear-gradient(#c0bfbc, #6e6d71); + color: #d8d7d3; +} + +avatar.contrasted { + color: #fbf1c7; +} + +avatar.image { + background: none; +} + +.card { + border-radius: 12px; + border: 1px solid rgba(251, 241, 199, 0.12); + background-clip: border-box; + color: rgba(251, 241, 199, 0.7); + box-shadow: none; + outline: none; + background-color: rgba(251, 241, 199, 0.04); + color: #fbf1c7; +} + +.card.activatable { + background-color: rgba(251, 241, 199, 0.08); + color: #fbf1c7; + border: none; + box-shadow: none; + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 300ms cubic-bezier(0, 0, 0.2, 1), background-image 1200ms cubic-bezier(0, 0, 0.2, 1), outline 300ms cubic-bezier(0, 0, 0.2, 1); + background-color: rgba(251, 241, 199, 0.04); +} + +.card.activatable:hover { + background-color: alpha(currentColor, 0.08); + color: #fbf1c7; + outline: 0 solid transparent; +} + +.card.activatable:active { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); + transition: all 75ms cubic-bezier(0, 0, 0.2, 1), background-size 0ms, background-image 0ms, border 0ms; +} + +toast { + margin: 12px; + margin-bottom: 24px; + border-radius: 9999px; + border-spacing: 6px; + padding: 6px; + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.1), 0 4px 6px 0 rgba(0, 0, 0, 0.12), 0 1px 10px 0 rgba(0, 0, 0, 0.1), inset 0 1px rgba(251, 241, 199, 0.1); + background-color: #242220; + color: #fbf1c7; + border: none; +} + +toast:dir(ltr) { + padding-left: 12px; +} + +toast:dir(rtl) { + padding-right: 12px; +} + +toast > label { + margin: 0 6px; +} + +viewswitcher { + min-height: 0; + padding: 3px; + margin: 6px 0; + border-radius: 12px; + background-color: rgba(251, 241, 199, 0.04); + border: none; +} + +viewswitcher.wide { + margin-top: 6px; + margin-bottom: 6px; +} + +viewswitcher.wide button.toggle { + margin: 0; + border-radius: 9px; +} + +viewswitcher.narrow button.toggle { + border-radius: 0; + margin: 0; +} + +viewswitcher.narrow button.toggle:focus-within, viewswitcher.narrow button.toggle:focus { + box-shadow: none; +} + +viewswitcher button.toggle { + font-weight: bold; + padding: 0; +} + +viewswitcher button.toggle > stack > box.narrow { + font-size: 0.75rem; + padding-top: 6px; + padding-bottom: 4px; + border-spacing: 4px; +} + +viewswitcher button.toggle > stack > box.narrow > stack > label { + padding-left: 6px; + padding-right: 6px; +} + +viewswitcher button.toggle > stack > box.wide { + padding: 2px 12px; + border-spacing: 6px; +} + +viewswitcherbar actionbar > revealer > box { + padding: 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle { + border-radius: 12px; + margin: 3px 0; +} + +viewswitcherbar actionbar > revealer > box viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 5px; + padding-bottom: 1px; + border-spacing: 0; +} + +viewswitchertitle { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher { + margin-left: 12px; + margin-right: 12px; +} + +viewswitchertitle viewswitcher.narrow { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle viewswitcher.narrow button.toggle > stack > box.narrow { + padding-top: 0; + padding-bottom: 0; + border-spacing: 0; +} + +viewswitchertitle viewswitcher.wide { + margin-top: 0; + margin-bottom: 0; +} + +viewswitchertitle windowtitle { + margin-top: 0; + margin-bottom: 0; +} + +indicatorbin > indicator, +indicatorbin > mask { + min-width: 6px; + min-height: 6px; + border-radius: 9999px; +} + +indicatorbin > indicator { + margin: 1px; + background-color: alpha(currentColor, 0.4); +} + +indicatorbin > indicator > label { + font-size: 0.6rem; + font-weight: bold; + padding: 1px 4px; + color: #fbf1c7; +} + +indicatorbin > mask { + padding: 1px; + background: black; +} + +indicatorbin.needs-attention > indicator { + background-color: #7daea3; +} + +indicatorbin.needs-attention > indicator > label { + color: rgba(40, 40, 40, 0.87); +} + +preferencespage > scrolledwindow > viewport > clamp > box { + margin: 24px 12px; + border-spacing: 24px; +} + +preferencesgroup > box background-preview widget.sidebar, +preferencesgroup > box widget.header-bar:not(.editable-area) { + background-color: #0d0907; +} + +preferencesgroup > box, +preferencesgroup > box .labels { + border-spacing: 6px; +} + +preferencesgroup > box > box.header:not(.single-line) { + margin-bottom: 6px; +} + +preferencesgroup > box > box.single-line { + min-height: 34px; +} + +preferencesgroup > box button.background-preview-button.toggle { + padding: 0; + background: none; + box-shadow: none; + outline-color: transparent; + outline-width: 3px; + outline-offset: 3px; + outline-style: solid; +} + +preferencesgroup > box button.background-preview-button.toggle, +preferencesgroup > box button.background-preview-button.toggle > background-preview { + border-radius: 12px; +} + +preferencesgroup > box button.background-preview-button.toggle:hover { + outline-color: rgba(251, 241, 199, 0.04); +} + +preferencesgroup > box button.background-preview-button.toggle:active { + outline-color: rgba(251, 241, 199, 0.3); +} + +preferencesgroup > box button.background-preview-button.toggle:checked { + outline-color: #7daea3; +} + +preferencesgroup > box .cutout-button { + background-color: #282524; +} + +preferencesgroup > box button.accent-button { + min-height: 24px; + min-width: 24px; + padding: 3px; + border-radius: 9px; + background: var(--accent-bg-color); + outline: none; + background-clip: content-box; + box-shadow: none; +} + +preferencesgroup > box button.accent-button:hover { + box-shadow: 0 0 0 3px alpha(currentColor, 0.08); +} + +preferencesgroup > box button.accent-button:checked { + box-shadow: 0 0 0 3px #7daea3; +} + +preferencesgroup > box button.accent-button.blue, preferencesgroup > box button.accent-button.teal, preferencesgroup > box button.accent-button.green, preferencesgroup > box button.accent-button.yellow, preferencesgroup > box button.accent-button.orange, preferencesgroup > box button.accent-button.red, preferencesgroup > box button.accent-button.pink, preferencesgroup > box button.accent-button.purple, preferencesgroup > box button.accent-button.slate { + --accent-color: oklab( + from var(--accent-bg-color) var(--standalone-color-oklab) + ); +} + +preferencesgroup > box button.accent-button.blue { + --accent-bg-color: var(--accent-blue); +} + +preferencesgroup > box button.accent-button.teal { + --accent-bg-color: var(--accent-teal); +} + +preferencesgroup > box button.accent-button.green { + --accent-bg-color: var(--accent-green); +} + +preferencesgroup > box button.accent-button.yellow { + --accent-bg-color: var(--accent-yellow); +} + +preferencesgroup > box button.accent-button.orange { + --accent-bg-color: var(--accent-orange); +} + +preferencesgroup > box button.accent-button.red { + --accent-bg-color: var(--accent-red); +} + +preferencesgroup > box button.accent-button.pink { + --accent-bg-color: var(--accent-pink); +} + +preferencesgroup > box button.accent-button.purple { + --accent-bg-color: var(--accent-purple); +} + +preferencesgroup > box button.accent-button.slate { + --accent-bg-color: var(--accent-slate); +} + +preferencesgroup > box box > list.boxed-list-separate { + background-color: transparent; + border-radius: 12px; + border: 1px solid rgba(251, 241, 199, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row { + color: rgba(251, 241, 199, 0.7); + background-color: rgba(251, 241, 199, 0.04); + border-radius: 12px 12px 0 0; + margin-top: 0px; + margin-bottom: 0px; +} + +preferencesgroup > box box > list.boxed-list-separate row:first-child { + border-radius: 12px 12px 0 0; + box-shadow: 0 1px rgba(251, 241, 199, 0.12); +} + +preferencesgroup > box box > list.boxed-list-separate row:last-child { + border-radius: 0 0 12px 12px; +} + +preferencesgroup > box box > list.boxed-list-separate row:hover, preferencesgroup > box box > list.boxed-list-separate row:focus { + color: #fbf1c7; + background-color: alpha(currentColor, 0.12); +} + +window.about .main-page > viewport > clamp > box { + margin: 12px; + border-spacing: 6px; +} + +window.about .main-page > viewport > clamp > box > box { + margin-top: 18px; + border-spacing: 18px; + margin-bottom: 6px; +} + +window.about .main-page .app-version { + padding: 3px 18px; + color: #7daea3; + border-radius: 12px; + margin-top: 3px; +} + +window.about .subpage > viewport > clamp > box { + margin: 18px 12px; + border-spacing: 18px; +} + +window.about .subpage > clamp > textview { + background: none; + color: inherit; +} + +statuspage > scrolledwindow > viewport > box { + margin: 36px 12px; + border-spacing: 36px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box { + border-spacing: 12px; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 128px; + color: alpha(currentColor, 0.55); +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:disabled { + opacity: 0.35; +} + +statuspage > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box { + margin: 24px 12px; + border-spacing: 24px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon { + -gtk-icon-size: 96px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .icon:not(:last-child) { + margin-bottom: 12px; +} + +statuspage.compact > scrolledwindow > viewport > box > clamp > box > .title { + font-size: 18pt; +} + +flap > dimming, +leaflet > dimming, +navigation-view > dimming, +overlay-split-view > dimming { + background-color: rgba(40, 40, 40, 0.2); + background-image: none; +} + +flap > border, +leaflet > border, +navigation-view > border, +overlay-split-view > border { + background-color: transparent; + background-image: none; +} + +flap > shadow, +leaflet > shadow, +navigation-view > shadow, +overlay-split-view > shadow { + min-width: 56px; + min-height: 56px; +} + +flap > shadow.left, +leaflet > shadow.left, +navigation-view > shadow.left, +overlay-split-view > shadow.left { + background-image: linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to right, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +flap > shadow.right, +leaflet > shadow.right, +navigation-view > shadow.right, +overlay-split-view > shadow.right { + background-image: linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to left, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +flap > shadow.up, +leaflet > shadow.up, +navigation-view > shadow.up, +overlay-split-view > shadow.up { + background-image: linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to bottom, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +flap > shadow.down, +leaflet > shadow.down, +navigation-view > shadow.down, +overlay-split-view > shadow.down { + background-image: linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.7), alpha(rgba(40, 40, 40, 0.2), 0.14) 40px, alpha(rgba(40, 40, 40, 0.2), 0) 56px), linear-gradient(to top, alpha(rgba(40, 40, 40, 0.2), 0.4), alpha(rgba(40, 40, 40, 0.2), 0.14) 7px, alpha(rgba(40, 40, 40, 0.2), 0) 24px); +} + +.sidebar-pane { + color: #fbf1c7; + border-top-left-radius: 12px; +} + +.sidebar-pane .sidebar-pane { + background-color: transparent; + color: inherit; +} + +.sidebar-pane headerbar, +.sidebar-pane .navigation-sidebar, +.sidebar-pane searchbar > revealer > box { + background-color: transparent; + box-shadow: none; + border: none; +} + +.sidebar-pane .navigation-sidebar { + padding: 2px 4px; + background: none; + color: rgba(251, 241, 199, 0.7); +} + +.sidebar-pane:dir(ltr), +.sidebar-pane:dir(ltr) banner > revealer > widget, .sidebar-pane.end:dir(rtl), +.sidebar-pane.end:dir(rtl) banner > revealer > widget { + /* box-shadow: inset 0 1px highlight($base-alt); */ + border-right: 1px solid rgba(251, 241, 199, 0.12); +} + +/* Middle pane in three-pane setups */ +.content-pane .sidebar-pane, +.sidebar-pane .content-pane { + background-color: transparent; + color: #fbf1c7; +} + +.content-pane .sidebar-pane:backdrop, +.sidebar-pane .content-pane:backdrop { + background-color: transparent; + transition: none; +} + +.content-pane { + background-color: #282828; + color: #fbf1c7; + border-top-right-radius: 12px; + /* box-shadow: inset 0 1px highlight($background); */ +} + +.content-pane headerbar, .content-pane headerbar:backdrop { + background-color: transparent; + box-shadow: none; + border: none; +} + +.maximized .content-pane, .fullscreen .content-pane, .tiled .content-pane, .tiled-top .content-pane, .tiled-right .content-pane, .tiled-bottom .content-pane, .tiled-left .content-pane { + border-radius: 0; + box-shadow: inset 0 1px rgba(251, 241, 199, 0.1); +} + +.top-bar { + box-shadow: none; + background: none; + border: none; +} + +.top-bar headerbar, .top-bar headerbar:backdrop { + background-color: transparent; + box-shadow: none; +} + +.top-bar .collapse-spacing { + padding: 0; +} + +themeselector, +panelthemeselector { + margin: 9px; +} + +themeselector checkbutton, +panelthemeselector checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.12); +} + +themeselector checkbutton.follow:checked, themeselector checkbutton.light:checked, themeselector checkbutton.dark:checked, +panelthemeselector checkbutton.follow:checked, +panelthemeselector checkbutton.light:checked, +panelthemeselector checkbutton.dark:checked { + box-shadow: inset 0 0 0 2px #7daea3; +} + +themeselector checkbutton.follow, +panelthemeselector checkbutton.follow { + background-image: linear-gradient(to bottom right, #f9f5d7 50%, #211f1e 50%); +} + +themeselector checkbutton.light, +panelthemeselector checkbutton.light { + background-color: #f9f5d7; +} + +themeselector checkbutton.dark, +panelthemeselector checkbutton.dark { + background-color: #211f1e; +} + +themeselector checkbutton.theme-selector radio, +panelthemeselector checkbutton.theme-selector radio { + -gtk-icon-source: none; + border: none; + background: none; + box-shadow: none; + min-height: 20px; + min-width: 20px; + padding: 0; +} + +themeselector checkbutton.theme-selector radio:hover, themeselector checkbutton.theme-selector radio:active, themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:hover, +panelthemeselector checkbutton.theme-selector radio:active, +panelthemeselector checkbutton.theme-selector radio:checked { + background-color: transparent; +} + +themeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked { + -gtk-icon-size: 20px; + -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/checkbox-checked-symbolic.svg")), -gtk-recolor(url("assets/checkbox-checked-symbolic@2.svg"))); + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +themeselector checkbutton.theme-selector radio:checked, themeselector checkbutton.theme-selector radio:checked:hover, themeselector checkbutton.theme-selector radio:checked:active, +panelthemeselector checkbutton.theme-selector radio:checked, +panelthemeselector checkbutton.theme-selector radio:checked:hover, +panelthemeselector checkbutton.theme-selector radio:checked:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher { + padding: 6px; +} + +themeswitcher .check { + min-height: 20px; + min-width: 20px; + background: none; + padding: 0; + margin: 0; + border-radius: 9999px; + color: rgba(40, 40, 40, 0.87); + background-color: #7daea3; +} + +themeswitcher .check, themeswitcher .check:hover, themeswitcher .check:active { + box-shadow: 0 2px 3px -1px rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.1); +} + +themeswitcher checkbutton { + padding: 0; + min-height: 44px; + min-width: 44px; + padding: 1px; + background-clip: content-box; + border-radius: 9999px; + box-shadow: inset 0 0 0 1px rgba(251, 241, 199, 0.12); +} + +themeswitcher checkbutton:checked { + box-shadow: inset 0 0 0 2px #7daea3; +} + +themeswitcher checkbutton radio, themeswitcher checkbutton radio:hover, themeswitcher checkbutton radio:active, themeswitcher checkbutton radio:checked, themeswitcher checkbutton radio:checked:hover, themeswitcher checkbutton radio:checked:active { + background-color: transparent; + border: none; + background: none; + box-shadow: none; + color: transparent; + -gtk-icon-source: none; + -gtk-icon-size: 0; +} + +themeswitcher checkbutton.system { + background: linear-gradient(-45deg, #282828 50%, #fbf1c7 50%); +} + +themeswitcher checkbutton.light { + color: alpha(black, 0.8); + background-color: #fbf1c7; +} + +themeswitcher checkbutton.dark { + color: #fbf1c7; + background-color: #282828; +} + +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +/* widget text/foreground color */ +@define-color theme_fg_color #fbf1c7; +/* text color for entries, views and content in general */ +@define-color theme_text_color #fbf1c7; +/* widget base background color */ +@define-color theme_bg_color #282828; +/* text widgets and the like base background color */ +@define-color theme_base_color #282524; +/* base background color of selections */ +@define-color theme_selected_bg_color #7daea3; +/* text/foreground color of selections */ +@define-color theme_selected_fg_color rgba(40, 40, 40, 0.87); +/* base background color of insensitive widgets */ +@define-color insensitive_bg_color #282828; +/* text foreground color of insensitive widgets */ +@define-color insensitive_fg_color rgba(251, 241, 199, 0.5); +/* insensitive text widgets and the like base background color */ +@define-color insensitive_base_color #282524; +/* widget text/foreground color on backdrop windows */ +@define-color theme_unfocused_fg_color #fbf1c7; +/* text color for entries, views and content in general on backdrop windows */ +@define-color theme_unfocused_text_color #fbf1c7; +/* widget base background color on backdrop windows */ +@define-color theme_unfocused_bg_color #282828; +/* text widgets and the like base background color on backdrop windows */ +@define-color theme_unfocused_base_color #282524; +/* base background color of selections on backdrop windows */ +@define-color theme_unfocused_selected_bg_color #7daea3; +/* text/foreground color of selections on backdrop windows */ +@define-color theme_unfocused_selected_fg_color rgba(40, 40, 40, 0.87); +/* insensitive color on backdrop windows */ +@define-color unfocused_insensitive_color rgba(251, 241, 199, 0.5); +/* widgets main borders color */ +@define-color borders rgba(251, 241, 199, 0.12); +/* widgets main borders color on backdrop windows */ +@define-color unfocused_borders rgba(251, 241, 199, 0.12); +/* these are pretty self explicative */ +@define-color warning_color #b47109; +@define-color error_color #c14a4a; +@define-color success_color #6c782e; +/* these colors are exported for the window manager and shouldn't be used in applications, +read if you used those and something break with a version upgrade you're on your own... */ +@define-color wm_focused_title #fbf1c7; +@define-color wm_unfocused_title rgba(251, 241, 199, 0.7); +@define-color wm_highlight rgba(251, 241, 199, 0.1); +@define-color wm_border #080707; +@define-color wm_focused_bg #282828; +@define-color wm_unfocused_bg #282828; +@define-color wm_button_icon #fbf1c7; +@define-color wm_button_icon alpha(black, 0.5); +@define-color wm_button_focused_bg #353432; +@define-color wm_button_unfocused_bg #353432; +@define-color wm_button_hover_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_active_fg rgba(40, 40, 40, 0.87); +@define-color wm_button_hover_bg #fbf1c7; +@define-color wm_button_active_bg #fbf1c7; +/* FIXME this is really an API */ +@define-color content_view_bg #282524; +@define-color placeholder_text_color #bcb496; +/* Very contrasty background for text views (@theme_text_color foreground) */ +@define-color text_view_bg #282524; +@define-color budgie_tasklist_indicator_color rgba(132, 128, 110, 0.7); +@define-color budgie_tasklist_indicator_color_active #7daea3; +@define-color budgie_tasklist_indicator_color_active_window rgba(102, 138, 130, 0.816); +@define-color budgie_tasklist_indicator_color_attention #b47109; +@define-color STRAWBERRY_100 #FF9262; +@define-color STRAWBERRY_300 #FF793E; +@define-color STRAWBERRY_500 #F15D22; +@define-color STRAWBERRY_700 #CF3B00; +@define-color STRAWBERRY_900 #AC1800; +@define-color ORANGE_100 #FFDB91; +@define-color ORANGE_300 #FFCA40; +@define-color ORANGE_500 #FAA41A; +@define-color ORANGE_700 #DE8800; +@define-color ORANGE_900 #C26C00; +@define-color BANANA_100 #FFFFA8; +@define-color BANANA_300 #FFFA7D; +@define-color BANANA_500 #FFCE51; +@define-color BANANA_700 #D1A023; +@define-color BANANA_900 #A27100; +@define-color LIME_100 #A2F3BE; +@define-color LIME_300 #8ADBA6; +@define-color LIME_500 #73C48F; +@define-color LIME_700 #479863; +@define-color LIME_900 #1C6D38; +@define-color BLUEBERRY_100 #94A6FF; +@define-color BLUEBERRY_300 #6A7CE0; +@define-color BLUEBERRY_500 #3F51B5; +@define-color BLUEBERRY_700 #213397; +@define-color BLUEBERRY_900 #031579; +@define-color GRAPE_100 #D25DE6; +@define-color GRAPE_300 #B84ACB; +@define-color GRAPE_500 #9C27B0; +@define-color GRAPE_700 #830E97; +@define-color GRAPE_900 #6A007E; +@define-color COCOA_100 #9F9792; +@define-color COCOA_300 #7B736E; +@define-color COCOA_500 #574F4A; +@define-color COCOA_700 #463E39; +@define-color COCOA_900 #342C27; +@define-color SILVER_100 #EEE; +@define-color SILVER_300 #CCC; +@define-color SILVER_500 #AAA; +@define-color SILVER_700 #888; +@define-color SILVER_900 #666; +@define-color SLATE_100 #888; +@define-color SLATE_300 #666; +@define-color SLATE_500 #444; +@define-color SLATE_700 #222; +@define-color SLATE_900 #111; +@define-color BLACK_100 #474341; +@define-color BLACK_300 #403C3A; +@define-color BLACK_500 #393634; +@define-color BLACK_700 #33302F; +@define-color BLACK_900 #2B2928; +@define-color blue_1 #99c1f1; +@define-color blue_2 #62a0ea; +@define-color blue_3 #3584e4; +@define-color blue_4 #1c71d8; +@define-color blue_5 #1a5fb4; +@define-color green_1 #8ff0a4; +@define-color green_2 #57e389; +@define-color green_3 #33d17a; +@define-color green_4 #2ec27e; +@define-color green_5 #26a269; +@define-color yellow_1 #f9f06b; +@define-color yellow_2 #f8e45c; +@define-color yellow_3 #f6d32d; +@define-color yellow_4 #f5c211; +@define-color yellow_5 #e5a50a; +@define-color orange_1 #ffbe6f; +@define-color orange_2 #ffa348; +@define-color orange_3 #ff7800; +@define-color orange_4 #e66100; +@define-color orange_5 #c64600; +@define-color red_1 #f66151; +@define-color red_2 #ed333b; +@define-color red_3 #e01b24; +@define-color red_4 #c01c28; +@define-color red_5 #a51d2d; +@define-color purple_1 #dc8add; +@define-color purple_2 #c061cb; +@define-color purple_3 #9141ac; +@define-color purple_4 #813d9c; +@define-color purple_5 #613583; +@define-color brown_1 #cdab8f; +@define-color brown_2 #b5835a; +@define-color brown_3 #986a44; +@define-color brown_4 #865e3c; +@define-color brown_5 #63452c; +@define-color light_1 #ffffff; +@define-color light_2 #f6f5f4; +@define-color light_3 #deddda; +@define-color light_4 #c0bfbc; +@define-color light_5 #9a9996; +@define-color dark_1 #77767b; +@define-color dark_2 #5e5c64; +@define-color dark_3 #3d3846; +@define-color dark_4 #241f31; +@define-color dark_5 #000000; +/* GTK NAMED COLORS + ---------------- + use responsibly! */ +@define-color accent_bg_color #7daea3; +@define-color accent_fg_color rgba(40, 40, 40, 0.87); +@define-color accent_color #7daea3; +@define-color destructive_bg_color #c14a4a; +@define-color destructive_fg_color #fbf1c7; +@define-color destructive_color #c14a4a; +@define-color success_bg_color #6c782e; +@define-color success_fg_color #fbf1c7; +@define-color success_color #6c782e; +@define-color warning_bg_color #b47109; +@define-color warning_fg_color #fbf1c7; +@define-color warning_color #b47109; +@define-color error_bg_color #c14a4a; +@define-color error_fg_color #fbf1c7; +@define-color error_color #c14a4a; +@define-color window_bg_color #282828; +@define-color window_fg_color #fbf1c7; +@define-color view_bg_color #282524; +@define-color view_fg_color #fbf1c7; +@define-color headerbar_bg_color #282828; +@define-color headerbar_fg_color #fbf1c7; +@define-color headerbar_border_color rgba(251, 241, 199, 0.12); +@define-color headerbar_backdrop_color #282828; +@define-color headerbar_shade_color rgba(251, 241, 199, 0.12); +@define-color card_bg_color #282524; +@define-color card_fg_color #fbf1c7; +@define-color card_shade_color rgba(251, 241, 199, 0.12); +@define-color dialog_bg_color #282524; +@define-color dialog_fg_color #fbf1c7; +@define-color popover_bg_color #242220; +@define-color popover_fg_color #fbf1c7; +@define-color shade_color rgba(251, 241, 199, 0.12); +@define-color scrollbar_outline_color rgba(251, 241, 199, 0.12); diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/thumbnail.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/thumbnail.png new file mode 100755 index 0000000..9e8bc77 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/gtk-4.0/thumbnail.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/index.theme b/local/share/themes/Gruvbox-B-LB-Dark-Medium/index.theme new file mode 100755 index 0000000..b26491d --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/index.theme @@ -0,0 +1,12 @@ +Type=X-GNOME-Metatheme +[Desktop Entry] +Name=Gruvbox-B-LB-Dark-Medium +Comment=An Flat Gtk+ theme based on Elegant Design +Encoding=UTF-8 + +[X-GNOME-Metatheme] +GtkTheme=Gruvbox-B-LB-Dark-Medium +MetacityTheme=Gruvbox-B-LB-Dark-Medium +IconTheme=Tela-circle-Dark +CursorTheme=Gruvbox-B-LB-cursors +ButtonLayout=close,minimize,maximize:menu diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/button.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/button.svg new file mode 100755 index 0000000..c2a738d --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/button.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="22" + height="22" + viewBox="0 0 22 22" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="button.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="11.5625" + inkscape:cx="2.8972973" + inkscape:cy="10.940541" + inkscape:window-width="1368" + inkscape:window-height="687" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <circle + cx="11" + cy="11" + r="11" + id="circle2" + style="stroke-width:1.375" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/close.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/close.svg new file mode 100755 index 0000000..fb798d7 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/close.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="close.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="11.978378" + inkscape:cy="12" + inkscape:window-width="1600" + inkscape:window-height="823" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <path + d="m 4.464745,3.96488 c -0.12775,0 -0.2555,0.0486 -0.35339,0.14649 -0.19578,0.19586 -0.19578,0.51116 0,0.70703 L 7.292955,8 l -3.1816,3.1816 c -0.19578,0.19586 -0.19578,0.51116 0,0.70703 0.19578,0.19586 0.51118,0.19586 0.70704,0 l 3.18161,-3.1816 3.1816,3.1816 c 0.19578,0.19586 0.51114,0.19586 0.70704,0 0.19578,-0.19586 0.19578,-0.51116 0,-0.70703 L 8.707045,8 l 3.1816,-3.1816 c 0.19578,-0.19586 0.19578,-0.51116 0,-0.70703 -0.19578,-0.19586 -0.51117,-0.19586 -0.70704,0 l -3.1816,3.1816 -3.18161,-3.1816 C 4.720495,4.01347 4.592755,3.96488 4.465005,3.96488 Z" + id="path2928" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/maximize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/maximize.svg new file mode 100755 index 0000000..0c2f170 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/maximize.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="maximize.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="11.978378" + inkscape:cy="12" + inkscape:window-width="1600" + inkscape:window-height="823" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <path + d="M 6,4 C 4.892,4 4,4.892 4,6 v 4 c 0,1.108 0.89201,2 2,2 h 4 c 1.10801,0 2,-0.892 2,-2 V 6 C 12,4.892 11.10799,4 10,4 Z m 0,1 h 4 c 0.554,0 1,0.44602 1,1 v 4 c 0,0.55398 -0.44602,1 -1,1 H 6 C 5.44603,11 5.00001,10.55398 5.00001,10 V 6 C 5.00001,5.44602 5.44604,5 6,5 Z" + id="path2930" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/menu.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/menu.svg new file mode 100755 index 0000000..179ff4c --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/menu.svg @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="menu.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="11.891892" + inkscape:cy="12" + inkscape:window-width="1200" + inkscape:window-height="675" + inkscape:window-x="190" + inkscape:window-y="85" + inkscape:window-maximized="0" + inkscape:current-layer="svg4" /> + <circle + cx="8" + cy="8" + r="2" + id="circle2" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/minimize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/minimize.svg new file mode 100755 index 0000000..76fe7cb --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/minimize.svg @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="minimize.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="true" + inkscape:zoom="65.407377" + inkscape:cx="7.246889" + inkscape:cy="9.3032319" + inkscape:window-width="1600" + inkscape:window-height="823" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4"> + <inkscape:grid + type="xygrid" + id="grid913" /> + </sodipodi:namedview> + <rect + x="4" + y="8" + width="8" + height="1" + rx="0.5" + ry="0.5" + id="rect2932" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/shade.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/shade.svg new file mode 100755 index 0000000..8213b03 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/shade.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="shade.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="11.978378" + inkscape:cy="12" + inkscape:window-width="1600" + inkscape:window-height="823" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <path + d="m 8.00007,4.464835 -6.3633,6.3633 0.70703,0.70703 5.6562,-5.6562 5.6562,5.6562 0.70703,-0.70703 -5.6562,-5.6562 z" + id="path199" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unmaximize.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unmaximize.svg new file mode 100755 index 0000000..8d60a57 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unmaximize.svg @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="unmaximize.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1600" + inkscape:window-height="823" + id="namedview6" + showgrid="true" + inkscape:zoom="5.2291666" + inkscape:cx="-24.095618" + inkscape:cy="33.179283" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid835" /> + </sodipodi:namedview> + <g + id="g917" + transform="translate(-4,-3)"> + <path + d="M 10,9 C 8.892,9 8,9.892 8,11 v 2 c 0,1.108 0.892,2 2,2 h 2 c 1.108,0 2,-0.892 2,-2 V 11 C 14,9.892 13.108,9 12,9 Z m 0,1 h 2 c 0.554,0 1,0.446 1,1 v 2 c 0,0.554 -0.446,1 -1,1 H 10 C 9.446,14 9,13.554 9,13 v -2 c 0,-0.554 0.446,-1 1,-1 z" + id="path2896" /> + <path + d="m 12,7 c -1.108,0 -2,0.892 -2,2 h 1 c 0,-0.554 0.446,-1 1,-1 h 2 c 0.554,0 1,0.446 1,1 v 2 c 0,0.554 -0.446,1 -1,1 v 1 c 1.108,0 2,-0.892 2,-2 V 9 C 16,7.892 15.108,7 14,7 Z" + opacity="0.35" + id="path2898" /> + </g> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unshade.svg b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unshade.svg new file mode 100755 index 0000000..a161564 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/assets/unshade.svg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + fill="#808080" + version="1.1" + id="svg4" + sodipodi:docname="unshade.svg" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs8" /> + <sodipodi:namedview + id="namedview6" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="23.125" + inkscape:cx="11.978378" + inkscape:cy="12" + inkscape:window-width="1600" + inkscape:window-height="823" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <path + d="m 8.00007,11.535165 -6.3633,-6.3633 0.70703,-0.70703 5.6562,5.6562 5.6562,-5.6562 0.70703,0.70703 -5.6562,5.6562 z" + id="path231" /> +</svg> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-1.xml b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-1.xml new file mode 120000 index 0000000..562ac74 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-1.xml @@ -0,0 +1 @@ +metacity-theme-3.xml \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-2.xml b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-2.xml new file mode 120000 index 0000000..562ac74 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-2.xml @@ -0,0 +1 @@ +metacity-theme-3.xml \ No newline at end of file diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-3.xml b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-3.xml new file mode 100755 index 0000000..250a8fa --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/metacity-theme-3.xml @@ -0,0 +1,820 @@ +<?xml version="1.0"?> +<metacity_theme> +<info> + <name>Tokyonight</name> + <author>vinceliucie | mod: fkorpsvart</author> + <copyright>GPL</copyright> + <date>2024</date> + <description>Tokyonight Metacity theme</description> +</info> + +<!-- meaningful constants --> + +<constant name="C_titlebar_focused" value="gtk:custom(wm_bg,gtk:bg[NORMAL])"/> +<constant name="C_titlebar_unfocused" value="gtk:custom(wm_unfocused_bg,gtk:bg[NORMAL])"/> +<constant name="C_highlight_focused" value="gtk:custom(wm_highlight,gtk:base[NORMAL])"/> +<constant name="C_highlight_unfocused" value="gtk:custom(wm_highlight,gtk:base[NORMAL])"/> +<constant name="C_title_focused" value="gtk:custom(wm_title,gtk:fg[NORMAL])"/> +<constant name="C_title_unfocused" value="gtk:custom(wm_unfocused_title,gtk:fg[INSENSITIVE])"/> +<constant name="C_border_focused" value="gtk:custom(wm_border,blend/#000000/gtk:bg[NORMAL]/0.5)"/> +<constant name="C_border_unfocused" value="gtk:custom(wm_border,blend/#000000/gtk:bg[NORMAL]/0.65)"/> + +<!-- geometries --> + +<frame_geometry name="normal" title_scale="medium" rounded_top_left="10" rounded_top_right="10"> + <distance name="left_width" value="1"/> + <distance name="right_width" value="1"/> + <distance name="bottom_height" value="1"/> + <distance name="left_titlebar_edge" value="6"/> + <distance name="right_titlebar_edge" value="6"/> + <distance name="title_vertical_pad" value="10"/> + <border name="title_border" left="10" right="10" top="6" bottom="6"/> + <border name="button_border" left="3" right="3" top="5" bottom="5"/> + <aspect_ratio name="button" value="1"/> +</frame_geometry> + +<frame_geometry name="max" rounded_top_left="false" rounded_top_right="false" parent="normal"> + <distance name="left_width" value="0"/> + <distance name="right_width" value="0"/> + <distance name="bottom_height" value="0"/> +</frame_geometry> + +<frame_geometry name="tiled_left" parent="max"> + <distance name="right_width" value="1"/> +</frame_geometry> + +<frame_geometry name="tiled_right" parent="max"> + <distance name="left_width" value="1"/> +</frame_geometry> + +<frame_geometry name="nobuttons" hide_buttons="true" parent="normal"> +</frame_geometry> + +<frame_geometry name="modal" parent="normal"> +</frame_geometry> + +<frame_geometry name="small" title_scale="small" parent="normal"> + <distance name="title_vertical_pad" value="8"/> +</frame_geometry> + +<frame_geometry name="border" has_title="false" rounded_top_left="false" rounded_top_right="false" parent="normal"> + <distance name="left_width" value="1"/> + <distance name="right_width" value="1"/> + <distance name="bottom_height" value="1"/> + <distance name="title_vertical_pad" value="0"/> + <border name="title_border" left="10" right="10" top="0" bottom="0"/> + <border name="button_border" left="0" right="0" top="0" bottom="0"/> +</frame_geometry> + +<frame_geometry name="borderless" has_title="false" rounded_top_left="false" rounded_top_right="false" parent="normal"> + <distance name="left_width" value="0"/> + <distance name="right_width" value="0"/> + <distance name="bottom_height" value="0"/> + <distance name="title_vertical_pad" value="0"/> + <border name="button_border" left="0" right="0" top="0" bottom="0"/> + <border name="title_border" left="0" right="0" top="0" bottom="0"/> +</frame_geometry> + +<frame_geometry name="attached" hide_buttons="true" rounded_bottom_left="6" rounded_bottom_right="6" parent="normal"> + <distance name="title_vertical_pad" value="6"/> +</frame_geometry> + +<!-- drawing operations --> + +<!-- title --> + +<draw_ops name="title_focused"> + <title version="< 3.1" + x="(0 `max` ((width - title_width) / 2))" + y="(0 `max` ((height - title_height) / 2))" + color="C_title_focused"/> + <title version=">= 3.1" + x="(0 `max` ((frame_x_center - title_width / 2) `min` (width - title_width)))" + y="(0 `max` ((height - title_height) / 2))" + ellipsize_width="width" + color="C_title_focused"/> +</draw_ops> + +<draw_ops name="title_unfocused"> + <title version="< 3.1" + x="(0 `max` ((width - title_width) / 2))" + y="(0 `max` ((height - title_height) / 2))" + color="C_title_unfocused"/> + <title version=">= 3.1" + x="(0 `max` ((frame_x_center - title_width / 2) `min` (width - title_width)))" + y="(0 `max` ((height - title_height) / 2))" + ellipsize_width="width" + color="C_title_unfocused"/> +</draw_ops> + +<!-- window decorations --> + +<draw_ops name="entire_background_focused"> + <rectangle color="C_titlebar_focused" x="0" y="0" width="width" height="height" filled="true"/> +</draw_ops> + +<draw_ops name="entire_background_unfocused"> + <rectangle color="C_titlebar_unfocused" x="0" y="0" width="width" height="height" filled="true"/> +</draw_ops> + +<draw_ops name="titlebar_focused"> + <include name="entire_background_focused"/> +</draw_ops> + +<draw_ops name="titlebar_unfocused"> + <include name="entire_background_unfocused"/> +</draw_ops> + +<draw_ops name="rounded_border_focused"> + <line color="C_border_focused" x1="12" y1="0" x2="width-13" y2="0" /> + <line color="C_border_focused" x1="0" y1="height-1" x2="width-1" y2="height-1" /> + <line color="C_border_focused" x1="0" y1="12" x2="0" y2="height-2" /> + <line color="C_border_focused" x1="width-1" y1="12" x2="width-1" y2="height-2" /> + <arc color="C_border_focused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_focused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <!-- double arcs for darker borders --> + <arc color="C_border_focused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_focused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <line color="C_highlight_focused" x1="13" y1="1" x2="width - 14" y2="1"/> + <arc color="C_highlight_focused" x="0" y="1" width="25" height="25" start_angle="270" extent_angle="90"/> + <arc color="C_highlight_focused" x="width - 26" y="1" width="25" height="25" start_angle="0" extent_angle="90"/> +</draw_ops> + +<draw_ops name="rounded_border_unfocused"> + <line color="C_border_unfocused" x1="12" y1="0" x2="width-13" y2="0" /> + <line color="C_border_unfocused" x1="0" y1="height-1" x2="width-1" y2="height-1" /> + <line color="C_border_unfocused" x1="0" y1="12" x2="0" y2="height-2" /> + <line color="C_border_unfocused" x1="width-1" y1="12" x2="width-1" y2="height-2" /> + <arc color="C_border_unfocused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_unfocused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <!-- double arcs for darker borders --> + <arc color="C_border_unfocused" x="0" y="0" width="25" height="25" start_angle="270" extent_angle="90" /> + <arc color="C_border_unfocused" x="width-26" y="0" width="25" height="25" start_angle="0" extent_angle="90" /> + <line color="C_highlight_unfocused" x1="13" y1="1" x2="width - 14" y2="1"/> + <arc color="C_highlight_unfocused" x="0" y="1" width="25" height="25" start_angle="270" extent_angle="90"/> + <arc color="C_highlight_unfocused" x="width - 26" y="1" width="25" height="25" start_angle="0" extent_angle="90"/> +</draw_ops> + +<!-- button icons --> + +<draw_ops name="windows_button_focused"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.1" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_focused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.15" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_focused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.2" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_unfocused"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.06" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_unfocused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.1" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_button_unfocused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.15" colorize="C_title_focused"/> +</draw_ops> + +<!-- close --> + +<draw_ops name="windows_close_icon_focused"> + <image filename="assets/close.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_close_icon_unfocused"> + <image filename="assets/close.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="close_focused"> + <include name="windows_close_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="close_focused_prelight"> + <include name="windows_close_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="close_focused_pressed"> + <include name="windows_close_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="close_unfocused"> + <include name="windows_close_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="close_unfocused_prelight"> + <include name="windows_close_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="close_unfocused_pressed"> + <include name="windows_close_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- maximize --> + +<draw_ops name="windows_maximize_icon_focused"> + <image filename="assets/maximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_maximize_icon_unfocused"> + <image filename="assets/maximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="maximize_focused"> + <include name="windows_maximize_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="maximize_focused_prelight"> + <include name="windows_maximize_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="maximize_focused_pressed"> + <include name="windows_maximize_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="maximize_unfocused"> + <include name="windows_maximize_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="maximize_unfocused_prelight"> + <include name="windows_maximize_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="maximize_unfocused_pressed"> + <include name="windows_maximize_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- unmaximize --> + +<draw_ops name="windows_unmaximize_icon_focused"> + <image filename="assets/unmaximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_unmaximize_icon_unfocused"> + <image filename="assets/unmaximize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="unmaximize_focused"> + <include name="windows_unmaximize_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="unmaximize_focused_prelight"> + <include name="windows_unmaximize_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="unmaximize_focused_pressed"> + <include name="windows_unmaximize_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="unmaximize_unfocused"> + <include name="windows_unmaximize_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="unmaximize_unfocused_prelight"> + <include name="windows_unmaximize_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="unmaximize_unfocused_pressed"> + <include name="windows_unmaximize_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- minimize --> + +<draw_ops name="windows_minimize_icon_focused"> + <image filename="assets/minimize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="windows_minimize_icon_unfocused"> + <image filename="assets/minimize.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.35" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="minimize_focused"> + <include name="windows_minimize_icon_focused"/> + <include name="windows_button_focused"/> +</draw_ops> + +<draw_ops name="minimize_focused_prelight"> + <include name="windows_minimize_icon_focused"/> + <include name="windows_button_focused_prelight"/> +</draw_ops> + +<draw_ops name="minimize_focused_pressed"> + <include name="windows_minimize_icon_focused"/> + <include name="windows_button_focused_pressed"/> +</draw_ops> + +<draw_ops name="minimize_unfocused"> + <include name="windows_minimize_icon_unfocused"/> + <include name="windows_button_unfocused"/> +</draw_ops> + +<draw_ops name="minimize_unfocused_prelight"> + <include name="windows_minimize_icon_unfocused"/> + <include name="windows_button_unfocused_prelight"/> +</draw_ops> + +<draw_ops name="minimize_unfocused_pressed"> + <include name="windows_minimize_icon_unfocused"/> + <include name="windows_button_unfocused_pressed"/> +</draw_ops> + +<!-- menu --> + +<draw_ops name="menu_focused"> + <image filename="assets/menu.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="menu_focused_prelight"> + <include name="menu_focused"/> +</draw_ops> + +<draw_ops name="menu_focused_pressed"> + <include name="menu_focused"/> +</draw_ops> + +<draw_ops name="menu_unfocused"> + <image filename="assets/menu.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="menu_unfocused_prelight"> + <include name="menu_unfocused"/> +</draw_ops> + +<draw_ops name="menu_unfocused_pressed"> + <include name="menu_unfocused"/> +</draw_ops> + +<!-- shade --> + +<draw_ops name="shade_focused"> + <image filename="assets/shade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="shade_focused_prelight"> + <include name="shade_focused"/> +</draw_ops> + +<draw_ops name="shade_focused_pressed"> + <include name="shade_focused"/> +</draw_ops> + +<draw_ops name="shade_unfocused"> + <image filename="assets/shade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="shade_unfocused_prelight"> + <include name="shade_unfocused"/> +</draw_ops> + +<draw_ops name="shade_unfocused_pressed"> + <include name="shade_unfocused"/> +</draw_ops> + +<!-- unshade --> + +<draw_ops name="unshade_focused"> + <image filename="assets/unshade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="unshade_focused_prelight"> + <include name="unshade_focused"/> +</draw_ops> + +<draw_ops name="unshade_focused_pressed"> + <include name="unshade_focused"/> +</draw_ops> + +<draw_ops name="unshade_unfocused"> + <image filename="assets/unshade.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.7" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="unshade_unfocused_prelight"> + <include name="unshade_unfocused"/> +</draw_ops> + +<draw_ops name="unshade_unfocused_pressed"> + <include name="unshade_unfocused"/> +</draw_ops> + +<!-- appmenu --> + +<constant name="D_appmenu_icon_size" value="16"/> + +<draw_ops name="appmenu_focused"> + <icon + x="(width - D_appmenu_icon_size) / 2" y="(height - D_appmenu_icon_size) / 2" + width="D_appmenu_icon_size" height="D_appmenu_icon_size"/> +</draw_ops> + +<draw_ops name="appmenu_focused_prelight"> + <include name="appmenu_focused"/> +</draw_ops> + +<draw_ops name="appmenu_focused_pressed"> + <include name="appmenu_focused"/> +</draw_ops> + +<draw_ops name="appmenu_unfocused"> + <icon + x="(width - D_appmenu_icon_size) / 2" y="(height - D_appmenu_icon_size) / 2" + width="D_appmenu_icon_size" height="D_appmenu_icon_size" + alpha="0.7"/> +</draw_ops> + +<draw_ops name="appmenu_unfocused_prelight"> + <include name="appmenu_unfocused"/> +</draw_ops> + +<draw_ops name="appmenu_unfocused_pressed"> + <include name="appmenu_unfocused"/> +</draw_ops> + +<!-- button backgrounds --> + +<draw_ops name="button_focused"> +</draw_ops> + +<draw_ops name="button_focused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.08" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="button_focused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.2" colorize="C_title_focused"/> +</draw_ops> + +<draw_ops name="button_unfocused"> +</draw_ops> + +<draw_ops name="button_unfocused_prelight"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.08" colorize="C_title_unfocused"/> +</draw_ops> + +<draw_ops name="button_unfocused_pressed"> + <image filename="assets/button.svg" x="(width - object_width) / 2" y="(height - object_height) / 2" width="object_width" height="object_height" alpha="0.2" colorize="C_title_unfocused"/> +</draw_ops> + +<!-- frame styles --> + +<frame_style name="normal_focused" geometry="normal"> + <piece position="entire_background" draw_ops="entire_background_focused"/> + <piece position="titlebar" draw_ops="titlebar_focused"/> + <piece position="title" draw_ops="title_focused"/> + <piece position="overlay" draw_ops="rounded_border_focused"/> + <button function="close" state="normal" draw_ops="close_focused"/> + <button function="close" state="prelight" draw_ops="close_focused_prelight"/> + <button function="close" state="pressed" draw_ops="close_focused_pressed"/> + <button function="maximize" state="normal" draw_ops="maximize_focused"/> + <button function="maximize" state="prelight" draw_ops="maximize_focused_prelight"/> + <button function="maximize" state="pressed" draw_ops="maximize_focused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_focused"/> + <button function="minimize" state="prelight" draw_ops="minimize_focused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_focused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_focused"/> + <button function="menu" state="prelight" draw_ops="menu_focused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_focused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_focused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_focused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_focused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_focused"/> + <button function="shade" state="prelight" draw_ops="shade_focused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_focused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_focused"/> + <button function="unshade" state="prelight" draw_ops="unshade_focused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_focused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_focused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_focused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="normal_unfocused" geometry="normal"> + <piece position="entire_background" draw_ops="entire_background_unfocused"/> + <piece position="titlebar" draw_ops="titlebar_unfocused"/> + <piece position="title" draw_ops="title_unfocused"/> + <piece position="overlay" draw_ops="rounded_border_unfocused"/> + <button function="close" state="normal" draw_ops="close_unfocused"/> + <button function="close" state="prelight" draw_ops="close_unfocused_prelight"/> + <button function="close" state="pressed" draw_ops="close_unfocused_pressed"/> + <button function="maximize" state="normal" draw_ops="maximize_unfocused"/> + <button function="maximize" state="prelight" draw_ops="maximize_unfocused_prelight"/> + <button function="maximize" state="pressed" draw_ops="maximize_unfocused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_unfocused"/> + <button function="minimize" state="prelight" draw_ops="minimize_unfocused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_unfocused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_unfocused"/> + <button function="menu" state="prelight" draw_ops="menu_unfocused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_unfocused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_unfocused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_unfocused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_unfocused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_unfocused"/> + <button function="shade" state="prelight" draw_ops="shade_unfocused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_unfocused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_unfocused"/> + <button function="unshade" state="prelight" draw_ops="unshade_unfocused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_unfocused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="normal_max_focused" geometry="max"> + <piece position="entire_background" draw_ops="entire_background_focused"/> + <piece position="titlebar" draw_ops="titlebar_focused"/> + <piece position="title" draw_ops="title_focused"/> + <button function="close" state="normal" draw_ops="close_focused"/> + <button function="close" state="prelight" draw_ops="close_focused_prelight"/> + <button function="close" state="pressed" draw_ops="close_focused_pressed"/> + <button function="maximize" state="normal" draw_ops="unmaximize_focused"/> + <button function="maximize" state="prelight" draw_ops="unmaximize_focused_prelight"/> + <button function="maximize" state="pressed" draw_ops="unmaximize_focused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_focused"/> + <button function="minimize" state="prelight" draw_ops="minimize_focused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_focused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_focused"/> + <button function="menu" state="prelight" draw_ops="menu_focused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_focused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_focused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_focused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_focused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_focused"/> + <button function="shade" state="prelight" draw_ops="shade_focused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_focused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_focused"/> + <button function="unshade" state="prelight" draw_ops="unshade_focused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_focused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_focused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_focused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_focused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_focused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="normal_max_unfocused" geometry="max"> + <piece position="entire_background" draw_ops="entire_background_unfocused"/> + <piece position="titlebar" draw_ops="titlebar_unfocused"/> + <piece position="title" draw_ops="title_unfocused"/> + <button function="close" state="normal" draw_ops="close_unfocused"/> + <button function="close" state="prelight" draw_ops="close_unfocused_prelight"/> + <button function="close" state="pressed" draw_ops="close_unfocused_pressed"/> + <button function="maximize" state="normal" draw_ops="unmaximize_unfocused"/> + <button function="maximize" state="prelight" draw_ops="unmaximize_unfocused_prelight"/> + <button function="maximize" state="pressed" draw_ops="unmaximize_unfocused_pressed"/> + <button function="minimize" state="normal" draw_ops="minimize_unfocused"/> + <button function="minimize" state="prelight" draw_ops="minimize_unfocused_prelight"/> + <button function="minimize" state="pressed" draw_ops="minimize_unfocused_pressed"/> + <button function="menu" state="normal" draw_ops="menu_unfocused"/> + <button function="menu" state="prelight" draw_ops="menu_unfocused_prelight"/> + <button function="menu" state="pressed" draw_ops="menu_unfocused_pressed"/> + <button version=">= 3.5" function="appmenu" state="normal" draw_ops="appmenu_unfocused"/> + <button version=">= 3.5" function="appmenu" state="prelight" draw_ops="appmenu_unfocused_prelight"/> + <button version=">= 3.5" function="appmenu" state="pressed" draw_ops="appmenu_unfocused_pressed"/> + <button function="shade" state="normal" draw_ops="shade_unfocused"/> + <button function="shade" state="prelight" draw_ops="shade_unfocused_prelight"/> + <button function="shade" state="pressed" draw_ops="shade_unfocused_pressed"/> + <button function="unshade" state="normal" draw_ops="unshade_unfocused"/> + <button function="unshade" state="prelight" draw_ops="unshade_unfocused_prelight"/> + <button function="unshade" state="pressed" draw_ops="unshade_unfocused_pressed"/> + + <button function="left_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="left_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="left_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + <button function="right_middle_background" state="normal" draw_ops="button_unfocused"/> + <button function="right_middle_background" state="prelight" draw_ops="button_unfocused_prelight"/> + <button function="right_middle_background" state="pressed" draw_ops="button_unfocused_pressed"/> + + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<frame_style name="tiled_left_focused" geometry="tiled_left" parent="normal_max_focused"> + <piece position="titlebar" draw_ops="entire_background_focused"/> +</frame_style> + +<frame_style name="tiled_left_unfocused" geometry="tiled_left" parent="normal_max_unfocused"> + <piece position="titlebar" draw_ops="entire_background_unfocused"/> +</frame_style> + +<frame_style name="tiled_right_focused" geometry="tiled_right" parent="normal_max_focused"> + <piece position="titlebar" draw_ops="entire_background_focused"/> +</frame_style> + +<frame_style name="tiled_right_unfocused" geometry="tiled_right" parent="normal_max_unfocused"> + <piece position="titlebar" draw_ops="entire_background_unfocused"/> +</frame_style> + +<frame_style name="dialog_focused" geometry="modal" parent="normal_focused"> +</frame_style> + +<frame_style name="dialog_unfocused" geometry="modal" parent="normal_unfocused"> +</frame_style> + +<frame_style name="modal_dialog_focused" geometry="modal" parent="normal_focused"> +</frame_style> + +<frame_style name="modal_dialog_unfocused" geometry="modal" parent="normal_unfocused"> +</frame_style> + +<frame_style name="utility_focused" geometry="small" parent="normal_focused"> +</frame_style> + +<frame_style name="utility_unfocused" geometry="small" parent="normal_unfocused"> +</frame_style> + +<frame_style name="border_focused" geometry="border" parent="normal_focused"> +</frame_style> + +<frame_style name="border_unfocused" geometry="border" parent="normal_unfocused"> +</frame_style> + +<frame_style name="borderless_focused" geometry="borderless" parent="normal_focused"> +</frame_style> + +<frame_style name="borderless_unfocused" geometry="borderless" parent="normal_unfocused"> +</frame_style> + +<frame_style name="attached_focused" geometry="attached" parent="modal_dialog_focused"> +</frame_style> + +<frame_style name="attached_unfocused" geometry="attached" parent="modal_dialog_unfocused"> +</frame_style> + +<!-- placeholder for unimplementated styles--> + +<frame_style name="blank" geometry="normal"> + <button function="close" state="normal"><draw_ops></draw_ops></button> + <button function="close" state="pressed"><draw_ops></draw_ops></button> + <button function="maximize" state="normal"><draw_ops></draw_ops></button> + <button function="maximize" state="pressed"><draw_ops></draw_ops></button> + <button function="minimize" state="normal"><draw_ops></draw_ops></button> + <button function="minimize" state="pressed"><draw_ops></draw_ops></button> + <button function="menu" state="normal"><draw_ops></draw_ops></button> + <button function="menu" state="pressed"><draw_ops></draw_ops></button> + <button version=">= 3.5" function="appmenu" state="normal"><draw_ops></draw_ops></button> + <button version=">= 3.5" function="appmenu" state="pressed"><draw_ops></draw_ops></button> + <button function="shade" state="normal"><draw_ops></draw_ops></button> + <button function="shade" state="pressed"><draw_ops></draw_ops></button> + <button function="unshade" state="normal"><draw_ops></draw_ops></button> + <button function="unshade" state="pressed"><draw_ops></draw_ops></button> + <button function="above" state="normal"><draw_ops></draw_ops></button> + <button function="above" state="pressed"><draw_ops></draw_ops></button> + <button function="unabove" state="normal"><draw_ops></draw_ops></button> + <button function="unabove" state="pressed"><draw_ops></draw_ops></button> + <button function="stick" state="normal"><draw_ops></draw_ops></button> + <button function="stick" state="pressed"><draw_ops></draw_ops></button> + <button function="unstick" state="normal"><draw_ops></draw_ops></button> + <button function="unstick" state="pressed"><draw_ops></draw_ops></button> +</frame_style> + +<!-- frame style sets --> + +<frame_style_set name="normal_style_set"> + <frame focus="yes" state="normal" resize="both" style="normal_focused"/> + <frame focus="no" state="normal" resize="both" style="normal_unfocused"/> + <frame focus="yes" state="maximized" style="normal_max_focused"/> + <frame focus="no" state="maximized" style="normal_max_unfocused"/> + <frame focus="yes" state="shaded" style="normal_focused"/> + <frame focus="no" state="shaded" style="normal_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="normal_max_focused"/> + <frame focus="no" state="maximized_and_shaded" style="normal_max_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_left" style="tiled_left_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_left" style="tiled_left_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_right" style="tiled_right_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_right" style="tiled_right_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_left_and_shaded" style="tiled_left_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_left_and_shaded" style="tiled_left_unfocused"/> + <frame version=">= 3.3" focus="yes" state="tiled_right_and_shaded" style="tiled_right_focused"/> + <frame version=">= 3.3" focus="no" state="tiled_right_and_shaded" style="tiled_right_unfocused"/> +</frame_style_set> + +<frame_style_set name="dialog_style_set"> + <frame focus="yes" state="normal" resize="both" style="dialog_focused"/> + <frame focus="no" state="normal" resize="both" style="dialog_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="dialog_focused"/> + <frame focus="no" state="shaded" style="dialog_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="modal_dialog_style_set"> + <frame focus="yes" state="normal" resize="both" style="modal_dialog_focused"/> + <frame focus="no" state="normal" resize="both" style="modal_dialog_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="modal_dialog_focused"/> + <frame focus="no" state="shaded" style="modal_dialog_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="utility_style_set"> + <frame focus="yes" state="normal" resize="both" style="utility_focused"/> + <frame focus="no" state="normal" resize="both" style="utility_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="utility_focused"/> + <frame focus="no" state="shaded" style="utility_unfocused"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="border_style_set"> + <frame focus="yes" state="normal" resize="both" style="border_focused"/> + <frame focus="no" state="normal" resize="both" style="border_unfocused"/> + <frame focus="yes" state="maximized" style="borderless_focused"/> + <frame focus="no" state="maximized" style="borderless_unfocused"/> + <frame focus="yes" state="shaded" style="blank"/> + <frame focus="no" state="shaded" style="blank"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<frame_style_set name="attached_style_set"> + <frame focus="yes" state="normal" resize="both" style="attached_focused"/> + <frame focus="no" state="normal" resize="both" style="attached_unfocused"/> + <frame focus="yes" state="maximized" style="blank"/> + <frame focus="no" state="maximized" style="blank"/> + <frame focus="yes" state="shaded" style="blank"/> + <frame focus="no" state="shaded" style="blank"/> + <frame focus="yes" state="maximized_and_shaded" style="blank"/> + <frame focus="no" state="maximized_and_shaded" style="blank"/> +</frame_style_set> + +<!-- windows --> + +<window type="normal" style_set="normal_style_set"/> +<window type="dialog" style_set="dialog_style_set"/> +<window type="modal_dialog" style_set="modal_dialog_style_set"/> +<window type="menu" style_set="utility_style_set"/> +<window type="utility" style_set="utility_style_set"/> +<window type="border" style_set="border_style_set"/> +<window version=">= 3.2" type="attached" style_set="attached_style_set"/> + +</metacity_theme> diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/thumbnail.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/thumbnail.png new file mode 100755 index 0000000..9f2f0b7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/metacity-1/thumbnail.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/plank/dock.theme b/local/share/themes/Gruvbox-B-LB-Dark-Medium/plank/dock.theme new file mode 100755 index 0000000..93fd8e8 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/plank/dock.theme @@ -0,0 +1,64 @@ +#This file based on: +#https://git.launchpad.net/plank/tree/data/themes/Default/dock.theme + +[PlankTheme] +#The roundness of the top corners. +TopRoundness=15 +#The roundness of the bottom corners. +BottomRoundness=15 +#The thickness (in pixels) of lines drawn. +LineWidth=1 +#The color (RGBA) of the outer stroke. +OuterStrokeColor=150;;158;;188;;50 +#The starting color (RGBA) of the fill gradient. +FillStartColor=40;;40;;40;;200 +#The ending color (RGBA) of the fill gradient. +FillEndColor=40;;40;;40;;200 +#The color (RGBA) of the inner stroke. +InnerStrokeColor=40;;40;;40;;100 + +[PlankDockTheme] +#The padding on the left/right dock edges, in tenths of a percent of IconSize. +HorizPadding=2 +#The padding on the top dock edge, in tenths of a percent of IconSize. +TopPadding=2 +#The padding on the bottom dock edge, in tenths of a percent of IconSize. +BottomPadding=1 +#The padding between items on the dock, in tenths of a percent of IconSize. +ItemPadding=2 +#The size of item indicators, in tenths of a percent of IconSize. +IndicatorSize=5 +#The size of the icon-shadow behind every item, in tenths of a percent of IconSize. +IconShadowSize=0 +#The height (in percent of IconSize) to bounce an icon when the application sets urgent. +UrgentBounceHeight=1.6666666666666667 +#The height (in percent of IconSize) to bounce an icon when launching an application. +LaunchBounceHeight=0.625 +#The opacity value (0 to 1) to fade the dock to when hiding it. +FadeOpacity=1 +#The amount of time (in ms) for click animations. +ClickTime=0 +#The amount of time (in ms) to bounce an urgent icon. +UrgentBounceTime=600 +#The amount of time (in ms) to bounce an icon when launching an application. +LaunchBounceTime=600 +#The amount of time (in ms) for active window indicator animations. +ActiveTime=150 +#The amount of time (in ms) to slide icons into/out of the dock. +SlideTime=300 +#The time (in ms) to fade the dock in/out on a hide (if FadeOpacity is < 1). +FadeTime=250 +#The time (in ms) to slide the dock in/out on a hide (if FadeOpacity is 1). +HideTime=250 +#The size of the urgent glow (shown when dock is hidden), in tenths of a percent of IconSize. +GlowSize=30 +#The total time (in ms) to show the hidden-dock urgent glow. +GlowTime=10000 +#The time (in ms) of each pulse of the hidden-dock urgent glow. +GlowPulseTime=2000 +#The hue-shift (-180 to 180) of the urgent indicator color. +UrgentHueShift=150 +#The time (in ms) to move an item to its new position or its addition/removal to/from the dock. +ItemMoveTime=450 +#Whether background and icons will unhide/hide with different speeds. The top-border of both will leave/hit the screen-edge at the same time. +CascadeHide=true diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-active.png new file mode 100755 index 0000000..4b6bc9a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-inactive.png new file mode 100755 index 0000000..8067218 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-active.png new file mode 100755 index 0000000..5c490c6 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-inactive.png new file mode 100755 index 0000000..ac14959 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-left-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-active.png new file mode 100755 index 0000000..d5b1403 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-inactive.png new file mode 100755 index 0000000..8ea3da0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/bottom-right-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-active.png new file mode 100755 index 0000000..c31f004 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-inactive.png new file mode 100755 index 0000000..f7d84ca Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-prelight.png new file mode 100755 index 0000000..c3614e1 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-pressed.png new file mode 100755 index 0000000..8eda912 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/close-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-active.png new file mode 100755 index 0000000..87234df Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-inactive.png new file mode 100755 index 0000000..a1e8bc5 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-prelight.png new file mode 100755 index 0000000..0be68ea Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-pressed.png new file mode 100755 index 0000000..f298582 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/hide-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-active.png new file mode 100755 index 0000000..92ec926 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-inactive.png new file mode 100755 index 0000000..b9b1ed5 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/left-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-active.png new file mode 100755 index 0000000..be1d1ca Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-inactive.png new file mode 100755 index 0000000..f428d27 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-prelight.png new file mode 100755 index 0000000..91c6267 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-pressed.png new file mode 100755 index 0000000..ebddb44 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-active.png new file mode 100755 index 0000000..9e57790 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-inactive.png new file mode 100755 index 0000000..0522307 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-prelight.png new file mode 100755 index 0000000..39e6b41 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-pressed.png new file mode 100755 index 0000000..f88e9ea Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/maximize-toggled-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-active.png new file mode 100755 index 0000000..023bfe4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-inactive.png new file mode 100755 index 0000000..d3a3b6f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-prelight.png new file mode 100755 index 0000000..f6a3ad0 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-pressed.png new file mode 100755 index 0000000..683ec58 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/menu-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-active.png new file mode 100755 index 0000000..37c8c6b Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-inactive.png new file mode 100755 index 0000000..b9b1ed5 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/right-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-active.png new file mode 100755 index 0000000..fd1aff7 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-inactive.png new file mode 100755 index 0000000..a2a196f Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-prelight.png new file mode 100755 index 0000000..294d0b9 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-pressed.png new file mode 100755 index 0000000..5eb49fd Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-active.png new file mode 100755 index 0000000..1c581de Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-inactive.png new file mode 100755 index 0000000..4107f5d Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-prelight.png new file mode 100755 index 0000000..3bec590 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-pressed.png new file mode 100755 index 0000000..8d7e145 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/shade-toggled-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-active.png new file mode 100755 index 0000000..937108e Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-inactive.png new file mode 100755 index 0000000..8c646e4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-prelight.png new file mode 100755 index 0000000..66db5a4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-pressed.png new file mode 100755 index 0000000..1851556 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-active.png new file mode 100755 index 0000000..3873f78 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-inactive.png new file mode 100755 index 0000000..e2a1ab8 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-prelight.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-prelight.png new file mode 100755 index 0000000..845aa2c Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-prelight.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-pressed.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-pressed.png new file mode 100755 index 0000000..2ca9273 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/stick-toggled-pressed.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/themerc b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/themerc new file mode 100755 index 0000000..22732f3 --- /dev/null +++ b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/themerc @@ -0,0 +1,23 @@ +button_offset=6 +button_spacing=0 + +show_app_icon=false + +full_width_title=true + +title_shadow_active=false +title_shadow_inactive=false + +title_horizontal_offset=3 + +active_text_color=#f0f7fe +active_text_shadow_color=#222426 + +inactive_text_color=#999da3 +inactive_text_shadow_color=#222426 + +shadow_delta_height=2 +shadow_delta_width=0 +shadow_delta_x=0 +shadow_delta_y=-5 +shadow_opacity=40 diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-active.png new file mode 100755 index 0000000..036091a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-inactive.png new file mode 100755 index 0000000..77c730a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-1-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-active.png new file mode 100755 index 0000000..036091a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-inactive.png new file mode 100755 index 0000000..77c730a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-2-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-active.png new file mode 100755 index 0000000..036091a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-inactive.png new file mode 100755 index 0000000..77c730a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-3-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-active.png new file mode 100755 index 0000000..036091a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-inactive.png new file mode 100755 index 0000000..77c730a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-4-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-active.png new file mode 100755 index 0000000..036091a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-inactive.png new file mode 100755 index 0000000..77c730a Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/title-5-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-active.png new file mode 100755 index 0000000..e8a20c4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-inactive.png new file mode 100755 index 0000000..c0b24a4 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-left-inactive.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-active.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-active.png new file mode 100755 index 0000000..59fb180 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-active.png differ diff --git a/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-inactive.png b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-inactive.png new file mode 100755 index 0000000..cce9b68 Binary files /dev/null and b/local/share/themes/Gruvbox-B-LB-Dark-Medium/xfwm4/top-right-inactive.png differ diff --git a/nixos/configuration/configuration.nix b/nixos/configuration/configuration.nix new file mode 100755 index 0000000..428f073 --- /dev/null +++ b/nixos/configuration/configuration.nix @@ -0,0 +1,132 @@ +{ + pkgs, + pkgsUnstable, + ... +}: let + unstable = pkgsUnstable; +in +{ + services = { + xserver = { + enable = true; + videoDrivers = ["modesetting" "nvidia"]; + }; + displayManager.ly.enable = true; + blueman.enable = false; + printing.enable = false; + pipewire = { + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + }; + security.rtkit.enable = true; + + boot = { + readOnlyNixStore = true; + initrd.compressor = "zstd"; + loader = { + systemd-boot = { + enable = true; + editor = false; + configurationLimit = 25; + }; + efi.canTouchEfiVariables = true; + }; + kernelParams = [ + "nvidia_drm" + "nvidia_modeset" + "nvidia_uvm" + "nvidia-drm.fbdev=1" + "nvidia" + ]; + }; + + networking.hostName = "gloria"; + networking.enableIPv6 = false; + networking.networkmanager.enable = true; + time.timeZone = "Asia/Tehran"; + + hardware = { + graphics.enable = true; + nvidia = { + modesetting.enable = true; + powerManagement.enable = true; + open = false; + nvidiaSettings = true; + package = pkgs.linuxPackages.nvidiaPackages.beta; + prime.offload = { + enable = true; + enableOffloadCmd = true; + }; + prime = { + intelBusId = "PCI:0:2:0"; + nvidiaBusId = "PCI:1:0:0"; + }; + }; + bluetooth.enable = true; + bluetooth.powerOnBoot = true; + }; + + security.sudo.enable = false; + security.sudo-rs.enable = true; + + virtualisation = { + podman.enable = true; + }; + + environment.systemPackages = with pkgs; [ + (pkgs.runCommand "vim-wrapper" { } '' + mkdir -p $out/bin + ln -s ${pkgs.neovim}/bin/nvim $out/bin/vim + '') + unstable.ungoogled-chromium + unstable.git + unstable.adwaita-icon-theme + unstable.nil + jmtpfs + android-tools + unstable.qbittorrent + unstable.zathura + unstable.rofi + ]; + + nixpkgs.config.allowUnfree = true; + + users.users.coast = { + isNormalUser = true; + extraGroups = [ "wheel" "podman" ]; + shell = pkgs.nushell; + }; + + programs = { + foot.enable = false; + nano.enable = false; + nekoray.enable = true; + nekoray.tunMode.enable = true; + niri.enable = true; + }; + + fonts.packages = with pkgs; [ + ubuntu-sans + ubuntu_font_family + nerd-fonts._0xproto + nerd-fonts.droid-sans-mono + nerd-fonts.jetbrains-mono + nerd-fonts.fira-code + vazir-fonts + ]; + + xdg.portal = { + enable = true; + xdgOpenUsePortal = true; + extraPortals = with pkgs; [ + xdg-desktop-portal-gtk + xdg-desktop-portal-gnome + ]; + }; + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + services.openssh.enable = true; + system.stateVersion = "25.05"; +} diff --git a/nixos/configuration/sys/coreutils-configuration.nix b/nixos/configuration/sys/coreutils-configuration.nix new file mode 100755 index 0000000..9532a3e --- /dev/null +++ b/nixos/configuration/sys/coreutils-configuration.nix @@ -0,0 +1,48 @@ +{ + pkgs, + ... +}: let + coreutils-full-name = "coreuutils-full" + builtins.concatStringsSep "" + (builtins.genList (_: "_") (builtins.stringLength pkgs.coreutils-full.version)); + + coreutils-name = "coreuutils" + builtins.concatStringsSep "" + (builtins.genList (_: "_") (builtins.stringLength pkgs.coreutils.version)); + + findutils-name = "finduutils" + builtins.concatStringsSep "" + (builtins.genList (_: "_") (builtins.stringLength pkgs.findutils.version)); + + diffutils-name = "diffuutils" + builtins.concatStringsSep "" + (builtins.genList (_: "_") (builtins.stringLength pkgs.diffutils.version)); +in +{ + system.replaceDependencies.replacements = [ + { + oldDependency = pkgs.coreutils-full; + newDependency = pkgs.symlinkJoin { + name = coreutils-full-name; + paths = [pkgs.uutils-coreutils-noprefix]; + }; + } + { + oldDependency = pkgs.coreutils; + newDependency = pkgs.symlinkJoin { + name = coreutils-name; + paths = [pkgs.uutils-coreutils-noprefix]; + }; + } + { + oldDependency = pkgs.findutils; + newDependency = pkgs.symlinkJoin { + name = findutils-name; + paths = [pkgs.uutils-findutils]; + }; + } + { + oldDependency = pkgs.diffutils; + newDependency = pkgs.symlinkJoin { + name = diffutils-name; + paths = [pkgs.uutils-diffutils]; + }; + } + ]; +} diff --git a/nixos/configuration/sys/swap.nix b/nixos/configuration/sys/swap.nix new file mode 100755 index 0000000..72cba4f --- /dev/null +++ b/nixos/configuration/sys/swap.nix @@ -0,0 +1,11 @@ +{ + ... +}: +{ + swapDevices = [ + { + device = "/var/lib/swapfile"; + size = 12*1024; + } + ]; +} diff --git a/nixos/configuration/sys/zram.nix b/nixos/configuration/sys/zram.nix new file mode 100755 index 0000000..8e7037d --- /dev/null +++ b/nixos/configuration/sys/zram.nix @@ -0,0 +1,10 @@ +{ + config, + ... +}: +{ + zramSwap = { + enable = true; + writebackDevice = "/dev/nvme0n1p3"; + }; +} diff --git a/nixos/flake.lock b/nixos/flake.lock new file mode 100755 index 0000000..d01b11f --- /dev/null +++ b/nixos/flake.lock @@ -0,0 +1,135 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1758463745, + "narHash": "sha256-uhzsV0Q0I9j2y/rfweWeGif5AWe0MGrgZ/3TjpDYdGA=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3b955f5f0a942f9f60cdc9cacb7844335d0f21c3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-25.05", + "repo": "home-manager", + "type": "github" + } + }, + "intelfetch": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1762005542, + "narHash": "sha256-oFE6raeSV/37OJUbR4F1/iqJR23Hij4jccv/BgrDciU=", + "ref": "refs/heads/master", + "rev": "090578fae67055f39155f677e8079f8b47c26cca", + "revCount": 19, + "type": "git", + "url": "https://git.sr.ht/~coasteen/intelfetch" + }, + "original": { + "type": "git", + "url": "https://git.sr.ht/~coasteen/intelfetch" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1735563628, + "narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1761672384, + "narHash": "sha256-o9KF3DJL7g7iYMZq9SWgfS1BFlNbsm6xplRjVlOCkXI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "08dacfca559e1d7da38f3cf05f1f45ee9bfd213c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1761597516, + "narHash": "sha256-wxX7u6D2rpkJLWkZ2E932SIvDJW8+ON/0Yy8+a5vsDU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "daf6dc47aa4b44791372d6139ab7b25269184d55", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "intelfetch": "intelfetch", + "nixpkgs": "nixpkgs_2", + "nixpkgs-unstable": "nixpkgs-unstable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/nixos/flake.nix b/nixos/flake.nix new file mode 100755 index 0000000..b9c9114 --- /dev/null +++ b/nixos/flake.nix @@ -0,0 +1,56 @@ +{ + description = "Flake"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; + intelfetch.url = "git+https://git.sr.ht/~coasteen/intelfetch"; + home-manager.url = "github:nix-community/home-manager/release-25.05"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { nixpkgs, nixpkgs-unstable, home-manager, intelfetch, ... }: let + system = "x86_64-linux"; + pkgs = import nixpkgs { + inherit system; + config = { allowUnfree = true; }; + }; + pkgsUnstable = import nixpkgs-unstable { inherit system; }; + in { + nixosConfigurations.gloria = nixpkgs.lib.nixosSystem { + inherit system; + + modules = [ + (import ./configuration/configuration.nix { inherit pkgs pkgsUnstable; }) + ./configuration/sys/coreutils-configuration.nix + ./configuration/sys/swap.nix + ./hardware-configuration.nix + + { + environment.systemPackages = [ + intelfetch.packages.${system}.intelfetch + ]; + } + + home-manager.nixosModules.home-manager { + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + backupFileExtension = "home-backup"; + + users.coast = { ... }: { + imports = [ + ./home-configuration/configuration.nix + ./home-configuration/apps/sway.nix + ./home-configuration/apps/zsh.nix + ./home-configuration/apps/nushell.nix + ./home-configuration/apps/alacritty.nix + ./home-configuration/apps/foot.nix + ]; + }; + }; + } + ]; + }; + }; +} diff --git a/nixos/home-configuration/apps/alacritty.nix b/nixos/home-configuration/apps/alacritty.nix new file mode 100755 index 0000000..8ce3197 --- /dev/null +++ b/nixos/home-configuration/apps/alacritty.nix @@ -0,0 +1,28 @@ +{ + pkgs, + config, + ... +}: +{ + programs.alacritty = { + enable = false; + theme = "gruvbox_dark"; + settings = { + window = { + opacity = 0.9; + padding = { + x = 2; + y = 2; + }; + blur = true; + }; + font = { + normal = { + family = "JetBrainsMono Nerd Font"; + style = "Regular"; + }; + size = 14; + }; + }; + }; +} diff --git a/nixos/home-configuration/apps/foot.nix b/nixos/home-configuration/apps/foot.nix new file mode 100755 index 0000000..6bbffda --- /dev/null +++ b/nixos/home-configuration/apps/foot.nix @@ -0,0 +1,31 @@ +{ + programs.foot = { + enable = true; + settings = { + main.font = "JetBrainsMono Nerd Font:size=14"; + main.pad = "4x4"; + scrollback.lines = 100000; + + colors.alpha = "0.9"; + colors.background = "191724"; + colors.foreground = "e0def4"; + colors.regular0 = "191724"; + colors.regular1 = "eb6f92"; + colors.regular2 = "9ccfd8"; + colors.regular3 = "f6c177"; + colors.regular4 = "31748f"; + colors.regular5 = "c4a7e7"; + colors.regular6 = "ebbcba"; + colors.regular7 = "e0def4"; + colors.bright0 = "6e6a86"; + colors.bright1 = "eb6f92"; + colors.bright2 = "9ccfd8"; + colors.bright3 = "f6c177"; + colors.bright4 = "31748f"; + colors.bright5 = "c4a7e7"; + colors.bright6 = "ebbcba"; + colors.bright7 = "e0def4"; + }; + }; +} + diff --git a/nixos/home-configuration/apps/nushell.nix b/nixos/home-configuration/apps/nushell.nix new file mode 100755 index 0000000..2d5d83a --- /dev/null +++ b/nixos/home-configuration/apps/nushell.nix @@ -0,0 +1,13 @@ +{ + pkgs, + config, + ... +}: +{ + programs = { + carapace = { + enable = true; + enableNushellIntegration = true; + }; + }; +} diff --git a/nixos/home-configuration/apps/sway.nix b/nixos/home-configuration/apps/sway.nix new file mode 100755 index 0000000..c5a2868 --- /dev/null +++ b/nixos/home-configuration/apps/sway.nix @@ -0,0 +1,111 @@ +{ + pkgs, + ... +}: let + left = "h"; + down = "j"; + up = "k"; + right = "l"; + + modifier = "Mod4"; + terminal = "${pkgs.foot}/bin/footclient"; + menu = "${pkgs.wmenu}/bin/wmenu-run"; +in +{ + wayland.windowManager.sway = { + enable = false; + wrapperFeatures.gtk = true; + extraConfig = '' + exec swaymsg workspace 1 + default_border pixel 2 + default_floating_border pixel 2 + for_window [class=".*"] border pixel 2 + + client.focused #F5C2E7 #6C7086 #C6D0F5 #6C7086 #6C7086 + client.focused_inactive #313244 #313244 #C6D0F5 #585B70 #313244 + client.unfocused #313244 #313244 #A6ADC8 #313244 #313244 + client.urgent #F38BA8 #6C7086 #FFFFFF #F38BA8 #6C7086 + + seat * xcursor_theme Adwaita 24 + + input * xkb_options caps:escape + ''; + config = { + modifier = "Mod4"; + gaps = { + inner = 8; + outer = 10; + }; + bars = []; + output.eDP-1.disable = ""; + keybindings = { + "${modifier}+Return" = "exec ${terminal}"; + "${modifier}+Shift+Return" = "exec ${menu} -l 10"; + "${modifier}+r" = "exec rofi -show drun"; + "${modifier}+s" = "kill"; + "${modifier}+Print" = "exec /home/coast/.local/src/local/bin/screenie-wlr"; + "${modifier}+1" = "workspace 1"; + "${modifier}+2" = "workspace 2"; + "${modifier}+3" = "workspace 3"; + "${modifier}+4" = "workspace 4"; + "${modifier}+5" = "workspace 5"; + "${modifier}+6" = "workspace 6"; + "${modifier}+7" = "workspace 7"; + "${modifier}+8" = "workspace 8"; + "${modifier}+9" = "workspace 9"; + "${modifier}+Shift+1" = "move container to workspace 1"; + "${modifier}+Shift+2" = "move container to workspace 2"; + "${modifier}+Shift+3" = "move container to workspace 3"; + "${modifier}+Shift+4" = "move container to workspace 4"; + "${modifier}+Shift+5" = "move container to workspace 5"; + "${modifier}+Shift+6" = "move container to workspace 6"; + "${modifier}+Shift+7" = "move container to workspace 7"; + "${modifier}+Shift+8" = "move container to workspace 8"; + "${modifier}+Shift+9" = "move container to workspace 9"; + "${modifier}+h" = "focus left"; + "${modifier}+j" = "focus down"; + "${modifier}+k" = "focus up"; + "${modifier}+l" = "focus right"; + "${modifier}+Shift+i" = "exec caja"; + "${modifier}+Shift+r" = "reload"; + "${modifier}+Shift+q" = "exit"; + "${modifier}+Shift+v" = "exec vesktop --ozone-platform=wayland"; + "${modifier}+Shift+p" = "exec /home/coast/.local/src/local/bin/setwall.py"; + "${modifier}+Shift+d" = "mode 'resize'"; + "${modifier}+space" = "floating toggle"; + + #lock the screen + "${modifier}+Shift+l" = "exec swaylock -c 000000"; + #layouts + "${modifier}+Shift+u" = "layout tabbed"; + "${modifier}+Shift+y" = "layout stacking"; + "${modifier}+Shift+t" = "layout toggle split"; + }; + modes = { + resize = { + ${right} = "resize shrink width 10 px"; + ${up} = "resize grow height 10 px"; + ${down} = "resize shrink height 10 px"; + ${left} = "resize grow width 10 px"; + + "Escape" = "mode default"; + "Return" = "mode default"; + }; + }; + startup = [ + { command = "swaybg -i /home/coast/Downloads/wall1.png -m fill"; always = true; } + { command = "waybar"; } + { command = "foot -s"; always = true; } + { command = "autotiling"; } + ]; + }; + }; + + services.swayidle = { + enable = true; + timeouts = [{ + timeout = 300; + command = "${pkgs.swaylock}/bin/swaylock --daemonize --color 000000"; + }]; + }; +} diff --git a/nixos/home-configuration/apps/zsh.nix b/nixos/home-configuration/apps/zsh.nix new file mode 100755 index 0000000..6eb6446 --- /dev/null +++ b/nixos/home-configuration/apps/zsh.nix @@ -0,0 +1,59 @@ +{ + config, + pkgs, + ... +}: +{ + programs.zsh = { + enable = false; + history = { + path = "/home/coast/.cache/zsh/history"; + size = 100000000; + save = 100000000; + append = true; + }; + enableCompletion = true; + shellAliases = { + nf = "neofetch"; + nrs = "sudo nixos-rebuild switch"; + emoji = "cat ~/.local/src/local/share/emoji | grep"; + ls = "ls --color=auto"; + smi = "nvidia-smi"; + battery = "sb-battery"; + weather = "curl wttr.in/masjedsoleyman"; + las = "ls"; + c = "clear"; + cear = "clear"; + ".." = "cd .."; + hotp = "htop"; + main = "man"; + mian = "man"; + mna = "man"; + delgen = "sudo nix-env --delete-generations old --profile /nix/var/nix/profiles/system"; + alsamixer = "alsamixer -c 0 --no-color"; + la = "ls --color=auto -la"; + sidp = "sudo"; + suod = "sudo"; + sduo = "sudo"; + sd = "sudo"; + fastfetch = "fastfetch --pipe false | uwuify.awk"; + }; + initContent = '' + autoload -U compinit + zstyle ':completion:*' menu select + zmodload zsh/complist + compinit + comp_options+=(globdots) + zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' + ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=12" + autoload -U colors && colors && setopt prompt_subst + source ~/.local/src/zsh.d/zsh-autosuggestions.zsh + export PATH="/usr/bin:$PATH" + export PATH="$HOME/.local/bin:$PATH" + EDITOR=vim + bindkey -e + PS1="[%n in %m %~] " + eval "$(starship init zsh)" + ''; + }; +} diff --git a/nixos/home-configuration/configuration.nix b/nixos/home-configuration/configuration.nix new file mode 100755 index 0000000..9df9ad0 --- /dev/null +++ b/nixos/home-configuration/configuration.nix @@ -0,0 +1,99 @@ +{ + config, + pkgs, + ... +}: let + dotDir = "${config.home.homeDirectory}/.local/src/config/"; + mkSl = path: config.lib.file.mkOutOfStoreSymlink path; + configs = { + kitty = "kitty"; + qtile = "qtile"; + mako = "mako"; + nvim = "nvim"; + eww = "eww"; + waybar = "waybar"; + rofi = "rofi"; + nushell = "nushell"; + niri = "niri"; + "starship.toml" = "starship.toml"; + }; +in { + xdg.configFile = builtins.mapAttrs (name: subpath: { + source = mkSl "${dotDir}/${subpath}"; + recursive = true; + }) configs; + + home = { + username = "coast"; + homeDirectory = "/home/coast"; + stateVersion = "25.05"; + packages = with pkgs; [ + alsa-utils + xwayland-satellite + nix-search-cli + fastfetch + lollypop + cmatrix + dysk + brightnessctl + ncurses + tree + xfce.ristretto + pyright + stylua + typescript-language-server + lua + vscode-langservers-extracted + swaylock + starship + gopls + lua-language-server + serve-d + wl-clipboard + appimage-run + libnotify + grim + slurp + yazi + nautilus + btop + nixpkgs-fmt + swww + wmenu + mako + nwg-look + xorg.xkill + xorg.xeyes + mpv + vesktop + wlr-randr + nodejs + clang_multi + gnumake + clang-tools + ruby_3_4 + pkg-config + dmd + dtools + rustup + python3 + python313Packages.pip + unzip + zip + go + gimp + waybar + glibc + man-pages + man-pages-posix + eww + ]; + }; + + programs.git = { + enable = true; + userEmail = "coasteen@proton.me"; + userName = "coast"; + }; + +} diff --git a/portage/make.conf b/portage/make.conf new file mode 100755 index 0000000..81f6c54 --- /dev/null +++ b/portage/make.conf @@ -0,0 +1,20 @@ +# These settings were set by the catalyst build script that automatically +# built this stage. +# Please consult /usr/share/portage/config/make.conf.example for a more +# detailed example. +COMMON_FLAGS="-march=alderlake -mabm -mno-cldemote -mno-kl -mno-pconfig -mno-sgx -mno-widekl -mshstk --param=l1-cache-line-size=64 --param=l1-cache-size=32 --param=l2-cache-size=12288 -O2 -pipe" +CFLAGS="${COMMON_FLAGS}" +CXXFLAGS="${COMMON_FLAGS}" +FCFLAGS="${COMMON_FLAGS}" +FFLAGS="${COMMON_FLAGS}" +RUSTFLAGS="${RUSTFLAGS} -C target-cpu=alderlake" +MAKEOPTS="-j12" +USE="-mate -kde -gnome -plasma nvidia intel -amdgpu amd64 -cinnamon -xfce -selinux -systemd openrc sysvinit wayland X pulseaudio -pipewire opengl elogind -fish -vmware vulkan" +VIDEO_CARDS="nvidia intel" +ACCEPT_LICENSE="*" + +# NOTE: This stage was built with the bindist USE flag enabled + +# This sets the language of build output to English. +# Please keep this setting intact when reporting bugs. +LC_MESSAGES=C.utf8 diff --git a/slock b/slock new file mode 160000 index 0000000..3791a99 --- /dev/null +++ b/slock @@ -0,0 +1 @@ +Subproject commit 3791a996e230aec59d61faea46634ae4f031e359 diff --git a/slstatus/LICENSE b/slstatus/LICENSE new file mode 100755 index 0000000..8bee9c8 --- /dev/null +++ b/slstatus/LICENSE @@ -0,0 +1,43 @@ +ISC License + +Copyright 2016-2022 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> + +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/Makefile b/slstatus/Makefile new file mode 100755 index 0000000..7a18274 --- /dev/null +++ b/slstatus/Makefile @@ -0,0 +1,69 @@ +# 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/arg.h b/slstatus/arg.h new file mode 100755 index 0000000..5f1f408 --- /dev/null +++ b/slstatus/arg.h @@ -0,0 +1,33 @@ +/* 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/components/battery.c b/slstatus/components/battery.c new file mode 100755 index 0000000..d5ef9ea --- /dev/null +++ b/slstatus/components/battery.c @@ -0,0 +1,247 @@ +/* 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", "󰚥" }, + { "Not charging", "󰚥"}, + }; + size_t i; + char path[PATH_MAX], state[12]; + + if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) + return NULL; + if (pscanf(path, "%12[a-zA-Z ]", state) != 1) + return NULL; + + for (i = 0; i < LEN(map); i++) + if (!strcmp(map[i].state, state)) + break; + + return (i == LEN(map)) ? "?" : map[i].symbol; + } + + const char * + battery_remaining(const char *bat) + { + uintmax_t charge_now, current_now, m, h; + double timeleft; + char path[PATH_MAX], state[12]; + + if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) + return NULL; + if (pscanf(path, "%12[a-zA-Z ]", state) != 1) + return NULL; + + if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path, + sizeof(path)) || + pscanf(path, "%ju", &charge_now) < 0) + return NULL; + + if (!strcmp(state, "Discharging")) { + if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path, + sizeof(path)) || + pscanf(path, "%ju", ¤t_now) < 0) + return NULL; + + if (current_now == 0) + return NULL; + + timeleft = (double)charge_now / (double)current_now; + h = timeleft; + m = (timeleft - (double)h) * 60; + + return bprintf("%juh %jum", h, m); + } + + return ""; + } +#elif defined(__OpenBSD__) + #include <fcntl.h> + #include <machine/apmvar.h> + #include <sys/ioctl.h> + #include <unistd.h> + + static int + load_apm_power_info(struct apm_power_info *apm_info) + { + int fd; + + fd = open("/dev/apm", O_RDONLY); + if (fd < 0) { + warn("open '/dev/apm':"); + return 0; + } + + memset(apm_info, 0, sizeof(struct apm_power_info)); + if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) { + warn("ioctl 'APM_IOC_GETPOWER':"); + close(fd); + return 0; + } + return close(fd), 1; + } + + const char * + battery_perc(const char *unused) + { + struct apm_power_info apm_info; + + if (load_apm_power_info(&apm_info)) + return bprintf("%d", apm_info.battery_life); + + return NULL; + } + + const char * + battery_state(const char *unused) + { + struct { + unsigned int state; + char *symbol; + } map[] = { + { APM_AC_ON, "+" }, + { APM_AC_OFF, "-" }, + }; + struct apm_power_info apm_info; + size_t i; + + if (load_apm_power_info(&apm_info)) { + for (i = 0; i < LEN(map); i++) + if (map[i].state == apm_info.ac_state) + break; + + return (i == LEN(map)) ? "?" : map[i].symbol; + } + + return NULL; + } + + const char * + battery_remaining(const char *unused) + { + struct apm_power_info apm_info; + unsigned int h, m; + + if (load_apm_power_info(&apm_info)) { + if (apm_info.ac_state != APM_AC_ON) { + h = apm_info.minutes_left / 60; + m = apm_info.minutes_left % 60; + return bprintf("%uh %02um", h, m); + } else { + return ""; + } + } + + return NULL; + } +#elif defined(__FreeBSD__) + #include <sys/sysctl.h> + + #define BATTERY_LIFE "hw.acpi.battery.life" + #define BATTERY_STATE "hw.acpi.battery.state" + #define BATTERY_TIME "hw.acpi.battery.time" + + const char * + battery_perc(const char *unused) + { + int cap_perc; + size_t len; + + len = sizeof(cap_perc); + if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len) + return NULL; + + return bprintf("%d", cap_perc); + } + + const char * + battery_state(const char *unused) + { + int state; + size_t len; + + len = sizeof(state); + if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len) + return NULL; + + switch (state) { + case 0: /* FALLTHROUGH */ + case 2: + return "+"; + case 1: + return "-"; + default: + return "?"; + } + } + + const char * + battery_remaining(const char *unused) + { + int rem; + size_t len; + + len = sizeof(rem); + if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len + || rem < 0) + return NULL; + + return bprintf("%uh %02um", rem / 60, rem % 60); + } +#endif diff --git a/slstatus/components/battery.o b/slstatus/components/battery.o new file mode 100644 index 0000000..6adf884 Binary files /dev/null and b/slstatus/components/battery.o differ diff --git a/slstatus/components/cat.c b/slstatus/components/cat.c new file mode 100755 index 0000000..07944cc --- /dev/null +++ b/slstatus/components/cat.c @@ -0,0 +1,32 @@ +/* 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/components/cat.o b/slstatus/components/cat.o new file mode 100644 index 0000000..ffc6a18 Binary files /dev/null and b/slstatus/components/cat.o differ diff --git a/slstatus/components/cpu.c b/slstatus/components/cpu.c new file mode 100755 index 0000000..d0d03c7 --- /dev/null +++ b/slstatus/components/cpu.c @@ -0,0 +1,157 @@ +/* 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/components/cpu.o b/slstatus/components/cpu.o new file mode 100644 index 0000000..3d5efac Binary files /dev/null and b/slstatus/components/cpu.o differ diff --git a/slstatus/components/datetime.c b/slstatus/components/datetime.c new file mode 100755 index 0000000..5b10daf --- /dev/null +++ b/slstatus/components/datetime.c @@ -0,0 +1,20 @@ +/* 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/components/datetime.o b/slstatus/components/datetime.o new file mode 100644 index 0000000..bedc621 Binary files /dev/null and b/slstatus/components/datetime.o differ diff --git a/slstatus/components/disk.c b/slstatus/components/disk.c new file mode 100755 index 0000000..e19a693 --- /dev/null +++ b/slstatus/components/disk.c @@ -0,0 +1,59 @@ +/* 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/components/disk.o b/slstatus/components/disk.o new file mode 100644 index 0000000..b051fdd Binary files /dev/null and b/slstatus/components/disk.o differ diff --git a/slstatus/components/entropy.c b/slstatus/components/entropy.c new file mode 100755 index 0000000..65010b0 --- /dev/null +++ b/slstatus/components/entropy.c @@ -0,0 +1,29 @@ +/* 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/components/entropy.o b/slstatus/components/entropy.o new file mode 100644 index 0000000..0611d9c Binary files /dev/null and b/slstatus/components/entropy.o differ diff --git a/slstatus/components/hostname.c b/slstatus/components/hostname.c new file mode 100755 index 0000000..dab8b63 --- /dev/null +++ b/slstatus/components/hostname.c @@ -0,0 +1,17 @@ +/* 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/components/hostname.o b/slstatus/components/hostname.o new file mode 100644 index 0000000..ed8e54a Binary files /dev/null and b/slstatus/components/hostname.o differ diff --git a/slstatus/components/ip.c b/slstatus/components/ip.c new file mode 100755 index 0000000..9476549 --- /dev/null +++ b/slstatus/components/ip.c @@ -0,0 +1,61 @@ +/* See LICENSE file for copyright and license details. */ +#include <ifaddrs.h> +#include <netdb.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); +} diff --git a/slstatus/components/ip.o b/slstatus/components/ip.o new file mode 100644 index 0000000..3672e24 Binary files /dev/null and b/slstatus/components/ip.o differ diff --git a/slstatus/components/kernel_release.c b/slstatus/components/kernel_release.c new file mode 100755 index 0000000..36a6a44 --- /dev/null +++ b/slstatus/components/kernel_release.c @@ -0,0 +1,19 @@ +/* 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/components/kernel_release.o b/slstatus/components/kernel_release.o new file mode 100644 index 0000000..d214b3c Binary files /dev/null and b/slstatus/components/kernel_release.o differ diff --git a/slstatus/components/keyboard_indicators.c b/slstatus/components/keyboard_indicators.c new file mode 100755 index 0000000..5f62bb7 --- /dev/null +++ b/slstatus/components/keyboard_indicators.c @@ -0,0 +1,50 @@ +/* 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/components/keyboard_indicators.o b/slstatus/components/keyboard_indicators.o new file mode 100644 index 0000000..fddf659 Binary files /dev/null and b/slstatus/components/keyboard_indicators.o differ diff --git a/slstatus/components/keymap.c b/slstatus/components/keymap.c new file mode 100755 index 0000000..f8a2a47 --- /dev/null +++ b/slstatus/components/keymap.c @@ -0,0 +1,86 @@ +/* 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/components/keymap.o b/slstatus/components/keymap.o new file mode 100644 index 0000000..a081f27 Binary files /dev/null and b/slstatus/components/keymap.o differ diff --git a/slstatus/components/load_avg.c b/slstatus/components/load_avg.c new file mode 100755 index 0000000..f278a40 --- /dev/null +++ b/slstatus/components/load_avg.c @@ -0,0 +1,19 @@ +/* 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/components/load_avg.o b/slstatus/components/load_avg.o new file mode 100644 index 0000000..946966e Binary files /dev/null and b/slstatus/components/load_avg.o differ diff --git a/slstatus/components/netspeeds.c b/slstatus/components/netspeeds.c new file mode 100755 index 0000000..cde6fa9 --- /dev/null +++ b/slstatus/components/netspeeds.c @@ -0,0 +1,129 @@ +/* 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/components/netspeeds.o b/slstatus/components/netspeeds.o new file mode 100644 index 0000000..ffcb639 Binary files /dev/null and b/slstatus/components/netspeeds.o differ diff --git a/slstatus/components/num_files.c b/slstatus/components/num_files.c new file mode 100755 index 0000000..df0acd1 --- /dev/null +++ b/slstatus/components/num_files.c @@ -0,0 +1,32 @@ +/* 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/components/num_files.o b/slstatus/components/num_files.o new file mode 100644 index 0000000..4fdd111 Binary files /dev/null and b/slstatus/components/num_files.o differ diff --git a/slstatus/components/pixVol.sh b/slstatus/components/pixVol.sh new file mode 100755 index 0000000..8f59505 --- /dev/null +++ b/slstatus/components/pixVol.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +volume=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -Po '\d+%' | head -n 1 | tr -d '%') +muted=$(pactl get-sink-mute @DEFAULT_SINK@ | awk '{print $2}') + +if [ "$muted" = "yes" ]; then + echo "Muted" +else + echo "${volume}" +fi diff --git a/slstatus/components/ram.c b/slstatus/components/ram.c new file mode 100755 index 0000000..15c4b74 --- /dev/null +++ b/slstatus/components/ram.c @@ -0,0 +1,212 @@ +/* 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/components/ram.o b/slstatus/components/ram.o new file mode 100644 index 0000000..a25c47a Binary files /dev/null and b/slstatus/components/ram.o differ diff --git a/slstatus/components/run_command.c b/slstatus/components/run_command.c new file mode 100755 index 0000000..93bf6da --- /dev/null +++ b/slstatus/components/run_command.c @@ -0,0 +1,31 @@ +/* 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/components/run_command.o b/slstatus/components/run_command.o new file mode 100644 index 0000000..2beb247 Binary files /dev/null and b/slstatus/components/run_command.o differ diff --git a/slstatus/components/swap.c b/slstatus/components/swap.c new file mode 100755 index 0000000..f270d93 --- /dev/null +++ b/slstatus/components/swap.c @@ -0,0 +1,274 @@ +/* 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/components/swap.o b/slstatus/components/swap.o new file mode 100644 index 0000000..acb689c Binary files /dev/null and b/slstatus/components/swap.o differ diff --git a/slstatus/components/temperature.c b/slstatus/components/temperature.c new file mode 100755 index 0000000..7cf1394 --- /dev/null +++ b/slstatus/components/temperature.c @@ -0,0 +1,73 @@ +/* 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/components/temperature.o b/slstatus/components/temperature.o new file mode 100644 index 0000000..baa2598 Binary files /dev/null and b/slstatus/components/temperature.o differ diff --git a/slstatus/components/uptime.c b/slstatus/components/uptime.c new file mode 100755 index 0000000..6227f73 --- /dev/null +++ b/slstatus/components/uptime.c @@ -0,0 +1,34 @@ +/* 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/components/uptime.o b/slstatus/components/uptime.o new file mode 100644 index 0000000..63cdc0d Binary files /dev/null and b/slstatus/components/uptime.o differ diff --git a/slstatus/components/user.c b/slstatus/components/user.c new file mode 100755 index 0000000..3517495 --- /dev/null +++ b/slstatus/components/user.c @@ -0,0 +1,33 @@ +/* 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/components/user.o b/slstatus/components/user.o new file mode 100644 index 0000000..32644f5 Binary files /dev/null and b/slstatus/components/user.o differ diff --git a/slstatus/components/volume.c b/slstatus/components/volume.c new file mode 100755 index 0000000..6cec556 --- /dev/null +++ b/slstatus/components/volume.c @@ -0,0 +1,219 @@ +/* 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/components/volume.o b/slstatus/components/volume.o new file mode 100644 index 0000000..2ec4df2 Binary files /dev/null and b/slstatus/components/volume.o differ diff --git a/slstatus/components/wifi.c b/slstatus/components/wifi.c new file mode 100755 index 0000000..4543d32 --- /dev/null +++ b/slstatus/components/wifi.c @@ -0,0 +1,267 @@ +/* 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 <limits.h> + #include <linux/wireless.h> + + #define NET_OPERSTATE "/sys/class/net/%s/operstate" + + const char * + wifi_perc(const char *interface) + { + int cur; + size_t i; + char *p, *datastart; + char path[PATH_MAX]; + char status[5]; + FILE *fp; + + if (esnprintf(path, sizeof(path), NET_OPERSTATE, interface) < 0) + return NULL; + if (!(fp = fopen(path, "r"))) { + warn("fopen '%s':", path); + return NULL; + } + p = fgets(status, 5, fp); + fclose(fp); + if (!p || strcmp(status, "up\n") != 0) + return NULL; + + if (!(fp = fopen("/proc/net/wireless", "r"))) { + warn("fopen '/proc/net/wireless':"); + return NULL; + } + + for (i = 0; i < 3; i++) + if (!(p = fgets(buf, sizeof(buf) - 1, fp))) + break; + + fclose(fp); + if (i < 2 || !p) + return NULL; + + if (!(datastart = strstr(buf, interface))) + return NULL; + + datastart = (datastart+(strlen(interface)+1)); + sscanf(datastart + 1, " %*d %d %*d %*d\t\t %*d\t " + "%*d\t\t%*d\t\t %*d\t %*d\t\t %*d", &cur); + + /* 70 is the max of /proc/net/wireless */ + return bprintf("%d", (int)((float)cur / 70 * 100)); + } + + const char * + wifi_essid(const char *interface) + { + static char id[IW_ESSID_MAX_SIZE+1]; + int sockfd; + struct iwreq wreq; + + memset(&wreq, 0, sizeof(struct iwreq)); + wreq.u.essid.length = IW_ESSID_MAX_SIZE+1; + if (esnprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", + interface) < 0) + return NULL; + + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + warn("socket 'AF_INET':"); + return NULL; + } + wreq.u.essid.pointer = id; + if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) { + warn("ioctl 'SIOCGIWESSID':"); + close(sockfd); + return NULL; + } + + close(sockfd); + + if (!strcmp(id, "")) + return NULL; + + return id; + } +#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/components/wifi.o b/slstatus/components/wifi.o new file mode 100644 index 0000000..8f24f5e Binary files /dev/null and b/slstatus/components/wifi.o differ diff --git a/slstatus/config.def.h b/slstatus/config.def.h new file mode 100755 index 0000000..70f58da --- /dev/null +++ b/slstatus/config.def.h @@ -0,0 +1,81 @@ +/* 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 + * 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_state, " %s /", "BAT1"}, + {battery_perc, "  %s% |", "BAT1"}, + {run_command, "  %s% |", "light -G | awk '{print int($1)}'"}, + {run_command, "  %s% |", "pamixer --get-volume"}, + {cpu_perc, "  %s% /", NULL}, + {temp, "  %s󰔄 |", "/sys/class/thermal/thermal_zone3/temp"}, + {ram_used, "  %s |", NULL}, + {run_command, " 󰸗 %s |", "date +'%b %d'"}, + {run_command, " 󱑃 %s |", "date +%H:%M"}, + {disk_perc, "  %s% |", "/home"}, + {wifi_essid, "  %s |", "wlan0"}, + {keymap, "  %s ", NULL}, + +}; diff --git a/slstatus/config.h b/slstatus/config.h new file mode 100755 index 0000000..efba7c2 --- /dev/null +++ b/slstatus/config.h @@ -0,0 +1,74 @@ +/* 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 + * 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 */ + {run_command, "[ %s]", "~/.local/bin/mpc-shuf.sh current"}, + {run_command, " [VOL%s%%] ", + "pactl list sinks | grep -A 15 'State: RUNNING' | grep 'Volume:' | awk " + "-F'[/%]' '{print int($2)}'"}, + {ram_used, "[RAM%s]", NULL}, + {run_command, " [%s]", "date '+%I:%M %p'"}, +}; diff --git a/slstatus/config.mk b/slstatus/config.mk new file mode 100755 index 0000000..7485796 --- /dev/null +++ b/slstatus/config.mk @@ -0,0 +1,22 @@ +# slstatus version +VERSION = 1.0 + +# customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/include +X11LIB = /usr/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 = gcc diff --git a/slstatus/slstatus b/slstatus/slstatus new file mode 100755 index 0000000..fcf3709 Binary files /dev/null and b/slstatus/slstatus differ diff --git a/slstatus/slstatus.1 b/slstatus/slstatus.1 new file mode 100755 index 0000000..73e7a60 --- /dev/null +++ b/slstatus/slstatus.1 @@ -0,0 +1,47 @@ +.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.c b/slstatus/slstatus.c new file mode 100755 index 0000000..fd31313 --- /dev/null +++ b/slstatus/slstatus.c @@ -0,0 +1,134 @@ +/* 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); + case '1': + done = 1; + /* FALLTHROUGH */ + case 's': + sflag = 1; + break; + default: + usage(); + } ARGEND + + if (argc) + usage(); + + memset(&act, 0, sizeof(act)); + act.sa_handler = terminate; + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); + act.sa_flags |= SA_RESTART; + sigaction(SIGUSR1, &act, NULL); + + if (!sflag && !(dpy = XOpenDisplay(NULL))) + die("XOpenDisplay: Failed to open display"); + + do { + if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) + die("clock_gettime:"); + + status[0] = '\0'; + for (i = len = 0; i < LEN(args); i++) { + if (!(res = args[i].func(args[i].args))) + res = unknown_str; + + if ((ret = esnprintf(status + len, sizeof(status) - len, + args[i].fmt, res)) < 0) + break; + + len += ret; + } + + if (sflag) { + puts(status); + fflush(stdout); + if (ferror(stdout)) + die("puts:"); + } else { + if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) + die("XStoreName: Allocation failed"); + XFlush(dpy); + } + + if (!done) { + if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) + die("clock_gettime:"); + difftimespec(&diff, ¤t, &start); + + intspec.tv_sec = interval / 1000; + intspec.tv_nsec = (interval % 1000) * 1E6; + difftimespec(&wait, &intspec, &diff); + + if (wait.tv_sec >= 0 && + nanosleep(&wait, NULL) < 0 && + errno != EINTR) + die("nanosleep:"); + } + } while (!done); + + if (!sflag) { + XStoreName(dpy, DefaultRootWindow(dpy), NULL); + if (XCloseDisplay(dpy) < 0) + die("XCloseDisplay: Failed to close display"); + } + + return 0; +} diff --git a/slstatus/slstatus.h b/slstatus/slstatus.h new file mode 100755 index 0000000..8ef5874 --- /dev/null +++ b/slstatus/slstatus.h @@ -0,0 +1,84 @@ +/* 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); + +/* 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.o b/slstatus/slstatus.o new file mode 100644 index 0000000..14d118f Binary files /dev/null and b/slstatus/slstatus.o differ diff --git a/slstatus/util.c b/slstatus/util.c new file mode 100755 index 0000000..bca9b2e --- /dev/null +++ b/slstatus/util.c @@ -0,0 +1,141 @@ +/* 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/util.h b/slstatus/util.h new file mode 100755 index 0000000..cf4b027 --- /dev/null +++ b/slstatus/util.h @@ -0,0 +1,16 @@ +/* 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/slstatus/util.o b/slstatus/util.o new file mode 100644 index 0000000..33eb08b Binary files /dev/null and b/slstatus/util.o differ diff --git a/sober/config.json b/sober/config.json new file mode 100755 index 0000000..eac69b0 --- /dev/null +++ b/sober/config.json @@ -0,0 +1,24 @@ +// !!! STOP !!! +// This file is not meant to be edited by hand unless you know what you're doing. You are encouraged to use the settings menu instead (Right click Sober in your apps menu, then hit "Settings") +// You can prevent Sober from launching by improperly formatting this file's JSON, or possibly mess up the Roblox engine by toggling certain flags intended for Roblox engineers. +// **If you got Fastflags from an FFlag guide, Reddit post, AI model, or a YouTuber, you shouldn't be here, and the FFlags provided are likely made up. We will not provide support for any bugs caused by Fastflag usage.** +// Incase you mess up, you can reset this file by deleting it. It will be recreated the next time you launch Sober. +// ------------------------------------------- +// Documentation is available at https://vinegarhq.org/Sober/Configuration/index.html - We encourage you to read it before toggling anything. +{ + "allow_gamepad_permission": false, + "close_on_leave": false, + "discord_rpc_enabled": false, + "enable_gamemode": true, + "enable_hidpi": false, + "fflags": { + "DFFlagTextureQualityOverrideEnabled": true, + "DFIntTextureQualityOverride": 3, + "FFlagExample": true + }, + "server_location_indicator_enabled": false, + "touch_mode": "off", + "use_console_experience": false, + "use_libsecret": false, + "use_opengl": true +} diff --git a/st/LEGACY b/st/LEGACY new file mode 100755 index 0000000..bf28b1e --- /dev/null +++ b/st/LEGACY @@ -0,0 +1,17 @@ +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/LICENSE b/st/LICENSE new file mode 100755 index 0000000..3cbf420 --- /dev/null +++ b/st/LICENSE @@ -0,0 +1,34 @@ +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/Makefile b/st/Makefile new file mode 100755 index 0000000..dfcea0f --- /dev/null +++ b/st/Makefile @@ -0,0 +1,52 @@ +# st - simple terminal +# See LICENSE file for copyright and license details. +.POSIX: + +include config.mk + +SRC = st.c x.c hb.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 hb.h +hb.o: st.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/README b/st/README new file mode 100755 index 0000000..6a846ed --- /dev/null +++ b/st/README @@ -0,0 +1,34 @@ +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/TODO b/st/TODO new file mode 100755 index 0000000..5f74cd5 --- /dev/null +++ b/st/TODO @@ -0,0 +1,28 @@ +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/arg.h b/st/arg.h new file mode 100755 index 0000000..a22e019 --- /dev/null +++ b/st/arg.h @@ -0,0 +1,50 @@ +/* + * 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/boxdraw.c b/st/boxdraw.c new file mode 100755 index 0000000..28a92d0 --- /dev/null +++ b/st/boxdraw.c @@ -0,0 +1,194 @@ +/* + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih + * MIT/X Consortium License + */ + +#include <X11/Xft/Xft.h> +#include "st.h" +#include "boxdraw_data.h" + +/* Rounded non-negative integers division of n / d */ +#define DIV(n, d) (((n) + (d) / 2) / (d)) + +static Display *xdpy; +static Colormap xcmap; +static XftDraw *xd; +static Visual *xvis; + +static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); +static void drawboxlines(int, int, int, int, XftColor *, ushort); + +/* public API */ + +void +boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) +{ + xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; +} + +int +isboxdraw(Rune u) +{ + Rune block = u & ~0xff; + return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || + (boxdraw_braille && block == 0x2800); +} + +/* the "index" is actually the entire shape data encoded as ushort */ +ushort +boxdrawindex(const Glyph *g) +{ + if (boxdraw_braille && (g->u & ~0xff) == 0x2800) + return BRL | (uint8_t)g->u; + if (boxdraw_bold && (g->mode & ATTR_BOLD)) + return BDB | boxdata[(uint8_t)g->u]; + return boxdata[(uint8_t)g->u]; +} + +void +drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, + const XftGlyphFontSpec *specs, int len) +{ + for ( ; len-- > 0; x += cw, specs++) + drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); +} + +/* implementation */ + +void +drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) +{ + ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ + if (bd & (BDL | BDA)) { + /* lines (light/double/heavy/arcs) */ + drawboxlines(x, y, w, h, fg, bd); + + } else if (cat == BBD) { + /* lower (8-X)/8 block */ + int d = DIV((uint8_t)bd * h, 8); + XftDrawRect(xd, fg, x, y + d, w, h - d); + + } else if (cat == BBU) { + /* upper X/8 block */ + XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); + + } else if (cat == BBL) { + /* left X/8 block */ + XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); + + } else if (cat == BBR) { + /* right (8-X)/8 block */ + int d = DIV((uint8_t)bd * w, 8); + XftDrawRect(xd, fg, x + d, y, w - d, h); + + } else if (cat == BBQ) { + /* Quadrants */ + int w2 = DIV(w, 2), h2 = DIV(h, 2); + if (bd & TL) + XftDrawRect(xd, fg, x, y, w2, h2); + if (bd & TR) + XftDrawRect(xd, fg, x + w2, y, w - w2, h2); + if (bd & BL) + XftDrawRect(xd, fg, x, y + h2, w2, h - h2); + if (bd & BR) + XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); + + } else if (bd & BBS) { + /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ + int d = (uint8_t)bd; + XftColor xfc; + XRenderColor xrc = { .alpha = 0xffff }; + + xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); + xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); + xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); + + XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); + XftDrawRect(xd, &xfc, x, y, w, h); + XftColorFree(xdpy, xvis, xcmap, &xfc); + + } else if (cat == BRL) { + /* braille, each data bit corresponds to one dot at 2x4 grid */ + int w1 = DIV(w, 2); + int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); + + if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); + if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); + if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); + if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); + if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); + if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); + if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); + if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); + + } +} + +void +drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) +{ + /* s: stem thickness. width/8 roughly matches underscore thickness. */ + /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ + /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ + int mwh = MIN(w, h); + int base_s = MAX(1, DIV(mwh, 8)); + int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ + int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; + int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); + /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ + /* The base length (per direction till edge) includes this square. */ + + int light = bd & (LL | LU | LR | LD); + int double_ = bd & (DL | DU | DR | DD); + + if (light) { + /* d: additional (negative) length to not-draw the center */ + /* texel - at arcs and avoid drawing inside (some) doubles */ + int arc = bd & BDA; + int multi_light = light & (light - 1); + int multi_double = double_ & (double_ - 1); + /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ + int d = arc || (multi_double && !multi_light) ? -s : 0; + + if (bd & LL) + XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); + if (bd & LU) + XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); + if (bd & LR) + XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); + if (bd & LD) + XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); + } + + /* double lines - also align with light to form heavy when combined */ + if (double_) { + /* + * going clockwise, for each double-ray: p is additional length + * to the single-ray nearer to the previous direction, and n to + * the next. p and n adjust from the base length to lengths + * which consider other doubles - shorter to avoid intersections + * (p, n), or longer to draw the far-corner texel (n). + */ + int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; + if (dl) { + int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; + XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); + XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); + } + if (du) { + int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; + XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); + XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); + } + if (dr) { + int p = du ? -s : 0, n = dd ? -s : du ? s : 0; + XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); + XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); + } + if (dd) { + int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; + XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); + XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); + } + } +} diff --git a/st/boxdraw_data.h b/st/boxdraw_data.h new file mode 100755 index 0000000..7890500 --- /dev/null +++ b/st/boxdraw_data.h @@ -0,0 +1,214 @@ +/* + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih + * MIT/X Consortium License + */ + +/* + * U+25XX codepoints data + * + * References: + * http://www.unicode.org/charts/PDF/U2500.pdf + * http://www.unicode.org/charts/PDF/U2580.pdf + * + * Test page: + * https://github.com/GNOME/vte/blob/master/doc/boxes.txt + */ + +/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ +/* Categories (mutually exclusive except BDB): */ +/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ +#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ +#define BDA (1<<9) /* Box Draw Arc (light) */ + +#define BBD (1<<10) /* Box Block Down (lower) X/8 */ +#define BBL (2<<10) /* Box Block Left X/8 */ +#define BBU (3<<10) /* Box Block Upper X/8 */ +#define BBR (4<<10) /* Box Block Right X/8 */ +#define BBQ (5<<10) /* Box Block Quadrants */ +#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ + +#define BBS (1<<14) /* Box Block Shades */ +#define BDB (1<<15) /* Box Draw is Bold */ + +/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ +/* Heavy is light+double (literally drawing light+double align to form heavy) */ +#define LL (1<<0) +#define LU (1<<1) +#define LR (1<<2) +#define LD (1<<3) +#define LH (LL+LR) +#define LV (LU+LD) + +#define DL (1<<4) +#define DU (1<<5) +#define DR (1<<6) +#define DD (1<<7) +#define DH (DL+DR) +#define DV (DU+DD) + +#define HL (LL+DL) +#define HU (LU+DU) +#define HR (LR+DR) +#define HD (LD+DD) +#define HH (HL+HR) +#define HV (HU+HD) + +/* (BBQ) Quadrants Top/Bottom x Left/Right */ +#define TL (1<<0) +#define TR (1<<1) +#define BL (1<<2) +#define BR (1<<3) + +/* Data for U+2500 - U+259F except dashes/diagonals */ +static const unsigned short boxdata[256] = { + /* light lines */ + [0x00] = BDL + LH, /* light horizontal */ + [0x02] = BDL + LV, /* light vertical */ + [0x0c] = BDL + LD + LR, /* light down and right */ + [0x10] = BDL + LD + LL, /* light down and left */ + [0x14] = BDL + LU + LR, /* light up and right */ + [0x18] = BDL + LU + LL, /* light up and left */ + [0x1c] = BDL + LV + LR, /* light vertical and right */ + [0x24] = BDL + LV + LL, /* light vertical and left */ + [0x2c] = BDL + LH + LD, /* light horizontal and down */ + [0x34] = BDL + LH + LU, /* light horizontal and up */ + [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ + [0x74] = BDL + LL, /* light left */ + [0x75] = BDL + LU, /* light up */ + [0x76] = BDL + LR, /* light right */ + [0x77] = BDL + LD, /* light down */ + + /* heavy [+light] lines */ + [0x01] = BDL + HH, + [0x03] = BDL + HV, + [0x0d] = BDL + HR + LD, + [0x0e] = BDL + HD + LR, + [0x0f] = BDL + HD + HR, + [0x11] = BDL + HL + LD, + [0x12] = BDL + HD + LL, + [0x13] = BDL + HD + HL, + [0x15] = BDL + HR + LU, + [0x16] = BDL + HU + LR, + [0x17] = BDL + HU + HR, + [0x19] = BDL + HL + LU, + [0x1a] = BDL + HU + LL, + [0x1b] = BDL + HU + HL, + [0x1d] = BDL + HR + LV, + [0x1e] = BDL + HU + LD + LR, + [0x1f] = BDL + HD + LR + LU, + [0x20] = BDL + HV + LR, + [0x21] = BDL + HU + HR + LD, + [0x22] = BDL + HD + HR + LU, + [0x23] = BDL + HV + HR, + [0x25] = BDL + HL + LV, + [0x26] = BDL + HU + LD + LL, + [0x27] = BDL + HD + LU + LL, + [0x28] = BDL + HV + LL, + [0x29] = BDL + HU + HL + LD, + [0x2a] = BDL + HD + HL + LU, + [0x2b] = BDL + HV + HL, + [0x2d] = BDL + HL + LD + LR, + [0x2e] = BDL + HR + LL + LD, + [0x2f] = BDL + HH + LD, + [0x30] = BDL + HD + LH, + [0x31] = BDL + HD + HL + LR, + [0x32] = BDL + HR + HD + LL, + [0x33] = BDL + HH + HD, + [0x35] = BDL + HL + LU + LR, + [0x36] = BDL + HR + LU + LL, + [0x37] = BDL + HH + LU, + [0x38] = BDL + HU + LH, + [0x39] = BDL + HU + HL + LR, + [0x3a] = BDL + HU + HR + LL, + [0x3b] = BDL + HH + HU, + [0x3d] = BDL + HL + LV + LR, + [0x3e] = BDL + HR + LV + LL, + [0x3f] = BDL + HH + LV, + [0x40] = BDL + HU + LH + LD, + [0x41] = BDL + HD + LH + LU, + [0x42] = BDL + HV + LH, + [0x43] = BDL + HU + HL + LD + LR, + [0x44] = BDL + HU + HR + LD + LL, + [0x45] = BDL + HD + HL + LU + LR, + [0x46] = BDL + HD + HR + LU + LL, + [0x47] = BDL + HH + HU + LD, + [0x48] = BDL + HH + HD + LU, + [0x49] = BDL + HV + HL + LR, + [0x4a] = BDL + HV + HR + LL, + [0x4b] = BDL + HV + HH, + [0x78] = BDL + HL, + [0x79] = BDL + HU, + [0x7a] = BDL + HR, + [0x7b] = BDL + HD, + [0x7c] = BDL + HR + LL, + [0x7d] = BDL + HD + LU, + [0x7e] = BDL + HL + LR, + [0x7f] = BDL + HU + LD, + + /* double [+light] lines */ + [0x50] = BDL + DH, + [0x51] = BDL + DV, + [0x52] = BDL + DR + LD, + [0x53] = BDL + DD + LR, + [0x54] = BDL + DR + DD, + [0x55] = BDL + DL + LD, + [0x56] = BDL + DD + LL, + [0x57] = BDL + DL + DD, + [0x58] = BDL + DR + LU, + [0x59] = BDL + DU + LR, + [0x5a] = BDL + DU + DR, + [0x5b] = BDL + DL + LU, + [0x5c] = BDL + DU + LL, + [0x5d] = BDL + DL + DU, + [0x5e] = BDL + DR + LV, + [0x5f] = BDL + DV + LR, + [0x60] = BDL + DV + DR, + [0x61] = BDL + DL + LV, + [0x62] = BDL + DV + LL, + [0x63] = BDL + DV + DL, + [0x64] = BDL + DH + LD, + [0x65] = BDL + DD + LH, + [0x66] = BDL + DD + DH, + [0x67] = BDL + DH + LU, + [0x68] = BDL + DU + LH, + [0x69] = BDL + DH + DU, + [0x6a] = BDL + DH + LV, + [0x6b] = BDL + DV + LH, + [0x6c] = BDL + DH + DV, + + /* (light) arcs */ + [0x6d] = BDA + LD + LR, + [0x6e] = BDA + LD + LL, + [0x6f] = BDA + LU + LL, + [0x70] = BDA + LU + LR, + + /* Lower (Down) X/8 block (data is 8 - X) */ + [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, + [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, + + /* Left X/8 block (data is X) */ + [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, + [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, + + /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ + [0x80] = BBU + 4, [0x94] = BBU + 1, + [0x90] = BBR + 4, [0x95] = BBR + 7, + + /* Quadrants */ + [0x96] = BBQ + BL, + [0x97] = BBQ + BR, + [0x98] = BBQ + TL, + [0x99] = BBQ + TL + BL + BR, + [0x9a] = BBQ + TL + BR, + [0x9b] = BBQ + TL + TR + BL, + [0x9c] = BBQ + TL + TR + BR, + [0x9d] = BBQ + TR, + [0x9e] = BBQ + BL + TR, + [0x9f] = BBQ + BL + TR + BR, + + /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ + [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, + + /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ + /* U+2571 - U+2573: unsupported (diagonals) */ +}; diff --git a/st/config.def.h b/st/config.def.h new file mode 100755 index 0000000..e3c30ed --- /dev/null +++ b/st/config.def.h @@ -0,0 +1,517 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static const char *font = "CaskaydiaMonoNerdFontMono-Bold:size=14:style=Bold"; +/* Spare fonts */ + +static char *font2[] = { + "CaskaydiaMonoNerdFontMono-Bold:pixelsize=12:antialias=true:autohint=true"}; +static int borderpx = 6; + +/* How to align the content in the window when the size of the terminal + * doesn't perfectly match the size of the window. The values are percentages. + * 50 means center, 0 means flush left/top, 100 means flush right/bottom. + */ +static int anysize_halign = 50; +static int anysize_valign = 50; + +/* + * 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 */ +/* By default, use the same one as kitty. */ + +char *vtiden = "\033[?62c"; +//char *vtiden = "\x1b[?62;4c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1; +static float chscale = 1; + +/* + * 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 = 1; +static double maxlatency = 10; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 100; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * 1: render most of the lines/blocks characters without using the font for + * perfect alignment between cells (U2500 - U259F except dashes/diagonals). + * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. + * 0: disable (render all U25XX glyphs normally from the font). + */ +const int boxdraw = 1; +const int boxdraw_bold = 1; + +/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ +const int boxdraw_braille = 0; + +/* + * 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"; + +/* + * 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", "blue2", "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; + +/* + * Graphics configuration + */ + +/// The template for the cache directory. +const char graphics_cache_dir_template[] = "/tmp/st-images-XXXXXX"; +/// The max size of a single image file, in bytes. +unsigned graphics_max_single_image_file_size = 20 * 1024 * 1024; +/// The max size of the cache, in bytes. +unsigned graphics_total_file_cache_size = 300 * 1024 * 1024; +/// The max ram size of an image or placement, in bytes. +unsigned graphics_max_single_image_ram_size = 100 * 1024 * 1024; +/// The max total size of all images loaded into RAM. +unsigned graphics_max_total_ram_size = 300 * 1024 * 1024; +/// The max total number of image placements and images. +unsigned graphics_max_total_placements = 4096; +/// The ratio by which limits can be exceeded. This is to reduce the frequency +/// of image removal. +double graphics_excess_tolerance_ratio = 0.05; +/// The minimum delay between redraws caused by animations, in milliseconds. +unsigned graphics_animation_min_delay = 20; + +/* + * 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 keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask | ShiftMask) + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release */ + {TERMMOD, Button3, previewimage, {.s = "feh"}}, + {TERMMOD, Button2, showimageinfo, {}, 1}, + {XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1}, + {ShiftMask, Button4, kscrollup, {.i = 1}}, + {ShiftMask, Button5, kscrolldown, {.i = 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. */ + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + {TERMMOD, XK_F1, togglegrdebug, {.i = 0}}, + {TERMMOD, XK_F6, dumpgrstate, {.i = 0}}, + {TERMMOD, XK_F7, unloadimages, {.i = 0}}, + {TERMMOD, XK_F8, toggleimages, {.i = 0}}, + {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_C, clipcopy, {.i = 0}}, + {TERMMOD, XK_V, clippaste, {.i = 0}}, + {TERMMOD, XK_Y, selpaste, {.i = 0}}, + {ShiftMask, XK_Page_Up, kscrollup, {.i = -1}}, + {ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}}, + {ShiftMask, XK_Insert, selpaste, {.i = 0}}, + {TERMMOD, XK_Num_Lock, numlock, {.i = 0}}, + {TERMMOD, XK_plus, zoom, {.f = +1}}, + {TERMMOD, XK_underscore, zoom, {.f = -1}}, + {TERMMOD, XK_equal, zoomreset, {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{|}~"; diff --git a/st/config.h b/st/config.h new file mode 100755 index 0000000..f245eb8 --- /dev/null +++ b/st/config.h @@ -0,0 +1,336 @@ +static char *font = + "JetBrainsMono Nerd Font:size=11:antialias=true:autohint=true"; +static int borderpx = 2; + +static char *shell = "/bin/sh"; +char *utmp = NULL; +char *scroll = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +char *vtiden = "\033[?6c"; + +static float cwscale = 0.95; +static float chscale = 0.95; + +wchar_t *worddelimiters = L" "; + +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +int allowaltscreen = 1; + +int allowwindowops = 0; + +static double minlatency = 2; +static double maxlatency = 33; + +static unsigned int blinktimeout = 800; + +static unsigned int cursorthickness = 2; + +static int bellvolume = 0; + +char *termname = "xterm"; + +unsigned int tabspaces = 8; + +float alpha = 0.95; +float alpha_def; + +static const char *colorname[] = { + "#e7d8b1", "#F38BA8", "#A6E3A1", "#F9E2AF", "#89B4FA", "#F5C2E7", "#94E2D5", + "#CDD6F4", "#6C7086", "#F38BA8", "#A6E3A1", "#F9E2AF", "#89B4FA", "#F5C2E7", + "#94E2D5", "#ECEFFF", [255] = 0, "#CDD6F4", "#1E1E2E", +}; + +unsigned int defaultfg = 256; +unsigned int defaultbg = 257; +unsigned int defaultcs = 256; +static unsigned int defaultrcs = 257; + +/* + * Default shape of cursor + * 2: Block ("█") + * 4: Underline ("_") + * 6: Pipe ("|") + * 7: Snowman ("☃") + */ +static unsigned int cursorshape = 2; + +static unsigned int cols = 160; +static unsigned int rows = 40; + +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +static unsigned int defaultattr = 11; + +static uint forcemousemod = ShiftMask; + +static MouseShortcut mshortcuts[] = { + /* mask button function argument release */ + {XK_NO_MOD, Button4, kscrollup, {.i = 1}}, + {XK_NO_MOD, Button5, kscrolldown, {.i = 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"}}, +}; + +#define MODKEY Mod1Mask +#define TERMMOD (Mod1Mask | ShiftMask) + +static Shortcut shortcuts[] = { + {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}}, + {ControlMask, XK_equal, zoom, {.f = +1}}, + {ControlMask, XK_minus, zoom, {.f = -1}}, + {TERMMOD, XK_Home, zoomreset, {.f = 0}}, + {MODKEY, XK_c, clipcopy, {.i = 0}}, + {MODKEY, XK_v, clippaste, {.i = 0}}, + {TERMMOD, XK_Y, selpaste, {.i = 0}}, + {ShiftMask, XK_Insert, selpaste, {.i = 0}}, + {TERMMOD, XK_Num_Lock, numlock, {.i = 0}}, + {MODKEY, XK_k, kscrollup, {.i = 1}}, + {MODKEY, XK_j, kscrolldown, {.i = 1}}, +}; + +static KeySym mappedkeys[] = {-1}; + +static uint ignoremod = Mod2Mask | XK_SWITCH_MOD; + +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_F16, 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{|}~"; diff --git a/st/config.h.save b/st/config.h.save new file mode 100755 index 0000000..b25362c --- /dev/null +++ b/st/config.h.save @@ -0,0 +1,486 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Terminus-9: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; + +/* bg opacity */ +float alpha = 0.8; + +/* Background opacity */ +float alpha_def; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + + /* 8 normal colors */ + "#0a0a0a", /* black */ + "#44516d", /* red */ + "#c95d38", /* green */ + "#de9e68", /* yellow */ + "#8b7675", /* blue */ + "#7e5f8c", /* magenta */ + "#8c82c2", /* cyan */ + "#eff7d0", /* white */ + + /* 8 bright colors */ + "#181818", /* black */ + "#7d87a1", /* red */ + "#e9673c", /* green */ + "#e0b18b", /* yellow */ + "#b9a192", /* blue */ + "#9a7ebd", /* magenta */ + "#bccce2", /* cyan */ + "#ffffff", /* white */ + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#gray90", /* default foreground colour */ + "#black", /* default background colour */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 256; +unsigned int defaultbg = 257; +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 = 6; + +/* + * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, + { XK_NO_MOD, Button5, kscrolldown, {.i = 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 (Mod1Mask|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} }, + { ControlMask, XK_j, zoom, {.f = +1} }, + { ControlMask, XK_minus, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { MODKEY, XK_c, clipcopy, {.i = 0} }, + { MODKEY, XK_v, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, + { MODKEY, XK_k, kscrollup, {.i = 1} }, + { MODKEY, XK_j, kscrolldown, {.i = 1} }, + { MODKEY, XK_a, chgalpha, {.f = -1} }, + { MODKEY, XK_s, chgalpha, {.f = +1} }, + { MODKEY, XK_d, chgalpha, {.f = 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{|}~"; diff --git a/st/config.h.save.1 b/st/config.h.save.1 new file mode 100755 index 0000000..d608c5a --- /dev/null +++ b/st/config.h.save.1 @@ -0,0 +1,486 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Terminus-9: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; + +/* bg opacity */ +float alpha = 0.8; + +/* Background opacity */ +float alpha_def; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + + /* 8 normal colors */ + "#0a0a0a", /* black */ + "#44516d", /* red */ + "#c95d38", /* green */ + "#de9e68", /* yellow */ + "#8b7675", /* blue */ + "#7e5f8c", /* magenta */ + "#8c82c2", /* cyan */ + "#eff7d0", /* white */ + + /* 8 bright colors */ + "#181818", /* black */ + "#7d87a1", /* red */ + "#e9673c", /* green */ + "#e0b18b", /* yellow */ + "#b9a192", /* blue */ + "#9a7ebd", /* magenta */ + "#bccce2", /* cyan */ + "#ffffff", /* white */ + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "gray90", /* default foreground colour */ + "black", /* default background colour */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 256; +unsigned int defaultbg = 257; +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 = 6; + +/* + * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, + { XK_NO_MOD, Button5, kscrolldown, {.i = 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 (Mod1Mask|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} }, + { ControlMask, XK_equal, zoom, {.f = +1} }, + { ControlMask, XK_minus, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { MODKEY, XK_c, clipcopy, {.i = 0} }, + { MODKEY, XK_v, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, + { ControlMask, XK_k, kscrollup, {.i = 1} }, + { ControlMask, XK_j, kscrolldown, {.i = 1} }, + { MODKEY, XK_a, chgalpha, {.f = -1} }, + { MODKEY, XK_s, chgalpha, {.f = +1} }, + { MODKEY, XK_d, chgalpha, {.f = 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{|}~"; diff --git a/st/config.h.save.2 b/st/config.h.save.2 new file mode 100755 index 0000000..4869423 --- /dev/null +++ b/st/config.h.save.2 @@ -0,0 +1,486 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Terminus-9: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; + +/* bg opacity */ +float alpha = 0.8; + +/* Background opacity */ +float alpha_def; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + + /* 8 normal colors */ + "#0a0a0a", /* black */ + "#44516d", /* red */ + "#c95d38", /* green */ + "#de9e68", /* yellow */ + "#8b7675", /* blue */ + "#7e5f8c", /* magenta */ + "#8c82c2", /* cyan */ + "#eff7d0", /* white */ + + /* 8 bright colors */ + "#181818", /* black */ + "#7d87a1", /* red */ + "#e9673c", /* green */ + "#e0b18b", /* yellow */ + "#b9a192", /* blue */ + "#9a7ebd", /* magenta */ + "#bccce2", /* cyan */ + "#ffffff", /* white */ + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "gray90", /* default foreground colour */ + "black", /* default background colour */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 256; +unsigned int defaultbg = 257; +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 = 6; + +/* + * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, + { XK_NO_MOD, Button5, kscrolldown, {.i = 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 (Mod1Mask|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} }, + { ControlMask, XK_equal, zoom, {.f = +1} }, + { ControlMask, XK_minus, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { ControlMask|Shift, XK_c, clipcopy, {.i = 0} }, + { MODKEY, XK_v, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, + { ControlMask, XK_k, kscrollup, {.i = 1} }, + { ControlMask, XK_j, kscrolldown, {.i = 1} }, + { MODKEY, XK_a, chgalpha, {.f = -1} }, + { MODKEY, XK_s, chgalpha, {.f = +1} }, + { MODKEY, XK_d, chgalpha, {.f = 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{|}~"; diff --git a/st/config.h.save.3 b/st/config.h.save.3 new file mode 100755 index 0000000..e2169a7 --- /dev/null +++ b/st/config.h.save.3 @@ -0,0 +1,486 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Terminus-9: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; + +/* bg opacity */ +float alpha = 0.8; + +/* Background opacity */ +float alpha_def; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + + /* 8 normal colors */ + "#333e21", /* black */ + "#757849", /* red */ + "#FF432A", /* green */ + "#c83e72", /* yellow */ + "#448C2C", /* blue */ + "#7d5f5f", /* magenta */ + "#bd8c77", /* cyan */ + "#efdceb", /* white */ + + /* 8 bright colors */ + "#686e50", /* black */ + "#A6AA6A", /* red */ + "#fa6d5a", /* green */ + "#d3658e", /* yellow */ + "#80BD6C", /* blue */ + "#B38887", /* magenta */ + "#f0bfaa", /* cyan */ + "#ffffff", /* white */ + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "gray90", /* default foreground colour */ + "black", /* default background colour */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 256; +unsigned int defaultbg = 257; +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 = 6; + +/* + * 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_NO_MOD, Button4, kscrollup, {.i = 1} }, + { XK_NO_MOD, Button5, kscrolldown, {.i = 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 (Mod1Mask|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} }, + { ControlMask, XK_equal, zoom, {.f = +1} }, + { ControlMask, XK_minus, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { MODKEY, XK_c, clipcopy, {.i = 0} }, + { MODKEY, 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_k, kscrollup, {.i = 1} }, + { ShiftMask, XK_j, kscrolldown, {.i = 1} }, + { MODKEY, XK_a, chgalpha, {.f = -1} }, + { MODKEY, XK_s, chgalpha, {.f = +1} }, + { MODKEY, XK_d, chgalpha, {.f = 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{|}~"; diff --git a/st/config.mk b/st/config.mk new file mode 100755 index 0000000..1261566 --- /dev/null +++ b/st/config.mk @@ -0,0 +1,38 @@ +# st version +VERSION = 0.9.2 + +# Customize below to fit your system + +# paths +PREFIX = /usr/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` \ + `$(PKG_CONFIG) --cflags harfbuzz` +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender \ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` \ + `$(PKG_CONFIG) --libs harfbuzz` + +# 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 = gcc diff --git a/st/graphics.c b/st/graphics.c new file mode 100755 index 0000000..64e6fe0 --- /dev/null +++ b/st/graphics.c @@ -0,0 +1,3812 @@ +/* The MIT License + + Copyright (c) 2021-2024 Sergei Grechanik <sergei.grechanik@gmail.com> + + 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. +*/ + +//////////////////////////////////////////////////////////////////////////////// +// +// This file implements a subset of the kitty graphics protocol. +// +//////////////////////////////////////////////////////////////////////////////// + +#define _POSIX_C_SOURCE 200809L + +#include <zlib.h> +#include <Imlib2.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xrender.h> +#include <assert.h> +#include <ctype.h> +#include <spawn.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> + +#include "graphics.h" +#include "khash.h" +#include "kvec.h" + +extern char **environ; + +#define MAX_FILENAME_SIZE 256 +#define MAX_INFO_LEN 256 +#define MAX_IMAGE_RECTS 20 + +/// The type used in this file to represent time. Used both for time differences +/// and absolute times (as milliseconds since an arbitrary point in time, see +/// `initialization_time`). +typedef int64_t Milliseconds; + +enum ScaleMode { + SCALE_MODE_UNSET = 0, + /// Stretch or shrink the image to fill the box, ignoring aspect ratio. + SCALE_MODE_FILL = 1, + /// Preserve aspect ratio and fit to width or to height so that the + /// whole image is visible. + SCALE_MODE_CONTAIN = 2, + /// Do not scale. The image may be cropped if the box is too small. + SCALE_MODE_NONE = 3, + /// Do not scale, unless the box is too small, in which case the image + /// will be shrunk like with `SCALE_MODE_CONTAIN`. + SCALE_MODE_NONE_OR_CONTAIN = 4, +}; + +enum AnimationState { + ANIMATION_STATE_UNSET = 0, + /// The animation is stopped. Display the current frame, but don't + /// advance to the next one. + ANIMATION_STATE_STOPPED = 1, + /// Run the animation to then end, then wait for the next frame. + ANIMATION_STATE_LOADING = 2, + /// Run the animation in a loop. + ANIMATION_STATE_LOOPING = 3, +}; + +/// The status of an image. Each image uploaded to the terminal is cached on +/// disk, then it is loaded to ram when needed. +enum ImageStatus { + STATUS_UNINITIALIZED = 0, + STATUS_UPLOADING = 1, + STATUS_UPLOADING_ERROR = 2, + STATUS_UPLOADING_SUCCESS = 3, + STATUS_RAM_LOADING_ERROR = 4, + STATUS_RAM_LOADING_IN_PROGRESS = 5, + STATUS_RAM_LOADING_SUCCESS = 6, +}; + +const char *image_status_strings[6] = { + "STATUS_UNINITIALIZED", + "STATUS_UPLOADING", + "STATUS_UPLOADING_ERROR", + "STATUS_UPLOADING_SUCCESS", + "STATUS_RAM_LOADING_ERROR", + "STATUS_RAM_LOADING_SUCCESS", +}; + +enum ImageUploadingFailure { + ERROR_OVER_SIZE_LIMIT = 1, + ERROR_CANNOT_OPEN_CACHED_FILE = 2, + ERROR_UNEXPECTED_SIZE = 3, + ERROR_CANNOT_COPY_FILE = 4, +}; + +const char *image_uploading_failure_strings[5] = { + "NO_ERROR", + "ERROR_OVER_SIZE_LIMIT", + "ERROR_CANNOT_OPEN_CACHED_FILE", + "ERROR_UNEXPECTED_SIZE", + "ERROR_CANNOT_COPY_FILE", +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// We use the following structures to represent images and placements: +// +// - Image: this is the main structure representing an image, usually created +// by actions 'a=t', 'a=T`. Each image has an id (image id aka client id, +// specified by 'i='). An image may have multiple frames (ImageFrame) and +// placements (ImagePlacement). +// +// - ImageFrame: represents a single frame of an image, usually created by +// the action 'a=f' (and the first frame is created with the image itself). +// Each frame has an index and also: +// - a file containing the frame data (considered to be "on disk", although +// it's probably in tmpfs), +// - an imlib object containing the fully composed frame (i.e. the frame +// data from the file composed onto the background frame or color). It is +// not ready for display yet, because it needs to be scaled and uploaded +// to the X server. +// +// - ImagePlacement: represents a placement of an image, created by 'a=p' and +// 'a=T'. Each placement has an id (placement id, specified by 'p='). Also +// each placement has an array of pixmaps: one for each frame of the image. +// Each pixmap is a scaled and uploaded image ready to be displayed. +// +// Images are store in the `images` hash table, mapping image ids to Image +// objects (allocated on the heap). +// +// Placements are stored in the `placements` hash table of each Image object, +// mapping placement ids to ImagePlacement objects (also allocated on the heap). +// +// ImageFrames are stored in the `first_frame` field and in the +// `frames_beyond_the_first` array of each Image object. They are stored by +// value, so ImageFrame pointer may be invalidated when frames are +// added/deleted, be careful. +// +//////////////////////////////////////////////////////////////////////////////// + +struct Image; +struct ImageFrame; +struct ImagePlacement; + +KHASH_MAP_INIT_INT(id2image, struct Image *) +KHASH_MAP_INIT_INT(id2placement, struct ImagePlacement *) + +typedef struct ImageFrame { + /// The image this frame belongs to. + struct Image *image; + /// The 1-based index of the frame. Zero if the frame isn't initialized. + int index; + /// The last time when the frame was displayed or otherwise touched. + Milliseconds atime; + /// The background color of the frame in the 0xRRGGBBAA format. + uint32_t background_color; + /// The index of the background frame. Zero to use the color instead. + int background_frame_index; + /// The duration of the frame in milliseconds. + int gap; + /// The expected size of the frame image file (specified with 'S='), + /// used to check if uploading succeeded. + unsigned expected_size; + /// Format specification (see the `f=` key). + int format; + /// Pixel width and height of the non-composed (on-disk) frame data. May + /// differ from the image (i.e. first frame) dimensions. + int data_pix_width, data_pix_height; + /// The offset of the frame relative to the first frame. + int x, y; + /// Compression mode (see the `o=` key). + char compression; + /// The status (see `ImageStatus`). + char status; + /// The reason of uploading failure (see `ImageUploadingFailure`). + char uploading_failure; + /// Whether failures and successes should be reported ('q='). + char quiet; + /// Whether to blend the frame with the background or replace it. + char blend; + /// The file corresponding to the on-disk cache, used when uploading. + FILE *open_file; + /// The size of the corresponding file cached on disk. + unsigned disk_size; + /// The imlib object containing the fully composed frame. It's not + /// scaled for screen display yet. + Imlib_Image imlib_object; +} ImageFrame; + +typedef struct Image { + /// The client id (the one specified with 'i='). Must be nonzero. + uint32_t image_id; + /// The client id specified in the query command (`a=q`). This one must + /// be used to create the response if it's non-zero. + uint32_t query_id; + /// The number specified in the transmission command (`I=`). If + /// non-zero, it may be used to identify the image instead of the + /// image_id, and it also should be mentioned in responses. + uint32_t image_number; + /// The last time when the image was displayed or otherwise touched. + Milliseconds atime; + /// The total duration of the animation in milliseconds. + int total_duration; + /// The total size of cached image files for all frames. + int total_disk_size; + /// The global index of the creation command. Used to decide which image + /// is newer if they have the same image number. + uint64_t global_command_index; + /// The 1-based index of the currently displayed frame. + int current_frame; + /// The state of the animation, see `AnimationState`. + char animation_state; + /// The absolute time that is assumed to be the start of the current + /// frame (in ms since initialization). + Milliseconds current_frame_time; + /// The absolute time of the last redraw (in ms since initialization). + /// Used to check whether it's the first time we draw the image in the + /// current redraw cycle. + Milliseconds last_redraw; + /// The absolute time of the next redraw (in ms since initialization). + /// 0 means no redraw is scheduled. + Milliseconds next_redraw; + /// The unscaled pixel width and height of the image. Usually inherited + /// from the first frame. + int pix_width, pix_height; + /// The first frame. + ImageFrame first_frame; + /// The array of frames beyond the first one. + kvec_t(ImageFrame) frames_beyond_the_first; + /// Image placements. + khash_t(id2placement) *placements; + /// The default placement. + uint32_t default_placement; + /// The initial placement id, specified with the transmission command, + /// used to report success or failure. + uint32_t initial_placement_id; +} Image; + +typedef struct ImagePlacement { + /// The image this placement belongs to. + Image *image; + /// The id of the placement. Must be nonzero. + uint32_t placement_id; + /// The last time when the placement was displayed or otherwise touched. + Milliseconds atime; + /// The 1-based index of the protected pixmap. We protect a pixmap in + /// gr_load_pixmap to avoid unloading it right after it was loaded. + int protected_frame; + /// Whether the placement is used only for Unicode placeholders. + char virtual; + /// The scaling mode (see `ScaleMode`). + char scale_mode; + /// Height and width in cells. + uint16_t rows, cols; + /// Top-left corner of the source rectangle ('x=' and 'y='). + int src_pix_x, src_pix_y; + /// Height and width of the source rectangle (zero if full image). + int src_pix_width, src_pix_height; + /// The image appropriately scaled and uploaded to the X server. This + /// pixmap is premultiplied by alpha. + Pixmap first_pixmap; + /// The array of pixmaps beyond the first one. + kvec_t(Pixmap) pixmaps_beyond_the_first; + /// The dimensions of the cell used to scale the image. If cell + /// dimensions are changed (font change), the image will be rescaled. + uint16_t scaled_cw, scaled_ch; + /// If true, do not move the cursor when displaying this placement + /// (non-virtual placements only). + char do_not_move_cursor; +} ImagePlacement; + +/// A rectangular piece of an image to be drawn. +typedef struct { + uint32_t image_id; + uint32_t placement_id; + /// The position of the rectangle in pixels. + int screen_x_pix, screen_y_pix; + /// The starting row on the screen. + int screen_y_row; + /// The part of the whole image to be drawn, in cells. Starts are + /// zero-based, ends are exclusive. + int img_start_col, img_end_col, img_start_row, img_end_row; + /// The current cell width and height in pixels. + int cw, ch; + /// Whether colors should be inverted. + int reverse; +} ImageRect; + +/// Executes `code` for each frame of an image. Example: +/// +/// foreach_frame(image, frame, { +/// printf("Frame %d\n", frame->index); +/// }); +/// +#define foreach_frame(image, framevar, code) { size_t __i; \ + for (__i = 0; __i <= kv_size((image).frames_beyond_the_first); ++__i) { \ + ImageFrame *framevar = \ + __i == 0 ? &(image).first_frame \ + : &kv_A((image).frames_beyond_the_first, __i - 1); \ + code; \ + } } + +/// Executes `code` for each pixmap of a placement. Example: +/// +/// foreach_pixmap(placement, pixmap, { +/// ... +/// }); +/// +#define foreach_pixmap(placement, pixmapvar, code) { size_t __i; \ + for (__i = 0; __i <= kv_size((placement).pixmaps_beyond_the_first); ++__i) { \ + Pixmap pixmapvar = \ + __i == 0 ? (placement).first_pixmap \ + : kv_A((placement).pixmaps_beyond_the_first, __i - 1); \ + code; \ + } } + + +static Image *gr_find_image(uint32_t image_id); +static void gr_get_frame_filename(ImageFrame *frame, char *out, size_t max_len); +static void gr_delete_image(Image *img); +static void gr_check_limits(); +static char *gr_base64dec(const char *src, size_t *size); +static void sanitize_str(char *str, size_t max_len); +static const char *sanitized_filename(const char *str); + +/// The array of image rectangles to draw. It is reset each frame. +static ImageRect image_rects[MAX_IMAGE_RECTS] = {{0}}; +/// The known images (including the ones being uploaded). +static khash_t(id2image) *images = NULL; +/// The total number of placements in all images. +static unsigned total_placement_count = 0; +/// The total size of all image files stored in the on-disk cache. +static int64_t images_disk_size = 0; +/// The total size of all images and placements loaded into ram. +static int64_t images_ram_size = 0; +/// The id of the last loaded image. +static uint32_t last_image_id = 0; +/// Current cell width and heigh in pixels. +static int current_cw = 0, current_ch = 0; +/// The id of the currently uploaded image (when using direct uploading). +static uint32_t current_upload_image_id = 0; +/// The index of the frame currently being uploaded. +static int current_upload_frame_index = 0; +/// The time when the graphics module was initialized. +static struct timespec initialization_time = {0}; +/// The time when the current frame drawing started, used for debugging fps and +/// to calculate the current frame for animations. +static Milliseconds drawing_start_time; +/// The global index of the current command. +static uint64_t global_command_counter = 0; +/// The next redraw times for each row of the terminal. Used for animations. +/// 0 means no redraw is scheduled. +static kvec_t(Milliseconds) next_redraw_times = {0, 0, NULL}; +/// The number of files loaded in the current redraw cycle. +static int this_redraw_cycle_loaded_files = 0; +/// The number of pixmaps loaded in the current redraw cycle. +static int this_redraw_cycle_loaded_pixmaps = 0; + +/// The directory where the cache files are stored. +static char cache_dir[MAX_FILENAME_SIZE - 16]; + +/// The table used for color inversion. +static unsigned char reverse_table[256]; + +// Declared in the header. +GraphicsDebugMode graphics_debug_mode = GRAPHICS_DEBUG_NONE; +char graphics_display_images = 1; +GraphicsCommandResult graphics_command_result = {0}; +int graphics_next_redraw_delay = INT_MAX; + +// Defined in config.h +extern const char graphics_cache_dir_template[]; +extern unsigned graphics_max_single_image_file_size; +extern unsigned graphics_total_file_cache_size; +extern unsigned graphics_max_single_image_ram_size; +extern unsigned graphics_max_total_ram_size; +extern unsigned graphics_max_total_placements; +extern double graphics_excess_tolerance_ratio; +extern unsigned graphics_animation_min_delay; + + +//////////////////////////////////////////////////////////////////////////////// +// Basic helpers. +//////////////////////////////////////////////////////////////////////////////// + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) + +/// Returns the difference between `end` and `start` in milliseconds. +static int64_t gr_timediff_ms(const struct timespec *end, + const struct timespec *start) { + return (end->tv_sec - start->tv_sec) * 1000 + + (end->tv_nsec - start->tv_nsec) / 1000000; +} + +/// Returns the current time in milliseconds since the initialization. +static Milliseconds gr_now_ms() { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + return gr_timediff_ms(&now, &initialization_time); +} + +//////////////////////////////////////////////////////////////////////////////// +// Logging. +//////////////////////////////////////////////////////////////////////////////// + +#define GR_LOG(...) \ + do { if(graphics_debug_mode) fprintf(stderr, __VA_ARGS__); } while(0) + +//////////////////////////////////////////////////////////////////////////////// +// Basic image management functions (create, delete, find, etc). +//////////////////////////////////////////////////////////////////////////////// + +/// Returns the 1-based index of the last frame. Note that you may want to use +/// `gr_last_uploaded_frame_index` instead since the last frame may be not +/// fully uploaded yet. +static inline int gr_last_frame_index(Image *img) { + return kv_size(img->frames_beyond_the_first) + 1; +} + +/// Returns the frame with the given index. Returns NULL if the index is out of +/// bounds. The index is 1-based. +static ImageFrame *gr_get_frame(Image *img, int index) { + if (!img) + return NULL; + if (index == 1) + return &img->first_frame; + if (2 <= index && index <= gr_last_frame_index(img)) + return &kv_A(img->frames_beyond_the_first, index - 2); + return NULL; +} + +/// Returns the last frame of the image. Returns NULL if `img` is NULL. +static ImageFrame *gr_get_last_frame(Image *img) { + if (!img) + return NULL; + return gr_get_frame(img, gr_last_frame_index(img)); +} + +/// Returns the 1-based index of the last frame or the second-to-last frame if +/// the last frame is not fully uploaded yet. +static inline int gr_last_uploaded_frame_index(Image *img) { + int last_index = gr_last_frame_index(img); + if (last_index > 1 && + gr_get_frame(img, last_index)->status < STATUS_UPLOADING_SUCCESS) + return last_index - 1; + return last_index; +} + +/// Returns the pixmap for the frame with the given index. Returns 0 if the +/// index is out of bounds. The index is 1-based. +static Pixmap gr_get_frame_pixmap(ImagePlacement *placement, int index) { + if (index == 1) + return placement->first_pixmap; + if (2 <= index && + index <= kv_size(placement->pixmaps_beyond_the_first) + 1) + return kv_A(placement->pixmaps_beyond_the_first, index - 2); + return 0; +} + +/// Sets the pixmap for the frame with the given index. The index is 1-based. +/// The array of pixmaps is resized if needed. +static void gr_set_frame_pixmap(ImagePlacement *placement, int index, + Pixmap pixmap) { + if (index == 1) { + placement->first_pixmap = pixmap; + return; + } + // Resize the array if needed. + size_t old_size = kv_size(placement->pixmaps_beyond_the_first); + if (old_size < index - 1) { + kv_a(Pixmap, placement->pixmaps_beyond_the_first, index - 2); + for (size_t i = old_size; i < index - 1; i++) + kv_A(placement->pixmaps_beyond_the_first, i) = 0; + } + kv_A(placement->pixmaps_beyond_the_first, index - 2) = pixmap; +} + +/// Finds the image corresponding to the client id. Returns NULL if cannot find. +static Image *gr_find_image(uint32_t image_id) { + khiter_t k = kh_get(id2image, images, image_id); + if (k == kh_end(images)) + return NULL; + Image *res = kh_value(images, k); + return res; +} + +/// Finds the newest image corresponding to the image number. Returns NULL if +/// cannot find. +static Image *gr_find_image_by_number(uint32_t image_number) { + if (image_number == 0) + return NULL; + Image *newest_img = NULL; + Image *img = NULL; + kh_foreach_value(images, img, { + if (img->image_number == image_number && + (!newest_img || newest_img->global_command_index < + img->global_command_index)) + newest_img = img; + }); + if (!newest_img) + GR_LOG("Image number %u not found\n", image_number); + else + GR_LOG("Found image number %u, its id is %u\n", image_number, + img->image_id); + return newest_img; +} + +/// Finds the placement corresponding to the id. If the placement id is 0, +/// returns some default placement. +static ImagePlacement *gr_find_placement(Image *img, uint32_t placement_id) { + if (!img) + return NULL; + if (placement_id == 0) { + // Try to get the default placement. + ImagePlacement *dflt = NULL; + if (img->default_placement != 0) + dflt = gr_find_placement(img, img->default_placement); + if (dflt) + return dflt; + // If there is no default placement, return the first one and + // set it as the default. + kh_foreach_value(img->placements, dflt, { + img->default_placement = dflt->placement_id; + return dflt; + }); + // If there are no placements, return NULL. + return NULL; + } + khiter_t k = kh_get(id2placement, img->placements, placement_id); + if (k == kh_end(img->placements)) + return NULL; + ImagePlacement *res = kh_value(img->placements, k); + return res; +} + +/// Finds the placement by image id and placement id. +static ImagePlacement *gr_find_image_and_placement(uint32_t image_id, + uint32_t placement_id) { + return gr_find_placement(gr_find_image(image_id), placement_id); +} + +/// Writes the name of the on-disk cache file to `out`. `max_len` should be the +/// size of `out`. The name will be something like +/// "/tmp/st-images-xxx/img-ID-FRAME". +static void gr_get_frame_filename(ImageFrame *frame, char *out, + size_t max_len) { + snprintf(out, max_len, "%s/img-%.3u-%.3u", cache_dir, + frame->image->image_id, frame->index); +} + +/// Returns the (estimation) of the RAM size used by the frame right now. +static unsigned gr_frame_current_ram_size(ImageFrame *frame) { + if (!frame->imlib_object) + return 0; + return (unsigned)frame->image->pix_width * frame->image->pix_height * 4; +} + +/// Returns the (estimation) of the RAM size used by a single frame pixmap. +static unsigned gr_placement_single_frame_ram_size(ImagePlacement *placement) { + return (unsigned)placement->rows * placement->cols * + placement->scaled_ch * placement->scaled_cw * 4; +} + +/// Returns the (estimation) of the RAM size used by the placemenet right now. +static unsigned gr_placement_current_ram_size(ImagePlacement *placement) { + unsigned single_frame_size = + gr_placement_single_frame_ram_size(placement); + unsigned result = 0; + foreach_pixmap(*placement, pixmap, { + if (pixmap) + result += single_frame_size; + }); + return result; +} + +/// Unload the frame from RAM (i.e. delete the corresponding imlib object). +/// If the on-disk file of the frame is preserved, it can be reloaded later. +static void gr_unload_frame(ImageFrame *frame) { + if (!frame->imlib_object) + return; + + unsigned frame_ram_size = gr_frame_current_ram_size(frame); + images_ram_size -= frame_ram_size; + + imlib_context_set_image(frame->imlib_object); + imlib_free_image_and_decache(); + frame->imlib_object = NULL; + + GR_LOG("After unloading image %u frame %u (atime %ld ms ago) " + "ram: %ld KiB (- %u KiB)\n", + frame->image->image_id, frame->index, + drawing_start_time - frame->atime, images_ram_size / 1024, + frame_ram_size / 1024); +} + +/// Unload all frames of the image. +static void gr_unload_all_frames(Image *img) { + foreach_frame(*img, frame, { + gr_unload_frame(frame); + }); +} + +/// Unload the placement from RAM (i.e. free all of the corresponding pixmaps). +/// If the on-disk files or imlib objects of the corresponding image are +/// preserved, the placement can be reloaded later. +static void gr_unload_placement(ImagePlacement *placement) { + unsigned placement_ram_size = gr_placement_current_ram_size(placement); + images_ram_size -= placement_ram_size; + + Display *disp = imlib_context_get_display(); + foreach_pixmap(*placement, pixmap, { + if (pixmap) + XFreePixmap(disp, pixmap); + }); + + placement->first_pixmap = 0; + placement->pixmaps_beyond_the_first.n = 0; + placement->scaled_ch = placement->scaled_cw = 0; + + GR_LOG("After unloading placement %u/%u (atime %ld ms ago) " + "ram: %ld KiB (- %u KiB)\n", + placement->image->image_id, placement->placement_id, + drawing_start_time - placement->atime, images_ram_size / 1024, + placement_ram_size / 1024); +} + +/// Unload a single pixmap of the placement from RAM. +static void gr_unload_pixmap(ImagePlacement *placement, int frameidx) { + Pixmap pixmap = gr_get_frame_pixmap(placement, frameidx); + if (!pixmap) + return; + + Display *disp = imlib_context_get_display(); + XFreePixmap(disp, pixmap); + gr_set_frame_pixmap(placement, frameidx, 0); + images_ram_size -= gr_placement_single_frame_ram_size(placement); + + GR_LOG("After unloading pixmap %ld of " + "placement %u/%u (atime %ld ms ago) " + "frame %u (atime %ld ms ago) " + "ram: %ld KiB (- %u KiB)\n", + pixmap, placement->image->image_id, placement->placement_id, + drawing_start_time - placement->atime, frameidx, + drawing_start_time - + gr_get_frame(placement->image, frameidx)->atime, + images_ram_size / 1024, + gr_placement_single_frame_ram_size(placement) / 1024); +} + +/// Deletes the on-disk cache file corresponding to the frame. The in-ram image +/// object (if it exists) is not deleted, placements are not unloaded either. +static void gr_delete_imagefile(ImageFrame *frame) { + // It may still be being loaded. Close the file in this case. + if (frame->open_file) { + fclose(frame->open_file); + frame->open_file = NULL; + } + + if (frame->disk_size == 0) + return; + + char filename[MAX_FILENAME_SIZE]; + gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); + remove(filename); + + unsigned disk_size = frame->disk_size; + images_disk_size -= disk_size; + frame->image->total_disk_size -= disk_size; + frame->disk_size = 0; + + GR_LOG("After deleting image file %u frame %u (atime %ld ms ago) " + "disk: %ld KiB (- %u KiB)\n", + frame->image->image_id, frame->index, + drawing_start_time - frame->atime, images_disk_size / 1024, + disk_size / 1024); +} + +/// Deletes all on-disk cache files of the image (for each frame). +static void gr_delete_imagefiles(Image *img) { + foreach_frame(*img, frame, { + gr_delete_imagefile(frame); + }); +} + +/// Deletes the given placement: unloads, frees the object, but doesn't change +/// the `placements` hash table. +static void gr_delete_placement_keep_id(ImagePlacement *placement) { + if (!placement) + return; + GR_LOG("Deleting placement %u/%u\n", placement->image->image_id, + placement->placement_id); + gr_unload_placement(placement); + kv_destroy(placement->pixmaps_beyond_the_first); + free(placement); + total_placement_count--; +} + +/// Deletes all placements of `img`. +static void gr_delete_all_placements(Image *img) { + ImagePlacement *placement = NULL; + kh_foreach_value(img->placements, placement, { + gr_delete_placement_keep_id(placement); + }); + kh_clear(id2placement, img->placements); +} + +/// Deletes the given image: unloads, deletes the file, frees the Image object, +/// but doesn't change the `images` hash table. +static void gr_delete_image_keep_id(Image *img) { + if (!img) + return; + GR_LOG("Deleting image %u\n", img->image_id); + foreach_frame(*img, frame, { + gr_delete_imagefile(frame); + gr_unload_frame(frame); + }); + kv_destroy(img->frames_beyond_the_first); + gr_delete_all_placements(img); + kh_destroy(id2placement, img->placements); + free(img); +} + +/// Deletes the given image: unloads, deletes the file, frees the Image object, +/// and also removes it from `images`. +static void gr_delete_image(Image *img) { + if (!img) + return; + uint32_t id = img->image_id; + gr_delete_image_keep_id(img); + khiter_t k = kh_get(id2image, images, id); + kh_del(id2image, images, k); +} + +/// Deletes the given placement: unloads, frees the object, and also removes it +/// from `placements`. +static void gr_delete_placement(ImagePlacement *placement) { + if (!placement) + return; + uint32_t id = placement->placement_id; + Image *img = placement->image; + gr_delete_placement_keep_id(placement); + khiter_t k = kh_get(id2placement, img->placements, id); + kh_del(id2placement, img->placements, k); +} + +/// Deletes all images and clears `images`. +static void gr_delete_all_images() { + Image *img = NULL; + kh_foreach_value(images, img, { + gr_delete_image_keep_id(img); + }); + kh_clear(id2image, images); +} + +/// Update the atime of the image. +static void gr_touch_image(Image *img) { + img->atime = gr_now_ms(); +} + +/// Update the atime of the frame. +static void gr_touch_frame(ImageFrame *frame) { + frame->image->atime = frame->atime = gr_now_ms(); +} + +/// Update the atime of the placement. Touches the images too. +static void gr_touch_placement(ImagePlacement *placement) { + placement->image->atime = placement->atime = gr_now_ms(); +} + +/// Creates a new image with the given id. If an image with that id already +/// exists, it is deleted first. If the provided id is 0, generates a +/// random id. +static Image *gr_new_image(uint32_t id) { + if (id == 0) { + do { + id = rand(); + // Avoid IDs that don't need full 32 bits. + } while ((id & 0xFF000000) == 0 || (id & 0x00FFFF00) == 0 || + gr_find_image(id)); + GR_LOG("Generated random image id %u\n", id); + } + Image *img = gr_find_image(id); + gr_delete_image_keep_id(img); + GR_LOG("Creating image %u\n", id); + img = malloc(sizeof(Image)); + memset(img, 0, sizeof(Image)); + img->placements = kh_init(id2placement); + int ret; + khiter_t k = kh_put(id2image, images, id, &ret); + kh_value(images, k) = img; + img->image_id = id; + gr_touch_image(img); + img->global_command_index = global_command_counter; + return img; +} + +/// Creates a new frame at the end of the frame array. It may be the first frame +/// if there are no frames yet. +static ImageFrame *gr_append_new_frame(Image *img) { + ImageFrame *frame = NULL; + if (img->first_frame.index == 0 && + kv_size(img->frames_beyond_the_first) == 0) { + frame = &img->first_frame; + frame->index = 1; + } else { + frame = kv_pushp(ImageFrame, img->frames_beyond_the_first); + memset(frame, 0, sizeof(ImageFrame)); + frame->index = kv_size(img->frames_beyond_the_first) + 1; + } + frame->image = img; + gr_touch_frame(frame); + GR_LOG("Appending frame %d to image %u\n", frame->index, img->image_id); + return frame; +} + +/// Creates a new placement with the given id. If a placement with that id +/// already exists, it is deleted first. If the provided id is 0, generates a +/// random id. +static ImagePlacement *gr_new_placement(Image *img, uint32_t id) { + if (id == 0) { + do { + // Currently we support only 24-bit IDs. + id = rand() & 0xFFFFFF; + // Avoid IDs that need only one byte. + } while ((id & 0x00FFFF00) == 0 || gr_find_placement(img, id)); + } + ImagePlacement *placement = gr_find_placement(img, id); + gr_delete_placement_keep_id(placement); + GR_LOG("Creating placement %u/%u\n", img->image_id, id); + placement = malloc(sizeof(ImagePlacement)); + memset(placement, 0, sizeof(ImagePlacement)); + total_placement_count++; + int ret; + khiter_t k = kh_put(id2placement, img->placements, id, &ret); + kh_value(img->placements, k) = placement; + placement->image = img; + placement->placement_id = id; + gr_touch_placement(placement); + if (img->default_placement == 0) + img->default_placement = id; + return placement; +} + +static int64_t ceil_div(int64_t a, int64_t b) { + return (a + b - 1) / b; +} + +/// Computes the best number of rows and columns for a placement if it's not +/// specified, and also adjusts the source rectangle size. +static void gr_infer_placement_size_maybe(ImagePlacement *placement) { + // The size of the image. + int image_pix_width = placement->image->pix_width; + int image_pix_height = placement->image->pix_height; + // Negative values are not allowed. Quietly set them to 0. + if (placement->src_pix_x < 0) + placement->src_pix_x = 0; + if (placement->src_pix_y < 0) + placement->src_pix_y = 0; + if (placement->src_pix_width < 0) + placement->src_pix_width = 0; + if (placement->src_pix_height < 0) + placement->src_pix_height = 0; + // If the source rectangle is outside the image, truncate it. + if (placement->src_pix_x > image_pix_width) + placement->src_pix_x = image_pix_width; + if (placement->src_pix_y > image_pix_height) + placement->src_pix_y = image_pix_height; + // If the source rectangle is not specified, use the whole image. If + // it's partially outside the image, truncate it. + if (placement->src_pix_width == 0 || + placement->src_pix_x + placement->src_pix_width > image_pix_width) + placement->src_pix_width = + image_pix_width - placement->src_pix_x; + if (placement->src_pix_height == 0 || + placement->src_pix_y + placement->src_pix_height > image_pix_height) + placement->src_pix_height = + image_pix_height - placement->src_pix_y; + + if (placement->cols != 0 && placement->rows != 0) + return; + if (placement->src_pix_width == 0 || placement->src_pix_height == 0) + return; + if (current_cw == 0 || current_ch == 0) + return; + + // If no size is specified, use the image size. + if (placement->cols == 0 && placement->rows == 0) { + placement->cols = + ceil_div(placement->src_pix_width, current_cw); + placement->rows = + ceil_div(placement->src_pix_height, current_ch); + return; + } + + // Some applications specify only one of the dimensions. + if (placement->scale_mode == SCALE_MODE_CONTAIN) { + // If we preserve aspect ratio and fit to width/height, the most + // logical thing is to find the minimum size of the + // non-specified dimension that allows the image to fit the + // specified dimension. + if (placement->cols == 0) { + placement->cols = ceil_div( + placement->src_pix_width * placement->rows * + current_ch, + placement->src_pix_height * current_cw); + return; + } + if (placement->rows == 0) { + placement->rows = + ceil_div(placement->src_pix_height * + placement->cols * current_cw, + placement->src_pix_width * current_ch); + return; + } + } else { + // Otherwise we stretch the image or preserve the original size. + // In both cases we compute the best number of columns from the + // pixel size and cell size. + // TODO: In the case of stretching it's not the most logical + // thing to do, may need to revisit in the future. + // Currently we switch to SCALE_MODE_CONTAIN when only one + // of the dimensions is specified, so this case shouldn't + // happen in practice. + if (!placement->cols) + placement->cols = + ceil_div(placement->src_pix_width, current_cw); + if (!placement->rows) + placement->rows = + ceil_div(placement->src_pix_height, current_ch); + } +} + +/// Adjusts the current frame index if enough time has passed since the display +/// of the current frame. Also computes the time of the next redraw of this +/// image (`img->next_redraw`). The current time is passed as an argument so +/// that all animations are in sync. +static void gr_update_frame_index(Image *img, Milliseconds now) { + if (img->current_frame == 0) { + img->current_frame_time = now; + img->current_frame = 1; + img->next_redraw = now + MAX(1, img->first_frame.gap); + return; + } + // If the animation is stopped, show the current frame. + if (!img->animation_state || + img->animation_state == ANIMATION_STATE_STOPPED || + img->animation_state == ANIMATION_STATE_UNSET) { + // The next redraw is never (unless the state is changed). + img->next_redraw = 0; + return; + } + int last_uploaded_frame_index = gr_last_uploaded_frame_index(img); + // If we are loading and we reached the last frame, show the last frame. + if (img->animation_state == ANIMATION_STATE_LOADING && + img->current_frame == last_uploaded_frame_index) { + // The next redraw is never (unless the state is changed or + // frames are added). + img->next_redraw = 0; + return; + } + + // Check how many milliseconds passed since the current frame was shown. + int passed_ms = now - img->current_frame_time; + // If the animation is looping and too much time has passes, we can + // make a shortcut. + if (img->animation_state == ANIMATION_STATE_LOOPING && + img->total_duration > 0 && passed_ms >= img->total_duration) { + passed_ms %= img->total_duration; + img->current_frame_time = now - passed_ms; + } + // Find the next frame. + int original_frame_index = img->current_frame; + while (1) { + ImageFrame *frame = gr_get_frame(img, img->current_frame); + if (!frame) { + // The frame doesn't exist, go to the first frame. + img->current_frame = 1; + img->current_frame_time = now; + img->next_redraw = now + MAX(1, img->first_frame.gap); + return; + } + if (frame->gap >= 0 && passed_ms < frame->gap) { + // Not enough time has passed, we are still in the same + // frame, and it's not a gapless frame. + img->next_redraw = + img->current_frame_time + MAX(1, frame->gap); + return; + } + // Otherwise go to the next frame. + passed_ms -= MAX(0, frame->gap); + if (img->current_frame >= last_uploaded_frame_index) { + // It's the last frame, if the animation is loading, + // remain on it. + if (img->animation_state == ANIMATION_STATE_LOADING) { + img->next_redraw = 0; + return; + } + // Otherwise the animation is looping. + img->current_frame = 1; + // TODO: Support finite number of loops. + } else { + img->current_frame++; + } + // Make sure we don't get stuck in an infinite loop. + if (img->current_frame == original_frame_index) { + // We looped through all frames, but haven't reached the + // next frame yet. This may happen if too much time has + // passed since the last redraw or all the frames are + // gapless. Just move on to the next frame. + img->current_frame++; + if (img->current_frame > + last_uploaded_frame_index) + img->current_frame = 1; + img->current_frame_time = now; + img->next_redraw = now + MAX( + 1, gr_get_frame(img, img->current_frame)->gap); + return; + } + // Adjust the start time of the frame. The next redraw time will + // be set in the next iteration. + img->current_frame_time += MAX(0, frame->gap); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Unloading and deleting images to save resources. +//////////////////////////////////////////////////////////////////////////////// + +/// A helper to compare frames by atime for qsort. +static int gr_cmp_frames_by_atime(const void *a, const void *b) { + ImageFrame *frame_a = *(ImageFrame *const *)a; + ImageFrame *frame_b = *(ImageFrame *const *)b; + if (frame_a->atime == frame_b->atime) + return frame_a->image->global_command_index - + frame_b->image->global_command_index; + return frame_a->atime - frame_b->atime; +} + +/// A helper to compare images by atime for qsort. +static int gr_cmp_images_by_atime(const void *a, const void *b) { + Image *img_a = *(Image *const *)a; + Image *img_b = *(Image *const *)b; + if (img_a->atime == img_b->atime) + return img_a->global_command_index - + img_b->global_command_index; + return img_a->atime - img_b->atime; +} + +/// A helper to compare placements by atime for qsort. +static int gr_cmp_placements_by_atime(const void *a, const void *b) { + ImagePlacement *p_a = *(ImagePlacement **)a; + ImagePlacement *p_b = *(ImagePlacement **)b; + if (p_a->atime == p_b->atime) + return p_a->image->global_command_index - + p_b->image->global_command_index; + return p_a->atime - p_b->atime; +} + +typedef kvec_t(Image *) ImageVec; +typedef kvec_t(ImagePlacement *) ImagePlacementVec; +typedef kvec_t(ImageFrame *) ImageFrameVec; + +/// Returns an array of pointers to all images sorted by atime. +static ImageVec gr_get_images_sorted_by_atime() { + ImageVec vec; + kv_init(vec); + if (kh_size(images) == 0) + return vec; + kv_resize(Image *, vec, kh_size(images)); + Image *img = NULL; + kh_foreach_value(images, img, { kv_push(Image *, vec, img); }); + qsort(vec.a, kv_size(vec), sizeof(Image *), gr_cmp_images_by_atime); + return vec; +} + +/// Returns an array of pointers to all placements sorted by atime. +static ImagePlacementVec gr_get_placements_sorted_by_atime() { + ImagePlacementVec vec; + kv_init(vec); + if (total_placement_count == 0) + return vec; + kv_resize(ImagePlacement *, vec, total_placement_count); + Image *img = NULL; + ImagePlacement *placement = NULL; + kh_foreach_value(images, img, { + kh_foreach_value(img->placements, placement, { + kv_push(ImagePlacement *, vec, placement); + }); + }); + qsort(vec.a, kv_size(vec), sizeof(ImagePlacement *), + gr_cmp_placements_by_atime); + return vec; +} + +/// Returns an array of pointers to all frames sorted by atime. +static ImageFrameVec gr_get_frames_sorted_by_atime() { + ImageFrameVec frames; + kv_init(frames); + Image *img = NULL; + kh_foreach_value(images, img, { + foreach_frame(*img, frame, { + kv_push(ImageFrame *, frames, frame); + }); + }); + qsort(frames.a, kv_size(frames), sizeof(ImageFrame *), + gr_cmp_frames_by_atime); + return frames; +} + +/// An object that can be unloaded from RAM. +typedef struct { + /// Some score, probably based on access time. The lower the score, the + /// more likely that the object should be unloaded. + int64_t score; + union { + ImagePlacement *placement; + ImageFrame *frame; + }; + /// If zero, the object is the imlib object of `frame`, if non-zero, + /// the object is a pixmap of `frameidx`-th frame of `placement`. + int frameidx; +} UnloadableObject; + +typedef kvec_t(UnloadableObject) UnloadableObjectVec; + +/// A helper to compare unloadable objects by score for qsort. +static int gr_cmp_unloadable_objects(const void *a, const void *b) { + UnloadableObject *obj_a = (UnloadableObject *)a; + UnloadableObject *obj_b = (UnloadableObject *)b; + return obj_a->score - obj_b->score; +} + +/// Unloads an unloadable object from RAM. +static void gr_unload_object(UnloadableObject *obj) { + if (obj->frameidx) { + if (obj->placement->protected_frame == obj->frameidx) + return; + gr_unload_pixmap(obj->placement, obj->frameidx); + } else { + gr_unload_frame(obj->frame); + } +} + +/// Returns the recency threshold for an image. Frames that were accessed within +/// this threshold from now are considered recent and may be handled +/// differently because we may need them again very soon. +static Milliseconds gr_recency_threshold(Image *img) { + return img->total_duration * 2 + 1000; +} + +/// Creates an unloadable object for the imlib object of a frame. +static UnloadableObject gr_unloadable_object_for_frame(Milliseconds now, + ImageFrame *frame) { + UnloadableObject obj = {0}; + obj.frameidx = 0; + obj.frame = frame; + Milliseconds atime = frame->atime; + obj.score = atime; + if (atime >= now - gr_recency_threshold(frame->image)) { + // This is a recent frame, probably from an active animation. + // Score it above `now` to prefer unloading non-active frames. + // Randomize the score because it's not very clear in which + // order we want to unload them: reloading a frame may require + // reloading other frames. + obj.score = now + 1000 + rand() % 1000; + } + return obj; +} + +/// Creates an unloadable object for a pixmap. +static UnloadableObject +gr_unloadable_object_for_pixmap(Milliseconds now, ImageFrame *frame, + ImagePlacement *placement) { + UnloadableObject obj = {0}; + obj.frameidx = frame->index; + obj.placement = placement; + obj.score = placement->atime; + // Since we don't store pixmap atimes, use the + // oldest atime of the frame and the placement. + Milliseconds atime = MIN(placement->atime, frame->atime); + obj.score = atime; + if (atime >= now - gr_recency_threshold(frame->image)) { + // This is a recent pixmap, probably from an active animation. + // Score it above `now` to prefer unloading non-active frames. + // Also assign higher scores to frames that are closer to the + // current frame (more likely to be used soon). + int num_frames = gr_last_frame_index(frame->image); + int dist = frame->index - frame->image->current_frame; + if (dist < 0) + dist += num_frames; + obj.score = + now + 1000 + (num_frames - dist) * 1000 / num_frames; + // If the pixmap is much larger than the imlib image, prefer to + // unload the pixmap by adding up to -1000 to the score. If the + // imlib image is larger, add up to +1000. + float imlib_size = gr_frame_current_ram_size(frame); + float pixmap_size = + gr_placement_single_frame_ram_size(placement); + obj.score += + 2000 * (imlib_size / (imlib_size + pixmap_size) - 0.5); + } + return obj; +} + +/// Returns an array of unloadable objects sorted by score. +static UnloadableObjectVec +gr_get_unloadable_objects_sorted_by_score(Milliseconds now) { + UnloadableObjectVec objects; + kv_init(objects); + Image *img = NULL; + ImagePlacement *placement = NULL; + kh_foreach_value(images, img, { + foreach_frame(*img, frame, { + if (!frame->imlib_object) + continue; + kv_push(UnloadableObject, objects, + gr_unloadable_object_for_frame(now, frame)); + int frameidx = frame->index; + kh_foreach_value(img->placements, placement, { + if (!gr_get_frame_pixmap(placement, frameidx)) + continue; + kv_push(UnloadableObject, objects, + gr_unloadable_object_for_pixmap( + now, frame, placement)); + }); + }); + }); + qsort(objects.a, kv_size(objects), sizeof(UnloadableObject), + gr_cmp_unloadable_objects); + return objects; +} + +/// Returns the limit adjusted by the excess tolerance ratio. +static inline unsigned apply_tolerance(unsigned limit) { + return limit + (unsigned)(limit * graphics_excess_tolerance_ratio); +} + +/// Checks RAM and disk cache limits and deletes/unloads some images. +static void gr_check_limits() { + Milliseconds now = gr_now_ms(); + ImageVec images_sorted = {0}; + ImagePlacementVec placements_sorted = {0}; + ImageFrameVec frames_sorted = {0}; + UnloadableObjectVec objects_sorted = {0}; + int images_begin = 0; + int placements_begin = 0; + char changed = 0; + // First reduce the number of images if there are too many. + if (kh_size(images) > apply_tolerance(graphics_max_total_placements)) { + GR_LOG("Too many images: %d\n", kh_size(images)); + changed = 1; + images_sorted = gr_get_images_sorted_by_atime(); + int to_delete = kv_size(images_sorted) - + graphics_max_total_placements; + for (; images_begin < to_delete; images_begin++) + gr_delete_image(images_sorted.a[images_begin]); + } + // Then reduce the number of placements if there are too many. + if (total_placement_count > + apply_tolerance(graphics_max_total_placements)) { + GR_LOG("Too many placements: %d\n", total_placement_count); + changed = 1; + placements_sorted = gr_get_placements_sorted_by_atime(); + int to_delete = kv_size(placements_sorted) - + graphics_max_total_placements; + for (; placements_begin < to_delete; placements_begin++) { + ImagePlacement *placement = + placements_sorted.a[placements_begin]; + if (placement->protected_frame) + break; + gr_delete_placement(placement); + } + } + // Then reduce the size of the image file cache. The files correspond to + // image frames. + if (images_disk_size > + apply_tolerance(graphics_total_file_cache_size)) { + GR_LOG("Too big disk cache: %ld KiB\n", + images_disk_size / 1024); + changed = 1; + frames_sorted = gr_get_frames_sorted_by_atime(); + for (int i = 0; i < kv_size(frames_sorted); i++) { + if (images_disk_size <= graphics_total_file_cache_size) + break; + gr_delete_imagefile(kv_A(frames_sorted, i)); + } + } + // Then unload images from RAM. + if (images_ram_size > apply_tolerance(graphics_max_total_ram_size)) { + changed = 1; + int frames_begin = 0; + GR_LOG("Too much ram: %ld KiB\n", images_ram_size / 1024); + objects_sorted = gr_get_unloadable_objects_sorted_by_score(now); + for (int i = 0; i < kv_size(objects_sorted); i++) { + if (images_ram_size <= graphics_max_total_ram_size) + break; + gr_unload_object(&kv_A(objects_sorted, i)); + } + } + if (changed) { + GR_LOG("After cleaning: ram: %ld KiB disk: %ld KiB " + "img count: %d placement count: %d\n", + images_ram_size / 1024, images_disk_size / 1024, + kh_size(images), total_placement_count); + } + kv_destroy(images_sorted); + kv_destroy(placements_sorted); + kv_destroy(frames_sorted); + kv_destroy(objects_sorted); +} + +/// Unloads all images by user request. +void gr_unload_images_to_reduce_ram() { + Image *img = NULL; + ImagePlacement *placement = NULL; + kh_foreach_value(images, img, { + kh_foreach_value(img->placements, placement, { + if (placement->protected_frame) + continue; + gr_unload_placement(placement); + }); + gr_unload_all_frames(img); + }); +} + +//////////////////////////////////////////////////////////////////////////////// +// Image loading. +//////////////////////////////////////////////////////////////////////////////// + +/// Copies `num_pixels` pixels (not bytes!) from a buffer `from` to an imlib2 +/// image data `to`. The format may be 24 (RGB) or 32 (RGBA), and it's converted +/// to imlib2's representation, which is 0xAARRGGBB (having BGRA memory layout +/// on little-endian architectures). +static inline void gr_copy_pixels(DATA32 *to, unsigned char *from, int format, + size_t num_pixels) { + size_t pixel_size = format == 24 ? 3 : 4; + if (format == 32) { + for (unsigned i = 0; i < num_pixels; ++i) { + unsigned byte_i = i * pixel_size; + to[i] = ((DATA32)from[byte_i + 2]) | + ((DATA32)from[byte_i + 1]) << 8 | + ((DATA32)from[byte_i]) << 16 | + ((DATA32)from[byte_i + 3]) << 24; + } + } else { + for (unsigned i = 0; i < num_pixels; ++i) { + unsigned byte_i = i * pixel_size; + to[i] = ((DATA32)from[byte_i + 2]) | + ((DATA32)from[byte_i + 1]) << 8 | + ((DATA32)from[byte_i]) << 16 | 0xFF000000; + } + } +} + +/// Loads uncompressed RGB or RGBA image data from a file. +static void gr_load_raw_pixel_data_uncompressed(DATA32 *data, FILE *file, + int format, + size_t total_pixels) { + unsigned char chunk[BUFSIZ]; + size_t pixel_size = format == 24 ? 3 : 4; + size_t chunk_size_pix = BUFSIZ / 4; + size_t chunk_size_bytes = chunk_size_pix * pixel_size; + size_t bytes = total_pixels * pixel_size; + for (size_t chunk_start_pix = 0; chunk_start_pix < total_pixels; + chunk_start_pix += chunk_size_pix) { + size_t read_size = fread(chunk, 1, chunk_size_bytes, file); + size_t read_pixels = read_size / pixel_size; + if (chunk_start_pix + read_pixels > total_pixels) + read_pixels = total_pixels - chunk_start_pix; + gr_copy_pixels(data + chunk_start_pix, chunk, format, + read_pixels); + } +} + +#define COMPRESSED_CHUNK_SIZE BUFSIZ +#define DECOMPRESSED_CHUNK_SIZE (BUFSIZ * 4) + +/// Loads compressed RGB or RGBA image data from a file. +static int gr_load_raw_pixel_data_compressed(DATA32 *data, FILE *file, + int format, size_t total_pixels) { + size_t pixel_size = format == 24 ? 3 : 4; + unsigned char compressed_chunk[COMPRESSED_CHUNK_SIZE]; + unsigned char decompressed_chunk[DECOMPRESSED_CHUNK_SIZE]; + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.next_out = decompressed_chunk; + strm.avail_out = DECOMPRESSED_CHUNK_SIZE; + strm.avail_in = 0; + strm.next_in = Z_NULL; + int ret = inflateInit(&strm); + if (ret != Z_OK) + return 1; + + int error = 0; + int progress = 0; + size_t total_copied_pixels = 0; + while (1) { + // If we don't have enough data in the input buffer, try to read + // from the file. + if (strm.avail_in <= COMPRESSED_CHUNK_SIZE / 4) { + // Move the existing data to the beginning. + memmove(compressed_chunk, strm.next_in, strm.avail_in); + strm.next_in = compressed_chunk; + // Read more data. + size_t bytes_read = fread( + compressed_chunk + strm.avail_in, 1, + COMPRESSED_CHUNK_SIZE - strm.avail_in, file); + strm.avail_in += bytes_read; + if (bytes_read != 0) + progress = 1; + } + + // Try to inflate the data. + int ret = inflate(&strm, Z_SYNC_FLUSH); + if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) { + error = 1; + fprintf(stderr, + "error: could not decompress the image, error " + "%s\n", + ret == Z_MEM_ERROR ? "Z_MEM_ERROR" + : "Z_DATA_ERROR"); + break; + } + + // Copy the data from the output buffer to the image. + size_t full_pixels = + (DECOMPRESSED_CHUNK_SIZE - strm.avail_out) / pixel_size; + // Make sure we don't overflow the image. + if (full_pixels > total_pixels - total_copied_pixels) + full_pixels = total_pixels - total_copied_pixels; + if (full_pixels > 0) { + // Copy pixels. + gr_copy_pixels(data, decompressed_chunk, format, + full_pixels); + data += full_pixels; + total_copied_pixels += full_pixels; + if (total_copied_pixels >= total_pixels) { + // We filled the whole image, there may be some + // data left, but we just truncate it. + break; + } + // Move the remaining data to the beginning. + size_t copied_bytes = full_pixels * pixel_size; + size_t leftover = + (DECOMPRESSED_CHUNK_SIZE - strm.avail_out) - + copied_bytes; + memmove(decompressed_chunk, + decompressed_chunk + copied_bytes, leftover); + strm.next_out -= copied_bytes; + strm.avail_out += copied_bytes; + progress = 1; + } + + // If we haven't made any progress, then we have reached the end + // of both the file and the inflated data. + if (!progress) + break; + progress = 0; + } + + inflateEnd(&strm); + return error; +} + +#undef COMPRESSED_CHUNK_SIZE +#undef DECOMPRESSED_CHUNK_SIZE + +/// Load the image from a file containing raw pixel data (RGB or RGBA), the data +/// may be compressed. +static Imlib_Image gr_load_raw_pixel_data(ImageFrame *frame, + const char *filename) { + size_t total_pixels = frame->data_pix_width * frame->data_pix_height; + if (total_pixels * 4 > graphics_max_single_image_ram_size) { + fprintf(stderr, + "error: image %u frame %u is too big too load: %zu > %u\n", + frame->image->image_id, frame->index, total_pixels * 4, + graphics_max_single_image_ram_size); + return NULL; + } + + FILE* file = fopen(filename, "rb"); + if (!file) { + fprintf(stderr, + "error: could not open image file: %s\n", + sanitized_filename(filename)); + return NULL; + } + + Imlib_Image image = imlib_create_image(frame->data_pix_width, + frame->data_pix_height); + if (!image) { + fprintf(stderr, + "error: could not create an image of size %d x %d\n", + frame->data_pix_width, frame->data_pix_height); + fclose(file); + return NULL; + } + + imlib_context_set_image(image); + imlib_image_set_has_alpha(1); + DATA32* data = imlib_image_get_data(); + + // The default format is 32. + int format = frame->format ? frame->format : 32; + + if (frame->compression == 0) { + gr_load_raw_pixel_data_uncompressed(data, file, format, + total_pixels); + } else { + int ret = gr_load_raw_pixel_data_compressed(data, file, format, + total_pixels); + if (ret != 0) { + imlib_image_put_back_data(data); + imlib_free_image(); + fclose(file); + return NULL; + } + } + + fclose(file); + imlib_image_put_back_data(data); + return image; +} + +/// Loads the unscaled frame into RAM as an imlib object. The frame imlib object +/// is fully composed on top of the background frame. If the frame is already +/// loaded, does nothing. Loading may fail, in which case the status of the +/// frame will be set to STATUS_RAM_LOADING_ERROR. +static void gr_load_imlib_object(ImageFrame *frame) { + if (frame->imlib_object) + return; + + // If the image is uninitialized or uploading has failed, or the file + // has been deleted, we cannot load the image. + if (frame->status < STATUS_UPLOADING_SUCCESS) + return; + if (frame->disk_size == 0) { + if (frame->status != STATUS_RAM_LOADING_ERROR) { + fprintf(stderr, + "error: cached image was deleted: %u frame %u\n", + frame->image->image_id, frame->index); + } + frame->status = STATUS_RAM_LOADING_ERROR; + return; + } + + // Prevent recursive dependences between frames. + if (frame->status == STATUS_RAM_LOADING_IN_PROGRESS) { + fprintf(stderr, + "error: recursive loading of image %u frame %u\n", + frame->image->image_id, frame->index); + frame->status = STATUS_RAM_LOADING_ERROR; + return; + } + frame->status = STATUS_RAM_LOADING_IN_PROGRESS; + + // Load the background frame if needed. Hopefully it's not recursive. + ImageFrame *bg_frame = NULL; + if (frame->background_frame_index) { + bg_frame = gr_get_frame(frame->image, + frame->background_frame_index); + if (!bg_frame) { + fprintf(stderr, + "error: could not find background " + "frame %d for image %u frame %d\n", + frame->background_frame_index, + frame->image->image_id, frame->index); + frame->status = STATUS_RAM_LOADING_ERROR; + return; + } + gr_load_imlib_object(bg_frame); + if (!bg_frame->imlib_object) { + fprintf(stderr, + "error: could not load background frame %d for " + "image %u frame %d\n", + frame->background_frame_index, + frame->image->image_id, frame->index); + frame->status = STATUS_RAM_LOADING_ERROR; + return; + } + } + + // Load the frame data image. + Imlib_Image frame_data_image = NULL; + char filename[MAX_FILENAME_SIZE]; + gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); + GR_LOG("Loading image: %s\n", sanitized_filename(filename)); + if (frame->format == 100 || frame->format == 0) + frame_data_image = imlib_load_image(filename); + if (frame->format == 32 || frame->format == 24 || + (!frame_data_image && frame->format == 0)) + frame_data_image = gr_load_raw_pixel_data(frame, filename); + this_redraw_cycle_loaded_files++; + + if (!frame_data_image) { + if (frame->status != STATUS_RAM_LOADING_ERROR) { + fprintf(stderr, "error: could not load image: %s\n", + sanitized_filename(filename)); + } + frame->status = STATUS_RAM_LOADING_ERROR; + return; + } + + imlib_context_set_image(frame_data_image); + int frame_data_width = imlib_image_get_width(); + int frame_data_height = imlib_image_get_height(); + GR_LOG("Successfully loaded, size %d x %d\n", frame_data_width, + frame_data_height); + // If imlib loading succeeded, and it is the first frame, set the + // information about the original image size, unless it's already set. + if (frame->index == 1 && frame->image->pix_width == 0 && + frame->image->pix_height == 0) { + frame->image->pix_width = frame_data_width; + frame->image->pix_height = frame_data_height; + } + + int image_width = frame->image->pix_width; + int image_height = frame->image->pix_height; + + // Compose the image with the background color or frame. + if (frame->background_color != 0 || bg_frame || + image_width != frame_data_width || + image_height != frame_data_height) { + GR_LOG("Composing the frame bg = 0x%08X, bgframe = %d\n", + frame->background_color, frame->background_frame_index); + Imlib_Image composed_image = imlib_create_image( + image_width, image_height); + imlib_context_set_image(composed_image); + imlib_image_set_has_alpha(1); + imlib_context_set_anti_alias(0); + + // Start with the background frame or color. + imlib_context_set_blend(0); + if (bg_frame && bg_frame->imlib_object) { + imlib_blend_image_onto_image( + bg_frame->imlib_object, 1, 0, 0, + image_width, image_height, 0, 0, + image_width, image_height); + } else { + int r = (frame->background_color >> 24) & 0xFF; + int g = (frame->background_color >> 16) & 0xFF; + int b = (frame->background_color >> 8) & 0xFF; + int a = frame->background_color & 0xFF; + imlib_context_set_color(r, g, b, a); + imlib_image_fill_rectangle(0, 0, image_width, + image_height); + } + + // Blend the frame data image onto the background. + imlib_context_set_blend(1); + imlib_blend_image_onto_image( + frame_data_image, 1, 0, 0, frame->data_pix_width, + frame->data_pix_height, frame->x, frame->y, + frame->data_pix_width, frame->data_pix_height); + + // Free the frame data image. + imlib_context_set_image(frame_data_image); + imlib_free_image(); + + frame_data_image = composed_image; + } + + frame->imlib_object = frame_data_image; + + images_ram_size += gr_frame_current_ram_size(frame); + frame->status = STATUS_RAM_LOADING_SUCCESS; + + GR_LOG("After loading image %u frame %d ram: %ld KiB (+ %u KiB)\n", + frame->image->image_id, frame->index, + images_ram_size / 1024, gr_frame_current_ram_size(frame) / 1024); +} + +/// Premultiplies the alpha channel of the image data. The data is an array of +/// pixels such that each pixel is a 32-bit integer in the format 0xAARRGGBB. +static void gr_premultiply_alpha(DATA32 *data, size_t num_pixels) { + for (size_t i = 0; i < num_pixels; ++i) { + DATA32 pixel = data[i]; + unsigned char a = pixel >> 24; + if (a == 0) { + data[i] = 0; + } else if (a != 255) { + unsigned char b = (pixel & 0xFF) * a / 255; + unsigned char g = ((pixel >> 8) & 0xFF) * a / 255; + unsigned char r = ((pixel >> 16) & 0xFF) * a / 255; + data[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + } +} + +/// Creates a pixmap for the frame of an image placement. The pixmap contain the +/// image data correctly scaled and fit to the box defined by the number of +/// rows/columns of the image placement and the provided cell dimensions in +/// pixels. If the placement is already loaded, it will be reloaded only if the +/// cell dimensions have changed. +Pixmap gr_load_pixmap(ImagePlacement *placement, int frameidx, int cw, int ch) { + Image *img = placement->image; + ImageFrame *frame = gr_get_frame(img, frameidx); + + // Update the atime uncoditionally. + gr_touch_placement(placement); + if (frame) + gr_touch_frame(frame); + + // If cw or ch are different, unload all the pixmaps. + if (placement->scaled_cw != cw || placement->scaled_ch != ch) { + gr_unload_placement(placement); + placement->scaled_cw = cw; + placement->scaled_ch = ch; + } + + // If it's already loaded, do nothing. + Pixmap pixmap = gr_get_frame_pixmap(placement, frameidx); + if (pixmap) + return pixmap; + + GR_LOG("Loading placement: %u/%u frame %u\n", img->image_id, + placement->placement_id, frameidx); + + // Load the imlib object for the frame. + if (!frame) { + fprintf(stderr, + "error: could not find frame %u for image %u\n", + frameidx, img->image_id); + return 0; + } + gr_load_imlib_object(frame); + if (!frame->imlib_object) + return 0; + + // Infer the placement size if needed. + gr_infer_placement_size_maybe(placement); + + // Create the scaled image. This is temporary, we will scale it + // appropriately, upload to the X server, and then delete immediately. + int scaled_w = (int)placement->cols * cw; + int scaled_h = (int)placement->rows * ch; + if (scaled_w * scaled_h * 4 > graphics_max_single_image_ram_size) { + fprintf(stderr, + "error: placement %u/%u would be too big to load: %d x " + "%d x 4 > %u\n", + img->image_id, placement->placement_id, scaled_w, + scaled_h, graphics_max_single_image_ram_size); + return 0; + } + Imlib_Image scaled_image = imlib_create_image(scaled_w, scaled_h); + if (!scaled_image) { + fprintf(stderr, + "error: imlib_create_image(%d, %d) returned " + "null\n", + scaled_w, scaled_h); + return 0; + } + imlib_context_set_image(scaled_image); + imlib_image_set_has_alpha(1); + + // First fill the scaled image with the transparent color. + imlib_context_set_blend(0); + imlib_context_set_color(0, 0, 0, 0); + imlib_image_fill_rectangle(0, 0, scaled_w, scaled_h); + imlib_context_set_anti_alias(1); + imlib_context_set_blend(1); + + // The source rectangle. + int src_x = placement->src_pix_x; + int src_y = placement->src_pix_y; + int src_w = placement->src_pix_width; + int src_h = placement->src_pix_height; + // Whether the box is too small to use the true size of the image. + char box_too_small = scaled_w < src_w || scaled_h < src_h; + char mode = placement->scale_mode; + + // Then blend the original image onto the transparent background. + if (src_w <= 0 || src_h <= 0) { + fprintf(stderr, "warning: image of zero size\n"); + } else if (mode == SCALE_MODE_FILL) { + imlib_blend_image_onto_image(frame->imlib_object, 1, src_x, + src_y, src_w, src_h, 0, 0, + scaled_w, scaled_h); + } else if (mode == SCALE_MODE_NONE || + (mode == SCALE_MODE_NONE_OR_CONTAIN && !box_too_small)) { + imlib_blend_image_onto_image(frame->imlib_object, 1, src_x, + src_y, src_w, src_h, 0, 0, src_w, + src_h); + } else { + if (mode != SCALE_MODE_CONTAIN && + mode != SCALE_MODE_NONE_OR_CONTAIN) { + fprintf(stderr, + "warning: unknown scale mode %u, using " + "'contain' instead\n", + mode); + } + int dest_x, dest_y; + int dest_w, dest_h; + if (scaled_w * src_h > src_w * scaled_h) { + // If the box is wider than the original image, fit to + // height. + dest_h = scaled_h; + dest_y = 0; + dest_w = src_w * scaled_h / src_h; + dest_x = (scaled_w - dest_w) / 2; + } else { + // Otherwise, fit to width. + dest_w = scaled_w; + dest_x = 0; + dest_h = src_h * scaled_w / src_w; + dest_y = (scaled_h - dest_h) / 2; + } + imlib_blend_image_onto_image(frame->imlib_object, 1, src_x, + src_y, src_w, src_h, dest_x, + dest_y, dest_w, dest_h); + } + + // XRender needs the alpha channel premultiplied. + DATA32 *data = imlib_image_get_data(); + gr_premultiply_alpha(data, scaled_w * scaled_h); + + // Upload the image to the X server. + Display *disp = imlib_context_get_display(); + Visual *vis = imlib_context_get_visual(); + Colormap cmap = imlib_context_get_colormap(); + Drawable drawable = imlib_context_get_drawable(); + if (!drawable) + drawable = DefaultRootWindow(disp); + pixmap = XCreatePixmap(disp, drawable, scaled_w, scaled_h, 32); + XVisualInfo visinfo; + XMatchVisualInfo(disp, DefaultScreen(disp), 32, TrueColor, &visinfo); + XImage *ximage = XCreateImage(disp, visinfo.visual, 32, ZPixmap, 0, + (char *)data, scaled_w, scaled_h, 32, 0); + GC gc = XCreateGC(disp, pixmap, 0, NULL); + XPutImage(disp, pixmap, gc, ximage, 0, 0, 0, 0, scaled_w, + scaled_h); + XFreeGC(disp, gc); + // XDestroyImage will free the data as well, but it is managed by imlib, + // so set it to NULL. + ximage->data = NULL; + XDestroyImage(ximage); + imlib_image_put_back_data(data); + imlib_free_image(); + + // Assign the pixmap to the frame and increase the ram size. + gr_set_frame_pixmap(placement, frameidx, pixmap); + images_ram_size += gr_placement_single_frame_ram_size(placement); + this_redraw_cycle_loaded_pixmaps++; + + GR_LOG("After loading placement %u/%u frame %d ram: %ld KiB (+ %u " + "KiB)\n", + frame->image->image_id, placement->placement_id, frame->index, + images_ram_size / 1024, + gr_placement_single_frame_ram_size(placement) / 1024); + + // Free up ram if needed, but keep the pixmap we've loaded no matter + // what. + placement->protected_frame = frameidx; + gr_check_limits(); + placement->protected_frame = 0; + + return pixmap; +} + +//////////////////////////////////////////////////////////////////////////////// +// Initialization and deinitialization. +//////////////////////////////////////////////////////////////////////////////// + +/// Creates a temporary directory. +static int gr_create_cache_dir() { + strncpy(cache_dir, graphics_cache_dir_template, sizeof(cache_dir)); + if (!mkdtemp(cache_dir)) { + fprintf(stderr, + "error: could not create temporary dir from template " + "%s\n", + sanitized_filename(cache_dir)); + return 0; + } + fprintf(stderr, "Graphics cache directory: %s\n", cache_dir); + return 1; +} + +/// Checks whether `tmp_dir` exists and recreates it if it doesn't. +static void gr_make_sure_tmpdir_exists() { + struct stat st; + if (stat(cache_dir, &st) == 0 && S_ISDIR(st.st_mode)) + return; + fprintf(stderr, + "error: %s is not a directory, will need to create a new " + "graphics cache directory\n", + sanitized_filename(cache_dir)); + gr_create_cache_dir(); +} + +/// Initialize the graphics module. +void gr_init(Display *disp, Visual *vis, Colormap cm) { + // Set the initialization time. + clock_gettime(CLOCK_MONOTONIC, &initialization_time); + + // Create the temporary dir. + if (!gr_create_cache_dir()) + abort(); + + // Initialize imlib. + imlib_context_set_display(disp); + imlib_context_set_visual(vis); + imlib_context_set_colormap(cm); + imlib_context_set_anti_alias(1); + imlib_context_set_blend(1); + // Imlib2 checks only the file name when caching, which is not enough + // for us since we reuse file names. Disable caching. + imlib_set_cache_size(0); + + // Prepare for color inversion. + for (size_t i = 0; i < 256; ++i) + reverse_table[i] = 255 - i; + + // Create data structures. + images = kh_init(id2image); + kv_init(next_redraw_times); + + atexit(gr_deinit); +} + +/// Deinitialize the graphics module. +void gr_deinit() { + // Remove the cache dir. + remove(cache_dir); + kv_destroy(next_redraw_times); + if (images) { + // Delete all images. + gr_delete_all_images(); + // Destroy the data structures. + kh_destroy(id2image, images); + images = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Dumping, debugging, and image preview. +//////////////////////////////////////////////////////////////////////////////// + +/// Returns a string containing a time difference in a human-readable format. +/// Uses a static buffer, so be careful. +static const char *gr_ago(Milliseconds diff) { + static char result[32]; + double seconds = (double)diff / 1000.0; + if (seconds < 1) + snprintf(result, sizeof(result), "%.2f sec ago", seconds); + else if (seconds < 60) + snprintf(result, sizeof(result), "%d sec ago", (int)seconds); + else if (seconds < 3600) + snprintf(result, sizeof(result), "%d min %d sec ago", + (int)(seconds / 60), (int)(seconds) % 60); + else { + snprintf(result, sizeof(result), "%d hr %d min %d sec ago", + (int)(seconds / 3600), (int)(seconds) % 3600 / 60, + (int)(seconds) % 60); + } + return result; +} + +/// Prints to `file` with an indentation of `ind` spaces. +static void fprintf_ind(FILE *file, int ind, const char *format, ...) { + fprintf(file, "%*s", ind, ""); + va_list args; + va_start(args, format); + vfprintf(file, format, args); + va_end(args); +} + +/// Dumps the image info to `file` with an indentation of `ind` spaces. +static void gr_dump_image_info(FILE *file, Image *img, int ind) { + if (!img) { + fprintf_ind(file, ind, "Image is NULL\n"); + return; + } + Milliseconds now = gr_now_ms(); + fprintf_ind(file, ind, "Image %u\n", img->image_id); + ind += 4; + fprintf_ind(file, ind, "number: %u\n", img->image_number); + fprintf_ind(file, ind, "global command index: %lu\n", + img->global_command_index); + fprintf_ind(file, ind, "accessed: %ld %s\n", img->atime, + gr_ago(now - img->atime)); + fprintf_ind(file, ind, "pix size: %ux%u\n", img->pix_width, + img->pix_height); + fprintf_ind(file, ind, "cur frame start time: %ld %s\n", + img->current_frame_time, + gr_ago(now - img->current_frame_time)); + if (img->next_redraw) + fprintf_ind(file, ind, "next redraw: %ld in %ld ms\n", + img->next_redraw, img->next_redraw - now); + fprintf_ind(file, ind, "total disk size: %u KiB\n", + img->total_disk_size / 1024); + fprintf_ind(file, ind, "total duration: %d\n", img->total_duration); + fprintf_ind(file, ind, "frames: %d\n", gr_last_frame_index(img)); + fprintf_ind(file, ind, "cur frame: %d\n", img->current_frame); + fprintf_ind(file, ind, "animation state: %d\n", img->animation_state); + fprintf_ind(file, ind, "default_placement: %u\n", + img->default_placement); +} + +/// Dumps the frame info to `file` with an indentation of `ind` spaces. +static void gr_dump_frame_info(FILE *file, ImageFrame *frame, int ind) { + if (!frame) { + fprintf_ind(file, ind, "Frame is NULL\n"); + return; + } + Milliseconds now = gr_now_ms(); + fprintf_ind(file, ind, "Frame %d\n", frame->index); + ind += 4; + if (frame->index == 0) { + fprintf_ind(file, ind, "NOT INITIALIZED\n"); + return; + } + if (frame->uploading_failure) + fprintf_ind(file, ind, "uploading failure: %s\n", + image_uploading_failure_strings + [frame->uploading_failure]); + fprintf_ind(file, ind, "gap: %d\n", frame->gap); + fprintf_ind(file, ind, "accessed: %ld %s\n", frame->atime, + gr_ago(now - frame->atime)); + fprintf_ind(file, ind, "data pix size: %ux%u\n", frame->data_pix_width, + frame->data_pix_height); + char filename[MAX_FILENAME_SIZE]; + gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); + if (access(filename, F_OK) != -1) + fprintf_ind(file, ind, "file: %s\n", + sanitized_filename(filename)); + else + fprintf_ind(file, ind, "not on disk\n"); + fprintf_ind(file, ind, "disk size: %u KiB\n", frame->disk_size / 1024); + if (frame->imlib_object) { + unsigned ram_size = gr_frame_current_ram_size(frame); + fprintf_ind(file, ind, + "loaded into ram, size: %d " + "KiB\n", + ram_size / 1024); + } else { + fprintf_ind(file, ind, "not loaded into ram\n"); + } +} + +/// Dumps the placement info to `file` with an indentation of `ind` spaces. +static void gr_dump_placement_info(FILE *file, ImagePlacement *placement, + int ind) { + if (!placement) { + fprintf_ind(file, ind, "Placement is NULL\n"); + return; + } + Milliseconds now = gr_now_ms(); + fprintf_ind(file, ind, "Placement %u\n", placement->placement_id); + ind += 4; + fprintf_ind(file, ind, "accessed: %ld %s\n", placement->atime, + gr_ago(now - placement->atime)); + fprintf_ind(file, ind, "scale_mode: %u\n", placement->scale_mode); + fprintf_ind(file, ind, "size: %u cols x %u rows\n", placement->cols, + placement->rows); + fprintf_ind(file, ind, "cell size: %ux%u\n", placement->scaled_cw, + placement->scaled_ch); + fprintf_ind(file, ind, "ram per frame: %u KiB\n", + gr_placement_single_frame_ram_size(placement) / 1024); + unsigned ram_size = gr_placement_current_ram_size(placement); + fprintf_ind(file, ind, "ram size: %d KiB\n", ram_size / 1024); +} + +/// Dumps placement pixmaps to `file` with an indentation of `ind` spaces. +static void gr_dump_placement_pixmaps(FILE *file, ImagePlacement *placement, + int ind) { + if (!placement) + return; + int frameidx = 1; + foreach_pixmap(*placement, pixmap, { + fprintf_ind(file, ind, "Frame %d pixmap %lu\n", frameidx, + pixmap); + ++frameidx; + }); +} + +/// Dumps the internal state (images and placements) to stderr. +void gr_dump_state() { + FILE *file = stderr; + int ind = 0; + fprintf_ind(file, ind, "======= Graphics module state dump =======\n"); + fprintf_ind(file, ind, + "sizeof(Image) = %lu sizeof(ImageFrame) = %lu " + "sizeof(ImagePlacement) = %lu\n", + sizeof(Image), sizeof(ImageFrame), sizeof(ImagePlacement)); + fprintf_ind(file, ind, "Image count: %u\n", kh_size(images)); + fprintf_ind(file, ind, "Placement count: %u\n", total_placement_count); + fprintf_ind(file, ind, "Estimated RAM usage: %ld KiB\n", + images_ram_size / 1024); + fprintf_ind(file, ind, "Estimated Disk usage: %ld KiB\n", + images_disk_size / 1024); + + Milliseconds now = gr_now_ms(); + + int64_t images_ram_size_computed = 0; + int64_t images_disk_size_computed = 0; + + Image *img = NULL; + ImagePlacement *placement = NULL; + kh_foreach_value(images, img, { + fprintf_ind(file, ind, "----------------\n"); + gr_dump_image_info(file, img, 0); + int64_t total_disk_size_computed = 0; + int total_duration_computed = 0; + foreach_frame(*img, frame, { + gr_dump_frame_info(file, frame, 4); + if (frame->image != img) + fprintf_ind(file, 8, + "ERROR: WRONG IMAGE POINTER\n"); + total_duration_computed += frame->gap; + images_disk_size_computed += frame->disk_size; + total_disk_size_computed += frame->disk_size; + if (frame->imlib_object) + images_ram_size_computed += + gr_frame_current_ram_size(frame); + }); + if (img->total_disk_size != total_disk_size_computed) { + fprintf_ind(file, ind, + " ERROR: total_disk_size is %u, but " + "computed value is %ld\n", + img->total_disk_size, total_disk_size_computed); + } + if (img->total_duration != total_duration_computed) { + fprintf_ind(file, ind, + " ERROR: total_duration is %d, but computed " + "value is %d\n", + img->total_duration, total_duration_computed); + } + kh_foreach_value(img->placements, placement, { + gr_dump_placement_info(file, placement, 4); + if (placement->image != img) + fprintf_ind(file, 8, + "ERROR: WRONG IMAGE POINTER\n"); + fprintf_ind(file, 8, + "Pixmaps:\n"); + gr_dump_placement_pixmaps(file, placement, 12); + unsigned ram_size = + gr_placement_current_ram_size(placement); + images_ram_size_computed += ram_size; + }); + }); + if (images_ram_size != images_ram_size_computed) { + fprintf_ind(file, ind, + "ERROR: images_ram_size is %ld, but computed value " + "is %ld\n", + images_ram_size, images_ram_size_computed); + } + if (images_disk_size != images_disk_size_computed) { + fprintf_ind(file, ind, + "ERROR: images_disk_size is %ld, but computed value " + "is %ld\n", + images_disk_size, images_disk_size_computed); + } + fprintf_ind(file, ind, "===========================================\n"); +} + +/// Executes `command` with the name of the file corresponding to `image_id` as +/// the argument. Executes xmessage with an error message on failure. +// TODO: Currently we do this for the first frame only. Not sure what to do with +// animations. +void gr_preview_image(uint32_t image_id, const char *exec) { + char command[256]; + size_t len; + Image *img = gr_find_image(image_id); + if (img) { + ImageFrame *frame = &img->first_frame; + char filename[MAX_FILENAME_SIZE]; + gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); + if (frame->disk_size == 0) { + len = snprintf(command, 255, + "xmessage 'Image with id=%u is not " + "fully copied to %s'", + image_id, sanitized_filename(filename)); + } else { + len = snprintf(command, 255, "%s %s &", exec, + sanitized_filename(filename)); + } + } else { + len = snprintf(command, 255, + "xmessage 'Cannot find image with id=%u'", + image_id); + } + if (len > 255) { + fprintf(stderr, "error: command too long: %s\n", command); + snprintf(command, 255, "xmessage 'error: command too long'"); + } + if (system(command) != 0) { + fprintf(stderr, "error: could not execute command %s\n", + command); + } +} + +/// Executes `<st> -e less <file>` where <file> is the name of a temporary file +/// containing the information about an image and placement, and <st> is +/// specified with `st_executable`. +void gr_show_image_info(uint32_t image_id, uint32_t placement_id, + uint32_t imgcol, uint32_t imgrow, + char is_classic_placeholder, int32_t diacritic_count, + char *st_executable) { + char filename[MAX_FILENAME_SIZE]; + snprintf(filename, sizeof(filename), "%s/info-%u", cache_dir, image_id); + FILE *file = fopen(filename, "w"); + if (!file) { + perror("fopen"); + return; + } + // Basic information about the cell. + fprintf(file, "image_id = %u = 0x%08X\n", image_id, image_id); + fprintf(file, "placement_id = %u = 0x%08X\n", placement_id, placement_id); + fprintf(file, "column = %d, row = %d\n", imgcol, imgrow); + fprintf(file, "classic/unicode placeholder = %s\n", + is_classic_placeholder ? "classic" : "unicode"); + fprintf(file, "original diacritic count = %d\n", diacritic_count); + // Information about the image and the placement. + Image *img = gr_find_image(image_id); + ImagePlacement *placement = gr_find_placement(img, placement_id); + gr_dump_image_info(file, img, 0); + gr_dump_placement_info(file, placement, 0); + if (img) { + fprintf(file, "Frames:\n"); + foreach_frame(*img, frame, { + gr_dump_frame_info(file, frame, 4); + }); + } + if (placement) { + fprintf(file, "Placement pixmaps:\n"); + gr_dump_placement_pixmaps(file, placement, 4); + } + fclose(file); + char *argv[] = {st_executable, "-e", "less", filename, NULL}; + if (posix_spawnp(NULL, st_executable, NULL, NULL, argv, environ) != 0) { + perror("posix_spawnp"); + return; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Appending and displaying image rectangles. +//////////////////////////////////////////////////////////////////////////////// + +/// Displays debug information in the rectangle using colors col1 and col2. +static void gr_displayinfo(Drawable buf, ImageRect *rect, int col1, int col2, + const char *message) { + int w_pix = (rect->img_end_col - rect->img_start_col) * rect->cw; + int h_pix = (rect->img_end_row - rect->img_start_row) * rect->ch; + Display *disp = imlib_context_get_display(); + GC gc = XCreateGC(disp, buf, 0, NULL); + char info[MAX_INFO_LEN]; + if (rect->placement_id) + snprintf(info, MAX_INFO_LEN, "%s%u/%u [%d:%d)x[%d:%d)", message, + rect->image_id, rect->placement_id, + rect->img_start_col, rect->img_end_col, + rect->img_start_row, rect->img_end_row); + else + snprintf(info, MAX_INFO_LEN, "%s%u [%d:%d)x[%d:%d)", message, + rect->image_id, rect->img_start_col, rect->img_end_col, + rect->img_start_row, rect->img_end_row); + XSetForeground(disp, gc, col1); + XDrawString(disp, buf, gc, rect->screen_x_pix + 4, + rect->screen_y_pix + h_pix - 3, info, strlen(info)); + XSetForeground(disp, gc, col2); + XDrawString(disp, buf, gc, rect->screen_x_pix + 2, + rect->screen_y_pix + h_pix - 5, info, strlen(info)); + XFreeGC(disp, gc); +} + +/// Draws a rectangle (bounding box) for debugging. +static void gr_showrect(Drawable buf, ImageRect *rect) { + int w_pix = (rect->img_end_col - rect->img_start_col) * rect->cw; + int h_pix = (rect->img_end_row - rect->img_start_row) * rect->ch; + Display *disp = imlib_context_get_display(); + GC gc = XCreateGC(disp, buf, 0, NULL); + XSetForeground(disp, gc, 0xFF00FF00); + XDrawRectangle(disp, buf, gc, rect->screen_x_pix, rect->screen_y_pix, + w_pix - 1, h_pix - 1); + XSetForeground(disp, gc, 0xFFFF0000); + XDrawRectangle(disp, buf, gc, rect->screen_x_pix + 1, + rect->screen_y_pix + 1, w_pix - 3, h_pix - 3); + XFreeGC(disp, gc); +} + +/// Updates the next redraw time for the given row. Resizes the +/// next_redraw_times array if needed. +static void gr_update_next_redraw_time(int row, Milliseconds next_redraw) { + if (next_redraw == 0) + return; + if (row >= kv_size(next_redraw_times)) { + size_t old_size = kv_size(next_redraw_times); + kv_a(Milliseconds, next_redraw_times, row); + for (size_t i = old_size; i <= row; ++i) + kv_A(next_redraw_times, i) = 0; + } + Milliseconds old_value = kv_A(next_redraw_times, row); + if (old_value == 0 || old_value > next_redraw) + kv_A(next_redraw_times, row) = next_redraw; +} + +/// Draws the given part of an image. +static void gr_drawimagerect(Drawable buf, ImageRect *rect) { + ImagePlacement *placement = + gr_find_image_and_placement(rect->image_id, rect->placement_id); + // If the image does not exist or image display is switched off, draw + // the bounding box. + if (!placement || !graphics_display_images) { + gr_showrect(buf, rect); + if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) + gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, ""); + return; + } + + Image *img = placement->image; + + if (img->last_redraw < drawing_start_time) { + // This is the first time we draw this image in this redraw + // cycle. Update the frame index we are going to display. Note + // that currently all image placements are synchronized. + int old_frame = img->current_frame; + gr_update_frame_index(img, drawing_start_time); + img->last_redraw = drawing_start_time; + } + + // Adjust next redraw times for the rows of this image rect. + if (img->next_redraw) { + for (int row = rect->screen_y_row; + row <= rect->screen_y_row + rect->img_end_row - + rect->img_start_row - 1; ++row) { + gr_update_next_redraw_time( + row, img->next_redraw); + } + } + + // Load the frame. + Pixmap pixmap = gr_load_pixmap(placement, img->current_frame, rect->cw, + rect->ch); + + // If the image couldn't be loaded, display the bounding box. + if (!pixmap) { + gr_showrect(buf, rect); + if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) + gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, ""); + return; + } + + int src_x = rect->img_start_col * rect->cw; + int src_y = rect->img_start_row * rect->ch; + int width = (rect->img_end_col - rect->img_start_col) * rect->cw; + int height = (rect->img_end_row - rect->img_start_row) * rect->ch; + int dst_x = rect->screen_x_pix; + int dst_y = rect->screen_y_pix; + + // Display the image. + Display *disp = imlib_context_get_display(); + Visual *vis = imlib_context_get_visual(); + + // Create an xrender picture for the window. + XRenderPictFormat *win_format = + XRenderFindVisualFormat(disp, vis); + Picture window_pic = + XRenderCreatePicture(disp, buf, win_format, 0, NULL); + + // If needed, invert the image pixmap. Note that this naive approach of + // inverting the pixmap is not entirely correct, because the pixmap is + // premultiplied. But the result is good enough to visually indicate + // selection. + if (rect->reverse) { + unsigned pixmap_w = + (unsigned)placement->cols * placement->scaled_cw; + unsigned pixmap_h = + (unsigned)placement->rows * placement->scaled_ch; + Pixmap invpixmap = + XCreatePixmap(disp, buf, pixmap_w, pixmap_h, 32); + XGCValues gcv = {.function = GXcopyInverted}; + GC gc = XCreateGC(disp, invpixmap, GCFunction, &gcv); + XCopyArea(disp, pixmap, invpixmap, gc, 0, 0, pixmap_w, + pixmap_h, 0, 0); + XFreeGC(disp, gc); + pixmap = invpixmap; + } + + // Create a picture for the image pixmap. + XRenderPictFormat *pic_format = + XRenderFindStandardFormat(disp, PictStandardARGB32); + Picture pixmap_pic = + XRenderCreatePicture(disp, pixmap, pic_format, 0, NULL); + + // Composite the image onto the window. In the reverse mode we ignore + // the alpha channel of the image because the naive inversion above + // seems to invert the alpha channel as well. + int pictop = rect->reverse ? PictOpSrc : PictOpOver; + XRenderComposite(disp, pictop, pixmap_pic, 0, window_pic, + src_x, src_y, src_x, src_y, dst_x, dst_y, width, + height); + + // Free resources + XRenderFreePicture(disp, pixmap_pic); + XRenderFreePicture(disp, window_pic); + if (rect->reverse) + XFreePixmap(disp, pixmap); + + // In debug mode always draw bounding boxes and print info. + if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) { + gr_showrect(buf, rect); + gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, ""); + } +} + +/// Removes the given image rectangle. +static void gr_freerect(ImageRect *rect) { memset(rect, 0, sizeof(ImageRect)); } + +/// Returns the bottom coordinate of the rect. +static int gr_getrectbottom(ImageRect *rect) { + return rect->screen_y_pix + + (rect->img_end_row - rect->img_start_row) * rect->ch; +} + +/// Prepare for image drawing. `cw` and `ch` are dimensions of the cell. +void gr_start_drawing(Drawable buf, int cw, int ch) { + current_cw = cw; + current_ch = ch; + this_redraw_cycle_loaded_files = 0; + this_redraw_cycle_loaded_pixmaps = 0; + drawing_start_time = gr_now_ms(); + imlib_context_set_drawable(buf); +} + +/// Finish image drawing. This functions will draw all the rectangles left to +/// draw. +void gr_finish_drawing(Drawable buf) { + // Draw and then delete all known image rectangles. + for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) { + ImageRect *rect = &image_rects[i]; + if (!rect->image_id) + continue; + gr_drawimagerect(buf, rect); + gr_freerect(rect); + } + + // Compute the delay until the next redraw as the minimum of the next + // redraw delays for all rows. + Milliseconds drawing_end_time = gr_now_ms(); + graphics_next_redraw_delay = INT_MAX; + for (int row = 0; row < kv_size(next_redraw_times); ++row) { + Milliseconds row_next_redraw = kv_A(next_redraw_times, row); + if (row_next_redraw > 0) { + int delay = MAX(graphics_animation_min_delay, + row_next_redraw - drawing_end_time); + graphics_next_redraw_delay = + MIN(graphics_next_redraw_delay, delay); + } + } + + // In debug mode display additional info. + if (graphics_debug_mode) { + int milliseconds = drawing_end_time - drawing_start_time; + + Display *disp = imlib_context_get_display(); + GC gc = XCreateGC(disp, buf, 0, NULL); + const char *debug_mode_str = + graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES + ? "(boxes shown) " + : ""; + int redraw_delay = graphics_next_redraw_delay == INT_MAX + ? -1 + : graphics_next_redraw_delay; + char info[MAX_INFO_LEN]; + snprintf(info, MAX_INFO_LEN, + "%sRender time: %d ms ram %ld K disk %ld K count " + "%d cell %dx%d delay %d", + debug_mode_str, milliseconds, images_ram_size / 1024, + images_disk_size / 1024, kh_size(images), current_cw, + current_ch, redraw_delay); + XSetForeground(disp, gc, 0xFF000000); + XFillRectangle(disp, buf, gc, 0, 0, 600, 16); + XSetForeground(disp, gc, 0xFFFFFFFF); + XDrawString(disp, buf, gc, 0, 14, info, strlen(info)); + XFreeGC(disp, gc); + + if (milliseconds > 0) { + fprintf(stderr, "%s (loaded %d files, %d pixmaps)\n", + info, this_redraw_cycle_loaded_files, + this_redraw_cycle_loaded_pixmaps); + } + } + + // Check the limits in case we have used too much ram for placements. + gr_check_limits(); +} + +// Add an image rectangle to the list of rectangles to draw. +void gr_append_imagerect(Drawable buf, uint32_t image_id, uint32_t placement_id, + int img_start_col, int img_end_col, int img_start_row, + int img_end_row, int x_col, int y_row, int x_pix, + int y_pix, int cw, int ch, int reverse) { + current_cw = cw; + current_ch = ch; + + ImageRect new_rect; + new_rect.image_id = image_id; + new_rect.placement_id = placement_id; + new_rect.img_start_col = img_start_col; + new_rect.img_end_col = img_end_col; + new_rect.img_start_row = img_start_row; + new_rect.img_end_row = img_end_row; + new_rect.screen_y_row = y_row; + new_rect.screen_x_pix = x_pix; + new_rect.screen_y_pix = y_pix; + new_rect.ch = ch; + new_rect.cw = cw; + new_rect.reverse = reverse; + + // Display some red text in debug mode. + if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) + gr_displayinfo(buf, &new_rect, 0xFF000000, 0xFFFF0000, "? "); + + // If it's the empty image (image_id=0) or an empty rectangle, do + // nothing. + if (image_id == 0 || img_end_col - img_start_col <= 0 || + img_end_row - img_start_row <= 0) + return; + // Try to find a rect to merge with. + ImageRect *free_rect = NULL; + for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) { + ImageRect *rect = &image_rects[i]; + if (rect->image_id == 0) { + if (!free_rect) + free_rect = rect; + continue; + } + if (rect->image_id != image_id || + rect->placement_id != placement_id || rect->cw != cw || + rect->ch != ch || rect->reverse != reverse) + continue; + // We only support the case when the new stripe is added to the + // bottom of an existing rectangle and they are perfectly + // aligned. + if (rect->img_end_row == img_start_row && + gr_getrectbottom(rect) == y_pix) { + if (rect->img_start_col == img_start_col && + rect->img_end_col == img_end_col && + rect->screen_x_pix == x_pix) { + rect->img_end_row = img_end_row; + return; + } + } + } + // If we haven't merged the new rect with any existing rect, and there + // is no free rect, we have to render one of the existing rects. + if (!free_rect) { + for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) { + ImageRect *rect = &image_rects[i]; + if (!free_rect || gr_getrectbottom(free_rect) > + gr_getrectbottom(rect)) + free_rect = rect; + } + gr_drawimagerect(buf, free_rect); + gr_freerect(free_rect); + } + // Start a new rectangle in `free_rect`. + *free_rect = new_rect; +} + +/// Mark rows containing animations as dirty if it's time to redraw them. Must +/// be called right after `gr_start_drawing`. +void gr_mark_dirty_animations(int *dirty, int rows) { + if (rows < kv_size(next_redraw_times)) + kv_size(next_redraw_times) = rows; + if (rows * 2 < kv_max(next_redraw_times)) + kv_resize(Milliseconds, next_redraw_times, rows); + for (int i = 0; i < MIN(rows, kv_size(next_redraw_times)); ++i) { + if (dirty[i]) { + kv_A(next_redraw_times, i) = 0; + continue; + } + Milliseconds next_update = kv_A(next_redraw_times, i); + if (next_update > 0 && next_update <= drawing_start_time) { + dirty[i] = 1; + kv_A(next_redraw_times, i) = 0; + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Command parsing and handling. +//////////////////////////////////////////////////////////////////////////////// + +/// A parsed kitty graphics protocol command. +typedef struct { + /// The command itself, without the 'G'. + char *command; + /// The payload (after ';'). + char *payload; + /// 'a=', may be 't', 'q', 'f', 'T', 'p', 'd', 'a'. + char action; + /// 'q=', 1 to suppress OK response, 2 to suppress errors too. + int quiet; + /// 'f=', use 24 or 32 for raw pixel data, 100 to autodetect with + /// imlib2. If 'f=0', will try to load with imlib2, then fallback to + /// 32-bit pixel data. + int format; + /// 'o=', may be 'z' for RFC 1950 ZLIB. + int compression; + /// 't=', may be 'f', 't' or 'd'. + char transmission_medium; + /// 'd=' + char delete_specifier; + /// 's=', 'v=', if 'a=t' or 'a=T', used only when 'f=24' or 'f=32'. + /// When 'a=f', this is the size of the frame rectangle when composed on + /// top of another frame. + int frame_pix_width, frame_pix_height; + /// 'x=', 'y=' - top-left corner of the source rectangle. + int src_pix_x, src_pix_y; + /// 'w=', 'h=' - width and height of the source rectangle. + int src_pix_width, src_pix_height; + /// 'r=', 'c=' + int rows, columns; + /// 'i=' + uint32_t image_id; + /// 'I=' + uint32_t image_number; + /// 'p=' + uint32_t placement_id; + /// 'm=', may be 0 or 1. + int more; + /// True if either 'm=0' or 'm=1' is specified. + char is_data_transmission; + /// True if turns out that this command is a continuation of a data + /// transmission and not the first one for this image. Populated by + /// `gr_handle_transmit_command`. + char is_direct_transmission_continuation; + /// 'S=', used to check the size of uploaded data. + int size; + /// 'U=', whether it's a virtual placement for Unicode placeholders. + int virtual; + /// 'C=', if true, do not move the cursor when displaying this placement + /// (non-virtual placements only). + char do_not_move_cursor; + // --------------------------------------------------------------------- + // Animation-related fields. Their keys often overlap with keys of other + // commands, so these make sense only if the action is 'a=f' (frame + // transmission) or 'a=a' (animation control). + // + // 'x=' and 'y=', the relative position of the frame image when it's + // composed on top of another frame. + int frame_dst_pix_x, frame_dst_pix_y; + /// 'X=', 'X=1' to replace colors instead of alpha blending on top of + /// the background color or frame. + char replace_instead_of_blending; + /// 'Y=', the background color in the 0xRRGGBBAA format (still + /// transmitted as a decimal number). + uint32_t background_color; + /// (Only for 'a=f'). 'c=', the 1-based index of the background frame. + int background_frame; + /// (Only for 'a=a'). 'c=', sets the index of the current frame. + int current_frame; + /// 'r=', the 1-based index of the frame to edit. + int edit_frame; + /// 'z=', the duration of the frame. Zero if not specified, negative if + /// the frame is gapless (i.e. skipped). + int gap; + /// (Only for 'a=a'). 's=', if non-zero, sets the state of the + /// animation, 1 to stop, 2 to run in loading mode, 3 to loop. + int animation_state; + /// (Only for 'a=a'). 'v=', if non-zero, sets the number of times the + /// animation will loop. 1 to loop infinitely, N to loop N-1 times. + int loops; +} GraphicsCommand; + +/// Replaces all non-printed characters in `str` with '?' and truncates the +/// string to `max_size`, maybe inserting ellipsis at the end. +static void sanitize_str(char *str, size_t max_size) { + assert(max_size >= 4); + for (size_t i = 0; i < max_size; ++i) { + unsigned c = str[i]; + if (c == '\0') + return; + if (c >= 128 || !isprint(c)) + str[i] = '?'; + } + str[max_size - 1] = '\0'; + str[max_size - 2] = '.'; + str[max_size - 3] = '.'; + str[max_size - 4] = '.'; +} + +/// A non-destructive version of `sanitize_str`. Uses a static buffer, so be +/// careful. +static const char *sanitized_filename(const char *str) { + static char buf[MAX_FILENAME_SIZE]; + strncpy(buf, str, sizeof(buf)); + sanitize_str(buf, sizeof(buf)); + return buf; +} + +/// Creates a response to the current command in `graphics_command_result`. +static void gr_createresponse(uint32_t image_id, uint32_t image_number, + uint32_t placement_id, const char *msg) { + if (!image_id && !image_number && !placement_id) { + // Nobody expects the response in this case, so just print it to + // stderr. + fprintf(stderr, + "error: No image id or image number or placement_id, " + "but still there is a response: %s\n", + msg); + return; + } + char *buf = graphics_command_result.response; + size_t maxlen = MAX_GRAPHICS_RESPONSE_LEN; + size_t written; + written = snprintf(buf, maxlen, "\033_G"); + buf += written; + maxlen -= written; + if (image_id) { + written = snprintf(buf, maxlen, "i=%u,", image_id); + buf += written; + maxlen -= written; + } + if (image_number) { + written = snprintf(buf, maxlen, "I=%u,", image_number); + buf += written; + maxlen -= written; + } + if (placement_id) { + written = snprintf(buf, maxlen, "p=%u,", placement_id); + buf += written; + maxlen -= written; + } + buf[-1] = ';'; + written = snprintf(buf, maxlen, "%s\033\\", msg); + buf += written; + maxlen -= written; + buf[-2] = '\033'; + buf[-1] = '\\'; +} + +/// Creates the 'OK' response to the current command, unless suppressed or a +/// non-final data transmission. +static void gr_reportsuccess_cmd(GraphicsCommand *cmd) { + if (cmd->quiet < 1 && !cmd->more) + gr_createresponse(cmd->image_id, cmd->image_number, + cmd->placement_id, "OK"); +} + +/// Creates the 'OK' response to the current command (unless suppressed). +static void gr_reportsuccess_frame(ImageFrame *frame) { + uint32_t id = frame->image->query_id ? frame->image->query_id + : frame->image->image_id; + if (frame->quiet < 1) + gr_createresponse(id, frame->image->image_number, + frame->image->initial_placement_id, "OK"); +} + +/// Creates an error response to the current command (unless suppressed). +static void gr_reporterror_cmd(GraphicsCommand *cmd, const char *format, ...) { + char errmsg[MAX_GRAPHICS_RESPONSE_LEN]; + graphics_command_result.error = 1; + va_list args; + va_start(args, format); + vsnprintf(errmsg, MAX_GRAPHICS_RESPONSE_LEN, format, args); + va_end(args); + + fprintf(stderr, "%s in command: %s\n", errmsg, cmd->command); + if (cmd->quiet < 2) + gr_createresponse(cmd->image_id, cmd->image_number, + cmd->placement_id, errmsg); +} + +/// Creates an error response to the current command (unless suppressed). +static void gr_reporterror_frame(ImageFrame *frame, const char *format, ...) { + char errmsg[MAX_GRAPHICS_RESPONSE_LEN]; + graphics_command_result.error = 1; + va_list args; + va_start(args, format); + vsnprintf(errmsg, MAX_GRAPHICS_RESPONSE_LEN, format, args); + va_end(args); + + if (!frame) { + fprintf(stderr, "%s\n", errmsg); + gr_createresponse(0, 0, 0, errmsg); + } else { + uint32_t id = frame->image->query_id ? frame->image->query_id + : frame->image->image_id; + fprintf(stderr, "%s id=%u\n", errmsg, id); + if (frame->quiet < 2) + gr_createresponse(id, frame->image->image_number, + frame->image->initial_placement_id, + errmsg); + } +} + +/// Loads an image and creates a success/failure response. Returns `frame`, or +/// NULL if it's a query action and the image was deleted. +static ImageFrame *gr_loadimage_and_report(ImageFrame *frame) { + gr_load_imlib_object(frame); + if (!frame->imlib_object) { + gr_reporterror_frame(frame, "EBADF: could not load image"); + } else { + gr_reportsuccess_frame(frame); + } + // If it was a query action, discard the image. + if (frame->image->query_id) { + gr_delete_image(frame->image); + return NULL; + } + return frame; +} + +/// Creates an appropriate uploading failure response to the current command. +static void gr_reportuploaderror(ImageFrame *frame) { + switch (frame->uploading_failure) { + case 0: + return; + case ERROR_CANNOT_OPEN_CACHED_FILE: + gr_reporterror_frame(frame, + "EIO: could not create a file for image"); + break; + case ERROR_OVER_SIZE_LIMIT: + gr_reporterror_frame( + frame, + "EFBIG: the size of the uploaded image exceeded " + "the image size limit %u", + graphics_max_single_image_file_size); + break; + case ERROR_UNEXPECTED_SIZE: + gr_reporterror_frame(frame, + "EINVAL: the size of the uploaded image %u " + "doesn't match the expected size %u", + frame->disk_size, frame->expected_size); + break; + }; +} + +/// Displays a non-virtual placement. This functions records the information in +/// `graphics_command_result`, the placeholder itself is created by the terminal +/// after handling the current command in the graphics module. +static void gr_display_nonvirtual_placement(ImagePlacement *placement) { + if (placement->virtual) + return; + if (placement->image->first_frame.status < STATUS_RAM_LOADING_SUCCESS) + return; + // Infer the placement size if needed. + gr_infer_placement_size_maybe(placement); + // Populate the information about the placeholder which will be created + // by the terminal. + graphics_command_result.create_placeholder = 1; + graphics_command_result.placeholder.image_id = placement->image->image_id; + graphics_command_result.placeholder.placement_id = placement->placement_id; + graphics_command_result.placeholder.columns = placement->cols; + graphics_command_result.placeholder.rows = placement->rows; + graphics_command_result.placeholder.do_not_move_cursor = + placement->do_not_move_cursor; + GR_LOG("Creating a placeholder for %u/%u %d x %d\n", + placement->image->image_id, placement->placement_id, + placement->cols, placement->rows); +} + +/// Marks the rows that are occupied by the image as dirty. +static void gr_schedule_image_redraw(Image *img) { + if (!img) + return; + gr_schedule_image_redraw_by_id(img->image_id); +} + +/// Appends data from `payload` to the frame `frame` when using direct +/// transmission. Note that we report errors only for the final command +/// (`!more`) to avoid spamming the client. If the frame is not specified, use +/// the image id and frame index we are currently uploading. +static void gr_append_data(ImageFrame *frame, const char *payload, int more) { + if (!frame) { + Image *img = gr_find_image(current_upload_image_id); + frame = gr_get_frame(img, current_upload_frame_index); + GR_LOG("Appending data to image %u frame %d\n", + current_upload_image_id, current_upload_frame_index); + if (!img) + GR_LOG("ERROR: this image doesn't exist\n"); + if (!frame) + GR_LOG("ERROR: this frame doesn't exist\n"); + } + if (!more) { + current_upload_image_id = 0; + current_upload_frame_index = 0; + } + if (!frame) { + if (!more) + gr_reporterror_frame(NULL, "ENOENT: could not find the " + "image to append data to"); + return; + } + if (frame->status != STATUS_UPLOADING) { + if (!more) + gr_reportuploaderror(frame); + return; + } + + // Decode the data. + size_t data_size = 0; + char *data = gr_base64dec(payload, &data_size); + + GR_LOG("appending %u + %zu = %zu bytes\n", frame->disk_size, data_size, + frame->disk_size + data_size); + + // Do not append this data if the image exceeds the size limit. + if (frame->disk_size + data_size > + graphics_max_single_image_file_size || + frame->expected_size > graphics_max_single_image_file_size) { + free(data); + gr_delete_imagefile(frame); + frame->uploading_failure = ERROR_OVER_SIZE_LIMIT; + if (!more) + gr_reportuploaderror(frame); + return; + } + + // If there is no open file corresponding to the image, create it. + if (!frame->open_file) { + gr_make_sure_tmpdir_exists(); + char filename[MAX_FILENAME_SIZE]; + gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE); + FILE *file = fopen(filename, frame->disk_size ? "a" : "w"); + if (!file) { + frame->status = STATUS_UPLOADING_ERROR; + frame->uploading_failure = ERROR_CANNOT_OPEN_CACHED_FILE; + if (!more) + gr_reportuploaderror(frame); + return; + } + frame->open_file = file; + } + + // Write data to the file and update disk size variables. + fwrite(data, 1, data_size, frame->open_file); + free(data); + frame->disk_size += data_size; + frame->image->total_disk_size += data_size; + images_disk_size += data_size; + gr_touch_frame(frame); + + if (more) { + current_upload_image_id = frame->image->image_id; + current_upload_frame_index = frame->index; + } else { + current_upload_image_id = 0; + current_upload_frame_index = 0; + // Close the file. + if (frame->open_file) { + fclose(frame->open_file); + frame->open_file = NULL; + } + frame->status = STATUS_UPLOADING_SUCCESS; + uint32_t placement_id = frame->image->default_placement; + if (frame->expected_size && + frame->expected_size != frame->disk_size) { + // Report failure if the uploaded image size doesn't + // match the expected size. + frame->status = STATUS_UPLOADING_ERROR; + frame->uploading_failure = ERROR_UNEXPECTED_SIZE; + gr_reportuploaderror(frame); + } else { + // Make sure to redraw all existing image instances. + gr_schedule_image_redraw(frame->image); + // Try to load the image into ram and report the result. + frame = gr_loadimage_and_report(frame); + // If there is a non-virtual image placement, we may + // need to display it. + if (frame && frame->index == 1) { + Image *img = frame->image; + ImagePlacement *placement = NULL; + kh_foreach_value(img->placements, placement, { + gr_display_nonvirtual_placement(placement); + }); + } + } + } + + // Check whether we need to delete old images. + gr_check_limits(); +} + +/// Finds the image either by id or by number specified in the command and sets +/// the image_id of `cmd` if the image was found. +static Image *gr_find_image_for_command(GraphicsCommand *cmd) { + if (cmd->image_id) + return gr_find_image(cmd->image_id); + Image *img = NULL; + // If the image number is not specified, we can't find the image, unless + // it's a put command, in which case we will try the last image. + if (cmd->image_number == 0 && cmd->action == 'p') + img = gr_find_image(last_image_id); + else + img = gr_find_image_by_number(cmd->image_number); + if (img) + cmd->image_id = img->image_id; + return img; +} + +/// Creates a new image or a new frame in an existing image (depending on the +/// command's action) and initializes its parameters from the command. +static ImageFrame *gr_new_image_or_frame_from_command(GraphicsCommand *cmd) { + if (cmd->format != 0 && cmd->format != 32 && cmd->format != 24 && + cmd->compression != 0) { + gr_reporterror_cmd(cmd, "EINVAL: compression is supported only " + "for raw pixel data (f=32 or f=24)"); + // Even though we report an error, we still create an image. + } + + Image *img = NULL; + if (cmd->action == 'f') { + // If it's a frame transmission action, there must be an + // existing image. + img = gr_find_image_for_command(cmd); + if (!img) { + gr_reporterror_cmd(cmd, "ENOENT: image not found"); + return NULL; + } + } else { + // Otherwise create a new image object. If the action is `q`, + // we'll use random id instead of the one specified in the + // command. + uint32_t image_id = cmd->action == 'q' ? 0 : cmd->image_id; + img = gr_new_image(image_id); + if (!img) + return NULL; + if (cmd->action == 'q') + img->query_id = cmd->image_id; + else if (!cmd->image_id) + cmd->image_id = img->image_id; + // Set the image number. + img->image_number = cmd->image_number; + } + + ImageFrame *frame = gr_append_new_frame(img); + // Initialize the frame. + frame->expected_size = cmd->size; + frame->format = cmd->format; + frame->compression = cmd->compression; + frame->background_color = cmd->background_color; + frame->background_frame_index = cmd->background_frame; + frame->gap = cmd->gap; + img->total_duration += frame->gap; + frame->blend = !cmd->replace_instead_of_blending; + frame->data_pix_width = cmd->frame_pix_width; + frame->data_pix_height = cmd->frame_pix_height; + if (cmd->action == 'f') { + frame->x = cmd->frame_dst_pix_x; + frame->y = cmd->frame_dst_pix_y; + } + // We save the quietness information in the frame because for direct + // transmission subsequent transmission command won't contain this info. + frame->quiet = cmd->quiet; + return frame; +} + +/// Removes a file if it actually looks like a temporary file. +static void gr_delete_tmp_file(const char *filename) { + if (strstr(filename, "tty-graphics-protocol") == NULL) + return; + if (strstr(filename, "/tmp/") != filename) { + const char *tmpdir = getenv("TMPDIR"); + if (!tmpdir || !tmpdir[0] || + strstr(filename, tmpdir) != filename) + return; + } + unlink(filename); +} + +/// Handles a data transmission command. +static ImageFrame *gr_handle_transmit_command(GraphicsCommand *cmd) { + // The default is direct transmission. + if (!cmd->transmission_medium) + cmd->transmission_medium = 'd'; + + // If neither id, nor image number is specified, and the transmission + // medium is 'd' (or unspecified), and there is an active direct upload, + // this is a continuation of the upload. + if (current_upload_image_id != 0 && cmd->image_id == 0 && + cmd->image_number == 0 && cmd->transmission_medium == 'd') { + cmd->image_id = current_upload_image_id; + GR_LOG("No images id is specified, continuing uploading %u\n", + cmd->image_id); + } + + ImageFrame *frame = NULL; + if (cmd->transmission_medium == 'f' || + cmd->transmission_medium == 't') { + // File transmission. + // Create a new image or a new frame of an existing image. + frame = gr_new_image_or_frame_from_command(cmd); + if (!frame) + return NULL; + last_image_id = frame->image->image_id; + // Decode the filename. + char *original_filename = gr_base64dec(cmd->payload, NULL); + GR_LOG("Copying image %s\n", + sanitized_filename(original_filename)); + // Stat the file and check that it's a regular file and not too + // big. + struct stat st; + int stat_res = stat(original_filename, &st); + const char *stat_error = NULL; + if (stat_res) + stat_error = strerror(errno); + else if (!S_ISREG(st.st_mode)) + stat_error = "Not a regular file"; + else if (st.st_size == 0) + stat_error = "The size of the file is zero"; + else if (st.st_size > graphics_max_single_image_file_size) + stat_error = "The file is too large"; + if (stat_error) { + gr_reporterror_cmd(cmd, + "EBADF: %s", stat_error); + fprintf(stderr, "Could not load the file %s\n", + sanitized_filename(original_filename)); + frame->status = STATUS_UPLOADING_ERROR; + frame->uploading_failure = ERROR_CANNOT_COPY_FILE; + } else { + gr_make_sure_tmpdir_exists(); + // Build the filename for the cached copy of the file. + char cache_filename[MAX_FILENAME_SIZE]; + gr_get_frame_filename(frame, cache_filename, + MAX_FILENAME_SIZE); + // We will create a symlink to the original file, and + // then copy the file to the temporary cache dir. We do + // this symlink trick mostly to be able to use cp for + // copying, and avoid escaping file name characters when + // calling system at the same time. + char tmp_filename_symlink[MAX_FILENAME_SIZE + 4] = {0}; + strcat(tmp_filename_symlink, cache_filename); + strcat(tmp_filename_symlink, ".sym"); + char command[MAX_FILENAME_SIZE + 256]; + size_t len = + snprintf(command, MAX_FILENAME_SIZE + 255, + "cp '%s' '%s'", tmp_filename_symlink, + cache_filename); + if (len > MAX_FILENAME_SIZE + 255 || + symlink(original_filename, tmp_filename_symlink) || + system(command) != 0) { + gr_reporterror_cmd(cmd, + "EBADF: could not copy the " + "image to the cache dir"); + fprintf(stderr, + "Could not copy the image " + "%s (symlink %s) to %s", + sanitized_filename(original_filename), + tmp_filename_symlink, cache_filename); + frame->status = STATUS_UPLOADING_ERROR; + frame->uploading_failure = ERROR_CANNOT_COPY_FILE; + } else { + // Get the file size of the copied file. + frame->status = STATUS_UPLOADING_SUCCESS; + frame->disk_size = st.st_size; + frame->image->total_disk_size += st.st_size; + images_disk_size += frame->disk_size; + if (frame->expected_size && + frame->expected_size != frame->disk_size) { + // The file has unexpected size. + frame->status = STATUS_UPLOADING_ERROR; + frame->uploading_failure = + ERROR_UNEXPECTED_SIZE; + gr_reportuploaderror(frame); + } else { + // Everything seems fine, try to load + // and redraw existing instances. + gr_schedule_image_redraw(frame->image); + frame = gr_loadimage_and_report(frame); + } + } + // Delete the symlink. + unlink(tmp_filename_symlink); + // Delete the original file if it's temporary. + if (cmd->transmission_medium == 't') + gr_delete_tmp_file(original_filename); + } + free(original_filename); + gr_check_limits(); + } else if (cmd->transmission_medium == 'd') { + // Direct transmission (default if 't' is not specified). + frame = gr_get_last_frame(gr_find_image_for_command(cmd)); + if (frame && frame->status == STATUS_UPLOADING) { + // This is a continuation of the previous transmission. + cmd->is_direct_transmission_continuation = 1; + gr_append_data(frame, cmd->payload, cmd->more); + return frame; + } + // If no action is specified, it's not the first transmission + // command. If we couldn't find the image, something went wrong + // and we should just drop this command. + if (cmd->action == 0) + return NULL; + // Otherwise create a new image or frame structure. + frame = gr_new_image_or_frame_from_command(cmd); + if (!frame) + return NULL; + last_image_id = frame->image->image_id; + frame->status = STATUS_UPLOADING; + // Start appending data. + gr_append_data(frame, cmd->payload, cmd->more); + } else { + gr_reporterror_cmd( + cmd, + "EINVAL: transmission medium '%c' is not supported", + cmd->transmission_medium); + return NULL; + } + + return frame; +} + +/// Handles the 'put' command by creating a placement. +static void gr_handle_put_command(GraphicsCommand *cmd) { + if (cmd->image_id == 0 && cmd->image_number == 0) { + gr_reporterror_cmd(cmd, + "EINVAL: neither image id nor image number " + "are specified or both are zero"); + return; + } + + // Find the image with the id or number. + Image *img = gr_find_image_for_command(cmd); + if (!img) { + gr_reporterror_cmd(cmd, "ENOENT: image not found"); + return; + } + + // Create a placement. If a placement with the same id already exists, + // it will be deleted. If the id is zero, a random id will be generated. + ImagePlacement *placement = gr_new_placement(img, cmd->placement_id); + placement->virtual = cmd->virtual; + placement->src_pix_x = cmd->src_pix_x; + placement->src_pix_y = cmd->src_pix_y; + placement->src_pix_width = cmd->src_pix_width; + placement->src_pix_height = cmd->src_pix_height; + placement->cols = cmd->columns; + placement->rows = cmd->rows; + placement->do_not_move_cursor = cmd->do_not_move_cursor; + + if (placement->virtual) { + placement->scale_mode = SCALE_MODE_CONTAIN; + } else if (placement->cols && placement->rows) { + // For classic placements the default is to stretch the image if + // both cols and rows are specified. + placement->scale_mode = SCALE_MODE_FILL; + } else if (placement->cols || placement->rows) { + // But if only one of them is specified, the default is to + // contain. + placement->scale_mode = SCALE_MODE_CONTAIN; + } else { + // If none of them are specified, the default is to use the + // original size. + placement->scale_mode = SCALE_MODE_NONE; + } + + // Display the placement unless it's virtual. + gr_display_nonvirtual_placement(placement); + + // Report success. + gr_reportsuccess_cmd(cmd); +} + +/// Information about what to delete. +typedef struct DeletionData { + uint32_t image_id; + uint32_t placement_id; + /// If true, delete the image object if there are no more placements. + char delete_image_if_no_ref; +} DeletionData; + +/// The callback called for each cell to perform deletion. +static int gr_deletion_callback(void *data, uint32_t image_id, + uint32_t placement_id, int col, + int row, char is_classic) { + DeletionData *del_data = data; + // Leave unicode placeholders alone. + if (!is_classic) + return 0; + if (del_data->image_id && del_data->image_id != image_id) + return 0; + if (del_data->placement_id && del_data->placement_id != placement_id) + return 0; + Image *img = gr_find_image(image_id); + // If the image is already deleted, just erase the placeholder. + if (!img) + return 1; + // Delete the placement. + if (placement_id) + gr_delete_placement(gr_find_placement(img, placement_id)); + // Delete the image if image deletion is requested (uppercase delete + // specifier) and there are no more placements. + if (del_data->delete_image_if_no_ref && kh_size(img->placements) == 0) + gr_delete_image(img); + return 1; +} + +/// Handles the delete command. +static void gr_handle_delete_command(GraphicsCommand *cmd) { + DeletionData del_data = {0}; + del_data.delete_image_if_no_ref = isupper(cmd->delete_specifier) != 0; + char d = tolower(cmd->delete_specifier); + + if (d == 'n') { + d = 'i'; + Image *img = gr_find_image_by_number(cmd->image_number); + if (!img) + return; + del_data.image_id = img->image_id; + } + + if (!d || d == 'a') { + // Delete all visible placements. + gr_for_each_image_cell(gr_deletion_callback, &del_data); + } else if (d == 'i') { + // Delete the specified image by image id and maybe placement + // id. + if (!del_data.image_id) + del_data.image_id = cmd->image_id; + if (!del_data.image_id) { + fprintf(stderr, + "ERROR: image id is not specified in the " + "delete command\n"); + return; + } + del_data.placement_id = cmd->placement_id; + // NOTE: It's not very clear whether we should delete the image + // even if there are no _visible_ placements to delete. We do + // this because otherwise there is no way to delete an image + // with virtual placements in one command. + if (!del_data.placement_id && del_data.delete_image_if_no_ref) + gr_delete_image(gr_find_image(cmd->image_id)); + gr_for_each_image_cell(gr_deletion_callback, &del_data); + } else { + fprintf(stderr, + "WARNING: unsupported value of the d key: '%c'. The " + "command is ignored.\n", + cmd->delete_specifier); + } +} + +static void gr_handle_animation_control_command(GraphicsCommand *cmd) { + if (cmd->image_id == 0 && cmd->image_number == 0) { + gr_reporterror_cmd(cmd, + "EINVAL: neither image id nor image number " + "are specified or both are zero"); + return; + } + + // Find the image with the id or number. + Image *img = gr_find_image_for_command(cmd); + if (!img) { + gr_reporterror_cmd(cmd, "ENOENT: image not found"); + return; + } + + // Find the frame to edit, if requested. + ImageFrame *frame = NULL; + if (cmd->edit_frame) + frame = gr_get_frame(img, cmd->edit_frame); + if (cmd->edit_frame || cmd->gap) { + if (!frame) { + gr_reporterror_cmd(cmd, "ENOENT: frame %d not found", + cmd->edit_frame); + return; + } + if (cmd->gap) { + img->total_duration -= frame->gap; + frame->gap = cmd->gap; + img->total_duration += frame->gap; + } + } + + // Set animation-related parameters of the image. + if (cmd->current_frame) + img->current_frame = cmd->current_frame; + if (cmd->animation_state) { + if (cmd->animation_state == 1) { + img->animation_state = ANIMATION_STATE_STOPPED; + } else if (cmd->animation_state == 2) { + img->animation_state = ANIMATION_STATE_LOADING; + } else if (cmd->animation_state == 3) { + img->animation_state = ANIMATION_STATE_LOOPING; + } else { + gr_reporterror_cmd( + cmd, "EINVAL: invalid animation state: %d", + cmd->animation_state); + } + } + // TODO: Set the number of loops to cmd->loops + + // Make sure we redraw all instances of the image. + gr_schedule_image_redraw(img); +} + +/// Handles a command. +static void gr_handle_command(GraphicsCommand *cmd) { + if (!cmd->image_id && !cmd->image_number) { + // If there is no image id or image number, nobody expects a + // response, so set quiet to 2. + cmd->quiet = 2; + } + ImageFrame *frame = NULL; + switch (cmd->action) { + case 0: + // If no action is specified, it may be a data transmission + // command if 'm=' is specified. + if (cmd->is_data_transmission) { + gr_handle_transmit_command(cmd); + break; + } + gr_reporterror_cmd(cmd, "EINVAL: no action specified"); + break; + case 't': + case 'q': + case 'f': + // Transmit data. 'q' means query, which is basically the same + // as transmit, but the image is discarded, and the id is fake. + // 'f' appends a frame to an existing image. + gr_handle_transmit_command(cmd); + break; + case 'p': + // Display (put) the image. + gr_handle_put_command(cmd); + break; + case 'T': + // Transmit and display. + frame = gr_handle_transmit_command(cmd); + if (frame && !cmd->is_direct_transmission_continuation) { + gr_handle_put_command(cmd); + if (cmd->placement_id) + frame->image->initial_placement_id = + cmd->placement_id; + } + break; + case 'd': + gr_handle_delete_command(cmd); + break; + case 'a': + gr_handle_animation_control_command(cmd); + break; + default: + gr_reporterror_cmd(cmd, "EINVAL: unsupported action: %c", + cmd->action); + return; + } +} + +/// A partially parsed key-value pair. +typedef struct KeyAndValue { + char *key_start; + char *val_start; + unsigned key_len, val_len; +} KeyAndValue; + +/// Parses the value of a key and assigns it to the appropriate field of `cmd`. +static void gr_set_keyvalue(GraphicsCommand *cmd, KeyAndValue *kv) { + char *key_start = kv->key_start; + char *key_end = key_start + kv->key_len; + char *value_start = kv->val_start; + char *value_end = value_start + kv->val_len; + // Currently all keys are one-character. + if (key_end - key_start != 1) { + gr_reporterror_cmd(cmd, "EINVAL: unknown key of length %ld: %s", + key_end - key_start, key_start); + return; + } + long num = 0; + if (*key_start == 'a' || *key_start == 't' || *key_start == 'd' || + *key_start == 'o') { + // Some keys have one-character values. + if (value_end - value_start != 1) { + gr_reporterror_cmd( + cmd, + "EINVAL: value of 'a', 't' or 'd' must be a " + "single char: %s", + key_start); + return; + } + } else { + // All the other keys have integer values. + char *num_end = NULL; + num = strtol(value_start, &num_end, 10); + if (num_end != value_end) { + gr_reporterror_cmd( + cmd, "EINVAL: could not parse number value: %s", + key_start); + return; + } + } + switch (*key_start) { + case 'a': + cmd->action = *value_start; + break; + case 't': + cmd->transmission_medium = *value_start; + break; + case 'd': + cmd->delete_specifier = *value_start; + break; + case 'q': + cmd->quiet = num; + break; + case 'f': + cmd->format = num; + if (num != 0 && num != 24 && num != 32 && num != 100) { + gr_reporterror_cmd( + cmd, + "EINVAL: unsupported format specification: %s", + key_start); + } + break; + case 'o': + cmd->compression = *value_start; + if (cmd->compression != 'z') { + gr_reporterror_cmd(cmd, + "EINVAL: unsupported compression " + "specification: %s", + key_start); + } + break; + case 's': + if (cmd->action == 'a') + cmd->animation_state = num; + else + cmd->frame_pix_width = num; + break; + case 'v': + if (cmd->action == 'a') + cmd->loops = num; + else + cmd->frame_pix_height = num; + break; + case 'i': + cmd->image_id = num; + break; + case 'I': + cmd->image_number = num; + break; + case 'p': + cmd->placement_id = num; + break; + case 'x': + cmd->src_pix_x = num; + cmd->frame_dst_pix_x = num; + break; + case 'y': + if (cmd->action == 'f') + cmd->frame_dst_pix_y = num; + else + cmd->src_pix_y = num; + break; + case 'w': + cmd->src_pix_width = num; + break; + case 'h': + cmd->src_pix_height = num; + break; + case 'c': + if (cmd->action == 'f') + cmd->background_frame = num; + else if (cmd->action == 'a') + cmd->current_frame = num; + else + cmd->columns = num; + break; + case 'r': + if (cmd->action == 'f' || cmd->action == 'a') + cmd->edit_frame = num; + else + cmd->rows = num; + break; + case 'm': + cmd->is_data_transmission = 1; + cmd->more = num; + break; + case 'S': + cmd->size = num; + break; + case 'U': + cmd->virtual = num; + break; + case 'X': + if (cmd->action == 'f') + cmd->replace_instead_of_blending = num; + else + break; /*ignore*/ + break; + case 'Y': + if (cmd->action == 'f') + cmd->background_color = num; + else + break; /*ignore*/ + break; + case 'z': + if (cmd->action == 'f' || cmd->action == 'a') + cmd->gap = num; + else + break; /*ignore*/ + break; + case 'C': + cmd->do_not_move_cursor = num; + break; + default: + gr_reporterror_cmd(cmd, "EINVAL: unsupported key: %s", + key_start); + return; + } +} + +/// Parse and execute a graphics command. `buf` must start with 'G' and contain +/// at least `len + 1` characters. Returns 1 on success. +int gr_parse_command(char *buf, size_t len) { + if (buf[0] != 'G') + return 0; + + memset(&graphics_command_result, 0, sizeof(GraphicsCommandResult)); + + global_command_counter++; + GR_LOG("### Command %lu: %.80s\n", global_command_counter, buf); + + // Eat the 'G'. + ++buf; + --len; + + GraphicsCommand cmd = {.command = buf}; + // The state of parsing. 'k' to parse key, 'v' to parse value, 'p' to + // parse the payload. + char state = 'k'; + // An array of partially parsed key-value pairs. + KeyAndValue key_vals[32]; + unsigned key_vals_count = 0; + char *key_start = buf; + char *key_end = NULL; + char *val_start = NULL; + char *val_end = NULL; + char *c = buf; + while (c - buf < len + 1) { + if (state == 'k') { + switch (*c) { + case ',': + case ';': + case '\0': + state = *c == ',' ? 'k' : 'p'; + key_end = c; + gr_reporterror_cmd( + &cmd, "EINVAL: key without value: %s ", + key_start); + break; + case '=': + key_end = c; + state = 'v'; + val_start = c + 1; + break; + default: + break; + } + } else if (state == 'v') { + switch (*c) { + case ',': + case ';': + case '\0': + state = *c == ',' ? 'k' : 'p'; + val_end = c; + if (key_vals_count >= + sizeof(key_vals) / sizeof(*key_vals)) { + gr_reporterror_cmd(&cmd, + "EINVAL: too many " + "key-value pairs"); + break; + } + key_vals[key_vals_count].key_start = key_start; + key_vals[key_vals_count].val_start = val_start; + key_vals[key_vals_count].key_len = + key_end - key_start; + key_vals[key_vals_count].val_len = + val_end - val_start; + ++key_vals_count; + key_start = c + 1; + break; + default: + break; + } + } else if (state == 'p') { + cmd.payload = c; + // break out of the loop, we don't check the payload + break; + } + ++c; + } + + // Set the action key ('a=') first because we need it to disambiguate + // some keys. Also set 'i=' and 'I=' for better error reporting. + for (unsigned i = 0; i < key_vals_count; ++i) { + if (key_vals[i].key_len == 1) { + char *start = key_vals[i].key_start; + if (*start == 'a' || *start == 'i' || *start == 'I') { + gr_set_keyvalue(&cmd, &key_vals[i]); + break; + } + } + } + // Set the rest of the keys. + for (unsigned i = 0; i < key_vals_count; ++i) + gr_set_keyvalue(&cmd, &key_vals[i]); + + if (!cmd.payload) + cmd.payload = buf + len; + + if (cmd.payload && cmd.payload[0]) + GR_LOG(" payload size: %ld\n", strlen(cmd.payload)); + + if (!graphics_command_result.error) + gr_handle_command(&cmd); + + if (graphics_debug_mode) { + fprintf(stderr, "Response: "); + for (const char *resp = graphics_command_result.response; + *resp != '\0'; ++resp) { + if (isprint(*resp)) + fprintf(stderr, "%c", *resp); + else + fprintf(stderr, "(0x%x)", *resp); + } + fprintf(stderr, "\n"); + } + + // Make sure that we suppress response if needed. Usually cmd.quiet is + // taken into account when creating the response, but it's not very + // reliable in the current implementation. + if (cmd.quiet) { + if (!graphics_command_result.error || cmd.quiet >= 2) + graphics_command_result.response[0] = '\0'; + } + + return 1; +} + +//////////////////////////////////////////////////////////////////////////////// +// base64 decoding part is basically copied from st.c +//////////////////////////////////////////////////////////////////////////////// + +static const char gr_base64_digits[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static char gr_base64_getc(const char **src) { + while (**src && !isprint(**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ +} + +char *gr_base64dec(const char *src, size_t *size) { + size_t in_len = strlen(src); + char *result, *dst; + + result = dst = malloc((in_len + 3) / 4 * 3 + 1); + while (*src) { + int a = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; + int b = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; + int c = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; + int d = gr_base64_digits[(unsigned char)gr_base64_getc(&src)]; + + 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'; + if (size) { + *size = dst - result; + } + return result; +} diff --git a/st/graphics.h b/st/graphics.h new file mode 100755 index 0000000..2e75dea --- /dev/null +++ b/st/graphics.h @@ -0,0 +1,107 @@ + +#include <stdint.h> +#include <sys/types.h> +#include <X11/Xlib.h> + +/// Initialize the graphics module. +void gr_init(Display *disp, Visual *vis, Colormap cm); +/// Deinitialize the graphics module. +void gr_deinit(); + +/// Add an image rectangle to a list if rectangles to draw. This function may +/// actually draw some rectangles, or it may wait till more rectangles are +/// appended. Must be called between `gr_start_drawing` and `gr_finish_drawing`. +/// - `img_start_col..img_end_col` and `img_start_row..img_end_row` define the +/// part of the image to draw (row/col indices are zero-based, ends are +/// excluded). +/// - `x_col` and `y_row` are the coordinates of the top-left corner of the +/// image in the terminal grid. +/// - `x_pix` and `y_pix` are the same but in pixels. +/// - `reverse` indicates whether colors should be inverted. +void gr_append_imagerect(Drawable buf, uint32_t image_id, uint32_t placement_id, + int img_start_col, int img_end_col, int img_start_row, + int img_end_row, int x_col, int y_row, int x_pix, + int y_pix, int cw, int ch, int reverse); +/// Prepare for image drawing. `cw` and `ch` are dimensions of the cell. +void gr_start_drawing(Drawable buf, int cw, int ch); +/// Finish image drawing. This functions will draw all the rectangles left to +/// draw. +void gr_finish_drawing(Drawable buf); +/// Mark rows containing animations as dirty if it's time to redraw them. Must +/// be called right after `gr_start_drawing`. +void gr_mark_dirty_animations(int *dirty, int rows); + +/// Parse and execute a graphics command. `buf` must start with 'G' and contain +/// at least `len + 1` characters (including '\0'). Returns 1 on success. +/// Additional informations is returned through `graphics_command_result`. +int gr_parse_command(char *buf, size_t len); + +/// Executes `command` with the name of the file corresponding to `image_id` as +/// the argument. Executes xmessage with an error message on failure. +void gr_preview_image(uint32_t image_id, const char *command); + +/// Executes `<st> -e less <file>` where <file> is the name of a temporary file +/// containing the information about an image and placement, and <st> is +/// specified with `st_executable`. +void gr_show_image_info(uint32_t image_id, uint32_t placement_id, + uint32_t imgcol, uint32_t imgrow, + char is_classic_placeholder, int32_t diacritic_count, + char *st_executable); + +/// Dumps the internal state (images and placements) to stderr. +void gr_dump_state(); + +/// Unloads images to reduce RAM usage. +void gr_unload_images_to_reduce_ram(); + +/// Executes `callback` for each image cell. `callback` may return 1 to erase +/// the cell or 0 to keep it. This function is implemented in `st.c`. +void gr_for_each_image_cell(int (*callback)(void *data, uint32_t image_id, + uint32_t placement_id, int col, + int row, char is_classic), + void *data); + +/// Marks all the rows containing the image with `image_id` as dirty. +void gr_schedule_image_redraw_by_id(uint32_t image_id); + +typedef enum { + GRAPHICS_DEBUG_NONE = 0, + GRAPHICS_DEBUG_LOG = 1, + GRAPHICS_DEBUG_LOG_AND_BOXES = 2, +} GraphicsDebugMode; + +/// Print additional information, draw bounding bounding boxes, etc. +extern GraphicsDebugMode graphics_debug_mode; + +/// Whether to display images or just draw bounding boxes. +extern char graphics_display_images; + +/// The time in milliseconds until the next redraw to update animations. +/// INT_MAX means no redraw is needed. Populated by `gr_finish_drawing`. +extern int graphics_next_redraw_delay; + +#define MAX_GRAPHICS_RESPONSE_LEN 256 + +/// A structure representing the result of a graphics command. +typedef struct { + /// Indicates if the terminal needs to be redrawn. + char redraw; + /// The response of the command that should be sent back to the client + /// (may be empty if the quiet flag is set). + char response[MAX_GRAPHICS_RESPONSE_LEN]; + /// Whether there was an error executing this command (not very useful, + /// the response must be sent back anyway). + char error; + /// Whether the terminal has to create a placeholder for a non-virtual + /// placement. + char create_placeholder; + /// The placeholder that needs to be created. + struct { + uint32_t rows, columns; + uint32_t image_id, placement_id; + char do_not_move_cursor; + } placeholder; +} GraphicsCommandResult; + +/// The result of a graphics command. +extern GraphicsCommandResult graphics_command_result; diff --git a/st/hb.c b/st/hb.c new file mode 100755 index 0000000..2bb334c --- /dev/null +++ b/st/hb.c @@ -0,0 +1,125 @@ +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <X11/Xft/Xft.h> +#include <X11/cursorfont.h> +#include <hb.h> +#include <hb-ft.h> + +#include "st.h" +#include "hb.h" + +#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END } +#define BUFFER_STEP 256 + +hb_font_t *hbfindfont(XftFont *match); + +typedef struct { + XftFont *match; + hb_font_t *font; +} HbFontMatch; + +typedef struct { + size_t capacity; + HbFontMatch *fonts; +} HbFontCache; + +static HbFontCache hbfontcache = { 0, NULL }; + +typedef struct { + size_t capacity; + Rune *runes; +} RuneBuffer; + +static RuneBuffer hbrunebuffer = { 0, NULL }; + +/* + * Poplulate the array with a list of font features, wrapped in FEATURE macro, + * e. g. + * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') + */ +hb_feature_t features[] = {0}; + +void +hbunloadfonts() +{ + for (int i = 0; i < hbfontcache.capacity; i++) { + hb_font_destroy(hbfontcache.fonts[i].font); + XftUnlockFace(hbfontcache.fonts[i].match); + } + + if (hbfontcache.fonts != NULL) { + free(hbfontcache.fonts); + hbfontcache.fonts = NULL; + } + hbfontcache.capacity = 0; +} + +hb_font_t * +hbfindfont(XftFont *match) +{ + for (int i = 0; i < hbfontcache.capacity; i++) { + if (hbfontcache.fonts[i].match == match) + return hbfontcache.fonts[i].font; + } + + /* Font not found in cache, caching it now. */ + hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMatch) * (hbfontcache.capacity + 1)); + FT_Face face = XftLockFace(match); + hb_font_t *font = hb_ft_font_create(face, NULL); + if (font == NULL) + die("Failed to load Harfbuzz font."); + + hbfontcache.fonts[hbfontcache.capacity].match = match; + hbfontcache.fonts[hbfontcache.capacity].font = font; + hbfontcache.capacity += 1; + + return font; +} + +void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) { + ushort mode = USHRT_MAX; + unsigned int glyph_count; + int rune_idx, glyph_idx, end = start + length; + + hb_font_t *font = hbfindfont(xfont); + if (font == NULL) + return; + + hb_buffer_t *buffer = hb_buffer_create(); + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); + hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); + + /* Resize the buffer if required length is larger. */ + if (hbrunebuffer.capacity < length) { + hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BUFFER_STEP; + hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrunebuffer.capacity * sizeof(Rune)); + } + + /* Fill buffer with codepoints. */ + for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_idx++, rune_idx++) { + hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u; + mode = glyphs[glyph_idx].mode; + if (mode & ATTR_WDUMMY) + hbrunebuffer.runes[rune_idx] = 0x0020; + } + hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length); + + /* Shape the segment. */ + hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); + + /* Get new glyph info. */ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count); + + /* Fill the output. */ + data->buffer = buffer; + data->glyphs = info; + data->positions = pos; + data->count = glyph_count; +} + +void hbcleanup(HbTransformData *data) { + hb_buffer_destroy(data->buffer); + memset(data, 0, sizeof(HbTransformData)); +} diff --git a/st/hb.h b/st/hb.h new file mode 100755 index 0000000..3b0ef44 --- /dev/null +++ b/st/hb.h @@ -0,0 +1,14 @@ +#include <X11/Xft/Xft.h> +#include <hb.h> +#include <hb-ft.h> + +typedef struct { + hb_buffer_t *buffer; + hb_glyph_info_t *glyphs; + hb_glyph_position_t *positions; + unsigned int count; +} HbTransformData; + +void hbunloadfonts(); +void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int); +void hbcleanup(HbTransformData *); diff --git a/st/icat-mini.sh b/st/icat-mini.sh new file mode 100755 index 0000000..cd822f3 --- /dev/null +++ b/st/icat-mini.sh @@ -0,0 +1,800 @@ +#!/bin/sh + +# vim: shiftwidth=4 + +script_name="$(basename "$0")" + +short_help="Usage: $script_name [OPTIONS] <image_file> + +This is a script to display images in the terminal using the kitty graphics +protocol with Unicode placeholders. It is very basic, please use something else +if you have alternatives. + +Options: + -h Show this help. + -s SCALE The scale of the image, may be floating point. + -c N, --cols N The number of columns. + -r N, --rows N The number of rows. + --max-cols N The maximum number of columns. + --max-rows N The maximum number of rows. + --cell-size WxH The cell size in pixels. + -m METHOD The uploading method, may be 'file', 'direct' or 'auto'. + --speed SPEED The multiplier for the animation speed (float). +" + +# Exit the script on keyboard interrupt +trap "echo 'icat-mini was interrupted' >&2; exit 1" INT + +cols="" +rows="" +file="" +tty="/dev/tty" +uploading_method="auto" +cell_size="" +scale=1 +max_cols="" +max_rows="" +speed="" + +# Parse the command line. +while [ $# -gt 0 ]; do + case "$1" in + -c|--columns|--cols) + cols="$2" + shift 2 + ;; + -r|--rows|-l|--lines) + rows="$2" + shift 2 + ;; + -s|--scale) + scale="$2" + shift 2 + ;; + -h|--help) + echo "$short_help" + exit 0 + ;; + -m|--upload-method|--uploading-method) + uploading_method="$2" + shift 2 + ;; + --cell-size) + cell_size="$2" + shift 2 + ;; + --max-cols) + max_cols="$2" + shift 2 + ;; + --max-rows) + max_rows="$2" + shift 2 + ;; + --speed) + speed="$2" + shift 2 + ;; + --) + file="$2" + shift 2 + ;; + -*) + echo "Unknown option: $1" >&2 + exit 1 + ;; + *) + if [ -n "$file" ]; then + echo "Multiple image files are not supported: $file and $1" >&2 + exit 1 + fi + file="$1" + shift + ;; + esac +done + +file="$(realpath "$file")" + +##################################################################### +# Adjust the terminal state +##################################################################### + +stty_orig="$(stty -g < "$tty")" +stty -echo < "$tty" +# Disable ctrl-z. Pressing ctrl-z during image uploading may cause some +# horrible issues otherwise. +stty susp undef < "$tty" +stty -icanon < "$tty" + +restore_echo() { + [ -n "$stty_orig" ] || return + stty $stty_orig < "$tty" +} + +trap restore_echo EXIT TERM + +##################################################################### +# Detect imagemagick +##################################################################### + +# If there is the 'magick' command, use it instead of separate 'convert' and +# 'identify' commands. +if command -v magick > /dev/null; then + identify="magick identify" + convert="magick" +else + identify="identify" + convert="convert" +fi + +##################################################################### +# Detect tmux +##################################################################### + +# Check if we are inside tmux. +inside_tmux="" +if [ -n "$TMUX" ]; then + case "$TERM" in + *tmux*|*screen*) + inside_tmux=1 + ;; + esac +fi + +##################################################################### +# Compute the number of rows and columns +##################################################################### + +is_pos_int() { + if [ -z "$1" ]; then + return 1 # false + fi + if [ -z "$(printf '%s' "$1" | tr -d '[:digit:]')" ]; then + if [ "$1" -gt 0 ]; then + return 0 # true + fi + fi + return 1 # false +} + +if [ -n "$cols" ] || [ -n "$rows" ]; then + if [ -n "$max_cols" ] || [ -n "$max_rows" ]; then + echo "You can't specify both max-cols/rows and cols/rows" >&2 + exit 1 + fi +fi +# Get the max number of cols and rows. +[ -n "$max_cols" ] || max_cols="$(tput cols)" +[ -n "$max_rows" ] || max_rows="$(tput lines)" +if [ "$max_rows" -gt 255 ]; then + max_rows=255 +fi + +python_ioctl_command="import array, fcntl, termios +buf = array.array('H', [0, 0, 0, 0]) +fcntl.ioctl(0, termios.TIOCGWINSZ, buf) +print(int(buf[2]/buf[1]), int(buf[3]/buf[0]))" + +# Get the cell size in pixels if either cols or rows are not specified. +if [ -z "$cols" ] || [ -z "$rows" ]; then + cell_width="" + cell_height="" + # If the cell size is specified, use it. + if [ -n "$cell_size" ]; then + cell_width="${cell_size%x*}" + cell_height="${cell_size#*x}" + if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then + echo "Invalid cell size: $cell_size" >&2 + exit 1 + fi + fi + # Otherwise try to use TIOCGWINSZ ioctl via python. + if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then + cell_size_ioctl="$(python3 -c "$python_ioctl_command" < "$tty" 2> /dev/null)" + cell_width="${cell_size_ioctl% *}" + cell_height="${cell_size_ioctl#* }" + if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then + cell_width="" + cell_height="" + fi + fi + # If it didn't work, try to use csi XTWINOPS. + if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then + if [ -n "$inside_tmux" ]; then + printf '\ePtmux;\e\e[16t\e\\' >> "$tty" + else + printf '\e[16t' >> "$tty" + fi + # The expected response will look like ^[[6;<height>;<width>t + term_response="" + while true; do + char=$(dd bs=1 count=1 <"$tty" 2>/dev/null) + if [ "$char" = "t" ]; then + break + fi + term_response="$term_response$char" + done + cell_height="$(printf '%s' "$term_response" | cut -d ';' -f 2)" + cell_width="$(printf '%s' "$term_response" | cut -d ';' -f 3)" + if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then + cell_width=8 + cell_height=16 + fi + fi +fi + +# Compute a formula with bc and round to the nearest integer. +bc_round() { + LC_NUMERIC=C printf '%.0f' "$(printf '%s\n' "scale=2;($1) + 0.5" | bc)" +} + +# Compute the number of rows and columns of the image. +if [ -z "$cols" ] || [ -z "$rows" ]; then + # Get the size of the image and its resolution. If it's an animation, use + # the first frame. + format_output="$($identify -format '%w %h\n' "$file" | head -1)" + img_width="$(printf '%s' "$format_output" | cut -d ' ' -f 1)" + img_height="$(printf '%s' "$format_output" | cut -d ' ' -f 2)" + if ! is_pos_int "$img_width" || ! is_pos_int "$img_height"; then + echo "Couldn't get image size from identify: $format_output" >&2 + echo >&2 + exit 1 + fi + opt_cols_expr="(${scale}*${img_width}/${cell_width})" + opt_rows_expr="(${scale}*${img_height}/${cell_height})" + if [ -z "$cols" ] && [ -z "$rows" ]; then + # If columns and rows are not specified, compute the optimal values + # using the information about rows and columns per inch. + cols="$(bc_round "$opt_cols_expr")" + rows="$(bc_round "$opt_rows_expr")" + # Make sure that automatically computed rows and columns are within some + # sane limits + if [ "$cols" -gt "$max_cols" ]; then + rows="$(bc_round "$rows * $max_cols / $cols")" + cols="$max_cols" + fi + if [ "$rows" -gt "$max_rows" ]; then + cols="$(bc_round "$cols * $max_rows / $rows")" + rows="$max_rows" + fi + elif [ -z "$cols" ]; then + # If only one dimension is specified, compute the other one to match the + # aspect ratio as close as possible. + cols="$(bc_round "${opt_cols_expr}*${rows}/${opt_rows_expr}")" + elif [ -z "$rows" ]; then + rows="$(bc_round "${opt_rows_expr}*${cols}/${opt_cols_expr}")" + fi + + if [ "$cols" -lt 1 ]; then + cols=1 + fi + if [ "$rows" -lt 1 ]; then + rows=1 + fi +fi + +##################################################################### +# Generate an image id +##################################################################### + +image_id="" +while [ -z "$image_id" ]; do + image_id="$(shuf -i 16777217-4294967295 -n 1)" + # Check that the id requires 24-bit fg colors. + if [ "$(expr \( "$image_id" / 256 \) % 65536)" -eq 0 ]; then + image_id="" + fi +done + +##################################################################### +# Uploading the image +##################################################################### + +# Choose the uploading method +if [ "$uploading_method" = "auto" ]; then + if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] || [ -n "$SSH_CONNECTION" ]; then + uploading_method="direct" + else + uploading_method="file" + fi +fi + +# Functions to emit the start and the end of a graphics command. +if [ -n "$inside_tmux" ]; then + # If we are in tmux we have to wrap the command in Ptmux. + graphics_command_start='\ePtmux;\e\e_G' + graphics_command_end='\e\e\\\e\\' +else + graphics_command_start='\e_G' + graphics_command_end='\e\\' +fi + +start_gr_command() { + printf "$graphics_command_start" >> "$tty" +} +end_gr_command() { + printf "$graphics_command_end" >> "$tty" +} + +# Send a graphics command with the correct start and end +gr_command() { + start_gr_command + printf '%s' "$1" >> "$tty" + end_gr_command +} + +# Send an uploading command. Usage: gr_upload <action> <command> <file> +# Where <action> is a part of command that specifies the action, it will be +# repeated for every chunk (if the method is direct), and <command> is the rest +# of the command that specifies the image parameters. <action> and <command> +# must not include the transmission method or ';'. +# Example: +# gr_upload "a=T,q=2" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file" +gr_upload() { + arg_action="$1" + arg_command="$2" + arg_file="$3" + if [ "$uploading_method" = "file" ]; then + # base64-encode the filename + encoded_filename=$(printf '%s' "$arg_file" | base64 -w0) + gr_command "${arg_action},${arg_command},t=f;${encoded_filename}" + fi + if [ "$uploading_method" = "direct" ]; then + # Create a temporary directory to store the chunked image. + chunkdir="$(mktemp -d)" + if [ ! "$chunkdir" ] || [ ! -d "$chunkdir" ]; then + echo "Can't create a temp dir" >&2 + exit 1 + fi + # base64-encode the file and split it into chunks. The size of each + # graphics command shouldn't be more than 4096, so we set the size of an + # encoded chunk to be 3968, slightly less than that. + chunk_size=3968 + cat "$arg_file" | base64 -w0 | split -b "$chunk_size" - "$chunkdir/chunk_" + + # Issue a command indicating that we want to start data transmission for + # a new image. + gr_command "${arg_action},${arg_command},t=d,m=1" + + # Transmit chunks. + for chunk in "$chunkdir/chunk_"*; do + start_gr_command + printf '%s' "${arg_action},i=${image_id},m=1;" >> "$tty" + cat "$chunk" >> "$tty" + end_gr_command + rm "$chunk" + done + + # Tell the terminal that we are done. + gr_command "${arg_action},i=$image_id,m=0" + + # Remove the temporary directory. + rmdir "$chunkdir" + fi +} + +delayed_frame_dir_cleanup() { + arg_frame_dir="$1" + sleep 2 + if [ -n "$arg_frame_dir" ]; then + for frame in "$arg_frame_dir"/frame_*.png; do + rm "$frame" + done + rmdir "$arg_frame_dir" + fi +} + +upload_image_and_print_placeholder() { + # Check if the file is an animation. + frame_count=$($identify -format '%n\n' "$file" | head -n 1) + if [ "$frame_count" -gt 1 ]; then + # The file is an animation, decompose into frames and upload each frame. + frame_dir="$(mktemp -d)" + frame_dir="$HOME/temp/frames${frame_dir}" + mkdir -p "$frame_dir" + if [ ! "$frame_dir" ] || [ ! -d "$frame_dir" ]; then + echo "Can't create a temp dir for frames" >&2 + exit 1 + fi + + # Decompose the animation into separate frames. + $convert "$file" -coalesce "$frame_dir/frame_%06d.png" + + # Get all frame delays at once, in centiseconds, as a space-separated + # string. + delays=$($identify -format "%T " "$file") + + frame_number=1 + for frame in "$frame_dir"/frame_*.png; do + # Read the delay for the current frame and convert it from + # centiseconds to milliseconds. + delay=$(printf '%s' "$delays" | cut -d ' ' -f "$frame_number") + delay=$((delay * 10)) + # If the delay is 0, set it to 100ms. + if [ "$delay" -eq 0 ]; then + delay=100 + fi + + if [ -n "$speed" ]; then + delay=$(bc_round "$delay / $speed") + fi + + if [ "$frame_number" -eq 1 ]; then + # Upload the first frame with a=T + gr_upload "q=2,a=T" "f=100,U=1,i=${image_id},c=${cols},r=${rows}" "$frame" + # Set the delay for the first frame and also play the animation + # in loading mode (s=2). + gr_command "a=a,v=1,s=2,r=${frame_number},z=${delay},i=${image_id}" + # Print the placeholder after the first frame to reduce the wait + # time. + print_placeholder + else + # Upload subsequent frames with a=f + gr_upload "q=2,a=f" "f=100,i=${image_id},z=${delay}" "$frame" + fi + + frame_number=$((frame_number + 1)) + done + + # Play the animation in loop mode (s=3). + gr_command "a=a,v=1,s=3,i=${image_id}" + + # Remove the temporary directory, but do it in the background with a + # delay to avoid removing files before they are loaded by the terminal. + delayed_frame_dir_cleanup "$frame_dir" 2> /dev/null & + else + # The file is not an animation, upload it directly + gr_upload "q=2,a=T" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file" + # Print the placeholder + print_placeholder + fi +} + +##################################################################### +# Printing the image placeholder +##################################################################### + +print_placeholder() { + # Each line starts with the escape sequence to set the foreground color to + # the image id. + blue="$(expr "$image_id" % 256 )" + green="$(expr \( "$image_id" / 256 \) % 256 )" + red="$(expr \( "$image_id" / 65536 \) % 256 )" + line_start="$(printf "\e[38;2;%d;%d;%dm" "$red" "$green" "$blue")" + line_end="$(printf "\e[39;m")" + + id4th="$(expr \( "$image_id" / 16777216 \) % 256 )" + eval "id_diacritic=\$d${id4th}" + + # Reset the brush state, mostly to reset the underline color. + printf "\e[0m" + + # Fill the output with characters representing the image + for y in $(seq 0 "$(expr "$rows" - 1)"); do + eval "row_diacritic=\$d${y}" + printf '%s' "$line_start" + for x in $(seq 0 "$(expr "$cols" - 1)"); do + eval "col_diacritic=\$d${x}" + # Note that when $x is out of bounds, the column diacritic will + # be empty, meaning that the column should be guessed by the + # terminal. + if [ "$x" -ge "$num_diacritics" ]; then + printf '%s' "${placeholder}${row_diacritic}" + else + printf '%s' "${placeholder}${row_diacritic}${col_diacritic}${id_diacritic}" + fi + done + printf '%s\n' "$line_end" + done + + printf "\e[0m" +} + +d0="̅" +d1="̍" +d2="̎" +d3="̐" +d4="̒" +d5="̽" +d6="̾" +d7="̿" +d8="͆" +d9="͊" +d10="͋" +d11="͌" +d12="͐" +d13="͑" +d14="͒" +d15="͗" +d16="͛" +d17="ͣ" +d18="ͤ" +d19="ͥ" +d20="ͦ" +d21="ͧ" +d22="ͨ" +d23="ͩ" +d24="ͪ" +d25="ͫ" +d26="ͬ" +d27="ͭ" +d28="ͮ" +d29="ͯ" +d30="҃" +d31="҄" +d32="҅" +d33="҆" +d34="҇" +d35="֒" +d36="֓" +d37="֔" +d38="֕" +d39="֗" +d40="֘" +d41="֙" +d42="֜" +d43="֝" +d44="֞" +d45="֟" +d46="֠" +d47="֡" +d48="֨" +d49="֩" +d50="֫" +d51="֬" +d52="֯" +d53="ׄ" +d54="ؐ" +d55="ؑ" +d56="ؒ" +d57="ؓ" +d58="ؔ" +d59="ؕ" +d60="ؖ" +d61="ؗ" +d62="ٗ" +d63="٘" +d64="ٙ" +d65="ٚ" +d66="ٛ" +d67="ٝ" +d68="ٞ" +d69="ۖ" +d70="ۗ" +d71="ۘ" +d72="ۙ" +d73="ۚ" +d74="ۛ" +d75="ۜ" +d76="۟" +d77="۠" +d78="ۡ" +d79="ۢ" +d80="ۤ" +d81="ۧ" +d82="ۨ" +d83="۫" +d84="۬" +d85="ܰ" +d86="ܲ" +d87="ܳ" +d88="ܵ" +d89="ܶ" +d90="ܺ" +d91="ܽ" +d92="ܿ" +d93="݀" +d94="݁" +d95="݃" +d96="݅" +d97="݇" +d98="݉" +d99="݊" +d100="߫" +d101="߬" +d102="߭" +d103="߮" +d104="߯" +d105="߰" +d106="߱" +d107="߳" +d108="ࠖ" +d109="ࠗ" +d110="࠘" +d111="࠙" +d112="ࠛ" +d113="ࠜ" +d114="ࠝ" +d115="ࠞ" +d116="ࠟ" +d117="ࠠ" +d118="ࠡ" +d119="ࠢ" +d120="ࠣ" +d121="ࠥ" +d122="ࠦ" +d123="ࠧ" +d124="ࠩ" +d125="ࠪ" +d126="ࠫ" +d127="ࠬ" +d128="࠭" +d129="॑" +d130="॓" +d131="॔" +d132="ྂ" +d133="ྃ" +d134="྆" +d135="྇" +d136="፝" +d137="፞" +d138="፟" +d139="៝" +d140="᤺" +d141="ᨗ" +d142="᩵" +d143="᩶" +d144="᩷" +d145="᩸" +d146="᩹" +d147="᩺" +d148="᩻" +d149="᩼" +d150="᭫" +d151="᭭" +d152="᭮" +d153="᭯" +d154="᭰" +d155="᭱" +d156="᭲" +d157="᭳" +d158="᳐" +d159="᳑" +d160="᳒" +d161="᳚" +d162="᳛" +d163="᳠" +d164="᷀" +d165="᷁" +d166="᷃" +d167="᷄" +d168="᷅" +d169="᷆" +d170="᷇" +d171="᷈" +d172="᷉" +d173="᷋" +d174="᷌" +d175="᷑" +d176="᷒" +d177="ᷓ" +d178="ᷔ" +d179="ᷕ" +d180="ᷖ" +d181="ᷗ" +d182="ᷘ" +d183="ᷙ" +d184="ᷚ" +d185="ᷛ" +d186="ᷜ" +d187="ᷝ" +d188="ᷞ" +d189="ᷟ" +d190="ᷠ" +d191="ᷡ" +d192="ᷢ" +d193="ᷣ" +d194="ᷤ" +d195="ᷥ" +d196="ᷦ" +d197="᷾" +d198="⃐" +d199="⃑" +d200="⃔" +d201="⃕" +d202="⃖" +d203="⃗" +d204="⃛" +d205="⃜" +d206="⃡" +d207="⃧" +d208="⃩" +d209="⃰" +d210="⳯" +d211="⳰" +d212="⳱" +d213="ⷠ" +d214="ⷡ" +d215="ⷢ" +d216="ⷣ" +d217="ⷤ" +d218="ⷥ" +d219="ⷦ" +d220="ⷧ" +d221="ⷨ" +d222="ⷩ" +d223="ⷪ" +d224="ⷫ" +d225="ⷬ" +d226="ⷭ" +d227="ⷮ" +d228="ⷯ" +d229="ⷰ" +d230="ⷱ" +d231="ⷲ" +d232="ⷳ" +d233="ⷴ" +d234="ⷵ" +d235="ⷶ" +d236="ⷷ" +d237="ⷸ" +d238="ⷹ" +d239="ⷺ" +d240="ⷻ" +d241="ⷼ" +d242="ⷽ" +d243="ⷾ" +d244="ⷿ" +d245="꙯" +d246="꙼" +d247="꙽" +d248="꛰" +d249="꛱" +d250="꣠" +d251="꣡" +d252="꣢" +d253="꣣" +d254="꣤" +d255="꣥" +d256="꣦" +d257="꣧" +d258="꣨" +d259="꣩" +d260="꣪" +d261="꣫" +d262="꣬" +d263="꣭" +d264="꣮" +d265="꣯" +d266="꣰" +d267="꣱" +d268="ꪰ" +d269="ꪲ" +d270="ꪳ" +d271="ꪷ" +d272="ꪸ" +d273="ꪾ" +d274="꪿" +d275="꫁" +d276="︠" +d277="︡" +d278="︢" +d279="︣" +d280="︤" +d281="︥" +d282="︦" +d283="𐨏" +d284="𐨸" +d285="𝆅" +d286="𝆆" +d287="𝆇" +d288="𝆈" +d289="𝆉" +d290="𝆪" +d291="𝆫" +d292="𝆬" +d293="𝆭" +d294="𝉂" +d295="𝉃" +d296="𝉄" + +num_diacritics="297" + +placeholder="􎻮" + +##################################################################### +# Upload the image and print the placeholder +##################################################################### + +upload_image_and_print_placeholder diff --git a/st/khash.h b/st/khash.h new file mode 100755 index 0000000..f75f347 --- /dev/null +++ b/st/khash.h @@ -0,0 +1,627 @@ +/* The MIT License + + Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk> + + 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. +*/ + +/* + An example: + +#include "khash.h" +KHASH_MAP_INIT_INT(32, char) +int main() { + int ret, is_missing; + khiter_t k; + khash_t(32) *h = kh_init(32); + k = kh_put(32, h, 5, &ret); + kh_value(h, k) = 10; + k = kh_get(32, h, 10); + is_missing = (k == kh_end(h)); + k = kh_get(32, h, 5); + kh_del(32, h, k); + for (k = kh_begin(h); k != kh_end(h); ++k) + if (kh_exist(h, k)) kh_value(h, k) = 1; + kh_destroy(32, h); + return 0; +} +*/ + +/* + 2013-05-02 (0.2.8): + + * Use quadratic probing. When the capacity is power of 2, stepping function + i*(i+1)/2 guarantees to traverse each bucket. It is better than double + hashing on cache performance and is more robust than linear probing. + + In theory, double hashing should be more robust than quadratic probing. + However, my implementation is probably not for large hash tables, because + the second hash function is closely tied to the first hash function, + which reduce the effectiveness of double hashing. + + Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php + + 2011-12-29 (0.2.7): + + * Minor code clean up; no actual effect. + + 2011-09-16 (0.2.6): + + * The capacity is a power of 2. This seems to dramatically improve the + speed for simple keys. Thank Zilong Tan for the suggestion. Reference: + + - http://code.google.com/p/ulib/ + - http://nothings.org/computer/judy/ + + * Allow to optionally use linear probing which usually has better + performance for random input. Double hashing is still the default as it + is more robust to certain non-random input. + + * Added Wang's integer hash function (not used by default). This hash + function is more robust to certain non-random input. + + 2011-02-14 (0.2.5): + + * Allow to declare global functions. + + 2009-09-26 (0.2.4): + + * Improve portability + + 2008-09-19 (0.2.3): + + * Corrected the example + * Improved interfaces + + 2008-09-11 (0.2.2): + + * Improved speed a little in kh_put() + + 2008-09-10 (0.2.1): + + * Added kh_clear() + * Fixed a compiling error + + 2008-09-02 (0.2.0): + + * Changed to token concatenation which increases flexibility. + + 2008-08-31 (0.1.2): + + * Fixed a bug in kh_get(), which has not been tested previously. + + 2008-08-31 (0.1.1): + + * Added destructor +*/ + + +#ifndef __AC_KHASH_H +#define __AC_KHASH_H + +/*! + @header + + Generic hash table library. + */ + +#define AC_VERSION_KHASH_H "0.2.8" + +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +/* compiler specific configuration */ + +#if UINT_MAX == 0xffffffffu +typedef unsigned int khint32_t; +#elif ULONG_MAX == 0xffffffffu +typedef unsigned long khint32_t; +#endif + +#if ULONG_MAX == ULLONG_MAX +typedef unsigned long khint64_t; +#else +typedef unsigned long long khint64_t; +#endif + +#ifndef kh_inline +#ifdef _MSC_VER +#define kh_inline __inline +#else +#define kh_inline inline +#endif +#endif /* kh_inline */ + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +typedef khint32_t khint_t; +typedef khint_t khiter_t; + +#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) +#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) +#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) +#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) +#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) +#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) +#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) + +#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) + +#ifndef kroundup32 +#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) +#endif + +#ifndef kcalloc +#define kcalloc(N,Z) calloc(N,Z) +#endif +#ifndef kmalloc +#define kmalloc(Z) malloc(Z) +#endif +#ifndef krealloc +#define krealloc(P,Z) realloc(P,Z) +#endif +#ifndef kfree +#define kfree(P) free(P) +#endif + +static const double __ac_HASH_UPPER = 0.77; + +#define __KHASH_TYPE(name, khkey_t, khval_t) \ + typedef struct kh_##name##_s { \ + khint_t n_buckets, size, n_occupied, upper_bound; \ + khint32_t *flags; \ + khkey_t *keys; \ + khval_t *vals; \ + } kh_##name##_t; + +#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ + extern kh_##name##_t *kh_init_##name(void); \ + extern void kh_destroy_##name(kh_##name##_t *h); \ + extern void kh_clear_##name(kh_##name##_t *h); \ + extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ + extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ + extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ + extern void kh_del_##name(kh_##name##_t *h, khint_t x); + +#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + SCOPE kh_##name##_t *kh_init_##name(void) { \ + return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \ + } \ + SCOPE void kh_destroy_##name(kh_##name##_t *h) \ + { \ + if (h) { \ + kfree((void *)h->keys); kfree(h->flags); \ + kfree((void *)h->vals); \ + kfree(h); \ + } \ + } \ + SCOPE void kh_clear_##name(kh_##name##_t *h) \ + { \ + if (h && h->flags) { \ + memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ + h->size = h->n_occupied = 0; \ + } \ + } \ + SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ + { \ + if (h->n_buckets) { \ + khint_t k, i, last, mask, step = 0; \ + mask = h->n_buckets - 1; \ + k = __hash_func(key); i = k & mask; \ + last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + i = (i + (++step)) & mask; \ + if (i == last) return h->n_buckets; \ + } \ + return __ac_iseither(h->flags, i)? h->n_buckets : i; \ + } else return 0; \ + } \ + SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ + { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ + khint32_t *new_flags = 0; \ + khint_t j = 1; \ + { \ + kroundup32(new_n_buckets); \ + if (new_n_buckets < 4) new_n_buckets = 4; \ + if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ + else { /* hash table size to be changed (shrink or expand); rehash */ \ + new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (!new_flags) return -1; \ + memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (h->n_buckets < new_n_buckets) { /* expand */ \ + khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + if (!new_keys) { kfree(new_flags); return -1; } \ + h->keys = new_keys; \ + if (kh_is_map) { \ + khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ + if (!new_vals) { kfree(new_flags); return -1; } \ + h->vals = new_vals; \ + } \ + } /* otherwise shrink */ \ + } \ + } \ + if (j) { /* rehashing is needed */ \ + for (j = 0; j != h->n_buckets; ++j) { \ + if (__ac_iseither(h->flags, j) == 0) { \ + khkey_t key = h->keys[j]; \ + khval_t val; \ + khint_t new_mask; \ + new_mask = new_n_buckets - 1; \ + if (kh_is_map) val = h->vals[j]; \ + __ac_set_isdel_true(h->flags, j); \ + while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ + khint_t k, i, step = 0; \ + k = __hash_func(key); \ + i = k & new_mask; \ + while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \ + __ac_set_isempty_false(new_flags, i); \ + if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ + { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ + if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ + __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ + } else { /* write the element and jump out of the loop */ \ + h->keys[i] = key; \ + if (kh_is_map) h->vals[i] = val; \ + break; \ + } \ + } \ + } \ + } \ + if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ + h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ + } \ + kfree(h->flags); /* free the working space */ \ + h->flags = new_flags; \ + h->n_buckets = new_n_buckets; \ + h->n_occupied = h->size; \ + h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ + } \ + return 0; \ + } \ + SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ + { \ + khint_t x; \ + if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ + if (h->n_buckets > (h->size<<1)) { \ + if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \ + *ret = -1; return h->n_buckets; \ + } \ + } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \ + *ret = -1; return h->n_buckets; \ + } \ + } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ + { \ + khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ + x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ + if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ + else { \ + last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + if (__ac_isdel(h->flags, i)) site = i; \ + i = (i + (++step)) & mask; \ + if (i == last) { x = site; break; } \ + } \ + if (x == h->n_buckets) { \ + if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ + else x = i; \ + } \ + } \ + } \ + if (__ac_isempty(h->flags, x)) { /* not present at all */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; ++h->n_occupied; \ + *ret = 1; \ + } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; \ + *ret = 2; \ + } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ + return x; \ + } \ + SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ + { \ + if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ + __ac_set_isdel_true(h->flags, x); \ + --h->size; \ + } \ + } + +#define KHASH_DECLARE(name, khkey_t, khval_t) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_PROTOTYPES(name, khkey_t, khval_t) + +#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +/* --- BEGIN OF HASH FUNCTIONS --- */ + +/*! @function + @abstract Integer hash function + @param key The integer [khint32_t] + @return The hash value [khint_t] + */ +#define kh_int_hash_func(key) (khint32_t)(key) +/*! @function + @abstract Integer comparison function + */ +#define kh_int_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract 64-bit integer hash function + @param key The integer [khint64_t] + @return The hash value [khint_t] + */ +#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) +/*! @function + @abstract 64-bit integer comparison function + */ +#define kh_int64_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract const char* hash function + @param s Pointer to a null terminated string + @return The hash value + */ +static kh_inline khint_t __ac_X31_hash_string(const char *s) +{ + khint_t h = (khint_t)*s; + if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; + return h; +} +/*! @function + @abstract Another interface to const char* hash function + @param key Pointer to a null terminated string [const char*] + @return The hash value [khint_t] + */ +#define kh_str_hash_func(key) __ac_X31_hash_string(key) +/*! @function + @abstract Const char* comparison function + */ +#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) + +static kh_inline khint_t __ac_Wang_hash(khint_t key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} +#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key) + +/* --- END OF HASH FUNCTIONS --- */ + +/* Other convenient macros... */ + +/*! + @abstract Type of the hash table. + @param name Name of the hash table [symbol] + */ +#define khash_t(name) kh_##name##_t + +/*! @function + @abstract Initiate a hash table. + @param name Name of the hash table [symbol] + @return Pointer to the hash table [khash_t(name)*] + */ +#define kh_init(name) kh_init_##name() + +/*! @function + @abstract Destroy a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_destroy(name, h) kh_destroy_##name(h) + +/*! @function + @abstract Reset a hash table without deallocating memory. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_clear(name, h) kh_clear_##name(h) + +/*! @function + @abstract Resize a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param s New size [khint_t] + */ +#define kh_resize(name, h, s) kh_resize_##name(h, s) + +/*! @function + @abstract Insert a key to the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @param r Extra return code: -1 if the operation failed; + 0 if the key is present in the hash table; + 1 if the bucket is empty (never used); 2 if the element in + the bucket has been deleted [int*] + @return Iterator to the inserted element [khint_t] + */ +#define kh_put(name, h, k, r) kh_put_##name(h, k, r) + +/*! @function + @abstract Retrieve a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] + */ +#define kh_get(name, h, k) kh_get_##name(h, k) + +/*! @function + @abstract Remove a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Iterator to the element to be deleted [khint_t] + */ +#define kh_del(name, h, k) kh_del_##name(h, k) + +/*! @function + @abstract Test whether a bucket contains data. + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return 1 if containing data; 0 otherwise [int] + */ +#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) + +/*! @function + @abstract Get key given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Key [type of keys] + */ +#define kh_key(h, x) ((h)->keys[x]) + +/*! @function + @abstract Get value given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Value [type of values] + @discussion For hash sets, calling this results in segfault. + */ +#define kh_val(h, x) ((h)->vals[x]) + +/*! @function + @abstract Alias of kh_val() + */ +#define kh_value(h, x) ((h)->vals[x]) + +/*! @function + @abstract Get the start iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The start iterator [khint_t] + */ +#define kh_begin(h) (khint_t)(0) + +/*! @function + @abstract Get the end iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The end iterator [khint_t] + */ +#define kh_end(h) ((h)->n_buckets) + +/*! @function + @abstract Get the number of elements in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of elements in the hash table [khint_t] + */ +#define kh_size(h) ((h)->size) + +/*! @function + @abstract Get the number of buckets in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of buckets in the hash table [khint_t] + */ +#define kh_n_buckets(h) ((h)->n_buckets) + +/*! @function + @abstract Iterate over the entries in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param kvar Variable to which key will be assigned + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h,__i)) continue; \ + (kvar) = kh_key(h,__i); \ + (vvar) = kh_val(h,__i); \ + code; \ + } } + +/*! @function + @abstract Iterate over the values in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach_value(h, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h,__i)) continue; \ + (vvar) = kh_val(h,__i); \ + code; \ + } } + +/* More convenient interfaces */ + +/*! @function + @abstract Instantiate a hash set containing integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT(name) \ + KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT(name, khval_t) \ + KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash set containing 64-bit integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT64(name) \ + KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing 64-bit integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT64(name, khval_t) \ + KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) + +typedef const char *kh_cstr_t; +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_STR(name) \ + KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_STR(name, khval_t) \ + KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) + +#endif /* __AC_KHASH_H */ diff --git a/st/kvec.h b/st/kvec.h new file mode 100755 index 0000000..10f1c5b --- /dev/null +++ b/st/kvec.h @@ -0,0 +1,90 @@ +/* The MIT License + + Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk> + + 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. +*/ + +/* + An example: + +#include "kvec.h" +int main() { + kvec_t(int) array; + kv_init(array); + kv_push(int, array, 10); // append + kv_a(int, array, 20) = 5; // dynamic + kv_A(array, 20) = 4; // static + kv_destroy(array); + return 0; +} +*/ + +/* + 2008-09-22 (0.1.0): + + * The initial version. + +*/ + +#ifndef AC_KVEC_H +#define AC_KVEC_H + +#include <stdlib.h> + +#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) + +#define kvec_t(type) struct { size_t n, m; type *a; } +#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) +#define kv_destroy(v) free((v).a) +#define kv_A(v, i) ((v).a[(i)]) +#define kv_pop(v) ((v).a[--(v).n]) +#define kv_size(v) ((v).n) +#define kv_max(v) ((v).m) + +#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m)) + +#define kv_copy(type, v1, v0) do { \ + if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ + (v1).n = (v0).n; \ + memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ + } while (0) \ + +#define kv_push(type, v, x) do { \ + if ((v).n == (v).m) { \ + (v).m = (v).m? (v).m<<1 : 2; \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ + } \ + (v).a[(v).n++] = (x); \ + } while (0) + +#define kv_pushp(type, v) ((((v).n == (v).m)? \ + ((v).m = ((v).m? (v).m<<1 : 2), \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ + : 0), ((v).a + ((v).n++))) + +#define kv_a(type, v, i) (((v).m <= (size_t)(i)? \ + ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ + : (v).n <= (size_t)(i)? (v).n = (i) + 1 \ + : 0), (v).a[(i)]) + +#endif diff --git a/st/rowcolumn_diacritics_helpers.c b/st/rowcolumn_diacritics_helpers.c new file mode 100755 index 0000000..829c0fc --- /dev/null +++ b/st/rowcolumn_diacritics_helpers.c @@ -0,0 +1,391 @@ +#include <stdint.h> + +uint16_t diacritic_to_num(uint32_t code) +{ + switch (code) { + case 0x305: + return code - 0x305 + 1; + case 0x30d: + case 0x30e: + return code - 0x30d + 2; + case 0x310: + return code - 0x310 + 4; + case 0x312: + return code - 0x312 + 5; + case 0x33d: + case 0x33e: + case 0x33f: + return code - 0x33d + 6; + case 0x346: + return code - 0x346 + 9; + case 0x34a: + case 0x34b: + case 0x34c: + return code - 0x34a + 10; + case 0x350: + case 0x351: + case 0x352: + return code - 0x350 + 13; + case 0x357: + return code - 0x357 + 16; + case 0x35b: + return code - 0x35b + 17; + case 0x363: + case 0x364: + case 0x365: + case 0x366: + case 0x367: + case 0x368: + case 0x369: + case 0x36a: + case 0x36b: + case 0x36c: + case 0x36d: + case 0x36e: + case 0x36f: + return code - 0x363 + 18; + case 0x483: + case 0x484: + case 0x485: + case 0x486: + case 0x487: + return code - 0x483 + 31; + case 0x592: + case 0x593: + case 0x594: + case 0x595: + return code - 0x592 + 36; + case 0x597: + case 0x598: + case 0x599: + return code - 0x597 + 40; + case 0x59c: + case 0x59d: + case 0x59e: + case 0x59f: + case 0x5a0: + case 0x5a1: + return code - 0x59c + 43; + case 0x5a8: + case 0x5a9: + return code - 0x5a8 + 49; + case 0x5ab: + case 0x5ac: + return code - 0x5ab + 51; + case 0x5af: + return code - 0x5af + 53; + case 0x5c4: + return code - 0x5c4 + 54; + case 0x610: + case 0x611: + case 0x612: + case 0x613: + case 0x614: + case 0x615: + case 0x616: + case 0x617: + return code - 0x610 + 55; + case 0x657: + case 0x658: + case 0x659: + case 0x65a: + case 0x65b: + return code - 0x657 + 63; + case 0x65d: + case 0x65e: + return code - 0x65d + 68; + case 0x6d6: + case 0x6d7: + case 0x6d8: + case 0x6d9: + case 0x6da: + case 0x6db: + case 0x6dc: + return code - 0x6d6 + 70; + case 0x6df: + case 0x6e0: + case 0x6e1: + case 0x6e2: + return code - 0x6df + 77; + case 0x6e4: + return code - 0x6e4 + 81; + case 0x6e7: + case 0x6e8: + return code - 0x6e7 + 82; + case 0x6eb: + case 0x6ec: + return code - 0x6eb + 84; + case 0x730: + return code - 0x730 + 86; + case 0x732: + case 0x733: + return code - 0x732 + 87; + case 0x735: + case 0x736: + return code - 0x735 + 89; + case 0x73a: + return code - 0x73a + 91; + case 0x73d: + return code - 0x73d + 92; + case 0x73f: + case 0x740: + case 0x741: + return code - 0x73f + 93; + case 0x743: + return code - 0x743 + 96; + case 0x745: + return code - 0x745 + 97; + case 0x747: + return code - 0x747 + 98; + case 0x749: + case 0x74a: + return code - 0x749 + 99; + case 0x7eb: + case 0x7ec: + case 0x7ed: + case 0x7ee: + case 0x7ef: + case 0x7f0: + case 0x7f1: + return code - 0x7eb + 101; + case 0x7f3: + return code - 0x7f3 + 108; + case 0x816: + case 0x817: + case 0x818: + case 0x819: + return code - 0x816 + 109; + case 0x81b: + case 0x81c: + case 0x81d: + case 0x81e: + case 0x81f: + case 0x820: + case 0x821: + case 0x822: + case 0x823: + return code - 0x81b + 113; + case 0x825: + case 0x826: + case 0x827: + return code - 0x825 + 122; + case 0x829: + case 0x82a: + case 0x82b: + case 0x82c: + case 0x82d: + return code - 0x829 + 125; + case 0x951: + return code - 0x951 + 130; + case 0x953: + case 0x954: + return code - 0x953 + 131; + case 0xf82: + case 0xf83: + return code - 0xf82 + 133; + case 0xf86: + case 0xf87: + return code - 0xf86 + 135; + case 0x135d: + case 0x135e: + case 0x135f: + return code - 0x135d + 137; + case 0x17dd: + return code - 0x17dd + 140; + case 0x193a: + return code - 0x193a + 141; + case 0x1a17: + return code - 0x1a17 + 142; + case 0x1a75: + case 0x1a76: + case 0x1a77: + case 0x1a78: + case 0x1a79: + case 0x1a7a: + case 0x1a7b: + case 0x1a7c: + return code - 0x1a75 + 143; + case 0x1b6b: + return code - 0x1b6b + 151; + case 0x1b6d: + case 0x1b6e: + case 0x1b6f: + case 0x1b70: + case 0x1b71: + case 0x1b72: + case 0x1b73: + return code - 0x1b6d + 152; + case 0x1cd0: + case 0x1cd1: + case 0x1cd2: + return code - 0x1cd0 + 159; + case 0x1cda: + case 0x1cdb: + return code - 0x1cda + 162; + case 0x1ce0: + return code - 0x1ce0 + 164; + case 0x1dc0: + case 0x1dc1: + return code - 0x1dc0 + 165; + case 0x1dc3: + case 0x1dc4: + case 0x1dc5: + case 0x1dc6: + case 0x1dc7: + case 0x1dc8: + case 0x1dc9: + return code - 0x1dc3 + 167; + case 0x1dcb: + case 0x1dcc: + return code - 0x1dcb + 174; + case 0x1dd1: + case 0x1dd2: + case 0x1dd3: + case 0x1dd4: + case 0x1dd5: + case 0x1dd6: + case 0x1dd7: + case 0x1dd8: + case 0x1dd9: + case 0x1dda: + case 0x1ddb: + case 0x1ddc: + case 0x1ddd: + case 0x1dde: + case 0x1ddf: + case 0x1de0: + case 0x1de1: + case 0x1de2: + case 0x1de3: + case 0x1de4: + case 0x1de5: + case 0x1de6: + return code - 0x1dd1 + 176; + case 0x1dfe: + return code - 0x1dfe + 198; + case 0x20d0: + case 0x20d1: + return code - 0x20d0 + 199; + case 0x20d4: + case 0x20d5: + case 0x20d6: + case 0x20d7: + return code - 0x20d4 + 201; + case 0x20db: + case 0x20dc: + return code - 0x20db + 205; + case 0x20e1: + return code - 0x20e1 + 207; + case 0x20e7: + return code - 0x20e7 + 208; + case 0x20e9: + return code - 0x20e9 + 209; + case 0x20f0: + return code - 0x20f0 + 210; + case 0x2cef: + case 0x2cf0: + case 0x2cf1: + return code - 0x2cef + 211; + case 0x2de0: + case 0x2de1: + case 0x2de2: + case 0x2de3: + case 0x2de4: + case 0x2de5: + case 0x2de6: + case 0x2de7: + case 0x2de8: + case 0x2de9: + case 0x2dea: + case 0x2deb: + case 0x2dec: + case 0x2ded: + case 0x2dee: + case 0x2def: + case 0x2df0: + case 0x2df1: + case 0x2df2: + case 0x2df3: + case 0x2df4: + case 0x2df5: + case 0x2df6: + case 0x2df7: + case 0x2df8: + case 0x2df9: + case 0x2dfa: + case 0x2dfb: + case 0x2dfc: + case 0x2dfd: + case 0x2dfe: + case 0x2dff: + return code - 0x2de0 + 214; + case 0xa66f: + return code - 0xa66f + 246; + case 0xa67c: + case 0xa67d: + return code - 0xa67c + 247; + case 0xa6f0: + case 0xa6f1: + return code - 0xa6f0 + 249; + case 0xa8e0: + case 0xa8e1: + case 0xa8e2: + case 0xa8e3: + case 0xa8e4: + case 0xa8e5: + case 0xa8e6: + case 0xa8e7: + case 0xa8e8: + case 0xa8e9: + case 0xa8ea: + case 0xa8eb: + case 0xa8ec: + case 0xa8ed: + case 0xa8ee: + case 0xa8ef: + case 0xa8f0: + case 0xa8f1: + return code - 0xa8e0 + 251; + case 0xaab0: + return code - 0xaab0 + 269; + case 0xaab2: + case 0xaab3: + return code - 0xaab2 + 270; + case 0xaab7: + case 0xaab8: + return code - 0xaab7 + 272; + case 0xaabe: + case 0xaabf: + return code - 0xaabe + 274; + case 0xaac1: + return code - 0xaac1 + 276; + case 0xfe20: + case 0xfe21: + case 0xfe22: + case 0xfe23: + case 0xfe24: + case 0xfe25: + case 0xfe26: + return code - 0xfe20 + 277; + case 0x10a0f: + return code - 0x10a0f + 284; + case 0x10a38: + return code - 0x10a38 + 285; + case 0x1d185: + case 0x1d186: + case 0x1d187: + case 0x1d188: + case 0x1d189: + return code - 0x1d185 + 286; + case 0x1d1aa: + case 0x1d1ab: + case 0x1d1ac: + case 0x1d1ad: + return code - 0x1d1aa + 291; + case 0x1d242: + case 0x1d243: + case 0x1d244: + return code - 0x1d242 + 295; + } + return 0; +} diff --git a/st/st-alpha-changealpha-20230519-b44f2ad.diff b/st/st-alpha-changealpha-20230519-b44f2ad.diff new file mode 100755 index 0000000..9d8bf6e --- /dev/null +++ b/st/st-alpha-changealpha-20230519-b44f2ad.diff @@ -0,0 +1,194 @@ +diff --git a/st/config.def.h b/st_patched/config.def.h +index 91ab8ca..59fc2a9 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -93,6 +93,10 @@ char *termname = "st-256color"; + */ + unsigned int tabspaces = 8; + ++/* bg opacity */ ++float alpha = 0.8; ++float alpha_def; ++ + /* Terminal colors (16 first used in escape sequence) */ + static const char *colorname[] = { + /* 8 normal colors */ +@@ -201,6 +205,9 @@ static Shortcut shortcuts[] = { + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, ++ { MODKEY, XK_bracketleft, chgalpha, {.f = -1} }, /* Decrease opacity */ ++ { MODKEY|ShiftMask, XK_braceright, chgalpha, {.f = +1} }, /* Increase opacity */ ++ { MODKEY, XK_bracketright,chgalpha, {.f = 0} }, /* Reset opacity */ + }; + + /* +diff --git a/st/st.h b/st_patched/st.h +index fd3b0d8..cda8c13 100644 +--- a/st.h ++++ b/st.h +@@ -124,3 +124,4 @@ extern unsigned int tabspaces; + extern unsigned int defaultfg; + extern unsigned int defaultbg; + extern unsigned int defaultcs; ++extern float alpha, alpha_def; +diff --git a/st/config.mk b/st_patched/config.mk +index 1e306f8..47c615e 100644 +--- a/config.mk ++++ b/config.mk +@@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config + INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` +-LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ ++LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` + +diff --git a/st/x.c b/st_patched/x.c +index aa09997..3b05a55 100644 +--- a/x.c ++++ b/x.c +@@ -59,6 +59,7 @@ static void zoom(const Arg *); + static void zoomabs(const Arg *); + static void zoomreset(const Arg *); + static void ttysend(const Arg *); ++static void chgalpha(const Arg *); + + /* config.h for applying patches and the configuration. */ + #include "config.h" +@@ -105,6 +106,7 @@ typedef struct { + XSetWindowAttributes attrs; + int scr; + int isfixed; /* is fixed geometry? */ ++ int depth; /* bit depth */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ + } XWindow; +@@ -243,6 +245,7 @@ static char *usedfont = NULL; + static double usedfontsize = 0; + static double defaultfontsize = 0; + ++static char *opt_alpha = NULL; + static char *opt_class = NULL; + static char **opt_cmd = NULL; + static char *opt_embed = NULL; +@@ -752,7 +755,7 @@ xresize(int col, int row) + + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); ++ xw.depth); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + +@@ -812,6 +815,13 @@ xloadcols(void) + else + die("could not allocate color %d\n", i); + } ++ ++ /* set alpha value of bg color */ ++ if (opt_alpha) ++ alpha = strtof(opt_alpha, NULL); ++ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); ++ dc.col[defaultbg].pixel &= 0x00FFFFFF; ++ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + loaded = 1; + } + +@@ -1134,11 +1144,23 @@ xinit(int cols, int rows) + Window parent; + pid_t thispid = getpid(); + XColor xmousefg, xmousebg; ++ XWindowAttributes attr; ++ XVisualInfo vis; + + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); +- xw.vis = XDefaultVisual(xw.dpy, xw.scr); ++ ++ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { ++ parent = XRootWindow(xw.dpy, xw.scr); ++ xw.depth = 32; ++ } else { ++ XGetWindowAttributes(xw.dpy, parent, &attr); ++ xw.depth = attr.depth; ++ } ++ ++ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); ++ xw.vis = vis.visual; + + /* font */ + if (!FcInit()) +@@ -1147,8 +1169,11 @@ xinit(int cols, int rows) + usedfont = (opt_font == NULL)? font : opt_font; + xloadfonts(usedfont, 0); + ++ /* Backup default alpha value */ ++ alpha_def = alpha; ++ + /* colors */ +- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); ++ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); + xloadcols(); + + /* adjust fixed window geometry */ +@@ -1168,19 +1193,15 @@ xinit(int cols, int rows) + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + xw.attrs.colormap = xw.cmap; + +- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) +- parent = XRootWindow(xw.dpy, xw.scr); + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, +- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, ++ win.w, win.h, 0, xw.depth, InputOutput, + xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity + | CWEventMask | CWColormap, &xw.attrs); + + memset(&gcvalues, 0, sizeof(gcvalues)); + 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 = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); ++ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + +@@ -1371,6 +1392,24 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x + return numspecs; + } + ++void ++chgalpha(const Arg *arg) ++{ ++ if (arg->f == -1.0f && alpha >= 0.1f) ++ alpha -= 0.1f; ++ else if (arg->f == 1.0f && alpha < 1.0f) ++ alpha += 0.1f; ++ else if (arg->f == 0.0f) ++ alpha = alpha_def; ++ else ++ return; ++ ++ dc.col[defaultbg].color.alpha = (unsigned short)(0xFFFF * alpha); ++ /* Required to remove artifacting from borderpx */ ++ cresize(0, 0); ++ redraw(); ++} ++ + void + xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) + { +@@ -2038,6 +2077,9 @@ main(int argc, char *argv[]) + case 'a': + allowaltscreen = 0; + break; ++ case 'A': ++ opt_alpha = EARGF(usage()); ++ break; + case 'c': + opt_class = EARGF(usage()); + break; diff --git a/st/st.1 b/st/st.1 new file mode 100755 index 0000000..ef8c956 --- /dev/null +++ b/st/st.1 @@ -0,0 +1,177 @@ +.TH ST 1 st\-VERSION +.SH NAME +st \- simple terminal (bread's build) +.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.c b/st/st.c new file mode 100755 index 0000000..5553872 --- /dev/null +++ b/st/st.c @@ -0,0 +1,2584 @@ +/* See LICENSE for license details. */ +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.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 "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 STR_BUF_SIZ ESC_BUF_SIZ +#define STR_ARG_SIZ ESC_ARG_SIZ + +/* 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 TSCREEN term.screen[IS_SET(MODE_ALTSCREEN)] +#define TLINEOFFSET(y) \ + (((y) + TSCREEN.cur - TSCREEN.off + TSCREEN.size) % TSCREEN.size) +#define TLINE(y) (TSCREEN.buffer[TLINEOFFSET(y)]) + +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 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; + +/* Screen lines */ +typedef struct { + Line *buffer; /* ring buffer */ + int size; /* size of buffer */ + int cur; /* start of active screen */ + int off; /* scrollback line offset */ + TCursor sc; /* saved cursor */ +} LineBuffer; + +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + LineBuffer screen[2]; /* screen and alternate screen */ + int linelen; /* allocated line length */ + 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]; +} 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 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); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tinsertblank(int); +static void tinsertblankline(int); +static int tlinelen(int); +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); +static void tscrolldown(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 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 clearline(Line, Glyph, int, int); +static Line ensureline(Line); + +static void selnormalize(void); +static void selscroll(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(int y) { + int i = term.col; + Line line = TLINE(y); + + if (line[i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && line[i - 1].u == ' ') + --i; + + return i; +} + +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; + selnormalize(); + sel.type = type; + + 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(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; +} + +int selected(int x, int y) { + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; + + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) && BETWEEN(x, sel.nb.x, sel.ne.x); + + return BETWEEN(y, sel.nb.y, sel.ne.y) && (y != sel.nb.y || x >= sel.nb.x) && + (y != sel.ne.y || x <= sel.ne.x); +} + +void selsnap(int *x, int *y, int direction) { + int newx, newy, xt, yt; + int delim, prevdelim; + const Glyph *gp, *prevgp; + + 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, 0, term.row - 1)) + break; + + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) + break; + } + + if (newx >= tlinelen(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 > 0; *y += direction) { + if (!(TLINE(*y - 1)[term.col - 1].mode & ATTR_WRAP)) { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row - 1; *y += direction) { + if (!(TLINE(*y)[term.col - 1].mode & ATTR_WRAP)) { + break; + } + } + } + break; + } +} + +char *getsel(void) { + char *str, *ptr; + int y, bufsize, lastx, linelen; + const Glyph *gp, *last; + + if (sel.ob.x == -1) + return NULL; + + bufsize = (term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); + + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &TLINE(y)[sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col - 1; + } + last = &TLINE(y)[MIN(lastx, linelen - 1)]; + while (last >= gp && last->u == ' ') + --last; + + for (; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * 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) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = 0; + return str; +} + +void selclear(void) { + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); +} + +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; + + 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; + int y = TLINEOFFSET(0); + + for (i = 0; i < term.row - 1; i++) { + Line line = TSCREEN.buffer[y]; + for (j = 0; j < term.col - 1; j++) { + if (line[j].mode & attr) + return 1; + } + y = (y + 1) % TSCREEN.size; + } + + 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; + int y = TLINEOFFSET(0); + + for (i = 0; i < term.row - 1; i++) { + Line line = TSCREEN.buffer[y]; + for (j = 0; j < term.col - 1; j++) { + if (line[j].mode & attr) { + tsetdirt(i, i); + break; + } + } + y = (y + 1) % TSCREEN.size; + } +} + +void tfulldirt(void) { tsetdirt(0, term.row - 1); } + +void tcursor(int mode) { + if (mode == CURSOR_SAVE) { + TSCREEN.sc = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = TSCREEN.sc; + tmoveto(term.c.x, term.c.y); + } +} + +void treset(void) { + int i, j; + Glyph g = (Glyph){.fg = defaultfg, .bg = defaultbg}; + + 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.bot = term.row - 1; + term.mode = MODE_WRAP | MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; + + for (i = 0; i < 2; i++) { + term.screen[i].sc = (TCursor){{.fg = defaultfg, .bg = defaultbg}}; + term.screen[i].cur = 0; + term.screen[i].off = 0; + for (j = 0; j < term.row; ++j) { + if (term.col != term.linelen) + term.screen[i].buffer[j] = + xrealloc(term.screen[i].buffer[j], term.col * sizeof(Glyph)); + clearline(term.screen[i].buffer[j], g, 0, term.col); + } + for (j = term.row; j < term.screen[i].size; ++j) { + free(term.screen[i].buffer[j]); + term.screen[i].buffer[j] = NULL; + } + } + tcursor(CURSOR_LOAD); + term.linelen = term.col; + tfulldirt(); +} + +void tnew(int col, int row) { + int i; + term = (Term){0}; + term.screen[0].buffer = xmalloc(HISTSIZE * sizeof(Line)); + term.screen[0].size = HISTSIZE; + term.screen[1].buffer = NULL; + for (i = 0; i < HISTSIZE; ++i) + term.screen[0].buffer[i] = NULL; + + tresize(col, row); + treset(); +} + +void tswapscreen(void) { + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); +} + +void kscrollup(const Arg *a) { + int n = a->i; + + if (IS_SET(MODE_ALTSCREEN)) + return; + + if (n < 0) + n = (-n) * term.row; + if (n > TSCREEN.size - term.row - TSCREEN.off) + n = TSCREEN.size - term.row - TSCREEN.off; + while (!TLINE(-n)) + --n; + TSCREEN.off += n; + selscroll(0, n); + tfulldirt(); +} + +void kscrolldown(const Arg *a) { + + int n = a->i; + + if (IS_SET(MODE_ALTSCREEN)) + return; + + if (n < 0) + n = (-n) * term.row; + if (n > TSCREEN.off) + n = TSCREEN.off; + TSCREEN.off -= n; + selscroll(0, -n); + tfulldirt(); +} + +void tscrolldown(int orig, int n) { + int i; + Line temp; + + LIMIT(n, 0, term.bot - orig + 1); + + /* Ensure that lines are allocated */ + for (i = -n; i < 0; i++) { + TLINE(i) = ensureline(TLINE(i)); + } + + /* Shift non-scrolling areas in ring buffer */ + for (i = term.bot + 1; i < term.row; i++) { + temp = TLINE(i); + TLINE(i) = TLINE(i - n); + TLINE(i - n) = temp; + } + for (i = 0; i < orig; i++) { + temp = TLINE(i); + TLINE(i) = TLINE(i - n); + TLINE(i - n) = temp; + } + + /* Scroll buffer */ + TSCREEN.cur = (TSCREEN.cur + TSCREEN.size - n) % TSCREEN.size; + /* Clear lines that have entered the view */ + tclearregion(0, orig, term.linelen - 1, orig + n - 1); + /* Redraw portion of the screen that has scrolled */ + tsetdirt(orig + n - 1, term.bot); + selscroll(orig, n); +} + +void tscrollup(int orig, int n) { + int i; + Line temp; + + LIMIT(n, 0, term.bot - orig + 1); + + /* Ensure that lines are allocated */ + for (i = term.row; i < term.row + n; i++) { + TLINE(i) = ensureline(TLINE(i)); + } + + /* Shift non-scrolling areas in ring buffer */ + for (i = orig - 1; i >= 0; i--) { + temp = TLINE(i); + TLINE(i) = TLINE(i + n); + TLINE(i + n) = temp; + } + for (i = term.row - 1; i > term.bot; i--) { + temp = TLINE(i); + TLINE(i) = TLINE(i + n); + TLINE(i + n) = temp; + } + + /* Scroll buffer */ + TSCREEN.cur = (TSCREEN.cur + n) % TSCREEN.size; + /* Clear lines that have entered the view */ + tclearregion(0, term.bot - n + 1, term.linelen - 1, term.bot); + /* Redraw portion of the screen that has scrolled */ + tsetdirt(orig, term.bot - n + 1); + selscroll(orig, -n); +} + +void selscroll(int orig, int n) { + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) + return; + + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || sel.oe.y < term.top || + sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } + } +} + +void tnewline(int first_col) { + int y = term.c.y; + + if (y == term.bot) { + tscrollup(term.top, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); +} + +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; + 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 - ~ */ + }; + Line line = TLINE(y); + + /* + * 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 (line[x].mode & ATTR_WIDE) { + if (x + 1 < term.col) { + line[x + 1].u = ' '; + line[x + 1].mode &= ~ATTR_WDUMMY; + } + } else if (line[x].mode & ATTR_WDUMMY) { + line[x - 1].u = ' '; + line[x - 1].mode &= ~ATTR_WIDE; + } + + term.dirty[y] = 1; + line[x] = *attr; + line[x].u = u; +} + +void tclearregion(int x1, int y1, int x2, int y2) { + int x, y, L, S, temp; + Glyph *gp; + + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; + + LIMIT(x1, 0, term.linelen - 1); + LIMIT(x2, 0, term.linelen - 1); + LIMIT(y1, 0, term.row - 1); + LIMIT(y2, 0, term.row - 1); + + L = TLINEOFFSET(y1); + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &TSCREEN.buffer[L][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } + L = (L + 1) % TSCREEN.size; + } +} + +void tdeletechar(int n) { + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = TLINE(term.c.y); + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col - n, term.c.y, term.col - 1, term.c.y); +} + +void tinsertblank(int n) { + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = TLINE(term.c.y); + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); +} + +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, n); +} + +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; + 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.mode |= ATTR_UNDERLINE; + 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: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + 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) { + int alt; + 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: + 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 */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col - 1, term.row - 1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + 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 len; + + 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); + if (term.c.y < term.row - 1) { + tclearregion(0, term.c.y + 1, term.col - 1, term.row - 1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, term.col - 1, term.c.y - 1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, 0, term.col - 1, term.row - 1); + 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); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col - 1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll <n> line up */ + if (csiescseq.priv) + break; + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0]); + 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 */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1, term.c.y); + 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" */ + len = + snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1, term.c.x + 1); + ttywrite(buf, len, 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) */ + 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: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 10: + case 11: + case 12: + 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; + } + 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 buf[UTF_SIZ]; + const Glyph *bp, *end; + + bp = &TLINE(n)[0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for (; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); +} + +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, 1); + } 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; + } + if (selected(term.c.x, term.c.y)) + selclear(); + + gp = &TLINE(term.c.y)[term.c.x]; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &TLINE(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 = &TLINE(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.c.state |= CURSOR_WRAPNEXT; + } +} + +int twrite(const char *buf, int buflen, int show_ctrl) { + int charsize; + Rune u; + int n; + + if (TSCREEN.off) { + TSCREEN.off = 0; + tfulldirt(); + } + + 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 clearline(Line line, Glyph g, int x, int xend) { + int i; + g.mode = 0; + g.u = ' '; + for (i = x; i < xend; ++i) { + line[i] = g; + } +} + +Line ensureline(Line line) { + if (!line) { + line = xmalloc(term.linelen * sizeof(Glyph)); + } + return line; +} + +void tresize(int col, int row) { + int i, j; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int linelen = MAX(col, term.linelen); + int *bp; + + if (col < 1 || row < 1 || row > HISTSIZE) { + fprintf(stderr, "tresize: error resizing to %dx%d\n", col, row); + return; + } + + /* Shift buffer to keep the cursor where we expect it */ + if (row <= term.c.y) { + term.screen[0].cur = + (term.screen[0].cur - row + term.c.y + 1) % term.screen[0].size; + } + + /* Resize and clear line buffers as needed */ + if (linelen > term.linelen) { + for (i = 0; i < term.screen[0].size; ++i) { + if (term.screen[0].buffer[i]) { + term.screen[0].buffer[i] = + xrealloc(term.screen[0].buffer[i], linelen * sizeof(Glyph)); + clearline(term.screen[0].buffer[i], term.c.attr, term.linelen, linelen); + } + } + for (i = 0; i < minrow; ++i) { + term.screen[1].buffer[i] = + xrealloc(term.screen[1].buffer[i], linelen * sizeof(Glyph)); + clearline(term.screen[1].buffer[i], term.c.attr, term.linelen, linelen); + } + } + /* Allocate all visible lines for regular line buffer */ + for (j = term.screen[0].cur, i = 0; i < row; + ++i, j = (j + 1) % term.screen[0].size) { + if (!term.screen[0].buffer[j]) { + term.screen[0].buffer[j] = xmalloc(linelen * sizeof(Glyph)); + } + if (i >= term.row) { + clearline(term.screen[0].buffer[j], term.c.attr, 0, linelen); + } + } + /* Resize alt screen */ + term.screen[1].cur = 0; + term.screen[1].size = row; + for (i = row; i < term.row; ++i) { + free(term.screen[1].buffer[i]); + } + term.screen[1].buffer = xrealloc(term.screen[1].buffer, row * sizeof(Line)); + for (i = term.row; i < row; ++i) { + term.screen[1].buffer[i] = xmalloc(linelen * sizeof(Glyph)); + clearline(term.screen[1].buffer[i], term.c.attr, 0, linelen); + } + + /* resize to new height */ + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + + /* fix tabstops */ + 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; + } + + /* update terminal size */ + term.col = col; + term.row = row; + term.linelen = linelen; + /* reset scrolling region */ + tsetscroll(0, row - 1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + tfulldirt(); +} + +void resettitle(void) { xsettitle(NULL); } + +void drawregion(int x1, int y1, int x2, int y2) { + int y, L; + + L = TLINEOFFSET(y1); + for (y = y1; y < y2; y++) { + if (term.dirty[y]) { + term.dirty[y] = 0; + xdrawline(TSCREEN.buffer[L], x1, y, x2); + } + L = (L + 1) % TSCREEN.size; + } +} + +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 (TLINE(term.ocy)[term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (TLINE(term.c.y)[cx].mode & ATTR_WDUMMY) + cx--; + + drawregion(0, 0, term.col, term.row); + if (TSCREEN.off == 0) + xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx], term.ocx, term.ocy, + TLINE(term.ocy)[term.ocx], TLINE(term.ocy), term.col); + + 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(); +} diff --git a/st/st.core b/st/st.core new file mode 100755 index 0000000..65be349 Binary files /dev/null and b/st/st.core differ diff --git a/st/st.h b/st/st.h new file mode 100755 index 0000000..4649646 --- /dev/null +++ b/st/st.h @@ -0,0 +1,130 @@ +/* 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 & (~ATTR_WRAP)) != ((b).mode & (~ATTR_WRAP)) || \ + (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)) +#define HISTSIZE 2000 + +enum glyph_attribute { + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, +}; + +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 */ +} 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 printscreen(const Arg *); +void printsel(const Arg *); +void sendbreak(const Arg *); +void toggleprinter(const Arg *); + +int tattrset(int); +void tnew(int, int); +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 *); + +/* 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; +extern float alpha; +extern float alpha_def; diff --git a/st/st.info b/st/st.info new file mode 100755 index 0000000..efab2cf --- /dev/null +++ b/st/st.info @@ -0,0 +1,243 @@ +st-mono| simpleterm monocolor, + 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/win.h b/st/win.h new file mode 100755 index 0000000..94679e4 --- /dev/null +++ b/st/win.h @@ -0,0 +1,41 @@ +/* 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, +}; + +void xbell(void); +void xclipcopy(void); +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int); +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 xximspot(int, int); diff --git a/st/x.c b/st/x.c new file mode 100755 index 0000000..0cb35e8 --- /dev/null +++ b/st/x.c @@ -0,0 +1,2319 @@ +/* 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> +#include <X11/Xresource.h> + +char *argv0; +#include "arg.h" +#include "st.h" +#include "win.h" +#include "hb.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; +} 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; + +/* 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 *); +static void chgalpha(const Arg *); +void kscrollup(const Arg *); +void kscrolldown(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 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 depth; /* bit depth */ + 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 void xresetfontsettings(ushort mode, Font **font, int *frcflags); +static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, 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_alpha = NULL; +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 - borderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; +} + +int +evrow(XEvent *e) +{ + int y = e->xbutton.y - borderpx; + 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 && + (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); + + 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, + xw.depth); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + + /* resize to new width */ + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) * 4); +} + +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); + } + + /* set alpha value of bg color */ + if (opt_alpha) + alpha = strtof(opt_alpha, NULL); + dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); + dc.col[defaultbg].pixel &= 0x00FFFFFF; + dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + 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 = win.ch; + sizeh->width_inc = win.cw; + 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) +{ + /* Clear Harfbuzz font cache. */ + hbunloadfonts(); + + /* 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; + XWindowAttributes attr; + XVisualInfo vis; + + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); + + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { + parent = XRootWindow(xw.dpy, xw.scr); + xw.depth = 32; + } else { + XGetWindowAttributes(xw.dpy, parent, &attr); + xw.depth = attr.depth; + } + + XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); + xw.vis = vis.visual; + + /* font */ + if (!FcInit()) + die("could not init fontconfig.\n"); + + usedfont = (opt_font == NULL)? font : opt_font; + xloadfonts(usedfont, 0); + + /* Backup default alpha value */ + alpha_def = alpha; + + /* colors */ + xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); + xloadcols(); + + /* adjust fixed window geometry */ + win.w = 2 * borderpx + cols * win.cw; + win.h = 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); + xw.win = XCreateWindow(xw.dpy, root, xw.l, xw.t, + win.w, win.h, 0, xw.depth, 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; + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); + dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); + 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) * 4); + + /* 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; +} + +void +xresetfontsettings(ushort mode, Font **font, int *frcflags) +{ + *font = &dc.font; + 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; + } +} + +int +xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) +{ + float winx = borderpx + x * win.cw, winy = borderpx + 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, length = 0, start = 0, numspecs = 0; + float cluster_xp = xp, cluster_yp = yp; + HbTransformData shaped = { 0 }; + + /* Initial values. */ + mode = prevmode = glyphs[0].mode & ~ATTR_WRAP; + xresetfontsettings(mode, &font, &frcflags); + + for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { + mode = glyphs[i].mode & ~ATTR_WRAP; + + /* Skip dummy wide-character spacing. */ + if (mode & ATTR_WDUMMY && i < (len - 1)) + continue; + + if ( + prevmode != mode + || ATTRCMP(glyphs[start], glyphs[i]) + || selected(x + i, y) != selected(x + start, y) + || i == (len - 1) + ) { + /* Handle 1-character wide segments and end of line */ + length = i - start; + if (i == start) { + length = 1; + } else if (i == (len - 1)) { + length = (i - start + 1); + } + + /* Shape the segment. */ + hbtransform(&shaped, font->match, glyphs, start, length); + runewidth = win.cw * ((glyphs[start].mode & ATTR_WIDE) ? 2.0f : 1.0f); + cluster_xp = xp; cluster_yp = yp; + for (int code_idx = 0; code_idx < shaped.count; code_idx++) { + int idx = shaped.glyphs[code_idx].cluster; + + if (glyphs[start + idx].mode & ATTR_WDUMMY) + continue; + + /* Advance the drawing cursor if we've moved to a new cluster */ + if (code_idx > 0 && idx != shaped.glyphs[code_idx - 1].cluster) { + xp += runewidth; + cluster_xp = xp; + cluster_yp = yp; + runewidth = win.cw * ((glyphs[start + idx].mode & ATTR_WIDE) ? 2.0f : 1.0f); + } + + if (shaped.glyphs[code_idx].codepoint != 0) { + /* If symbol is found, put it into the specs. */ + specs[numspecs].font = font->match; + specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint; + specs[numspecs].x = cluster_xp + (short)(shaped.positions[code_idx].x_offset / 64.); + specs[numspecs].y = cluster_yp - (short)(shaped.positions[code_idx].y_offset / 64.); + cluster_xp += shaped.positions[code_idx].x_advance / 64.; + cluster_yp += shaped.positions[code_idx].y_advance / 64.; + numspecs++; + } else { + /* If it's not found, try to fetch it through the font cache. */ + rune = glyphs[start + idx].u; + 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; + numspecs++; + } + } + + /* Cleanup and get ready for next segment. */ + hbcleanup(&shaped); + start = i; + + /* Determine font for glyph if different from previous glyph. */ + if (prevmode != mode) { + prevmode = mode; + xresetfontsettings(mode, &font, &frcflags); + yp = winy + font->ascent; + } + } + } + + return numspecs; +} + +void +chgalpha(const Arg *arg) +{ + if (arg->f == -1.0f && alpha >= 0.1f) + alpha -= 0.1f; + else if (arg->f == 1.0f && alpha < 1.0f) + alpha += 0.1f; + else if (arg->f == 0.0f) + alpha = alpha_def; + else + return; + + dc.col[defaultbg].color.alpha = (unsigned short)(0xFFFF * alpha); + /* Required to remove artifacting from borderpx */ + cresize(0, 0); + redraw(); +} + +void +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int charlen) +{ + int winx = borderpx + x * win.cw, winy = borderpx + 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, borderpx, + winy + win.ch + + ((winy + win.ch >= borderpx + win.th)? win.h : 0)); + } + if (winx + width >= borderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, borderpx); + if (winy + win.ch >= borderpx + 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) { + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, + width, 1); + } + + 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 *specs = xw.specbuf; + + numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y); + xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 : 1); +} + +void +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len) +{ + Color drawcol; + + /* remove the old cursor */ + if (selected(ox, oy)) + og.mode ^= ATTR_REVERSE; + + /* Redraw the line where cursor was previously. + * It will restore the ligatures broken by the cursor. */ + xdrawline(line, 0, oy, len); + + 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, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - \ + cursorthickness, + win.cw, cursorthickness); + break; + case 5: /* Blinking bar */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + (cx + 1) * win.cw - 1, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + (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; + + i = ox = 0; + for (x = x1; x < x2; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if ((i > 0) && ATTRCMP(base, new)) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1); + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - ox); + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; + } + if (i > 0) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1); + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox); + } +} + +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); + } + /* 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; + } +} + + +#define XRESOURCE_LOAD_META(NAME) \ + if(!XrmGetResource(xrdb, "st." NAME, "st." NAME, &type, &ret)) \ + XrmGetResource(xrdb, "*." NAME, "*." NAME, &type, &ret); \ + if (ret.addr != NULL && !strncmp("String", type, 64)) + +#define XRESOURCE_LOAD_STRING(NAME, DST) \ + XRESOURCE_LOAD_META(NAME) \ + DST = ret.addr; + +#define XRESOURCE_LOAD_CHAR(NAME, DST) \ + XRESOURCE_LOAD_META(NAME) \ + DST = ret.addr[0]; + +#define XRESOURCE_LOAD_INTEGER(NAME, DST) \ + XRESOURCE_LOAD_META(NAME) \ + DST = strtoul(ret.addr, NULL, 10); + +#define XRESOURCE_LOAD_FLOAT(NAME, DST) \ + XRESOURCE_LOAD_META(NAME) \ + DST = strtof(ret.addr, NULL); + +void +xrdb_load(void) +{ + /* XXX */ + char *xrm; + char *type; + XrmDatabase xrdb; + XrmValue ret; + Display *dpy; + + if(!(dpy = XOpenDisplay(NULL))) + die("Can't open display\n"); + + XrmInitialize(); + xrm = XResourceManagerString(dpy); + + if (xrm != NULL) { + xrdb = XrmGetStringDatabase(xrm); + + /* handling colors here without macros to do via loop. */ + int i = 0; + char loadValue[12] = ""; + for (i = 0; i < 256; i++) + { + sprintf(loadValue, "%s%d", "st.color", i); + + if(!XrmGetResource(xrdb, loadValue, loadValue, &type, &ret)) + { + sprintf(loadValue, "%s%d", "*.color", i); + if (!XrmGetResource(xrdb, loadValue, loadValue, &type, &ret)) + /* reset if not found (unless in range for defaults). */ + if (i > 15) + colorname[i] = NULL; + } + + if (ret.addr != NULL && !strncmp("String", type, 64)) + colorname[i] = ret.addr; + } + + XRESOURCE_LOAD_STRING("foreground", colorname[defaultfg]); + XRESOURCE_LOAD_STRING("background", colorname[defaultbg]); + XRESOURCE_LOAD_STRING("cursorColor", colorname[defaultcs]) + else { + // this looks confusing because we are chaining off of the if + // in the macro. probably we should be wrapping everything blocks + // so this isn't possible... + defaultcs = defaultfg; + } + XRESOURCE_LOAD_STRING("reverse-cursor", colorname[defaultrcs]) + else { + // see above. + defaultrcs = defaultbg; + } + + XRESOURCE_LOAD_STRING("font", font); + XRESOURCE_LOAD_STRING("termname", termname); + + XRESOURCE_LOAD_INTEGER("blinktimeout", blinktimeout); + XRESOURCE_LOAD_INTEGER("bellvolume", bellvolume); + XRESOURCE_LOAD_INTEGER("borderpx", borderpx); + XRESOURCE_LOAD_INTEGER("cursorshape", cursorshape); + + XRESOURCE_LOAD_FLOAT("cwscale", cwscale); + XRESOURCE_LOAD_FLOAT("chscale", chscale); + } + XFlush(dpy); +} + +void +reload(int sig) +{ + xrdb_load(); + + /* colors, fonts */ + xloadcols(); + xunloadfonts(); + xloadfonts(font, 0); + + /* pretend the window just got resized */ + cresize(win.w, win.h); + + redraw(); + + /* triggers re-render if we're visible. */ + ttywrite("\033[O", 3, 1); + + signal(SIGUSR1, reload); +} + + +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); +} + +int +main(int argc, char *argv[]) +{ + xw.l = xw.t = 0; + xw.isfixed = False; + xsetcursor(cursorshape); + + ARGBEGIN { + case 'a': + allowaltscreen = 0; + break; + case 'A': + opt_alpha = EARGF(usage()); + 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(""); + xrdb_load(); + signal(SIGUSR1, reload); + cols = MAX(cols, 1); + rows = MAX(rows, 1); + tnew(cols, rows); + xinit(cols, rows); + xsetenv(); + selinit(); + run(); + + return 0; +} diff --git a/wmenu/.gitignore b/wmenu/.gitignore new file mode 100755 index 0000000..378eac2 --- /dev/null +++ b/wmenu/.gitignore @@ -0,0 +1 @@ +build diff --git a/wmenu/LICENSE b/wmenu/LICENSE new file mode 100755 index 0000000..27b06f0 --- /dev/null +++ b/wmenu/LICENSE @@ -0,0 +1,32 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe <anselm@garbe.ca> +© 2006-2008 Sander van Dijk <a.h.vandijk@gmail.com> +© 2006-2007 Michał Janeczek <janeczek@gmail.com> +© 2007 Kris Maglione <jg@suckless.org> +© 2009 Gottox <gottox@s01.de> +© 2009 Markus Schnalke <meillo@marmaro.de> +© 2009 Evan Gates <evan.gates@gmail.com> +© 2010-2012 Connor Lane Smith <cls@lubutu.com> +© 2014-2020 Hiltjo Posthuma <hiltjo@codemadness.org> +© 2015-2019 Quentin Rameau <quinq@fifth.space> +© 2018-2019 Henrik Nyman <h@nyymanni.com> +© 2022 adnano + +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/wmenu/README.md b/wmenu/README.md new file mode 100755 index 0000000..62a34a7 --- /dev/null +++ b/wmenu/README.md @@ -0,0 +1,32 @@ +# wmenu + +wmenu is an efficient dynamic menu for Sway and wlroots based Wayland +compositors. It provides a Wayland-native dmenu replacement which maintains the +look and feel of dmenu. + +## Installation + +Dependencies: + +- cairo +- pango +- wayland +- xkbcommon +- scdoc (optional) + +``` +$ meson setup build +$ ninja -C build +# ninja -C build install +``` + +## Usage + +See wmenu(1) + +To use wmenu with Sway, you can add the following to your configuration file: + +``` +set $menu wmenu-run +bindsym $mod+d exec $menu +``` diff --git a/wmenu/docs/meson.build b/wmenu/docs/meson.build new file mode 100755 index 0000000..39498d8 --- /dev/null +++ b/wmenu/docs/meson.build @@ -0,0 +1,26 @@ +scdoc_dep = dependency('scdoc', version: '>=1.9.2', native: true, required: false) + +if scdoc_dep.found() + scdoc = find_program( + scdoc_dep.get_pkgconfig_variable('scdoc'), + native: true, + ) + mandir = get_option('mandir') + + docs = [ + 'wmenu.1', + ] + + foreach path : docs + custom_target( + path, + output: path, + input: '@0@.scd'.format(path), + capture: true, + feed: true, + command: [scdoc], + install: true, + install_dir: '@0@/man1'.format(mandir) + ) + endforeach +endif diff --git a/wmenu/docs/wmenu.1.scd b/wmenu/docs/wmenu.1.scd new file mode 100755 index 0000000..4519e8b --- /dev/null +++ b/wmenu/docs/wmenu.1.scd @@ -0,0 +1,186 @@ +WMENU(1) + +# NAME + +wmenu - dynamic menu for Wayland + +# SYNOPSIS + +*wmenu* [-biPv] \ + [-f _font_] \ + [-l _lines_] \ + [-o _output_] \ + [-p _prompt_] \ + [-N _color_] [-n _color_] \ + [-M _color_] [-m _color_] \ + [-S _color_] [-s _color_] + +*wmenu-run* ... + +# DESCRIPTION + +*wmenu* is a dynamic menu for Wayland, which reads a list of newline-separated +items from stdin. When the user selects an item and presses Return, their choice +is printed to stdout and wmenu terminates. Entering text will narrow the items +to those matching the tokens in the input. + +*wmenu-run* is a special invocation of wmenu which lists programs in the user's +$PATH and runs the result. + +# OPTIONS + +*-b* + wmenu appears at the bottom of the screen. + +*-i* + wmenu matches menu items case insensitively. + +*-P* + wmenu will not directly display the keyboard input, but instead replace it + with asterisks. + +*-v* + prints version information to stdout, then exits. + +*-f* _font_ + defines the font used. For more information, see + https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html + +*-l* _lines_ + wmenu lists items vertically, with the given number of lines. + +*-o* _output_ + wmenu is displayed on the output with the given name. + +*-p* _prompt_ + defines the prompt to be displayed to the left of the input field. + +*-N* _RRGGBB[AA]_ + defines the normal background color. + +*-n* _RRGGBB[AA]_ + defines the normal foreground color. + +*-M* _RRGGBB[AA]_ + defines the prompt background color. + +*-m* _RRGGBB[AA]_ + defines the prompt foreground color. + +*-S* _RRGGBB[AA]_ + defines the selection background color. + +*-s* _RRGGBB[AA]_ + defines the selection foreground color. + +# USAGE + +wmenu is completely controlled by the keyboard. Items are selected using the +arrow keys, page up, page down, home, and end. + +*Tab* + Copy the selected item to the input field. + +*Return* + Confirm selection. Prints the selected item to stdout and exits, returning + success. + +*Ctrl-Return* + Confirm selection. Prints the selected item to stdout and continues. + +*Shift-Return* + Confirm input. Prints the input text to stdout and exits, returning success. + +*Escape* + Exit without selecting an item, returning failure. + +*Ctrl-Left* + Move cursor to the start of the current word. + +*Ctrl-Right* + Move cursor to the end of the current word. + +|[ *C-a* +:< Home + +|[ *C-b* +:< Left + +|[ *C-c* +:< Escape + +|[ *C-d* +:< Delete + +|[ *C-e* +:< End + +|[ *C-f* +:< Right + +|[ *C-g* +:< Escape + +|[ *C-[* +:< Escape + +|[ *C-h* +:< Backspace + +|[ *C-i* +:< Tab + +|[ *C-j* +:< Return + +|[ *C-J* +:< Shift-Return + +|[ *C-k* +:< Delete line right + +|[ *C-m* +:< Return + +|[ *C-M* +:< Shift-Return + +|[ *C-n* +:< Down + +|[ *C-p* +:< Up + +|[ *C-u* +:< Delete line left + +|[ *C-w* +:< Delete word left + +|[ *C-Y* +:< Paste from Wayland clipboard + +|[ *M-b* +:< Move cursor to the start of the current word + +|[ *M-f* +:< Move cursor to the end of the current word + +|[ *M-g* +:< Home + +|[ *M-G* +:< End + +|[ *M-h* +:< Up + +|[ *M-j* +:< Page down + +|[ *M-k* +:< Page up + +|[ *M-l* +:< Down + diff --git a/wmenu/menu.c b/wmenu/menu.c new file mode 100755 index 0000000..65bc177 --- /dev/null +++ b/wmenu/menu.c @@ -0,0 +1,692 @@ +#define _POSIX_C_SOURCE 200809L +#include <assert.h> +#include <ctype.h> +#include <poll.h> +#include <stdbool.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <time.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/timerfd.h> +#include <wayland-client.h> +#include <wayland-client-protocol.h> +#include <xkbcommon/xkbcommon.h> + +#include "menu.h" + +#include "pango.h" +#include "render.h" +#include "wayland.h" + +// Creates and returns a new menu. +struct menu *menu_create(menu_callback callback) { + struct menu *menu = calloc(1, sizeof(struct menu)); + menu->strncmp = strncmp; + menu->font = "Ubuntu Mono 17"; +menu->normalbg = 0x1c1c1cff; +menu->normalfg = 0xB0B0B0ff; +menu->promptbg = 0x1c1c1cff; +menu->promptfg = 0xB0B0B0ff; +menu->selectionbg = 0xB0B0B0ff; +menu->selectionfg = 0x1c1c1cff; + + menu->callback = callback; + menu->test_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); + menu->test_cairo = cairo_create(menu->test_surface); + return menu; +} + +static void free_pages(struct menu *menu) { + struct page *next = menu->pages; + while (next) { + struct page *page = next; + next = page->next; + free(page); + } +} + +static void free_items(struct menu *menu) { + for (size_t i = 0; i < menu->item_count; i++) { + struct item *item = &menu->items[i]; + free(item->text); + } + free(menu->items); +} + +// Destroys the menu, freeing memory associated with it. +void menu_destroy(struct menu *menu) { + free_pages(menu); + free_items(menu); + cairo_destroy(menu->test_cairo); + cairo_surface_destroy(menu->test_surface); + free(menu); +} + +static bool parse_color(const char *color, uint32_t *result) { + if (color[0] == '#') { + ++color; + } + size_t len = strlen(color); + if ((len != 6 && len != 8) || !isxdigit(color[0]) || !isxdigit(color[1])) { + return false; + } + char *ptr; + uint32_t parsed = (uint32_t)strtoul(color, &ptr, 16); + if (*ptr != '\0') { + return false; + } + *result = len == 6 ? ((parsed << 8) | 0xFF) : parsed; + return true; +} + +// Parse menu options from command line arguments. +void menu_getopts(struct menu *menu, int argc, char *argv[]) { + const char *usage = + "Usage: wmenu [-biPv] [-f font] [-l lines] [-o output] [-p prompt]\n" + "\t[-N color] [-n color] [-M color] [-m color] [-S color] [-s color]\n"; + + int opt; + while ((opt = getopt(argc, argv, "bhiPvf:l:o:p:N:n:M:m:S:s:")) != -1) { + switch (opt) { + case 'b': + menu->bottom = true; + break; + case 'i': + menu->strncmp = strncasecmp; + break; + case 'P': + menu->passwd = true; + break; + case 'v': + puts("wmenu " VERSION); + exit(EXIT_SUCCESS); + case 'f': + menu->font = optarg; + break; + case 'l': + menu->lines = atoi(optarg); + break; + case 'o': + menu->output_name = optarg; + break; + case 'p': + menu->prompt = optarg; + break; + case 'N': + if (!parse_color(optarg, &menu->normalbg)) { + fprintf(stderr, "Invalid background color: %s", optarg); + } + break; + case 'n': + if (!parse_color(optarg, &menu->normalfg)) { + fprintf(stderr, "Invalid foreground color: %s", optarg); + } + break; + case 'M': + if (!parse_color(optarg, &menu->promptbg)) { + fprintf(stderr, "Invalid prompt background color: %s", optarg); + } + break; + case 'm': + if (!parse_color(optarg, &menu->promptfg)) { + fprintf(stderr, "Invalid prompt foreground color: %s", optarg); + } + break; + case 'S': + if (!parse_color(optarg, &menu->selectionbg)) { + fprintf(stderr, "Invalid selection background color: %s", optarg); + } + break; + case 's': + if (!parse_color(optarg, &menu->selectionfg)) { + fprintf(stderr, "Invalid selection foreground color: %s", optarg); + } + break; + default: + fprintf(stderr, "%s", usage); + exit(EXIT_FAILURE); + } + } + + if (optind < argc) { + fprintf(stderr, "%s", usage); + exit(EXIT_FAILURE); + } + + int height = get_font_height(menu->font); + menu->line_height = height + 2; + menu->height = menu->line_height; + if (menu->lines > 0) { + menu->height += menu->height * menu->lines; + } + menu->padding = height / 2; +} + +// Add an item to the menu. +void menu_add_item(struct menu *menu, char *text) { + if ((menu->item_count & (menu->item_count - 1)) == 0) { + size_t alloc_size = menu->item_count ? 2 * menu->item_count : 1; + void *new_array = realloc(menu->items, sizeof(struct item) * alloc_size); + if (!new_array) { + fprintf(stderr, "could not realloc %zu bytes", sizeof(struct item) * alloc_size); + exit(EXIT_FAILURE); + } + menu->items = new_array; + } + + struct item *new = &menu->items[menu->item_count]; + new->text = text; + + menu->item_count++; +} + +static int compare_items(const void *a, const void *b) { + const struct item *item_a = a; + const struct item *item_b = b; + return strcmp(item_a->text, item_b->text); +} + +void menu_sort_and_deduplicate(struct menu *menu) { + size_t j = 1; + size_t i; + + qsort(menu->items, menu->item_count, sizeof(*menu->items), compare_items); + + for (i = 1; i < menu->item_count; i++) { + if (strcmp(menu->items[i].text, menu->items[j - 1].text) == 0) { + free(menu->items[i].text); + } else { + menu->items[j] = menu->items[i]; + j++; + } + } + menu->item_count = j; +} + +static void append_page(struct page *page, struct page **first, struct page **last) { + if (*last) { + (*last)->next = page; + } else { + *first = page; + } + page->prev = *last; + page->next = NULL; + *last = page; +} + +static void page_items(struct menu *menu) { + // Free existing pages + while (menu->pages != NULL) { + struct page *page = menu->pages; + menu->pages = menu->pages->next; + free(page); + } + + if (!menu->matches) { + return; + } + + // Make new pages + if (menu->lines > 0) { + struct page *pages_end = NULL; + struct item *item = menu->matches; + while (item) { + struct page *page = calloc(1, sizeof(struct page)); + page->first = item; + + for (int i = 1; item && i <= menu->lines; i++) { + item->page = page; + page->last = item; + item = item->next_match; + } + append_page(page, &menu->pages, &pages_end); + } + } else { + // Calculate available space + int max_width = menu->width - menu->inputw - menu->promptw + - menu->left_arrow - menu->right_arrow; + + struct page *pages_end = NULL; + struct item *item = menu->matches; + while (item) { + struct page *page = calloc(1, sizeof(struct page)); + page->first = item; + + int total_width = 0; + int items = 0; + while (item) { + total_width += item->width + 2 * menu->padding; + if (total_width > max_width && items > 0) { + break; + } + items++; + + item->page = page; + page->last = item; + item = item->next_match; + } + append_page(page, &menu->pages, &pages_end); + } + } +} + +static const char *fstrstr(struct menu *menu, const char *s, const char *sub) { + for (size_t len = strlen(sub); *s; s++) { + if (!menu->strncmp(s, sub, len)) { + return s; + } + } + return NULL; +} + +static void append_match(struct item *item, struct item **first, struct item **last) { + if (*last) { + (*last)->next_match = item; + } else { + *first = item; + } + item->prev_match = *last; + item->next_match = NULL; + *last = item; +} + +static void match_items(struct menu *menu) { + struct item *lexact = NULL, *exactend = NULL; + struct item *lprefix = NULL, *prefixend = NULL; + struct item *lsubstr = NULL, *substrend = NULL; + char buf[sizeof menu->input], *tok; + char **tokv = NULL; + int i, tokc = 0; + size_t k; + size_t tok_len; + menu->matches = NULL; + menu->matches_end = NULL; + menu->sel = NULL; + + size_t input_len = strlen(menu->input); + + /* tokenize input by space for matching the tokens individually */ + strcpy(buf, menu->input); + tok = strtok(buf, " "); + while (tok) { + tokv = realloc(tokv, (tokc + 1) * sizeof *tokv); + if (!tokv) { + fprintf(stderr, "could not realloc %zu bytes", + (tokc + 1) * sizeof *tokv); + exit(EXIT_FAILURE); + } + tokv[tokc] = tok; + tokc++; + tok = strtok(NULL, " "); + } + tok_len = tokc ? strlen(tokv[0]) : 0; + + for (k = 0; k < menu->item_count; k++) { + struct item *item = &menu->items[k]; + for (i = 0; i < tokc; i++) { + if (!fstrstr(menu, item->text, tokv[i])) { + /* token does not match */ + break; + } + } + if (i != tokc) { + /* not all tokens match */ + continue; + } + if (!tokc || !menu->strncmp(menu->input, item->text, input_len + 1)) { + append_match(item, &lexact, &exactend); + } else if (!menu->strncmp(tokv[0], item->text, tok_len)) { + append_match(item, &lprefix, &prefixend); + } else { + append_match(item, &lsubstr, &substrend); + } + } + + free(tokv); + + if (lexact) { + menu->matches = lexact; + menu->matches_end = exactend; + } + if (lprefix) { + if (menu->matches_end) { + menu->matches_end->next_match = lprefix; + lprefix->prev_match = menu->matches_end; + } else { + menu->matches = lprefix; + } + menu->matches_end = prefixend; + } + if (lsubstr) { + if (menu->matches_end) { + menu->matches_end->next_match = lsubstr; + lsubstr->prev_match = menu->matches_end; + } else { + menu->matches = lsubstr; + } + menu->matches_end = substrend; + } + + page_items(menu); + if (menu->pages) { + menu->sel = menu->pages->first; + } +} + +// Marks the menu as needing to be rendered again. +void menu_invalidate(struct menu *menu) { + menu->rendered = false; +} + +// Render menu items. +void menu_render_items(struct menu *menu) { + calc_widths(menu); + match_items(menu); + render_menu(menu); +} + +static void insert(struct menu *menu, const char *text, ssize_t len) { + if (strlen(menu->input) + len > sizeof menu->input - 1) { + return; + } + memmove(menu->input + menu->cursor + len, menu->input + menu->cursor, + sizeof menu->input - menu->cursor - MAX(len, 0)); + if (len > 0 && text != NULL) { + memcpy(menu->input + menu->cursor, text, len); + } + menu->cursor += len; +} + +// Add pasted text to the menu input. +void menu_paste(struct menu *menu, const char *text, ssize_t len) { + insert(menu, text, len); +} + +static size_t nextrune(struct menu *menu, int incr) { + size_t n, len; + + len = strlen(menu->input); + for(n = menu->cursor + incr; n < len && (menu->input[n] & 0xc0) == 0x80; n += incr); + return n; +} + +// Move the cursor to the beginning or end of the word, skipping over any preceding whitespace. +static void movewordedge(struct menu *menu, int dir) { + if (dir < 0) { + // Move to beginning of word + while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') { + menu->cursor = nextrune(menu, -1); + } + while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] != ' ') { + menu->cursor = nextrune(menu, -1); + } + } else { + // Move to end of word + size_t len = strlen(menu->input); + while (menu->cursor < len && menu->input[menu->cursor] == ' ') { + menu->cursor = nextrune(menu, +1); + } + while (menu->cursor < len && menu->input[menu->cursor] != ' ') { + menu->cursor = nextrune(menu, +1); + } + } +} + +// Handle a keypress. +void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state, + xkb_keysym_t sym) { + if (key_state != WL_KEYBOARD_KEY_STATE_PRESSED) { + return; + } + + struct xkb_state *state = context_get_xkb_state(menu->context); + bool ctrl = xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + bool meta = xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + bool shift = xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + + size_t len = strlen(menu->input); + + if (ctrl) { + // Emacs-style line editing bindings + switch (sym) { + case XKB_KEY_a: + sym = XKB_KEY_Home; + break; + case XKB_KEY_b: + sym = XKB_KEY_Left; + break; + case XKB_KEY_c: + sym = XKB_KEY_Escape; + break; + case XKB_KEY_d: + sym = XKB_KEY_Delete; + break; + case XKB_KEY_e: + sym = XKB_KEY_End; + break; + case XKB_KEY_f: + sym = XKB_KEY_Right; + break; + case XKB_KEY_g: + sym = XKB_KEY_Escape; + break; + case XKB_KEY_bracketleft: + sym = XKB_KEY_Escape; + break; + case XKB_KEY_h: + sym = XKB_KEY_BackSpace; + break; + case XKB_KEY_i: + sym = XKB_KEY_Tab; + break; + case XKB_KEY_j: + case XKB_KEY_J: + case XKB_KEY_m: + case XKB_KEY_M: + sym = XKB_KEY_Return; + ctrl = false; + break; + case XKB_KEY_n: + sym = XKB_KEY_Down; + break; + case XKB_KEY_p: + sym = XKB_KEY_Up; + break; + + case XKB_KEY_k: + // Delete right + menu->input[menu->cursor] = '\0'; + match_items(menu); + menu_invalidate(menu); + return; + case XKB_KEY_u: + // Delete left + insert(menu, NULL, 0 - menu->cursor); + match_items(menu); + menu_invalidate(menu); + return; + case XKB_KEY_w: + // Delete word + while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') { + insert(menu, NULL, nextrune(menu, -1) - menu->cursor); + } + while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] != ' ') { + insert(menu, NULL, nextrune(menu, -1) - menu->cursor); + } + match_items(menu); + menu_invalidate(menu); + return; + case XKB_KEY_Y: + // Paste clipboard + if (!context_paste(menu->context)) { + return; + } + match_items(menu); + menu_invalidate(menu); + return; + case XKB_KEY_Left: + case XKB_KEY_KP_Left: + movewordedge(menu, -1); + menu_invalidate(menu); + return; + case XKB_KEY_Right: + case XKB_KEY_KP_Right: + movewordedge(menu, +1); + menu_invalidate(menu); + return; + + case XKB_KEY_Return: + case XKB_KEY_KP_Enter: + break; + default: + return; + } + } else if (meta) { + // Emacs-style line editing bindings + switch (sym) { + case XKB_KEY_b: + movewordedge(menu, -1); + menu_invalidate(menu); + return; + case XKB_KEY_f: + movewordedge(menu, +1); + menu_invalidate(menu); + return; + case XKB_KEY_g: + sym = XKB_KEY_Home; + break; + case XKB_KEY_G: + sym = XKB_KEY_End; + break; + case XKB_KEY_h: + sym = XKB_KEY_Up; + break; + case XKB_KEY_j: + sym = XKB_KEY_Next; + break; + case XKB_KEY_k: + sym = XKB_KEY_Prior; + break; + case XKB_KEY_l: + sym = XKB_KEY_Down; + break; + default: + return; + } + } + + char buf[8]; + switch (sym) { + case XKB_KEY_Return: + case XKB_KEY_KP_Enter: + if (shift) { + menu->callback(menu, menu->input, true); + } else { + char *text = menu->sel ? menu->sel->text : menu->input; + menu->callback(menu, text, !ctrl); + } + break; + case XKB_KEY_Left: + case XKB_KEY_KP_Left: + case XKB_KEY_Up: + case XKB_KEY_KP_Up: + if (menu->sel && menu->sel->prev_match) { + menu->sel = menu->sel->prev_match; + menu_invalidate(menu); + } else if (menu->cursor > 0) { + menu->cursor = nextrune(menu, -1); + menu_invalidate(menu); + } + break; + case XKB_KEY_Right: + case XKB_KEY_KP_Right: + case XKB_KEY_Down: + case XKB_KEY_KP_Down: + if (menu->cursor < len) { + menu->cursor = nextrune(menu, +1); + menu_invalidate(menu); + } else if (menu->sel && menu->sel->next_match) { + menu->sel = menu->sel->next_match; + menu_invalidate(menu); + } + break; + case XKB_KEY_Prior: + case XKB_KEY_KP_Prior: + if (menu->sel && menu->sel->page->prev) { + menu->sel = menu->sel->page->prev->first; + menu_invalidate(menu); + } + break; + case XKB_KEY_Next: + case XKB_KEY_KP_Next: + if (menu->sel && menu->sel->page->next) { + menu->sel = menu->sel->page->next->first; + menu_invalidate(menu); + } + break; + case XKB_KEY_Home: + case XKB_KEY_KP_Home: + if (menu->sel == menu->matches) { + menu->cursor = 0; + menu_invalidate(menu); + } else { + menu->sel = menu->matches; + menu_invalidate(menu); + } + break; + case XKB_KEY_End: + case XKB_KEY_KP_End: + if (menu->cursor < len) { + menu->cursor = len; + menu_invalidate(menu); + } else { + menu->sel = menu->matches_end; + menu_invalidate(menu); + } + break; + case XKB_KEY_BackSpace: + if (menu->cursor > 0) { + insert(menu, NULL, nextrune(menu, -1) - menu->cursor); + match_items(menu); + menu_invalidate(menu); + } + break; + case XKB_KEY_Delete: + case XKB_KEY_KP_Delete: + if (menu->cursor == len) { + return; + } + menu->cursor = nextrune(menu, +1); + insert(menu, NULL, nextrune(menu, -1) - menu->cursor); + match_items(menu); + menu_invalidate(menu); + break; + case XKB_KEY_Tab: + if (!menu->sel) { + return; + } + menu->cursor = strnlen(menu->sel->text, sizeof menu->input - 1); + memcpy(menu->input, menu->sel->text, menu->cursor); + menu->input[menu->cursor] = '\0'; + match_items(menu); + menu_invalidate(menu); + break; + case XKB_KEY_Escape: + menu->exit = true; + menu->failure = true; + break; + default: + if (xkb_keysym_to_utf8(sym, buf, 8)) { + insert(menu, buf, strnlen(buf, 8)); + match_items(menu); + menu_invalidate(menu); + } + } +} diff --git a/wmenu/menu.h b/wmenu/menu.h new file mode 100755 index 0000000..fdd9ad2 --- /dev/null +++ b/wmenu/menu.h @@ -0,0 +1,95 @@ +#ifndef WMENU_MENU_H +#define WMENU_MENU_H + +#include <cairo/cairo.h> +#include <stdbool.h> +#include <sys/types.h> +#include <xkbcommon/xkbcommon.h> +#include <wayland-client.h> + +struct menu; +typedef void (*menu_callback)(struct menu *menu, char *text, bool exit); + +// A menu item. +struct item { + char *text; + int width; + struct item *prev_match; // previous matching item + struct item *next_match; // next matching item + struct page *page; // the page holding this item +}; + +// A page of menu items. +struct page { + struct item *first; // first item in the page + struct item *last; // last item in the page + struct page *prev; // previous page + struct page *next; // next page +}; + +// Menu state. +struct menu { + // Whether the menu appears at the bottom of the screen + bool bottom; + // The function used to match menu items + int (*strncmp)(const char *, const char *, size_t); + // Whether the input is a password + bool passwd; + // The font used to display the menu + char *font; + // The number of lines to list items vertically + int lines; + // The name of the output to display on + char *output_name; + // The prompt displayed to the left of the input field + char *prompt; + // Normal colors + uint32_t normalbg, normalfg; + // Prompt colors + uint32_t promptbg, promptfg; + // Selection colors + uint32_t selectionbg, selectionfg; + + struct wl_context *context; + + // 1x1 surface used estimate text sizes with pango + cairo_surface_t *test_surface; + cairo_t *test_cairo; + + int width; + int height; + int line_height; + int padding; + int inputw; + int promptw; + int left_arrow; + int right_arrow; + bool rendered; + + char input[BUFSIZ]; + size_t cursor; + + struct item *items; // array of all items + size_t item_count; + struct item *matches; // list of matching items + struct item *matches_end; // last matching item + struct item *sel; // selected item + struct page *pages; // list of pages + + menu_callback callback; + bool exit; + bool failure; +}; + +struct menu *menu_create(menu_callback callback); +void menu_destroy(struct menu *menu); +void menu_getopts(struct menu *menu, int argc, char *argv[]); +void menu_add_item(struct menu *menu, char *text); +void menu_sort_and_deduplicate(struct menu *menu); +void menu_invalidate(struct menu *menu); +void menu_render_items(struct menu *menu); +void menu_paste(struct menu *menu, const char *text, ssize_t len); +void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state, + xkb_keysym_t sym); + +#endif diff --git a/wmenu/meson.build b/wmenu/meson.build new file mode 100755 index 0000000..3a5cb18 --- /dev/null +++ b/wmenu/meson.build @@ -0,0 +1,80 @@ +project( + 'wmenu', + 'c', + version: '0.2.0', + license: 'MIT', + default_options: [ + 'c_std=c11', + 'warning_level=2', + 'werror=true', + ] +) + +cc = meson.get_compiler('c') + +add_project_arguments(cc.get_supported_arguments([ + '-DVERSION="@0@"'.format(meson.project_version()), + + '-Wno-missing-field-initializers', + '-Wno-unused-parameter', + '-Wundef', + '-Wvla', +]), language : 'c') + +cairo = dependency('cairo') +pango = dependency('pango') +pangocairo = dependency('pangocairo') +wayland_client = dependency('wayland-client') +wayland_protos = dependency('wayland-protocols') +xkbcommon = dependency('xkbcommon') + +rt = cc.find_library('rt') + +subdir('protocols') +subdir('docs') + +executable( + 'wmenu', + files( + 'menu.c', + 'pango.c', + 'pool-buffer.c', + 'render.c', + 'wayland.c', + 'wmenu.c', + ), + dependencies: [ + cairo, + client_protos, + pango, + pangocairo, + rt, + wayland_client, + wayland_protos, + xkbcommon, + ], + install: true, +) + +executable( + 'wmenu-run', + files( + 'menu.c', + 'pango.c', + 'pool-buffer.c', + 'render.c', + 'wayland.c', + 'wmenu-run.c', + ), + dependencies: [ + cairo, + client_protos, + pango, + pangocairo, + rt, + wayland_client, + wayland_protos, + xkbcommon, + ], + install: true, +) diff --git a/wmenu/pango.c b/wmenu/pango.c new file mode 100755 index 0000000..07d4c5b --- /dev/null +++ b/wmenu/pango.c @@ -0,0 +1,71 @@ +#include <cairo/cairo.h> +#include <pango/pangocairo.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "pango.h" + +int get_font_height(const char *fontstr) { + PangoFontMap *fontmap = pango_cairo_font_map_get_default(); + PangoContext *context = pango_font_map_create_context(fontmap); + PangoFontDescription *desc = pango_font_description_from_string(fontstr); + PangoFont *font = pango_font_map_load_font(fontmap, context, desc); + if (font == NULL) { + pango_font_description_free(desc); + g_object_unref(context); + return -1; + } + PangoFontMetrics *metrics = pango_font_get_metrics(font, NULL); + int height = pango_font_metrics_get_height(metrics) / PANGO_SCALE; + pango_font_metrics_unref(metrics); + g_object_unref(font); + pango_font_description_free(desc); + g_object_unref(context); + return height; +} + +PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, + const char *text, double scale) { + PangoLayout *layout = pango_cairo_create_layout(cairo); + PangoAttrList *attrs = pango_attr_list_new(); + pango_layout_set_text(layout, text, -1); + pango_attr_list_insert(attrs, pango_attr_scale_new(scale)); + PangoFontDescription *desc = pango_font_description_from_string(font); + pango_layout_set_font_description(layout, desc); + pango_layout_set_single_paragraph_mode(layout, 1); + pango_layout_set_attributes(layout, attrs); + pango_font_description_free(desc); + pango_attr_list_unref(attrs); + return layout; +} + +void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, + int *baseline, double scale, const char *text) { + PangoLayout *layout = get_pango_layout(cairo, font, text, scale); + pango_cairo_update_layout(cairo, layout); + pango_layout_get_pixel_size(layout, width, height); + if (baseline) { + *baseline = pango_layout_get_baseline(layout) / PANGO_SCALE; + } + g_object_unref(layout); +} + +int text_width(cairo_t *cairo, const char *font, const char *text) { + int text_width; + get_text_size(cairo, font, &text_width, NULL, NULL, 1, text); + return text_width; +} + +void pango_printf(cairo_t *cairo, const char *font, double scale, + const char *text) { + PangoLayout *layout = get_pango_layout(cairo, font, text, scale); + cairo_font_options_t *fo = cairo_font_options_create(); + cairo_get_font_options(cairo, fo); + pango_cairo_context_set_font_options(pango_layout_get_context(layout), fo); + cairo_font_options_destroy(fo); + pango_cairo_update_layout(cairo, layout); + pango_cairo_show_layout(cairo, layout); + g_object_unref(layout); +} diff --git a/wmenu/pango.h b/wmenu/pango.h new file mode 100755 index 0000000..482d49a --- /dev/null +++ b/wmenu/pango.h @@ -0,0 +1,16 @@ +#ifndef WMENU_PANGO_H +#define WMENU_PANGO_H +#include <stdbool.h> +#include <cairo/cairo.h> +#include <pango/pangocairo.h> + +int get_font_height(const char *font); +PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, + const char *text, double scale); +void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, + int *baseline, double scale, const char *text); +int text_width(cairo_t *cairo, const char *font, const char *text); +void pango_printf(cairo_t *cairo, const char *font, double scale, + const char *text); + +#endif diff --git a/wmenu/pool-buffer.c b/wmenu/pool-buffer.c new file mode 100755 index 0000000..daa84fd --- /dev/null +++ b/wmenu/pool-buffer.c @@ -0,0 +1,146 @@ +#define _POSIX_C_SOURCE 200809L +#include <assert.h> +#include <cairo.h> +#include <errno.h> +#include <fcntl.h> +#include <pango/pangocairo.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <time.h> +#include <unistd.h> +#include <wayland-client.h> + +#include "pool-buffer.h" + +static void randname(char *buf) { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + long r = ts.tv_nsec; + for (int i = 0; i < 6; ++i) { + buf[i] = 'A'+(r&15)+(r&16)*2; + r >>= 5; + } +} + +static int anonymous_shm_open(void) { + char name[] = "/wmenu-XXXXXX"; + int retries = 100; + + do { + randname(name + strlen(name) - 6); + + --retries; + // shm_open guarantees that O_CLOEXEC is set + int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd >= 0) { + shm_unlink(name); + return fd; + } + } while (retries > 0 && errno == EEXIST); + + return -1; +} + +static int create_shm_file(off_t size) { + int fd = anonymous_shm_open(); + if (fd < 0) { + return fd; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static void buffer_release(void *data, struct wl_buffer *wl_buffer) { + struct pool_buffer *buffer = data; + buffer->busy = false; +} + +static const struct wl_buffer_listener buffer_listener = { + .release = buffer_release +}; + +static struct pool_buffer *create_buffer(struct wl_shm *shm, + struct pool_buffer *buf, int32_t width, int32_t height, + int32_t scale, uint32_t format) { + int32_t stride = width * scale * 4; + int32_t size = stride * height * scale; + + int fd = create_shm_file(size); + assert(fd != -1); + void *data = mmap(NULL, (size_t)size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); + buf->buffer = wl_shm_pool_create_buffer(pool, 0, + width * scale, height * scale, stride, format); + wl_shm_pool_destroy(pool); + close(fd); + + buf->size = (size_t)size; + buf->width = width; + buf->height = height; + buf->scale = scale; + buf->data = data; + buf->surface = cairo_image_surface_create_for_data(data, + CAIRO_FORMAT_ARGB32, width * scale, height * scale, stride); + cairo_surface_set_device_scale(buf->surface, scale, scale); + buf->cairo = cairo_create(buf->surface); + buf->pango = pango_cairo_create_context(buf->cairo); + + wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); + return buf; +} + +void destroy_buffer(struct pool_buffer *buffer) { + if (buffer->buffer) { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->cairo) { + cairo_destroy(buffer->cairo); + } + if (buffer->surface) { + cairo_surface_destroy(buffer->surface); + } + if (buffer->pango) { + g_object_unref(buffer->pango); + } + if (buffer->data) { + munmap(buffer->data, buffer->size); + } + memset(buffer, 0, sizeof(struct pool_buffer)); +} + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], int32_t width, int32_t height, int32_t scale) { + struct pool_buffer *buffer = NULL; + + for (size_t i = 0; i < 2; ++i) { + if (pool[i].busy) { + continue; + } + buffer = &pool[i]; + } + + if (!buffer) { + return NULL; + } + + if (buffer->width != width || buffer->height != height + || buffer->scale != scale) { + destroy_buffer(buffer); + } + + if (!buffer->buffer) { + if (!create_buffer(shm, buffer, width, height, scale, + WL_SHM_FORMAT_ARGB8888)) { + return NULL; + } + } + buffer->busy = true; + return buffer; +} diff --git a/wmenu/pool-buffer.h b/wmenu/pool-buffer.h new file mode 100755 index 0000000..e07802d --- /dev/null +++ b/wmenu/pool-buffer.h @@ -0,0 +1,26 @@ +/* Taken from sway. MIT licensed */ +#ifndef WMENU_POOL_BUFFER_H +#define WMENU_POOL_BUFFER_H + +#include <cairo.h> +#include <pango/pangocairo.h> +#include <stdbool.h> +#include <stdint.h> +#include <wayland-client.h> + +struct pool_buffer { + struct wl_buffer *buffer; + cairo_surface_t *surface; + cairo_t *cairo; + PangoContext *pango; + size_t size; + int32_t width, height, scale; + bool busy; + void *data; +}; + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], int32_t width, int32_t height, int32_t scale); +void destroy_buffer(struct pool_buffer *buffer); + +#endif diff --git a/wmenu/protocols/meson.build b/wmenu/protocols/meson.build new file mode 100755 index 0000000..5c9973d --- /dev/null +++ b/wmenu/protocols/meson.build @@ -0,0 +1,47 @@ +wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') + +wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true) +if wayland_scanner_dep.found() + wayland_scanner = find_program( + wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'), + native: true, + ) +else + wayland_scanner = find_program('wayland-scanner', native: true) +endif + +protocols = [ + [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], + [wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'], + ['wlr-layer-shell-unstable-v1.xml'], +] + +wl_protos_src = [] +wl_protos_headers = [] + +foreach p : protocols + xml = join_paths(p) + wl_protos_src += custom_target( + xml.underscorify() + '_protocol_c', + input: xml, + output: '@BASENAME@-protocol.c', + command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'], + ) + wl_protos_headers += custom_target( + xml.underscorify() + '_client_h', + input: xml, + output: '@BASENAME@-client-protocol.h', + command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'], + ) +endforeach + +lib_client_protos = static_library( + 'client_protos', + wl_protos_src + wl_protos_headers, + dependencies: wayland_client.partial_dependency(compile_args: true), +) + +client_protos = declare_dependency( + link_with: lib_client_protos, + sources: wl_protos_headers, +) diff --git a/wmenu/protocols/wlr-layer-shell-unstable-v1.xml b/wmenu/protocols/wlr-layer-shell-unstable-v1.xml new file mode 100755 index 0000000..216e0d9 --- /dev/null +++ b/wmenu/protocols/wlr-layer-shell-unstable-v1.xml @@ -0,0 +1,285 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="wlr_layer_shell_unstable_v1"> + <copyright> + Copyright © 2017 Drew DeVault + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, 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. + </copyright> + + <interface name="zwlr_layer_shell_v1" version="1"> + <description summary="create surfaces that are layers of the desktop"> + Clients can use this interface to assign the surface_layer role to + wl_surfaces. Such surfaces are assigned to a "layer" of the output and + rendered with a defined z-depth respective to each other. They may also be + anchored to the edges and corners of a screen and specify input handling + semantics. This interface should be suitable for the implementation of + many desktop shell components, and a broad number of other applications + that interact with the desktop. + </description> + + <request name="get_layer_surface"> + <description summary="create a layer_surface from a surface"> + Create a layer surface for an existing surface. This assigns the role of + layer_surface, or raises a protocol error if another role is already + assigned. + + Creating a layer surface from a wl_surface which has a buffer attached + or committed is a client error, and any attempts by a client to attach + or manipulate a buffer prior to the first layer_surface.configure call + must also be treated as errors. + + You may pass NULL for output to allow the compositor to decide which + output to use. Generally this will be the one that the user most + recently interacted with. + + Clients can specify a namespace that defines the purpose of the layer + surface. + </description> + <arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/> + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="output" type="object" interface="wl_output" allow-null="true"/> + <arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/> + <arg name="namespace" type="string" summary="namespace for the layer surface"/> + </request> + + <enum name="error"> + <entry name="role" value="0" summary="wl_surface has another role"/> + <entry name="invalid_layer" value="1" summary="layer value is invalid"/> + <entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/> + </enum> + + <enum name="layer"> + <description summary="available layers for surfaces"> + These values indicate which layers a surface can be rendered in. They + are ordered by z depth, bottom-most first. Traditional shell surfaces + will typically be rendered between the bottom and top layers. + Fullscreen shell surfaces are typically rendered at the top layer. + Multiple surfaces can share a single layer, and ordering within a + single layer is undefined. + </description> + + <entry name="background" value="0"/> + <entry name="bottom" value="1"/> + <entry name="top" value="2"/> + <entry name="overlay" value="3"/> + </enum> + </interface> + + <interface name="zwlr_layer_surface_v1" version="1"> + <description summary="layer metadata interface"> + An interface that may be implemented by a wl_surface, for surfaces that + are designed to be rendered as a layer of a stacked desktop-like + environment. + + Layer surface state (size, anchor, exclusive zone, margin, interactivity) + is double-buffered, and will be applied at the time wl_surface.commit of + the corresponding wl_surface is called. + </description> + + <request name="set_size"> + <description summary="sets the size of the surface"> + Sets the size of the surface in surface-local coordinates. The + compositor will display the surface centered with respect to its + anchors. + + If you pass 0 for either value, the compositor will assign it and + inform you of the assignment in the configure event. You must set your + anchor to opposite edges in the dimensions you omit; not doing so is a + protocol error. Both values are 0 by default. + + Size is double-buffered, see wl_surface.commit. + </description> + <arg name="width" type="uint"/> + <arg name="height" type="uint"/> + </request> + + <request name="set_anchor"> + <description summary="configures the anchor point of the surface"> + Requests that the compositor anchor the surface to the specified edges + and corners. If two orthoginal edges are specified (e.g. 'top' and + 'left'), then the anchor point will be the intersection of the edges + (e.g. the top left corner of the output); otherwise the anchor point + will be centered on that edge, or in the center if none is specified. + + Anchor is double-buffered, see wl_surface.commit. + </description> + <arg name="anchor" type="uint" enum="anchor"/> + </request> + + <request name="set_exclusive_zone"> + <description summary="configures the exclusive geometry of this surface"> + Requests that the compositor avoids occluding an area of the surface + with other surfaces. The compositor's use of this information is + implementation-dependent - do not assume that this region will not + actually be occluded. + + A positive value is only meaningful if the surface is anchored to an + edge, rather than a corner. The zone is the number of surface-local + coordinates from the edge that are considered exclusive. + + Surfaces that do not wish to have an exclusive zone may instead specify + how they should interact with surfaces that do. If set to zero, the + surface indicates that it would like to be moved to avoid occluding + surfaces with a positive excluzive zone. If set to -1, the surface + indicates that it would not like to be moved to accommodate for other + surfaces, and the compositor should extend it all the way to the edges + it is anchored to. + + For example, a panel might set its exclusive zone to 10, so that + maximized shell surfaces are not shown on top of it. A notification + might set its exclusive zone to 0, so that it is moved to avoid + occluding the panel, but shell surfaces are shown underneath it. A + wallpaper or lock screen might set their exclusive zone to -1, so that + they stretch below or over the panel. + + The default value is 0. + + Exclusive zone is double-buffered, see wl_surface.commit. + </description> + <arg name="zone" type="int"/> + </request> + + <request name="set_margin"> + <description summary="sets a margin from the anchor point"> + Requests that the surface be placed some distance away from the anchor + point on the output, in surface-local coordinates. Setting this value + for edges you are not anchored to has no effect. + + The exclusive zone includes the margin. + + Margin is double-buffered, see wl_surface.commit. + </description> + <arg name="top" type="int"/> + <arg name="right" type="int"/> + <arg name="bottom" type="int"/> + <arg name="left" type="int"/> + </request> + + <request name="set_keyboard_interactivity"> + <description summary="requests keyboard events"> + Set to 1 to request that the seat send keyboard events to this layer + surface. For layers below the shell surface layer, the seat will use + normal focus semantics. For layers above the shell surface layers, the + seat will always give exclusive keyboard focus to the top-most layer + which has keyboard interactivity set to true. + + Layer surfaces receive pointer, touch, and tablet events normally. If + you do not want to receive them, set the input region on your surface + to an empty region. + + Events is double-buffered, see wl_surface.commit. + </description> + <arg name="keyboard_interactivity" type="uint"/> + </request> + + <request name="get_popup"> + <description summary="assign this layer_surface as an xdg_popup parent"> + This assigns an xdg_popup's parent to this layer_surface. This popup + should have been created via xdg_surface::get_popup with the parent set + to NULL, and this request must be invoked before committing the popup's + initial state. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + </description> + <arg name="popup" type="object" interface="xdg_popup"/> + </request> + + <request name="ack_configure"> + <description summary="ack a configure event"> + When a configure event is received, if a client commits the + surface in response to the configure event, then the client + must make an ack_configure request sometime before the commit + request, passing along the serial of the configure event. + + If the client receives multiple configure events before it + can respond to one, it only has to ack the last configure event. + + A client is not required to commit immediately after sending + an ack_configure request - it may even ack_configure several times + before its next surface commit. + + A client may send multiple ack_configure requests before committing, but + only the last request sent before a commit indicates which configure + event the client really is responding to. + </description> + <arg name="serial" type="uint" summary="the serial from the configure event"/> + </request> + + <request name="destroy" type="destructor"> + <description summary="destroy the layer_surface"> + This request destroys the layer surface. + </description> + </request> + + <event name="configure"> + <description summary="suggest a surface change"> + The configure event asks the client to resize its surface. + + Clients should arrange their surface for the new states, and then send + an ack_configure request with the serial sent in this configure event at + some point before committing the new surface. + + The client is free to dismiss all but the last configure event it + received. + + The width and height arguments specify the size of the window in + surface-local coordinates. + + The size is a hint, in the sense that the client is free to ignore it if + it doesn't resize, pick a smaller size (to satisfy aspect ratio or + resize in steps of NxM pixels). If the client picks a smaller size and + is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the + surface will be centered on this axis. + + If the width or height arguments are zero, it means the client should + decide its own window dimension. + </description> + <arg name="serial" type="uint"/> + <arg name="width" type="uint"/> + <arg name="height" type="uint"/> + </event> + + <event name="closed"> + <description summary="surface should be closed"> + The closed event is sent by the compositor when the surface will no + longer be shown. The output may have been destroyed or the user may + have asked for it to be removed. Further changes to the surface will be + ignored. The client should destroy the resource after receiving this + event, and create a new surface if they so choose. + </description> + </event> + + <enum name="error"> + <entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/> + <entry name="invalid_size" value="1" summary="size is invalid"/> + <entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/> + </enum> + + <enum name="anchor" bitfield="true"> + <entry name="top" value="1" summary="the top edge of the anchor rectangle"/> + <entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/> + <entry name="left" value="4" summary="the left edge of the anchor rectangle"/> + <entry name="right" value="8" summary="the right edge of the anchor rectangle"/> + </enum> + </interface> +</protocol> diff --git a/wmenu/render.c b/wmenu/render.c new file mode 100755 index 0000000..e86d93b --- /dev/null +++ b/wmenu/render.c @@ -0,0 +1,212 @@ +#define _POSIX_C_SOURCE 200809L +#include <cairo/cairo.h> +#include <stdlib.h> +#include <string.h> + +#include "render.h" + +#include "menu.h" +#include "pango.h" +#include "pool-buffer.h" +#include "wayland.h" + +// Calculate text widths. +void calc_widths(struct menu *menu) { + struct wl_context *context = menu->context; + int scale = context_get_scale(context); + cairo_surface_set_device_scale(menu->test_surface, scale, scale); + cairo_set_antialias(menu->test_cairo, CAIRO_ANTIALIAS_BEST); + cairo_font_options_t *fo = cairo_font_options_create(); + cairo_set_font_options(menu->test_cairo, fo); + cairo_font_options_destroy(fo); + cairo_t *cairo = menu->test_cairo; + + // Calculate prompt width + if (menu->prompt) { + menu->promptw = text_width(cairo, menu->font, menu->prompt) + menu->padding + menu->padding/2; + } else { + menu->promptw = 0; + } + + // Calculate scroll indicator widths + menu->left_arrow = text_width(cairo, menu->font, "<") + 2 * menu->padding; + menu->right_arrow = text_width(cairo, menu->font, ">") + 2 * menu->padding; + + // Calculate item widths and input area width + for (size_t i = 0; i < menu->item_count; i++) { + struct item *item = &menu->items[i]; + item->width = text_width(cairo, menu->font, item->text); + if (item->width > menu->inputw) { + menu->inputw = item->width; + } + } +} + +static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { + cairo_set_source_rgba(cairo, + (color >> (3*8) & 0xFF) / 255.0, + (color >> (2*8) & 0xFF) / 255.0, + (color >> (1*8) & 0xFF) / 255.0, + (color >> (0*8) & 0xFF) / 255.0); +} + +// Renders text to cairo. +static int render_text(struct menu *menu, cairo_t *cairo, const char *str, + int x, int y, int width, uint32_t bg_color, uint32_t fg_color, + int left_padding, int right_padding) { + + int text_width, text_height; + get_text_size(cairo, menu->font, &text_width, &text_height, NULL, 1, str); + int text_y = (menu->line_height / 2.0) - (text_height / 2.0); + + if (width == 0) { + width = text_width + left_padding + right_padding; + } + if (bg_color) { + cairo_set_source_u32(cairo, bg_color); + cairo_rectangle(cairo, x, y, width, menu->line_height); + cairo_fill(cairo); + } + cairo_move_to(cairo, x + left_padding, y + text_y); + cairo_set_source_u32(cairo, fg_color); + pango_printf(cairo, menu->font, 1, str); + + return width; +} + +// Renders the prompt message. +static void render_prompt(struct menu *menu, cairo_t *cairo) { + if (!menu->prompt) { + return; + } + render_text(menu, cairo, menu->prompt, 0, 0, 0, + menu->promptbg, menu->promptfg, menu->padding, menu->padding/2); +} + +// Renders the input text. +static void render_input(struct menu *menu, cairo_t *cairo) { + char *censort = NULL; + + if (menu->passwd) { + censort = calloc(1, sizeof(menu->input)); + if (!censort) { + return; + } + memset(censort, '*', strlen(menu->input)); + } + + render_text(menu, cairo, menu->passwd ? censort : menu->input, + menu->promptw, 0, 0, 0, menu->normalfg, menu->padding, menu->padding); + + if (censort) { + free(censort); + } +} + +// Renders a cursor for the input field. +static void render_cursor(struct menu *menu, cairo_t *cairo) { + const int cursor_width = 2; + const int cursor_margin = 2; + int cursor_pos = menu->promptw + menu->padding + + text_width(cairo, menu->font, menu->input) + - text_width(cairo, menu->font, &menu->input[menu->cursor]) + - cursor_width / 2; + cairo_rectangle(cairo, cursor_pos, cursor_margin, cursor_width, + menu->line_height - 2 * cursor_margin); + cairo_fill(cairo); +} + +// Renders a single menu item horizontally. +static int render_horizontal_item(struct menu *menu, cairo_t *cairo, struct item *item, int x) { + uint32_t bg_color = menu->sel == item ? menu->selectionbg : menu->normalbg; + uint32_t fg_color = menu->sel == item ? menu->selectionfg : menu->normalfg; + + return render_text(menu, cairo, item->text, x, 0, 0, + bg_color, fg_color, menu->padding, menu->padding); +} + +// Renders a single menu item vertically. +static int render_vertical_item(struct menu *menu, cairo_t *cairo, struct item *item, int x, int y) { + uint32_t bg_color = menu->sel == item ? menu->selectionbg : menu->normalbg; + uint32_t fg_color = menu->sel == item ? menu->selectionfg : menu->normalfg; + + render_text(menu, cairo, item->text, x, y, menu->width - x, + bg_color, fg_color, menu->padding, 0); + return menu->line_height; +} + +// Renders a page of menu items horizontally. +static void render_horizontal_page(struct menu *menu, cairo_t *cairo, struct page *page) { + int x = menu->promptw + menu->inputw + menu->left_arrow; + for (struct item *item = page->first; item != page->last->next_match; item = item->next_match) { + x += render_horizontal_item(menu, cairo, item, x); + } + + // Draw left and right scroll indicators if necessary + if (page->prev) { + cairo_move_to(cairo, menu->promptw + menu->inputw + menu->padding, 0); + pango_printf(cairo, menu->font, 1, "<"); + } + if (page->next) { + cairo_move_to(cairo, menu->width - menu->right_arrow + menu->padding, 0); + pango_printf(cairo, menu->font, 1, ">"); + } +} + +// Renders a page of menu items vertically. +static void render_vertical_page(struct menu *menu, cairo_t *cairo, struct page *page) { + int x = menu->promptw; + int y = menu->line_height; + for (struct item *item = page->first; item != page->last->next_match; item = item->next_match) { + y += render_vertical_item(menu, cairo, item, x, y); + } +} + +// Renders the menu to cairo. +static void render_to_cairo(struct menu *menu, cairo_t *cairo) { + // Render background + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_source_u32(cairo, menu->normalbg); + cairo_paint(cairo); + + // Render prompt and input + render_prompt(menu, cairo); + render_input(menu, cairo); + render_cursor(menu, cairo); + + // Render selected page + if (!menu->sel) { + return; + } + if (menu->lines > 0) { + render_vertical_page(menu, cairo, menu->sel->page); + } else { + render_horizontal_page(menu, cairo, menu->sel->page); + } +} + +// Renders a single frame of the menu. +void render_menu(struct menu *menu) { + struct wl_context *context = menu->context; + + int scale = context_get_scale(context); + struct pool_buffer *buffer = context_get_next_buffer(context, scale); + if (!buffer) { + return; + } + + cairo_t *shm = buffer->cairo; + cairo_set_antialias(shm, CAIRO_ANTIALIAS_BEST); + cairo_font_options_t *fo = cairo_font_options_create(); + cairo_set_font_options(shm, fo); + cairo_font_options_destroy(fo); + render_to_cairo(menu, shm); + + struct wl_surface *surface = context_get_surface(context); + wl_surface_set_buffer_scale(surface, scale); + wl_surface_attach(surface, buffer->buffer, 0, 0); + wl_surface_damage(surface, 0, 0, menu->width, menu->height); + wl_surface_commit(surface); + + menu->rendered = true; +} diff --git a/wmenu/render.h b/wmenu/render.h new file mode 100755 index 0000000..af5fb67 --- /dev/null +++ b/wmenu/render.h @@ -0,0 +1,9 @@ +#ifndef WMENU_RENDER_H +#define WMENU_RENDER_H + +#include "menu.h" + +void calc_widths(struct menu *menu); +void render_menu(struct menu *menu); + +#endif diff --git a/wmenu/wayland.c b/wmenu/wayland.c new file mode 100755 index 0000000..823ced1 --- /dev/null +++ b/wmenu/wayland.c @@ -0,0 +1,510 @@ +#define _POSIX_C_SOURCE 200809L +#include <assert.h> +#include <errno.h> +#include <poll.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <time.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/timerfd.h> +#include <wayland-client.h> +#include <wayland-client-protocol.h> +#include <xkbcommon/xkbcommon.h> + +#include "menu.h" +#include "pool-buffer.h" +#include "render.h" +#include "wayland.h" +#include "xdg-activation-v1-client-protocol.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" + +// A Wayland output. +struct output { + struct wl_context *context; + struct wl_output *output; + const char *name; // output name + int32_t scale; // output scale + struct output *next; // next output +}; + +// Creates and returns a new output. +static struct output *output_create(struct wl_context *context, struct wl_output *wl_output) { + struct output *output = calloc(1, sizeof(struct output)); + output->context = context; + output->output = wl_output; + output->scale = 1; + return output; +} + +// Keyboard state. +struct keyboard { + struct menu *menu; + struct wl_keyboard *keyboard; + struct xkb_context *context; + struct xkb_keymap *keymap; + struct xkb_state *state; + + int repeat_timer; + int repeat_delay; + int repeat_period; + enum wl_keyboard_key_state repeat_key_state; + xkb_keysym_t repeat_sym; +}; + +// Creates and returns a new keyboard. +static struct keyboard *keyboard_create(struct menu *menu, struct wl_keyboard *wl_keyboard) { + struct keyboard *keyboard = calloc(1, sizeof(struct keyboard)); + keyboard->menu = menu; + keyboard->keyboard = wl_keyboard; + keyboard->context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + assert(keyboard->context != NULL); + keyboard->repeat_timer = timerfd_create(CLOCK_MONOTONIC, 0); + assert(keyboard->repeat_timer != -1); + return keyboard; +} + +// Frees the keyboard. +static void free_keyboard(struct keyboard *keyboard) { + wl_keyboard_release(keyboard->keyboard); + xkb_state_unref(keyboard->state); + xkb_keymap_unref(keyboard->keymap); + xkb_context_unref(keyboard->context); + free(keyboard); +} + +// Wayland context. +struct wl_context { + struct menu *menu; + + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shm *shm; + struct wl_seat *seat; + struct wl_data_device_manager *data_device_manager; + struct zwlr_layer_shell_v1 *layer_shell; + struct output *output_list; + struct xdg_activation_v1 *activation; + + struct keyboard *keyboard; + struct wl_data_device *data_device; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + struct wl_data_offer *data_offer; + struct output *output; + + struct pool_buffer buffers[2]; + struct pool_buffer *current; +}; + +// Returns the current output_scale. +int context_get_scale(struct wl_context *context) { + return context->output ? context->output->scale : 1; +} + +// Returns the current buffer from the pool. +struct pool_buffer *context_get_current_buffer(struct wl_context *context) { + return context->current; +} + +// Returns the next buffer from the pool. +struct pool_buffer *context_get_next_buffer(struct wl_context *context, int scale) { + struct menu *menu = context->menu; + context->current = get_next_buffer(context->shm, context->buffers, menu->width, menu->height, scale); + return context->current; +} + +// Returns the Wayland surface for the context. +struct wl_surface *context_get_surface(struct wl_context *context) { + return context->surface; +} + +// Returns the XKB state for the context. +struct xkb_state *context_get_xkb_state(struct wl_context *context) { + return context->keyboard->state; +} + +// Returns the XDG activation object for the context. +struct xdg_activation_v1 *context_get_xdg_activation(struct wl_context *context) { + return context->activation; +} + +// Retrieves pasted text from a Wayland data offer. +bool context_paste(struct wl_context *context) { + if (!context->data_offer) { + return false; + } + + int fds[2]; + if (pipe(fds) == -1) { + // Pipe failed + return false; + } + wl_data_offer_receive(context->data_offer, "text/plain", fds[1]); + close(fds[1]); + + wl_display_roundtrip(context->display); + + while (true) { + char buf[1024]; + ssize_t n = read(fds[0], buf, sizeof(buf)); + if (n <= 0) { + break; + } + menu_paste(context->menu, buf, n); + } + close(fds[0]); + + wl_data_offer_destroy(context->data_offer); + context->data_offer = NULL; + return true; +} + +// Adds an output to the output list. +static void context_add_output(struct wl_context *context, struct output *output) { + output->next = context->output_list; + context->output_list = output; +} + +// Frees the outputs. +static void free_outputs(struct wl_context *context) { + struct output *next = context->output_list; + while (next) { + struct output *output = next; + next = output->next; + wl_output_destroy(output->output); + free(output); + } +} + +// Destroys the Wayland context, freeing memory associated with it. +static void context_destroy(struct wl_context *context) { + wl_registry_destroy(context->registry); + wl_compositor_destroy(context->compositor); + wl_shm_destroy(context->shm); + wl_seat_destroy(context->seat); + wl_data_device_manager_destroy(context->data_device_manager); + zwlr_layer_shell_v1_destroy(context->layer_shell); + free_outputs(context); + + free_keyboard(context->keyboard); + wl_data_device_destroy(context->data_device); + wl_surface_destroy(context->surface); + zwlr_layer_surface_v1_destroy(context->layer_surface); + xdg_activation_v1_destroy(context->activation); + + wl_display_disconnect(context->display); + free(context); +} + +static void noop() { + // Do nothing +} + +static void surface_enter(void *data, struct wl_surface *surface, struct wl_output *wl_output) { + struct wl_context *context = data; + context->output = wl_output_get_user_data(wl_output); + menu_invalidate(context->menu); +} + +static const struct wl_surface_listener surface_listener = { + .enter = surface_enter, + .leave = noop, +}; + +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct wl_context *context = data; + context->menu->width = width; + context->menu->height = height; + zwlr_layer_surface_v1_ack_configure(surface, serial); +} + +static void layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *surface) { + struct wl_context *context = data; + context->menu->exit = true; +} + +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; + +static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) { + struct output *output = data; + output->scale = factor; +} + +static void output_name(void *data, struct wl_output *wl_output, const char *name) { + struct output *output = data; + output->name = name; + + struct wl_context *context = output->context; + if (context->menu->output_name && strcmp(context->menu->output_name, name) == 0) { + context->output = output; + } +} + +static const struct wl_output_listener output_listener = { + .geometry = noop, + .mode = noop, + .done = noop, + .scale = output_scale, + .name = output_name, + .description = noop, +}; + +static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, + uint32_t format, int32_t fd, uint32_t size) { + struct keyboard *keyboard = data; + assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); + + char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + assert(map_shm != MAP_FAILED); + + keyboard->keymap = xkb_keymap_new_from_string(keyboard->context, + map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, 0); + munmap(map_shm, size); + close(fd); + + keyboard->state = xkb_state_new(keyboard->keymap); +} + +static void keyboard_repeat(struct keyboard *keyboard) { + menu_keypress(keyboard->menu, keyboard->repeat_key_state, keyboard->repeat_sym); + struct itimerspec spec = { 0 }; + spec.it_value.tv_sec = keyboard->repeat_period / 1000; + spec.it_value.tv_nsec = (keyboard->repeat_period % 1000) * 1000000l; + timerfd_settime(keyboard->repeat_timer, 0, &spec, NULL); +} + +static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t time, uint32_t key, uint32_t _key_state) { + struct keyboard *keyboard = data; + + enum wl_keyboard_key_state key_state = _key_state; + xkb_keysym_t sym = xkb_state_key_get_one_sym(keyboard->state, key + 8); + menu_keypress(keyboard->menu, key_state, sym); + + if (key_state == WL_KEYBOARD_KEY_STATE_PRESSED && keyboard->repeat_period >= 0) { + keyboard->repeat_key_state = key_state; + keyboard->repeat_sym = sym; + + struct itimerspec spec = { 0 }; + spec.it_value.tv_sec = keyboard->repeat_delay / 1000; + spec.it_value.tv_nsec = (keyboard->repeat_delay % 1000) * 1000000l; + timerfd_settime(keyboard->repeat_timer, 0, &spec, NULL); + } else if (key_state == WL_KEYBOARD_KEY_STATE_RELEASED) { + struct itimerspec spec = { 0 }; + timerfd_settime(keyboard->repeat_timer, 0, &spec, NULL); + } +} + +static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, + int32_t rate, int32_t delay) { + struct keyboard *keyboard = data; + keyboard->repeat_delay = delay; + if (rate > 0) { + keyboard->repeat_period = 1000 / rate; + } else { + keyboard->repeat_period = -1; + } +} + +static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, + uint32_t group) { + struct keyboard *keyboard = data; + xkb_state_update_mask(keyboard->state, mods_depressed, mods_latched, + mods_locked, 0, 0, group); +} + +static const struct wl_keyboard_listener keyboard_listener = { + .keymap = keyboard_keymap, + .enter = noop, + .leave = noop, + .key = keyboard_key, + .modifiers = keyboard_modifiers, + .repeat_info = keyboard_repeat_info, +}; + +static void seat_capabilities(void *data, struct wl_seat *seat, + enum wl_seat_capability caps) { + struct wl_context *context = data; + if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { + struct wl_keyboard *wl_keyboard = wl_seat_get_keyboard(seat); + struct keyboard *keyboard = keyboard_create(context->menu, wl_keyboard); + wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, keyboard); + context->keyboard = keyboard; + } +} + +static const struct wl_seat_listener seat_listener = { + .capabilities = seat_capabilities, + .name = noop, +}; + +static void data_device_selection(void *data, struct wl_data_device *data_device, + struct wl_data_offer *data_offer) { + struct wl_context *context = data; + context->data_offer = data_offer; +} + +static const struct wl_data_device_listener data_device_listener = { + .data_offer = noop, + .enter = noop, + .leave = noop, + .motion = noop, + .drop = noop, + .selection = data_device_selection, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + struct wl_context *context = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + context->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + context->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + context->seat = wl_registry_bind(registry, name, &wl_seat_interface, 4); + wl_seat_add_listener(context->seat, &seat_listener, data); + } else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) { + context->data_device_manager = wl_registry_bind(registry, name, &wl_data_device_manager_interface, 3); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + context->layer_shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + struct wl_output *wl_output = wl_registry_bind(registry, name, &wl_output_interface, 4); + struct output *output = output_create(context, wl_output); + wl_output_set_user_data(wl_output, output); + wl_output_add_listener(wl_output, &output_listener, output); + context_add_output(context, output); + } else if (strcmp(interface, xdg_activation_v1_interface.name) == 0) { + context->activation = wl_registry_bind(registry, name, &xdg_activation_v1_interface, 1); + } +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = noop, +}; + +// Connect to the Wayland display and run the menu. +int menu_run(struct menu *menu) { + struct wl_context *context = calloc(1, sizeof(struct wl_context)); + context->menu = menu; + menu->context = context; + + context->display = wl_display_connect(NULL); + if (!context->display) { + fprintf(stderr, "Failed to connect to display.\n"); + exit(EXIT_FAILURE); + } + + struct wl_registry *registry = wl_display_get_registry(context->display); + wl_registry_add_listener(registry, ®istry_listener, context); + wl_display_roundtrip(context->display); + assert(context->compositor != NULL); + assert(context->shm != NULL); + assert(context->seat != NULL); + assert(context->data_device_manager != NULL); + assert(context->layer_shell != NULL); + assert(context->activation != NULL); + context->registry = registry; + + // Get data device for seat + struct wl_data_device *data_device = wl_data_device_manager_get_data_device( + context->data_device_manager, context->seat); + wl_data_device_add_listener(data_device, &data_device_listener, context); + context->data_device = data_device; + + // Second roundtrip for seat and output listeners + wl_display_roundtrip(context->display); + assert(context->keyboard != NULL); + + if (menu->output_name && !context->output) { + fprintf(stderr, "Output %s not found\n", menu->output_name); + exit(EXIT_FAILURE); + } + + context->surface = wl_compositor_create_surface(context->compositor); + wl_surface_add_listener(context->surface, &surface_listener, context); + + struct zwlr_layer_surface_v1 *layer_surface = zwlr_layer_shell_v1_get_layer_surface( + context->layer_shell, + context->surface, + context->output ? context->output->output : NULL, + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + "menu" + ); + assert(layer_surface != NULL); + context->layer_surface = layer_surface; + + uint32_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if (menu->bottom) { + anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + } else { + anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; + } + + zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); + zwlr_layer_surface_v1_set_size(layer_surface, 0, menu->height); + zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, -1); + zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface, true); + zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, context); + + wl_surface_commit(context->surface); + wl_display_roundtrip(context->display); + menu_render_items(menu); + + struct pollfd fds[] = { + { wl_display_get_fd(context->display), POLLIN }, + { context->keyboard->repeat_timer, POLLIN }, + }; + const size_t nfds = sizeof(fds) / sizeof(*fds); + + while (!menu->exit) { + errno = 0; + do { + if (wl_display_flush(context->display) == -1 && errno != EAGAIN) { + fprintf(stderr, "wl_display_flush: %s\n", strerror(errno)); + break; + } + } while (errno == EAGAIN); + + if (poll(fds, nfds, -1) < 0) { + fprintf(stderr, "poll: %s\n", strerror(errno)); + break; + } + + if (fds[0].revents & POLLIN) { + if (wl_display_dispatch(context->display) < 0) { + menu->exit = true; + } + } + + if (fds[1].revents & POLLIN) { + keyboard_repeat(context->keyboard); + } + + // Render the menu if necessary + if (!menu->rendered) { + render_menu(menu); + } + } + + context_destroy(context); + menu->context = NULL; + + if (menu->failure) { + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/wmenu/wayland.h b/wmenu/wayland.h new file mode 100755 index 0000000..c5d7ce5 --- /dev/null +++ b/wmenu/wayland.h @@ -0,0 +1,19 @@ +#ifndef WMENU_WAYLAND_H +#define WMENU_WAYLAND_H + +#include "menu.h" +#include <wayland-client-protocol.h> + +struct wl_context; + +int menu_run(struct menu *menu); + +int context_get_scale(struct wl_context *context); +struct pool_buffer *context_get_current_buffer(struct wl_context *context); +struct pool_buffer *context_get_next_buffer(struct wl_context *context, int scale); +struct wl_surface *context_get_surface(struct wl_context *context); +struct xkb_state *context_get_xkb_state(struct wl_context *context); +struct xdg_activation_v1 *context_get_xdg_activation(struct wl_context *context); +bool context_paste(struct wl_context *context); + +#endif diff --git a/wmenu/wmenu-run.c b/wmenu/wmenu-run.c new file mode 100755 index 0000000..1b7b8c1 --- /dev/null +++ b/wmenu/wmenu-run.c @@ -0,0 +1,78 @@ +#define _POSIX_C_SOURCE 200809L +#include <dirent.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "menu.h" +#include "wayland.h" +#include "xdg-activation-v1-client-protocol.h" + +static void read_items(struct menu *menu) { + char *path = strdup(getenv("PATH")); + for (char *p = strtok(path, ":"); p != NULL; p = strtok(NULL, ":")) { + DIR *dir = opendir(p); + if (dir == NULL) { + continue; + } + for (struct dirent *ent = readdir(dir); ent != NULL; ent = readdir(dir)) { + if (ent->d_name[0] == '.') { + continue; + } + menu_add_item(menu, strdup(ent->d_name)); + } + closedir(dir); + } + menu_sort_and_deduplicate(menu); + free(path); +} + +struct command { + struct menu *menu; + char *text; + bool exit; +}; + +static void activation_token_done(void *data, struct xdg_activation_token_v1 *activation_token, + const char *token) { + struct command *cmd = data; + xdg_activation_token_v1_destroy(activation_token); + + int pid = fork(); + if (pid == 0) { + setenv("XDG_ACTIVATION_TOKEN", token, true); + char *argv[] = {"/bin/sh", "-c", cmd->text, NULL}; + execvp(argv[0], (char**)argv); + } else { + if (cmd->exit) { + cmd->menu->exit = true; + } + } +} + +static const struct xdg_activation_token_v1_listener activation_token_listener = { + .done = activation_token_done, +}; + +static void exec_item(struct menu *menu, char *text, bool exit) { + struct command *cmd = calloc(1, sizeof(struct command)); + cmd->menu = menu; + cmd->text = strdup(text); + cmd->exit = exit; + + struct xdg_activation_v1 *activation = context_get_xdg_activation(menu->context); + struct xdg_activation_token_v1 *activation_token = xdg_activation_v1_get_activation_token(activation); + xdg_activation_token_v1_set_surface(activation_token, context_get_surface(menu->context)); + xdg_activation_token_v1_add_listener(activation_token, &activation_token_listener, cmd); + xdg_activation_token_v1_commit(activation_token); +} + +int main(int argc, char *argv[]) { + struct menu *menu = menu_create(exec_item); + menu_getopts(menu, argc, argv); + read_items(menu); + int status = menu_run(menu); + menu_destroy(menu); + return status; +} diff --git a/wmenu/wmenu.c b/wmenu/wmenu.c new file mode 100755 index 0000000..38e78b9 --- /dev/null +++ b/wmenu/wmenu.c @@ -0,0 +1,35 @@ +#define _POSIX_C_SOURCE 200809L + +#include <stdio.h> +#include <string.h> + +#include "menu.h" +#include "wayland.h" + +static void read_items(struct menu *menu) { + char buf[sizeof menu->input]; + while (fgets(buf, sizeof buf, stdin)) { + char *p = strchr(buf, '\n'); + if (p) { + *p = '\0'; + } + menu_add_item(menu, strdup(buf)); + } +} + +static void print_item(struct menu *menu, char *text, bool exit) { + puts(text); + fflush(stdout); + if (exit) { + menu->exit = true; + } +} + +int main(int argc, char *argv[]) { + struct menu *menu = menu_create(print_item); + menu_getopts(menu, argc, argv); + read_items(menu); + int status = menu_run(menu); + menu_destroy(menu); + return status; +} -- cgit v1.2.3