Wai Hon's Blog

Automating i3 Scratchpad Setup

2022-03-17 #i3wm

Problem Statement

Scratchpad is a useful i3 feature to always have your favorite apps at hand. A typical configuration is to define a key binding to show or hide the scratchpad window. For example,

# Show the Emacs scratchpad window, if any.
bindsym $mod+j [class="(i?)emacs"] scratchpad show

However, i3 does nothing if the targeted scratchpad window does not exist. When it happens, I need to set up the scratchpad window manually by

  1. creating the Emacs window,
  2. moving it to the scratchpad workspace, and
  3. pressing the key binding again

I found it is annoying. This post describes my solution to automate these manual steps.

Solution

Step 1: Create a script called i3_scratchpad_show_or_create.sh.

#!/bin/sh

if [ $# -ne 2 ]; then
    echo "Usage: "${0}" <i3_mark> <launch_cmd>"
    echo "Example: ${0} 'scratch-emacs' 'emacsclient -c -a emacs'"
    exit 1
fi

I3_MARK=${1}
LAUNCH_CMD=${2}

scratchpad_show() {
    i3-msg "[con_mark=${I3_MARK}]" scratchpad show
}

# try showing the scratchpad window
if ! scratchpad_show; then
    # if there is no such window...

    # launch the application.
    eval "${LAUNCH_CMD}" &

    # Wait for the next window event.
    i3-msg -t subscribe  '[ "window" ]'

    # Set a mark
    i3-msg mark ${I3_MARK}

    # Move it to the scratchpad workspace
    i3-msg move scratchpad

    # show the scratchpad window
    scratchpad_show
fi

The key ideas are to

  1. automates the manual scratchpad setup mentioned above, and
  2. speeds up by querying with con_mark= instead of title= so that it does not need to wait for the application title, which might not be ready at launch.

Step 2: Update the i3 config

# Show or create the Emacs scratchpad window.
bindsym $mod+j exec /path/to/i3_scratchpad_show_or_create.sh \
  'scratch-emacs' 'emacsclient -c -a emacs'

That is! When pressing $mod+j, I can always get the scratchpad window.


Update: After writing this post, I found https://gitlab.com/aquator/i3-scratchpad to be a more sophisticated solution. It brings its own features like setting position, dimension and display for the window but seems to be laggy when showing/hiding window.