summaryrefslogtreecommitdiff
path: root/archive
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2024-04-22 07:32:20 +0100
committerSean Whitton <spwhitton@spwhitton.name>2024-04-22 07:33:14 +0100
commit4772be9dbdc18a7ead4339ee2500d9e828af4c8a (patch)
tree9e0cc9caf5694ae9bac3b4cd369b36367c98b5e2 /archive
parent05ba620733f91b2994d04f8cdf1e49d9a0c7a511 (diff)
downloaddotfiles-4772be9dbdc18a7ead4339ee2500d9e828af4c8a.tar.gz
archive remaining i3-specific config
Diffstat (limited to 'archive')
-rw-r--r--archive/.config/i3/config382
-rwxr-xr-xarchive/bin/choose-wallpaper38
-rw-r--r--archive/perl5/Desktop.pm156
-rwxr-xr-xarchive/scripts/desktop/dmenu_ssh7
-rwxr-xr-xarchive/scripts/desktop/dmenu_window8
-rwxr-xr-xarchive/scripts/desktop/i3-startup-always119
6 files changed, 710 insertions, 0 deletions
diff --git a/archive/.config/i3/config b/archive/.config/i3/config
new file mode 100644
index 00000000..ffb81c9b
--- /dev/null
+++ b/archive/.config/i3/config
@@ -0,0 +1,382 @@
+# i3 config file (v4)
+#
+# Please see http://i3wm.org/docs/userguide.html for a complete reference!
+
+# ** not updated for, or tested with, papersway **
+
+# Font for window titles. Will also be used by the bar unless a different font
+# is used in the bar {} block below.
+font pango:Hack 10
+
+# This font is widely installed, provides lots of unicode glyphs, right-to-left
+# text rendering and scalability on retina/hidpi displays (thanks to pango).
+#font pango:DejaVu Sans Mono 8
+
+# Before i3 v4.8, we used to recommend this one as the default:
+# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+# The font above is very space-efficient, that is, it looks good, sharp and
+# clear in small sizes. However, its unicode glyph coverage is limited, the old
+# X core fonts rendering does not support right-to-left and this being a bitmap
+# font, it doesn’t scale on retina/hidpi displays.
+
+# class border bground text indicator child_border
+client.focused #000000 #B4EEB4 #000000 #B4EEB4 #000000
+client.focused_inactive #000000 #FFFFF6 #000000 #AA9E9F #AA9E9F
+client.unfocused #000000 #E5E5E5 #000000 #AA9E9F #AA9E9F
+client.urgent #000000 #702020 #FFFFF6 #AA9E9F #AA9E9F
+client.placeholder #000000 #000000 #FFFFF6 #AA9E9F #AA9E9F
+
+client.background #FFFFF6
+
+# Use Mouse+Mod4 to drag floating windows to their wanted position
+floating_modifier Mod4
+
+# default workspace layout
+workspace_layout tabbed
+
+# this is so that C-i o will stay within the same output; I have convenient
+# bindings to get to other outputs so no need for directional movement to
+# permit moving between outputs (it would be even better if we could just
+# toggle this setting around the execution of C-i o, however)
+focus_wrapping workspace
+
+mouse_warping output
+
+# Key binding strategy:
+#
+# Use Ctrl+N and Mod1+Ctrl+N, which will never be bound in Emacs, for bindings
+# I will often need to type more than once in a row. Otherwise put the
+# bindings under the C-i prefix map, which will never be bound by Emacs
+# because text terminals typically can't distinguish between C-i and TAB.
+# If we need it, we can bind C-i Ctrl+N, C-i Mod1+Ctrl+N to pass the keys
+# through, like C-\ \ in tmux.
+#
+# Previously we used Mod4 modifying a key on the right side of the keyboard
+# instead of Ctrl+N and Mod1+Ctrl+N; there are enough of these that we can
+# still avoid any one-handed chording with only a single Super key. However,
+# this means using the weak little finger to hold down a modifier key for more
+# than one keypress with the other hand, which is worth avoiding.
+
+mode "C-i-" {
+ # make a fresh Emacs frame -- typically this gets invoked only on
+ # empty workspaces, as otherwise I use commands under `C-x 5` to get
+ # more Emacs frames
+ bindsym e exec emacsclient -ncw15, mode "default"
+
+ # override the script's usual logic to start a fresh, non-debug daemon
+ bindsym Ctrl+Mod1+e exec emacsclient -ncw8 --spw/installed, \
+ mode "default"
+
+ # special daemon instance for debugging primary instance & Gnus
+ bindsym r exec emacsclient -ncw8 -sgdbmacs, mode "default"
+
+ # Fresh Emacs frame and get a shell in HOME. Without this it's
+ # C-i e M-& which is too many keys esp. compared to C-i DEL
+ bindsym Return exec emacsclient -ncw15 -e \
+ "(let ((default-directory (expand-file-name "'"'~/'"'")) \
+ (display-buffer-overriding-action \
+ '(display-buffer-same-window \
+ . ((inhibit-same-window . nil))))) \
+ (transient-cycles-cmd-spw/eshell-jump-from-here))", \
+ mode "default"
+
+ # start a terminal emulator
+ bindsym BackSpace exec xfce4-terminal, mode "default"
+
+ # make a fresh browser window
+ bindsym b exec firefox -new-window, mode "default"
+
+ # lock screen -- relies on xss-lock
+ # note that this won't lock other VTs (lock-session*s*
+ # requires root password)
+ bindsym l exec loginctl lock-session \
+ && sleep 0.5 && xset dpms force standby, \
+ mode "default"
+
+ # go to sleep -- xss-lock will lock screen
+ bindsym Ctrl+l exec systemctl suspend, mode "default"
+
+ # kill focused window
+ # Unlike in sway config we don't send USR1 to i3status-wrapper because
+ # under i3bar that causes i3status-wrapper to exit 0 for some reason.
+ # For the time being there is no need to send the signal as
+ # expensive() does nothing useful under i3.
+ bindsym k kill, mode "default"
+
+ # start dmenu (a program launcher)
+ bindsym Ctrl+p exec dmenu_run \
+ -nf '#000000' -nb '#FFFFF6' -sb '#B4EEB4' -sf '#000000', \
+ mode "default"
+
+ # There also is the (new) i3-dmenu-desktop which only displays applications
+ # shipping a .desktop file. It is a wrapper around dmenu, so you need that
+ # installed.
+ bindsym p exec --no-startup-id i3-dmenu-desktop \
+ --dmenu="dmenu -i -nf '#000000' -nb '#FFFFF6' -sb '#B4EEB4' -sf '#000000'", \
+ mode "default"
+
+ bindsym s exec ~/src/dotfiles/scripts/desktop/dmenu_ssh \
+ -nf '#000000' -nb '#FFFFF6' -sb '#B4EEB4' -sf '#000000', \
+ mode "default"
+
+ # split in horizontal orientation
+ bindsym h split h, mode "default"
+
+ # split in vertical orientation
+ bindsym v split v, mode "default"
+
+ # enter fullscreen mode for the focused container
+ bindsym f fullscreen toggle, mode "default"
+
+ # change container layout (stacked, tabbed, toggle split)
+ # bindsym s layout stacking, mode "default"
+ bindsym w layout tabbed, mode "default"
+
+ # make a container independently tabbed
+ bindsym a split v, layout tabbed, mode "default"
+
+ # toggle tiling / floating
+ bindsym t floating toggle, mode "default"
+
+ # change focus between tiling / floating windows
+ bindsym Tab focus mode_toggle, mode "default"
+
+ # focus the parent container
+ bindsym u focus parent, mode "default"
+
+ # focus the child container
+ bindsym d focus child, mode "default"
+
+ # when screen is divided into two containers where at least one has
+ # several tabs, as I usually have it on a small laptop screen, this
+ # works well to go back and forth
+ bindsym o focus parent, focus right, mode "default"
+
+ # switch to workspace
+ bindsym 1 workspace 1, mode "default"
+ bindsym 2 workspace 2, mode "default"
+ bindsym 3 workspace 3, mode "default"
+ bindsym 4 workspace 4, mode "default"
+ bindsym 5 workspace 5, mode "default"
+ bindsym 6 workspace 6, mode "default"
+ bindsym 7 workspace 7, mode "default"
+ bindsym 8 workspace 8, mode "default"
+ bindsym 9 workspace 9, mode "default"
+ bindsym 0 workspace 10, mode "default"
+ bindsym F1 workspace 11:F1, mode "default"
+ bindsym F2 workspace 12:F2, mode "default"
+ bindsym F3 workspace 13:F3, mode "default"
+ bindsym F4 workspace 14:F4, mode "default"
+ bindsym F5 workspace 15:F5, mode "default"
+ bindsym F6 workspace 16:F6, mode "default"
+ bindsym F7 workspace 17:F7, mode "default"
+ bindsym F8 workspace 18:F8, mode "default"
+ bindsym F9 workspace 19:F9, mode "default"
+ bindsym F10 workspace 20:F10, mode "default"
+ bindsym F11 workspace 21:F11, mode "default"
+ bindsym F12 workspace 22:F12, mode "default"
+ bindsym semicolon workspace back_and_forth, mode "default"
+
+ # move focused container to workspace
+ bindsym Mod1+1 move container to workspace 1, mode "default"
+ bindsym Mod1+2 move container to workspace 2, mode "default"
+ bindsym Mod1+3 move container to workspace 3, mode "default"
+ bindsym Mod1+4 move container to workspace 4, mode "default"
+ bindsym Mod1+5 move container to workspace 5, mode "default"
+ bindsym Mod1+6 move container to workspace 6, mode "default"
+ bindsym Mod1+7 move container to workspace 7, mode "default"
+ bindsym Mod1+8 move container to workspace 8, mode "default"
+ bindsym Mod1+9 move container to workspace 9, mode "default"
+ bindsym Mod1+0 move container to workspace 10, mode "default"
+ bindsym Mod1+F1 move container to workspace 11:F1, mode "default"
+ bindsym Mod1+F2 move container to workspace 12:F2, mode "default"
+ bindsym Mod1+F3 move container to workspace 13:F3, mode "default"
+ bindsym Mod1+F4 move container to workspace 14:F4, mode "default"
+ bindsym Mod1+F5 move container to workspace 15:F5, mode "default"
+ bindsym Mod1+F6 move container to workspace 16:F6, mode "default"
+ bindsym Mod1+F7 move container to workspace 17:F7, mode "default"
+ bindsym Mod1+F8 move container to workspace 18:F8, mode "default"
+ bindsym Mod1+F9 move container to workspace 19:F9, mode "default"
+ bindsym Mod1+F10 move container to workspace 20:F10, mode "default"
+ bindsym Mod1+F11 move container to workspace 21:F11, mode "default"
+ bindsym Mod1+F12 move container to workspace 22:F12, mode "default"
+ bindsym Mod1+semicolon move container to workspace back_and_forth, \
+ mode "default"
+ bindsym Mod1+Ctrl+semicolon move container to workspace back_and_forth, \
+ workspace back_and_forth, mode "default"
+
+ # next unused workspace
+ bindsym j exec --no-startup-id \
+ ~/src/dotfiles/scripts/desktop/fresh-workspace, \
+ mode "default"
+ # sends window to next unused but doesn't change view
+ bindsym Mod1+j exec --no-startup-id \
+ ~/src/dotfiles/scripts/desktop/fresh-workspace --send, \
+ mode "default"
+ # sends window to next unused and changes view
+ bindsym Mod1+Ctrl+j exec --no-startup-id \
+ ~/src/dotfiles/scripts/desktop/fresh-workspace --take, \
+ mode "default"
+
+ # go to windows for tasks without needing to know the workspace
+ # bindsym slash exec --no-startup-id rofi -show window, mode "default"
+ bindsym slash exec ~/src/dotfiles/scripts/desktop/dmenu_window \
+ -nf '#000000' -nb '#FFFFF6' -sb '#B4EEB4' -sf '#000000', \
+ mode "default"
+
+ # reload the configuration file -- useful simply to reexecute
+ # startup scripts
+ bindsym Ctrl+Mod1+c reload; \
+ exec --no-startup-id ~/src/dotfiles/scripts/desktop/i3-startup-always, \
+ mode "default"
+ # restart i3 inplace (preserves your layout/session, can be
+ # used to upgrade i3)
+ bindsym Ctrl+Mod1+r restart, mode "default"
+ # exit i3 (logs you out of your X session)
+ bindsym Ctrl+Mod1+Shift+e exec "i3-nagbar -t warning \
+ -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' \
+ -b 'Yes, exit i3' 'i3-msg exit'", mode "default"
+
+ bindsym g mode "C-i g-"
+
+ bindsym n exec i3-msg '[title="\[mosh\] tmux default on athena"]' focus \
+ || xfce4-terminal -x ssh-and-tmux athena.silentflame.com, mode "default"
+
+ bindsym Ctrl+g mode "default"
+}
+bindsym Ctrl+i mode "C-i-"
+
+# change focus
+bindsym Ctrl+7 focus left
+bindsym Ctrl+0 focus right
+bindsym Ctrl+8 focus down
+bindsym Ctrl+9 focus up
+
+# move focused window
+bindsym Mod1+Ctrl+7 move left
+bindsym Mod1+Ctrl+0 move right
+bindsym Mod1+Ctrl+8 move down
+bindsym Mod1+Ctrl+9 move up
+
+bindsym Ctrl+5 kill
+bindsym Ctrl+6 fullscreen toggle
+
+bindsym Ctrl+apostrophe layout toggle splith splitv tabbed
+
+# Cycle through all workspaces on monitor.
+bindsym Ctrl+1 workspace prev_on_output
+bindsym Ctrl+4 workspace next_on_output
+bindsym Mod1+Ctrl+1 move container to workspace prev_on_output, \
+ workspace prev_on_output
+bindsym Mod1+Ctrl+4 move container to workspace next_on_output, \
+ workspace next_on_output
+
+# # move focus between monitors -- if we have more than one monitor, we
+# # probably have a numeric keypad available.
+# # subtleties: <https://github.com/i3/i3/issues/2558>
+# bindsym Mod4+Mod2+KP_4 focus output left
+# bindsym Mod4+KP_Left focus output left
+# bindsym Mod4+Mod2+KP_6 focus output right
+# bindsym Mod4+KP_Right focus output right
+
+# # move focused workspace between monitors
+# bindsym Mod4+Ctrl+Mod2+KP_Left move workspace to output left
+# bindsym Mod4+Ctrl+KP_4 move workspace to output left
+# bindsym Mod4+Ctrl+Mod2+KP_Right move workspace to output right
+# bindsym Mod4+Ctrl+KP_6 move workspace to output right
+
+bindsym Ctrl+2 focus output left
+bindsym Mod1+Ctrl+2 move workspace to output left
+bindsym Ctrl+3 focus output right
+bindsym Mod1+Ctrl+3 move workspace to output right
+
+# Start i3bar to display a workspace bar (plus the system information i3status
+# finds out, if available)
+bar {
+ # i3status is designed to be highly performant so it continues
+ # to be refreshed when the system is under load; we're giving
+ # up some of that with i3status-wrapper, but let's see if it
+ # actually matters
+ status_command ~/src/dotfiles/scripts/desktop/i3status-wrapper
+
+ # default behaviour is to cycle through workspaces when scroll
+ # wheel is used on the bar. However, don't think I've ever
+ # used this deliberately, and often I do it by mistake, so
+ # let's disable it
+ bindsym button4 nop
+ bindsym button5 nop
+
+ colors {
+ background #FFFFF6
+ statusline #000000
+ separator #000000
+
+ focused_workspace #000000 #B4EEB4 #000000
+ active_workspace #000000 #FFFFF6 #000000
+ inactive_workspace #000000 #E5E5E5 #000000
+ urgent_workspace #000000 #702020 #FFFFF6
+ binding_mode #000000 #EECD82 #000000
+ }
+
+ position bottom
+ strip_workspace_numbers yes
+
+ tray_output primary
+}
+
+# single key launching
+mode "C-i g-" {
+ # start a graphical file manager
+ bindsym g exec thunar , mode "default"
+
+ # launch xrandr graphical config
+ bindsym x exec arandr , mode "default"
+ # bindsym x exec xfce4-display-settings , mode "default"
+
+ # # get a new VT from lightdm
+ # bindsym g exec dm-tool switch-to-greeter , mode "default"
+
+ # adjust volume
+ bindsym v exec xfce4-terminal -e alsamixer , mode "default"
+
+ # work around bugs -- this fixes Emacs suddenly not accepting any
+ # keyboard input until a new frame is opened and then closed using
+ # emacsclient(1)
+ bindsym i exec ibus restart , mode "default"
+
+ bindsym Ctrl+g mode "default"
+}
+
+# audio
+bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5%
+bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5%
+bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle
+
+exec --no-startup-id emacsclient --spw/update-environment
+exec --no-startup-id emacsclient \
+ -sgdbmacs --spw/no-start --spw/update-environment
+exec --no-startup-id xss-lock --transfer-sleep-lock -- \
+ i3lock --nofork --ignore-empty-password --color=FFFFF6
+
+exec --no-startup-id nm-applet
+exec --no-startup-id caffeine-indicator
+
+# relies on existence of ~/.config/redshift.conf with latitude and longitude
+exec --no-startup-id redshift-gtk
+
+# for brightness control
+exec --no-startup-id xfce4-power-manager
+
+# idempotent settings and tweaks script
+exec_always --no-startup-id ~/src/dotfiles/scripts/desktop/i3-startup-always
+
+popup_during_fullscreen leave_fullscreen
+
+# windows that should always float
+for_window [title="^vokoscreen"] floating enable
+for_window [title="vokoscreen webcam"] border pixel 1
+for_window [title="^Ediff"] floating enable
+
+# # i3 titlebars are not very useful for Emacs frames; let's have an extra line
+# # of buffer text
+# for_window [class="^Emacs"] border pixel 2
diff --git a/archive/bin/choose-wallpaper b/archive/bin/choose-wallpaper
new file mode 100755
index 00000000..5fc14c83
--- /dev/null
+++ b/archive/bin/choose-wallpaper
@@ -0,0 +1,38 @@
+#!/usr/bin/env perl
+
+use 5.028;
+use strict;
+use warnings;
+use lib "$ENV{HOME}/src/dotfiles/perl5";
+
+use Local::Desktop;
+use File::Copy;
+
+# dirs where wallpaper can be found
+our @dirs = ("$ENV{HOME}/annex/wallpaper/pro");
+
+if (@ARGV and $ARGV[0] eq "--check-have") {
+ # ensure_resize_for_current_outputs;
+ exit !<"$ENV{HOME}/local/wallpaper??.*">;
+}
+
+die "need --random and/or some image files" unless @ARGV;
+
+my @wallpapers;
+if ($ARGV[0] eq "--random") {
+ shift;
+ push @wallpapers, pick_random_wallpapers 4, @dirs;
+}
+unshift @wallpapers, @ARGV;
+select_wallpaper_files @wallpapers;
+
+# resize_for_current_outputs;
+# system "$ENV{HOME}/src/dotfiles/scripts/desktop/i3-startup-always"; # feh & restart i3lock
+
+# now give develacc something
+if (-e "$ENV{HOME}/local/develacc") {
+ my $develacc_wallpaper = @ARGV ? $ARGV[$#ARGV] : $wallpapers[$#wallpapers];
+ my ($ext) = $develacc_wallpaper =~ /\.([^.]+)\z/;
+ copy $develacc_wallpaper,
+ "$ENV{HOME}/local/develacc/local/wallpaper00.$ext";
+}
diff --git a/archive/perl5/Desktop.pm b/archive/perl5/Desktop.pm
new file mode 100644
index 00000000..858e57cd
--- /dev/null
+++ b/archive/perl5/Desktop.pm
@@ -0,0 +1,156 @@
+package Local::Desktop;
+
+# graphical desktop management functions
+#
+# Copyright (C) 2020-2022 Sean Whitton
+#
+# 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 <https://www.gnu.org/licenses/>.
+
+use 5.028;
+use strict;
+use warnings;
+
+use Carp;
+use JSON;
+use File::Find;
+use File::LibMagic;
+use File::Spec::Functions "rel2abs";
+use Exporter "import";
+use File::Copy;
+use List::Util "first", "any";
+
+our @EXPORT = qw(
+ $wmipc wmipc
+ select_wallpaper_files
+ ensure_resize_for_current_outputs
+ resize_for_current_outputs
+ pick_random_wallpapers );
+
+`sh -c "command -v i3-msg"`;
+our $wmipc = $? == 0 ? "i3-msg" : "swaymsg";
+sub wmipc { system $wmipc, "-q", join "; ", @_ }
+
+my $output_re = qr/ ([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+) /;
+
+=head select_wallpaper_files(@files)
+
+Select the first entry of @files as the wallpaper for the first output, the
+second entry of @files as the wallpaper for the second output, etc.
+
+This function works by creating copies of those wallpapers in ~/local.
+
+=cut
+
+sub select_wallpaper_files {
+ my $i;
+ unlink <"$ENV{HOME}/local/wallpaper??.*">;
+ for (@_) {
+ -r or croak "$_ could not be read!";
+ copy $_,
+ sprintf "$ENV{HOME}/local/wallpaper%02d." . (/\.([^.]+)\z/)[0], $i++;
+ }
+}
+
+=head resize_for_current_outputs()
+
+Based on the output of xrandr(1), create ~/local/wallpaper.png from
+~/local/wallpaperNN.*, such that executing `feh --bg-scale --no-xinerama
+~/local/wallpaper.png` will put wallpaper00.* on the first output,
+wallpaper01.* on the second, etc. There should not be more than one file
+matching ~/local/wallpaperNN.* for each NN.
+
+Returns the value of $? right after executing convert(1).
+
+=cut
+
+sub resize_for_current_outputs {
+ # note that swaybg and swaylock have per-output wallpapers built in, so
+ # this function is only for X11
+
+ chomp(my @xrandr = `xrandr`);
+ my ($canvas_w, $canvas_h) = _get_screen_size(@xrandr);
+ # sort the displays from left to right and then from top to bottom
+ my @displays = sort {
+ my (undef, undef, $a_x, $a_y) = $a =~ $output_re;
+ my (undef, undef, $b_x, $b_y) = $b =~ $output_re;
+ $a_y <=> $b_y or $a_x <=> $b_x
+ } grep / connected /, @xrandr;
+
+ my @wallpapers = sort {
+ ($a =~ /wallpaper([0-9]+)\./)[0] <=> ($b =~ /wallpaper([0-9]+)\./)[0]
+ } <"$ENV{HOME}/local/wallpaper??.*">;
+
+ my @args = ("-page", "${canvas_w}x${canvas_h}", qw(-background none));
+ for (@displays) {
+ /$output_re/;
+ push @args, '(', (shift @wallpapers || "canvas:#FFFFF6"),
+ "-resize", "${1}x${2}^",
+ qw(-gravity center -extent), "${1}x${2}",
+ "-repage", "${1}x${2}+${3}+${4}", ')';
+ }
+ push @args, qw(-layers merge), "$ENV{HOME}/local/wallpaper.png";
+
+ system "convert", @args;
+ return $?;
+}
+
+=head ensure_resize_for_current_outputs()
+
+Call C<resize_for_current_outputs()> if it looks to be needed.
+
+=cut
+
+sub ensure_resize_for_current_outputs {
+ return unless <"$ENV{HOME}/local/wallpaper??.*">;
+ resize_for_current_outputs(), return
+ unless -e "$ENV{HOME}/local/wallpaper.png";
+ my ($screen_w, $screen_h) = _get_screen_size(`xrandr`);
+ my $magic = File::LibMagic->new;
+ my ($img_w, $img_h)
+ = $magic->info_from_filename("$ENV{HOME}/local/wallpaper.png")
+ ->{description} =~ / ([0-9]+) x ([0-9]+),/;
+ resize_for_current_outputs()
+ if $img_w
+ and $img_h
+ and ($screen_w != $img_w or $screen_h != $img_h);
+}
+
+=head pick_random_wallpapers($n, @dirs)
+
+Pick C<$n> random wallpapers from files in any of the directories listed in
+C<@dirs>.
+
+=cut
+
+sub pick_random_wallpapers {
+ my $n = shift;
+ my $magic = File::LibMagic->new(follow_symlinks => 1);
+ my (@images, @picks);
+ find sub {
+ push @images, $File::Find::name
+ if $magic->info_from_filename($_)->{description} =~ /^\w+ image/
+ }, @_;
+ push @picks, splice @images, int(rand @images), 1 for 1 .. $n;
+ return @picks;
+}
+
+sub _get_screen_size {
+ chomp(@_);
+ my ($canvas) = grep /^Screen 0:/, @_;
+ $canvas =~ /current ([0-9]+) x ([0-9]+)/;
+}
+
+sub _wsnum { (split /:/, $_[0])[0] }
+
+1;
diff --git a/archive/scripts/desktop/dmenu_ssh b/archive/scripts/desktop/dmenu_ssh
new file mode 100755
index 00000000..76d9aa72
--- /dev/null
+++ b/archive/scripts/desktop/dmenu_ssh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+host=$(perl -wlne'/^Host\s+(\S+)/ and !/\*/ and print $1' $HOME/.ssh/config \
+ | dmenu -p "ssh to tmux on host" "$@")
+if [ -n "$host" ]; then
+ xfce4-terminal -x ssh-and-tmux "$host"
+fi
diff --git a/archive/scripts/desktop/dmenu_window b/archive/scripts/desktop/dmenu_window
new file mode 100755
index 00000000..8dc33fde
--- /dev/null
+++ b/archive/scripts/desktop/dmenu_window
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+window=$(i3-msg -t get_tree \
+ | jq -r "recurse(.nodes[]) | select(.window) | .name" \
+ | dmenu -i -p "select window" "$@")
+if [ -n "$window" ]; then
+ i3-msg '[title="'$window'"] focus'
+fi
diff --git a/archive/scripts/desktop/i3-startup-always b/archive/scripts/desktop/i3-startup-always
new file mode 100755
index 00000000..b2a02e25
--- /dev/null
+++ b/archive/scripts/desktop/i3-startup-always
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+# idempotent X settings
+
+xrdb -merge "$HOME/.Xresources"
+
+# ---- don't let other local users spawn windows on my main X session
+
+xhost -local:
+
+# ---- no bell please
+
+xset b off
+
+# ---- keyboard settings
+
+xset r rate 380 25
+
+# enable numlock if using USB keyboard, with an exception
+if ! lsusb | grep -q "SiGma Micro Keyboard TRACER Gamma Ivory"; then
+ . /etc/X11/Xsession.d/55numlockx
+fi
+
+# disable caps lock if I accidently hit it before running this script
+if xset -q | grep "Caps Lock: *on" >/dev/null; then
+ xdotool key Caps_Lock
+fi
+
+# ---- wallpaper rotation
+
+# if [ -e "$HOME/local/wallpaper.png" ] \
+# && ! systemctl --user --quiet is-enabled i3-rotate-wallpaper.timer; then
+# # Persistent=true only works if the timer has been triggered at
+# # least once, but my computer is generally suspended at midnight.
+# # So pretend that the job just fired
+# mkdir -p "$HOME/.local/share/systemd/timers"
+# touch "$HOME/.local/share/systemd/timers/stamp-i3-rotate-wallpaper.timer"
+
+# systemctl --user --now enable i3-rotate-wallpaper.timer
+# fi
+
+# ---- monitor settings
+
+# if this machine is always plugged into the same monitor, may
+# `convert ~/lib/annex/doc/img/wallpaper/foo -resize 1366x768\!
+# ~/local/wallpaper.png` or add a cronjob to call i3-rotate-wallpaper.
+# Otherwise, stick to a solid colour, because doing otherwise requires
+# resizing the image file, setting the root window and restarting
+# i3lock every time an external monitor is plugged or unplugged
+#
+# For images that look bad stretched, to get black borders: convert foo.jpg -resize 1920x1080 -background black -gravity center -extent 1920x1080 ~/local/wallpaper.png
+
+# xsetroot -solid \#2c2c2e
+# xsetroot -solid \#111111
+# xsetroot -solid \#E5E5E5
+# xsetroot -solid \#FFFFF6
+
+# machine-specific display settings
+if [ "$(hostname -f)" = "iris.silentflame.com" ]; then
+ # set-half-brightness
+ if xrandr | grep "VGA-1 connected"; then
+ xrandr \
+ --output VGA-1 --primary --mode 1920x1080 --pos 0x0 --rotate normal \
+ --output LVDS-1 --mode 1366x768 --pos 1920x312 --rotate normal
+ else
+ xrandr \
+ --output VGA-1 --off \
+ --output LVDS-1 --primary --mode 1366x768 --pos 0x0 --rotate normal
+ fi
+elif [ "$(hostname -f)" = "melete.silentflame.com" ]; then
+ # set-half-brightness
+ # need this to set --primary, to ensure that i3 tray icons appear on
+ # laptop monitor
+ xrandr --output eDP-1 --primary --mode 1920x1080 --pos 0x0 --rotate normal
+fi
+
+# # use wallpaper.png if it's the right size
+# if i3-wallpaper --check-have; then
+# feh --bg-scale --no-xinerama $HOME/local/wallpaper.png
+
+# # restart i3lock, in case the wallpaper changed
+# i3-startup-i3lock
+# else
+ # feh --bg-tile ~/src/dotfiles/lib-src/img/diagmonds_2X.png
+# fi
+
+feh --bg-tile ~/src/dotfiles/lib-src/img/green_gobbler.png
+
+# Set how long before automatic lock. We have the DPMS time and the
+# automatic lock time set to the same value.
+#
+# I used to have have (e.g.) `xset s 150 180; xset dpms 1200 1200 0`
+# with a --notifier option passed to xss-lock which used i3-nagbar to
+# warn of an impending lock. This warning was necessary because
+# xtrlock's visual feedback is low. However, when i3-nagbar (or,
+# indeed, notify-send) is launched by xss-lock, they break the
+# display of various windows until the mouse is moved around. This
+# problem does not occur if I launch i3-nagbar from a terminal window.
+# In that case, everything gets redrawn as it should be.
+#
+# So instead, we wait to lock the screen until the point at which we
+# are blanking it for power saving. The screen going blank is
+# sufficient visual feedback.
+#
+# If my screen actually needs locking, I always just do that manually,
+# so this is only a fallback, in any case.
+#
+# Changes to these values should be kept in sync with comproc.org
+# notes for configuring xfce4-power-manager
+xset s default
+if [ "$(hostname)" = develacc ]; then
+ xset s 0
+ xset dpms 0 0 0
+ xset -dpms
+else
+ xset s 1200
+ xset dpms 1200 1200 1200
+ xset +dpms
+fi