How Special Workspaces (Scratchpads) Work in Hyprland: A Deep Dive into the Source Code

Hyprland implements scratchpads as special workspaces using the CWorkspace class with the m_isSpecialWorkspace flag, negative ID ranges, and isolated rendering logic that prevents interference with normal tiling layouts.

Special workspaces in Hyprland function as floating "scratchpads" that exist outside the standard workspace hierarchy. According to the hyprwm/Hyprland source code, these workspaces operate through a distinct identifier system and specialized state management that separates them from regular tiling workspaces.

Core Implementation: The CWorkspace Class

The foundation of special workspace functionality resides in the CWorkspace class defined in src/desktop/Workspace.hpp. This class maintains the boolean flag m_isSpecialWorkspace to distinguish scratchpads from normal workspaces throughout the compositor's lifecycle.

Special Workspace Identification

Hyprland identifies special workspaces by their ID values. In src/state/WorkspaceQueryCore.cpp, the isSpecial() function determines workspace type by checking if the ID falls within the range SPECIAL_WORKSPACE_START … -2. Any workspace carrying an ID in this negative range is automatically classified as special and handled accordingly by the state tracking systems.

Workspace Construction

When creating a workspace, the system passes a special boolean parameter to the constructor. In src/desktop/Workspace.cpp, the create() method receives this flag and initializes the workspace with m_isSpecialWorkspace = true. This occurs when WorkspaceStateTracker::create() in src/state/WorkspaceState.cpp queries CWorkspaceQueryCore::isSpecial(id) and passes the result to CWorkspace::create().

State Tracking Integration

The WorkspaceState and MonitorState classes coordinate special workspace lifecycle management. The WorkspaceStateTracker::create() method determines the special status before instantiation, ensuring that scratchpads are properly registered in the compositor's state machine without conflicting with normal workspace indexing.

How Special Workspaces Differ from Normal Workspaces

Special workspaces exhibit distinct behaviors across activation, visibility, animation, placement, and rendering pipelines.

Activation and Monitor State

Unlike normal workspaces that change the monitor's active layout when switched, special workspaces are stored in Monitor::m_activeSpecialWorkspace. Activating a scratchpad does not alter the underlying tiling layout of the monitor—it overlays on top without displacing existing windows.

Visibility and Window Management

Windows residing on special workspaces follow unique visibility rules. When a special workspace is inactive, its windows are automatically hidden. The logic in src/desktop/view/Window.cpp checks m_workspace->m_isSpecialWorkspace to determine whether windows should be rendered based on the scratchpad's active state, while tracking the last focused window via CWorkspace::m_lastFocusedWindow for seamless restoration.

Animation Configuration

Special workspaces use dedicated animation profiles. In src/desktop/Workspace.cpp, the CWorkspace::init method selects between standard workspace animations and special workspace animations based on the m_isSpecialWorkspace flag. Scratchpads utilize the "specialWorkspaceIn" and "specialWorkspaceOut" configuration values rather than the standard "workspacesIn" / "workspacesOut" animations.

Layout Placement Exclusion

The WorkspacePlacementController explicitly skips special workspaces during layout calculations. The logic in src/state/WorkspacePlacementController.cpp contains the guard if (!valid(ws) || ws->m_isSpecialWorkspace) to ensure scratchpads never participate in tiling algorithms or workspace arrangement operations.

Rendering Pipeline Isolation

The rendering system treats special workspaces distinctly. In src/render/Renderer.cpp, checks such as if (PWINDOWWORKSPACE && !PWINDOWWORKSPACE->m_isSpecialWorkspace && …) ensure that inactive scratchpad windows are excluded from the render loop while active ones are drawn with appropriate overlay characteristics.

Practical Workflow: Creating and Using Scratchpads

Understanding the configuration and command interfaces allows effective utilization of special workspaces.

Defining a Special Workspace

Special workspaces are defined in your Hyprland configuration using the special: prefix:

workspace = special:scratchpad

This creates a named special workspace that persists across session restarts.

Moving Windows to the Scratchpad

Send focused windows to a special workspace using the dispatch command:

hyprctl dispatch movetoworkspace special:scratchpad

Internally, this triggers the workspace creation logic in src/state/WorkspaceState.cpp with the special flag set to true, then updates the window's workspace association via window->setWorkspace(ws).

Toggling Visibility

Toggle scratchpad visibility with:

hyprctl dispatch togglespecial scratchpad

This command interacts with src/protocols/ExtWorkspace.cpp to manage activation states, showing the workspace if hidden or hiding it if active, without affecting the underlying tiling layout.

Key Source Files and Their Roles

The special workspace implementation spans multiple core components:

Summary

  • Special workspaces use negative ID ranges (SPECIAL_WORKSPACE_START to -2) to distinguish themselves from normal workspaces
  • The m_isSpecialWorkspace flag in CWorkspace controls lifecycle, rendering, and placement behavior throughout the compositor
  • Activation stores scratchpads in Monitor::m_activeSpecialWorkspace without disrupting tiling layouts
  • Rendering isolates special workspaces through explicit checks in the renderer and window visibility logic
  • Configuration uses the special: prefix and dedicated animation configs for consistent scratchpad behavior

Frequently Asked Questions

What is the ID range for special workspaces in Hyprland?

Special workspaces occupy the ID range from SPECIAL_WORKSPACE_START to -2, as implemented in src/state/WorkspaceQueryCore.cpp. The isSpecial() function identifies any workspace within this negative range as a scratchpad, triggering special handling in the state management and rendering systems.

How do I move a window to a scratchpad using hyprctl?

Use the dispatch command hyprctl dispatch movetoworkspace special:NAME, replacing NAME with your scratchpad identifier (commonly scratchpad). This executes the internal logic in src/state/WorkspaceState.cpp that creates or retrieves the special workspace and updates the window's workspace association while preserving its original workspace metadata for later restoration.

Do special workspaces affect the normal tiling layout?

No. Special workspaces are explicitly excluded from tiling calculations in src/state/WorkspacePlacementController.cpp and do not modify the Monitor's active workspace layout. They exist as overlay workspaces that can be summoned or dismissed without rearranging existing tiled windows.

Where are scratchpad animations configured?

Scratchpad animations use the specialWorkspaceIn and specialWorkspaceOut configuration keys, distinct from standard workspace animations. In src/desktop/Workspace.cpp, the CWorkspace::init method selects these animation properties when m_isSpecialWorkspace is true, allowing independent visual effects for scratchpad transitions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →