Skip to content

Scratchpads

Bakkeby edited this page Apr 18, 2024 · 12 revisions

The general idea of scratchpads is to have a window that you can quickly open to make some quick notes and then hide again, much like a physical scratchpad or notebook.

When it comes to window managers the term scratchpads have become synonymous with windows that pop in and out of existence on demand (i.e. using keybindings).

In practice any window can be used as a scratchpad, for example a web browser or even a combination of multiple windows.

Scratchpads can complement your workflow in the most delightful ways.

scratchpads.gif

Features

  • launch an application (e.g. a terminal) and toggle visibility using a keybinding
  • scratchpads can be tiled or floating
  • optionally scratchpads can automatically hide when you move to other workspaces
  • arbitrary windows can be assigned to a scratch key
  • assign multiple windows to a scratch key, toggle them on and off in unison
  • toggling the scratchpad on another monitor moves the scratchpad across and centers it on the screen
  • toggling multiple scratchpads on another monitor moves the scratchpads across with positions relative to the aspect ratio of the two monitors
  • toggling multiple scratchpads where windows reside on separate monitors leaves scratchpads in place

Configuration

Scratchpads are set up similarly to normal spawn commands with the exception that they specify a unique "scratch key" character that is set on a client identifying it as a particular scratchpad. A client rule is also set up to set the scratch key for the window when it is managed.

Synopsis for scratchpad commands:

/* Scratch command:            scratchkey, command, argument, argument, ..., NULL */
static const char *spcmd[] = { "s",        command, argument, argument, ..., NULL };

Example configuration:

static const char *spcmd_w[] = {"w", "st", "-n", "spterm (w)", "-g", "120x34", NULL };
static const char *spcmd_e[] = {"e", "st", "-n", "spterm (e)", "-g", "120x34", NULL };
static const char *spcmd_r[] = {"r", "st", "-n", "spfm (r)", "-g", "144x41", "-e", "ranger", NULL };

Here the scratch keys of "w", "e" and "r" are set for three spawn commands.

Client rules are then set up to set the corresponding scratch keys for the window when it is spawned.

  { .instance = "spterm (w)", .scratchkey = 'w', .flags = Floating },
  { .instance = "spterm (e)", .scratchkey = 'e', .flags = Floating },
  { .instance = "spfm (r)", .scratchkey = 'r', .flags = Floating },

In the example commands above the window title, e.g. "spterm (w)", is specified when spawning the terminal and the corresponding client rule that sets the scratchkey to w if said title is found.

This complexity around this comes from that the spawning of new programs and a window popping up is asynchronous.

The spawning part simply starts a new process and the window manager later receives a mapping request from the X server about a new X window. There is no direct correlation between the process ID and the X window hence the window manager can't know for sure that the mapping request received is for the process that was last spawned.

Granted many windows have the _NET_WM_PID property set, but this is no guarantee. Setting up a client rule like the above is the easiest way to mark a window as belonging to a scratchpad.

Which character is used for the scratchpad is not important as long as it is 1) unique and 2) a single byte.

For ease of reference the scratchpad characters used here are the same as the keyboard shortcuts used to spawn the scratchpads.

  SCRATCHKEYS(MODKEY, XK_w, spcmd_w)
  SCRATCHKEYS(MODKEY, XK_e, spcmd_e)
  SCRATCHKEYS(MODKEY, XK_r, spcmd_r)

Refer to the SCRATCHKEYS macro for more details on that.


Tip: When using tiled scratchpads and toggling a window into view the placement in the stack can be controlled by setting one of the attach flags via client rules.

If no attach flags are set in the client rules then:

  • the window position will be determined by the attachdefault setting as normal and
  • the window will be attached at the bottom when moved between workspaces and
  • the window will retain its position in the stack when toggled into and out of view on the same workspace

Functions

Here is a list of functions relating to scratchpads.

Function Description
removescratch Removes scratchpad assignment for the selected client
setscratch Adds scratchpad assignment for the selected client
togglescratch Toggles scratchpad clients into or out of view

Functionality

Here is a list of functionality that is directly related to tiled windows.

Functionality Description
AutoHideScratchpads Automatically hide open scratchpads when moving to another workspace

Flags

Here is a list of client flags relating to scratchpads.

Flag Description
Invisible By default all clients are visible, used by scratchpads to hide clients
ScratchpadStayOnMon Prevents the scratchpad from being moved to the active monitor when toggled
SemiScratchpad A window that switches between being a normal window and a scratchpad window
Permanent A permanent scratchpad window will hide rather than be killed when using killclient

Alternatives

A standalone alternative for scratchpads would be tdrop which is a very capable bash script which uses xdotool under the hood.

Two main things to note about it in terms of compatibility with dusk or dwm in general:

  • while you can resize the window while it is shown the tool won't restore the size when you hide and reveal the scratchpad window again
  • windows are unmapped when they are hidden by the tool, which means that a) the window is unmanaged on the window manager's side and b) any client rules matching the client will be re-applied every time the window is shown again

Another alternative is jumpapp which is probably more of tool for a desktop environment. This relies on rather comprehensive extended window manager hints (EWMH) to work properly. It particularly relies on IconicState to hide client windows and appears to expect that applying IconicState a second time will make the client go back to NormalState, which seems to be outside of the specification.


Back to Features.

Clone this wiki locally