aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustine Smithies <justine@smithies.me.uk>2026-08-03 21:04:57 +0100
committerJustine Smithies <justine@smithies.me.uk>2026-08-03 21:04:57 +0100
commit8c45e11ca4963df099e98ed41c8fd88478cd2161 (patch)
tree39e8e4da0a0a1578f1c1fc42c2783374a3c25975
parent2242abe2d2a353d96fa81968544ca08147062d08 (diff)
This is a WIP so will change quite a bit and other stuff like scripts external to CoW will be added later.
-rwxr-xr-x.config/cow/after-start.sh40
-rw-r--r--.config/cow/cow.conf531
2 files changed, 571 insertions, 0 deletions
diff --git a/.config/cow/after-start.sh b/.config/cow/after-start.sh
new file mode 100755
index 0000000..025027b
--- /dev/null
+++ b/.config/cow/after-start.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# Authentication dialog
+
+pkill -f /usr/local/libexec/polkit-gnome-authentication-agent-1
+/usr/local/libexec/polkit-gnome-authentication-agent-1 &
+
+# Start xdg-desktop-portal-wlr
+
+pkill -f /usr/local/libexec/xdg-desktop-portal-wlr
+/usr/local/libexec/xdg-desktop-portal-wlr &
+
+# Start Waybar
+pkill -f waybar
+waybar &
+
+# Start Kanshi
+pkill -f kanshi
+kanshi &
+
+# $wallpaper is set in your shells config file like below.
+read -r wallpaper<"$HOME/.cache/wallpaper"
+pkill -f swaybg
+swaybg -m fill -i "$wallpaper" &
+
+pkill -f dunst
+dunst &
+
+pkill -f wlsunset
+wlsunset -l 57.4 -L -1.9 &
+
+# Restore previous brightness
+backlight "$(grep 'brightness:' ~/.cache/brightness | awk '{print $2}')"
+
+# Restore audio volume
+mixer vol.volume="$(grep 'vol.volume=' ~/.cache/audio-volume | awk -F ':' '{print $2}')"
+mixer vol.mute="$(grep 'vol.mute=' ~/.cache/audio-volume | awk -F '=' '{print $2}')"
+
+sh "$HOME/.config/waybar/scripts/swayidle-update.sh"
+
diff --git a/.config/cow/cow.conf b/.config/cow/cow.conf
new file mode 100644
index 0000000..5e9112c
--- /dev/null
+++ b/.config/cow/cow.conf
@@ -0,0 +1,531 @@
+# cow window manager configuration
+#
+# This file is read directly from cow(1) but every command herein can be
+# sent to cow(1) via it's IPC mechanism with moocow(1).
+
+# Global settings
+
+# How much to move a window by when using key-bindings.
+set step 5
+
+# Set the focus policy -- can be `sloppy`, or `click`. Note that `sloppy`
+# does not imply root window focus, and perhaps this should be fixed, or
+# renamed to `follows-mouse`?
+set focus sloppy
+
+# How many pixels before a window is snapped.
+set snap_distance 12
+
+# Hide the pointer after this many milliseconds without input. Zero disables
+# pointer hiding.
+set cursor.hide_timeout 4000
+
+# Reserve an area on the screen. Can be reserved.{top, bottom, left, right}
+set reserved.top 35
+set reserved.left 10
+set reserved.right 10
+set reserved.bottom 10
+
+# Default decoration profile.
+decor -d default border.width 5
+decor -d default border.style fvwm
+# decor -d default border.corner_length 20
+decor -d default titlebar.height 22
+# decor -d default titlebar.position top
+decor -d default titlebar.font 'GoMono Nerd Font Mono 10'
+decor -d default icon.enabled true
+decor -d default icon.size 64
+# icon.image defaults to CoW's installed icon.
+# decor -d default icon.background 0x465457
+# decor -d default icon.foreground 0xFFFFFF
+# decor -d default icon.title_relief true
+decor -d default titlebar.enabled true
+decor -d default titlebar.button.1.vector 5 25x40@1 25x60@1 75x60@0 75x40@0 25x40@1
+decor -d default titlebar.button.1.action 'winops -c'
+decor -d default titlebar.button.2.vector 4 50x75@1 25x25@1 75x25@1 50x75@0
+decor -d default titlebar.button.2.action 'winops -i'
+decor -d default titlebar.button.0.vector 4 50x25@1 75x75@0 25x75@0 50x25@1
+decor -d default titlebar.button.0.action 'window-maximize -T'
+decor -a default
+
+# Theme packs can define decor profiles in separate files, with image paths
+# relative to that theme file. For example:
+#
+# include ~/.config/cow/themes/steel/theme.conf
+# decor -a steel
+#
+# See examples/themes/steel for a theme which uses SVG images for borders,
+# titlebars, tabs, and a titlebar button.
+
+# Container tab strip styling (optional overrides).
+#
+# By default, active tabs use the titlebar's base colour and inactive tabs
+# use the darkened (sunken) variant, with the titlebar's fg colour for all
+# labels so that text is readable regardless of background darkness.
+#
+# Uncomment and adjust to use distinct colours per-tab state:
+# container.tab.active_colour 0x3434E0
+# container.tab.fg_active 0xFFFFFF
+# Uncomment to restore the classic sunken bevel on inactive tabs:
+# container.tab.sunken true
+
+# Squeeze Titlebars.
+#
+# Similar to what CTWM used to allow, a squeeze titlebar is one whose length
+# is shortened to match the window title length. The remaining space is not
+# part of the window.
+#
+# For example:
+#
+titlebar.squeeze natural
+titlebar.squeeze.justify left
+#
+# Other justify options are right, centre
+# titlebar.squeeze fixed can be used as well to give a slightly larger
+# titlebar.
+
+# The colour to use for the background (globally across all outputs).
+set output.colour.background 0x3B05A6
+
+# Titlebar and frame gradients. Use `none` to return to solid colours.
+#
+# set titlebar.active_gradient HGradient 0x303030 0xC0C0C0
+# set titlebar.inactive_gradient VGradient 0x202020 0x606060
+# set border.active.gradient HGradient 0x404850 0xA0A8B0
+# set border.active.n.gradient HGradient 0x202830 0x90A0B0
+# set container.tab.active_gradient HGradient 0x607080 0xC0CCD0
+
+# Default window decoration (applies to all windows).
+#
+# Note that the colour options are still in hex, but are prefixed with `0x` to
+# disambiguate them from comments.
+#
+# Here. the window is styled by gicing each border a different colour, and the
+# handles (corners) a different colour as well.
+#
+# Inactive windows all have a grey (0xCDC9C9) colour. Note as well that
+# specifying the colour for `border.inactive` oe `border.active` in this way
+# sets the colour for all components, and are inherited. For example:
+#
+# Set the default colour of inactive windows:
+#
+# border.inactive = 0xCDC9C9
+# border.inactive.n = 0xFF00FF
+#
+# This would set the all components of the inactive window to grey, and style
+# just the north border as magenta,
+# decor -d global-on-map border.active.n 0xE50000
+# decor -d global-on-map border.active.s 0xC4D30D
+# decor -d global-on-map border.active.e 0xFFA500
+# decor -d global-on-map border.active.w 0x006400
+# decor -d global-on-map border.active.nw 0xFF00FF
+# decor -d global-on-map border.active.ne 0xFF00FF
+# decor -d global-on-map border.active.sw 0xFF00FF
+# decor -d global-on-map border.active.se 0xFF00FF
+# decor -d global-on-map border.inactive 0xCDC9C9
+# decor -d global-on-map titlebar.active_colour 0x83a598 # 3434E0
+# decor -d global-on-map titlebar.fg_active 0xFFFFFF
+# decor -d global-on-map titlebar.inactive_colour 0xCDC9C9
+
+decor -d global-on-map border.style fvwm
+decor -d global-on-map border.active.image none
+decor -d global-on-map border.inactive.image none
+decor -d global-on-map border.active.gradient HGradient 0x458588 0x83a598
+decor -d global-on-map border.inactive.gradient HGradient 0xa89984 0xebdbb2
+decor -d global-on-map titlebar.active_gradient HGradient 0x458588 0x83a598
+decor -d global-on-map titlebar.inactive_gradient HGradient 0xa89984 0xebdbb2
+decor -d global-on-map container.tab.active_gradient HGradient 0x458588 0x83a598
+decor -d global-on-map container.tab.inactive_gradient HGradient 0xa89984 0xebdbb2
+
+rule -g -Ton-map -nglobal-on-map decor -a global-on-map
+
+# Module chrome example. Sparse decor profiles are applied as overlays, so
+# this keeps the active theme colours/images and only removes cowiconman's
+# frame chrome.
+#
+# decor -d cowiconman-chrome border.width 0
+# decor -d cowiconman-chrome border.handles false
+# decor -d cowiconman-chrome titlebar.enabled false
+# rule -g -Ton-map -ncowiconman-chrome -s %cowiconman decor -a cowiconman-chrome
+
+# Per-desk override example, here windows on desks 1 and 2 have a different
+# style compared to the global rule '*', above. on-desk re-fires whenever
+# a desk becomes current (or a view maps onto it), and the rule subsystem
+# fans the body out across every view currently on the matching desk.
+# `-t :1` means "any output, desk 1"; the second colon syntax used previously
+# (`::1`) is now rejected as malformed.
+# decor -d per-1 titlebar.active_colour 0xFF8C00
+# decor -d per-1 titlebar.active_gradient none
+# decor -d per-1 titlebar.inactive_colour 0xB28E4C
+# decor -d per-1 border.inactive 0xB28E4C
+# decor -d per-2 titlebar.active_colour 0xFFD700
+# decor -d per-2 titlebar.active_gradient none
+#rule -T on-desk -t :1 -n per-1 decor -a per-1
+#rule -T on-desk -t :2 -n per-2 decor -a per-2
+
+# The restart rule allows for general cleanup. The `exec` command will always
+# run in this config on (re)start, so not doing things such as killing conky
+# or waybar will mean more than one instance will run.
+# rule -g -T on-restart -n cleanup \
+# exec killall waybar \; \
+# exec killall conky \; \
+# exec killall pasystray
+
+# Window placement policy. Can also be "centre", or "undermouse".
+set placement undermouse
+
+# Set the desk policy. Can be "global" where all screens share the same
+# desktop, or "per-output" where desks are unique to their outputs and each
+# output can be changed independently from one another.
+#
+# The default is `global`
+set desktop-configuration per-output
+
+# Virtual page grid. Anything greater than 1x1 enables paging; each desk
+# is then a `cols x rows` grid of pages navigated with the `scroll` command
+# (and optionally with edge_scroll for cursor-at-edge auto-pan).
+set desktop_size 1 1
+
+# Desktop management: cow defaults to setting up ten desks, which have a name
+# of 0..9 respectively.
+#
+# Both the name and the number of desktops available can be altered. For
+# example, to only have five desks, set the `desks.count` settings:
+#
+# set desks.count 5
+#
+# Without any further adjustment, cow would name those desks 0..4
+# respectively.
+#
+# To change a name of a desk, use the `desk-name` command. For example, to
+# name the first desk to 'main', use:
+#
+# desk-name 0 main
+#
+# This would set desk 0's name to 'main'.
+#
+# cowbar(1) can be told to use names explicitly rather than a desk number, by
+# using its `-n` option.
+
+# Smooth page transition animation (default: instant cut)
+#set page_scroll_animate true
+#set page_scroll_ms 200
+
+# Edge scroll: dwell at a screen edge to switch page (default: off).
+# The page switches once the cursor has been at the edge for
+# edge_scroll_delay_ms milliseconds. No-op directions (already at
+# the page-grid boundary) don't arm.
+#
+# If this is disabled, it's recommended to setup key bindings to switch pages.
+set edge_scroll true
+set edge_scroll_delay_ms 300
+
+# Raise on focus: raise window when focused (default: on).
+set raise_on_focus true
+
+# Desk switching.
+bind L+0 desk -d 0
+bind L+1 desk -d 1
+bind L+2 desk -d 2
+bind L+3 desk -d 3
+bind L+4 desk -d 4
+bind L+5 desk -d 5
+bind L+6 desk -d 6
+bind L+7 desk -d 7
+bind L+8 desk -d 8
+bind L+9 desk -d 9
+bind L+bracketright desk -n
+bind L+bracketleft desk -p
+
+# Send window to desk
+bind LS+0 window-move -k 0
+bind LS+1 window-move -k 1
+bind LS+2 window-move -k 2
+bind LS+3 window-move -k 3
+bind LS+4 window-move -k 4
+bind LS+5 window-move -k 5
+bind LS+6 window-move -k 6
+bind LS+7 window-move -k 7
+bind LS+8 window-move -k 8
+bind LS+9 window-move -k 9
+
+# Desk collection. This will show windows on the specified desk (the current
+# output is implied). When this happens, these "collected" windows can be
+# moved resized, etc. When the desk is uncollected (this command acts as a
+# toggle), the windows go back to their original desk, and their geometries
+# are restored.
+#
+# This gives a handy-way of glancing at other windows without having to make
+# them sticky, for example.
+bind LA+0 desk -c 0
+bind LA+1 desk -c 1
+bind LA+2 desk -c 2
+bind LA+3 desk -c 3
+bind LA+4 desk -c 4
+bind LA+5 desk -c 5
+bind LA+6 desk -c 6
+bind LA+7 desk -c 7
+bind LA+8 desk -c 8
+bind LA+9 desk -c 9
+
+# Window operations. -c close, -r raise, -l lower, etc.
+bind LS+a winops -c
+
+# -s sticks to desks, -S sticks to pages. Combine the two for window
+# stickiness over everything.
+bind L+s winops -sS
+bind A+up winops -r
+bind A+down winops -l
+bind L+m window-maximize -T
+bind C+Return window-expand -T
+bind C+i winops -i
+
+# Focus windows, next/prev.
+bind A+Tab focus -nw -F 'self.current_output'
+bind AS+Tab focus -pw -F 'self.current_output'
+
+# Move (see the `step` setting) -r after bind is for auto repeat
+bind -r LS+Up window-move -d up
+bind -r LS+Down window-move -d down
+bind -r LS+Left window-move -d left
+bind -r LS+Right window-move -d right
+
+# Move (snap to nearest edge / cross monitor)
+bind L+Up window-move -nw -d up
+bind L+Down window-move -nw -d down
+bind L+Left window-move -nw -d left
+bind L+Right window-move -nw -d right
+
+# Centre the window and focus.
+bind L+c script {
+ window-move -c
+ focus -w
+}
+
+# Resize
+bind LA+Up window-resize -s -d up
+bind LAS+Up window-resize -g -d up
+bind LA+Down window-resize -g -d down
+bind LAS+Down window-resize -s -d down
+bind LA+Left window-resize -s -d left
+bind LAS+Left window-resize -g -d left
+bind LA+Right window-resize -g -d right
+bind LAS+Right window-resize -s -d right
+
+# Session
+bind LCA+q quit
+
+# Custom bindings to run commands.
+bind L+Return exec foot
+bind L+d exec fuzzel
+
+# Power menu
+bind LS+p exec sh "$HOME/.local/bin/power-menu-fuzzel.sh"
+
+# Emoji menu
+bind LS+z exec sh "$HOME/.local/bin/emoji-menu.sh"
+
+# Take a screenshot of the focused output
+bind 0+Print exec sh "$HOME/.local/bin/screenshot.sh"
+
+# Take a screenshot of the focused window
+bind S+Print exec sh "$HOME/.local/bin/screenshot.sh focused-window"
+
+# Take a screenshot of the selected region
+bind L+Print exec sh "$HOME/.local/bin/screenshot.sh selected-region"
+
+# Take a screenshot and save it to the clipboard
+bind LS+Print exec sh "$HOME/.local/bin/screenshot.sh save-to-clipboard"
+
+# Mouse bindings
+mouse L+left window-move
+mouse L+right window-resize
+# Super+middle-drag: drag a window's titlebar onto another to containerise
+# them. Release over the target's titlebar to group; release over empty
+# space completes a normal move. Super+Shift+left is an alternative for
+# environments where middle-click is unavailable (e.g. VNC).
+mouse LA+left window-move -C
+mouse LS+left window-container -r
+
+# Decoration click bindings.
+#
+# The primary mouse button (button 1) can be bound to actions on a window's
+# decoration. See the *ANATOMY OF A WINDOW* section in cow(1).
+#
+# The -2 argument makes a binding fire on a double-click.
+#
+# A region can carry both a single-click and a double-click binding at
+# the same time.
+
+# Single-click edges / corners: interactive resize on the matching side.
+bind-decoration N window-resize -e n
+bind-decoration S window-resize -e s
+bind-decoration E window-resize -e e
+bind-decoration W window-resize -e w
+bind-decoration NE window-resize -e ne
+bind-decoration NW window-resize -e nw
+bind-decoration SE window-resize -e se
+bind-decoration SW window-resize -e sw
+
+# Single-click titlebar: interactive move.
+# Double-click titlebar: shade / unshade.
+bind-decoration titlebar window-move
+bind-decoration -2 titlebar window-shade -d titlebar
+
+# Example overrides (commented out):
+#bind-decoration titlebar window-maximize -m # left-click maximises
+#bind-decoration -2 NE winops -c # NE double-click closes
+
+# Container bindings
+# Super+G: group focused window with the next window in stacking order.
+# Works without a mouse -- useful in VNC or keyboard-only environments.
+bind L+g window-container -a
+# Super+Shift+G: remove the focused window from its container.
+bind LS+g window-container -r
+# Super+Tab / Super+Shift+Tab: cycle tabs within the focused container.
+bind L+Tab window-container -n
+bind LS+Tab window-container -p
+# Super+Ctrl+Tab / Super+Ctrl+Shift+Tab: reorder tabs within the container.
+bind LC+Tab window-container -N
+bind LCS+Tab window-container -P
+
+# Page navigation (only useful when desktop_size > 1x1). The `scroll`
+# command subsumes the old `page` command: it pans the desk viewport
+# by whole pages (with -d / -n / -P) or by arbitrary sub-page offsets
+# (a bare "H V" percentage, "-p H V" pixels, or an interactive
+# "-r" drag bound to a mouse button). See `list-commands` for the
+# full surface.
+#
+# Super+Ctrl+Right/Left/Down/Up: jump one page in that direction
+#bind LC+Right scroll -d right
+#bind LC+Left scroll -d left
+#bind LC+Down scroll -d down
+#bind LC+Up scroll -d up
+
+# Super+Ctrl+n / Super+Ctrl+p: next / previous page (with wrap)
+#bind LC+n scroll -n
+#bind LC+p scroll -P
+
+# Ctrl+Meta+Button1: grab and drag the desk viewport
+#mouse CM+Left scroll -r
+
+# Rules
+
+# Make mpv appear on top and become sticky
+rule -g -n mpv -T on-map -s %mpv script {
+ winops -sS
+ winops -L =top
+ window-resize -w 640 -h 360
+ window-move -x 1265 -y 705
+}
+
+exec sh "$HOME/.config/cow/after-start.sh"
+
+# Clipboard persistence (retain clipboard content after an app closes):
+#exec wl-clip-persist --clipboard regular
+
+# Menus
+#
+# Define menus with menu-add, then bind them to mouse buttons or keys.
+
+# Blue 3D menu appearance.
+# Solid colours are the fallback/base colours. Gradient values use:
+# none | HGradient <colour> <colour> | VGradient <colour> <colour>
+menu-style bg 0x174f9f
+menu-style fg 0xffffff
+menu-style title.bg 0x0f3977
+menu-style title.fg 0xffffff
+menu-style separator 0x082653
+menu-style bg.gradient VGradient 0x2b6fc4 0x123f84
+menu-style title.bg.gradient VGradient 0x1d5ba8 0x0b2f68
+menu-style border.width 2
+menu-style padding.x 8
+menu-style padding.y 3
+menu-style title.underlines 2
+menu-style automatic.hotkeys true
+
+# Sub-menu: send window to a desk.
+menu-add SendToDesk "Send to Desk" title
+menu-add SendToDesk "Desk 0" "window-move -k 0"
+menu-add SendToDesk "Desk 1" "window-move -k 1"
+menu-add SendToDesk "Desk 2" "window-move -k 2"
+menu-add SendToDesk "Desk 3" "window-move -k 3"
+menu-add SendToDesk "Desk 4" "window-move -k 4"
+menu-add SendToDesk "Desk 5" "window-move -k 5"
+menu-add SendToDesk "Desk 6" "window-move -k 6"
+
+# Window operations menu.
+menu-add WindowOps "Window" title
+menu-add WindowOps "Move" "window-move"
+menu-add WindowOps "Resize" "window-resize"
+menu-add WindowOps "Maximise" "window-maximize"
+menu-add WindowOps "Shade North" "window-shade -d n"
+menu-add WindowOps - -
+menu-add WindowOps "Send To Desk" "popup SendToDesk"
+menu-add WindowOps - -
+menu-add WindowOps "Iconify" "winops -i"
+menu-add WindowOps "Close" "winops -c"
+
+# Root menu.
+menu-add RootMenu "cow" title
+menu-add RootMenu "Foot" "exec foot"
+menu-add RootMenu - -
+menu-add RootMenu "Window Ops" "popup-pick WindowOps"
+menu-add RootMenu - -
+menu-add RootMenu "Restart" "exec moocow exec cow"
+menu-add RootMenu "Quit" "quit"
+
+# Mouse bindings for menus.
+# Left-click on the root window → root menu.
+root-mouse 0+left "menu-show RootMenu"
+#
+# If a window menu is not invoked from a known window context, use
+# pick-window so the selected menu action targets the picked window.
+# bind M+w "pick-window menu-show WindowOps"
+
+# Keyboard navigation while a menu is open.
+# Bind standard arrow/enter/escape keys to menu navigation.
+# These are no-ops when no menu is open.
+# cow bind format: <modifiers>+<XKB keysym name> (0 = no modifier)
+bind 0+Up menu-key up
+bind 0+Down menu-key down
+bind 0+Left menu-key left
+bind 0+Right menu-key right
+bind 0+Return menu-key select
+bind 0+Escape menu-key close
+bind 0+a menu-key a
+bind 0+b menu-key b
+bind 0+c menu-key c
+bind 0+d menu-key d
+bind 0+e menu-key e
+bind 0+f menu-key f
+bind 0+g menu-key g
+bind 0+h menu-key h
+bind 0+i menu-key i
+bind 0+j menu-key j
+bind 0+k menu-key k
+bind 0+l menu-key l
+bind 0+m menu-key m
+bind 0+n menu-key n
+bind 0+o menu-key o
+bind 0+p menu-key p
+bind 0+q menu-key q
+bind 0+r menu-key r
+bind 0+s menu-key s
+bind 0+t menu-key t
+bind 0+u menu-key u
+bind 0+v menu-key v
+bind 0+w menu-key w
+bind 0+x menu-key x
+bind 0+y menu-key y
+bind 0+z menu-key z
+bind 0+0 menu-key 0
+bind 0+1 menu-key 1
+bind 0+2 menu-key 2
+bind 0+3 menu-key 3
+bind 0+4 menu-key 4
+bind 0+5 menu-key 5
+bind 0+6 menu-key 6
+bind 0+7 menu-key 7
+bind 0+8 menu-key 8
+bind 0+9 menu-key 9