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:
src/desktop/Workspace.hpp— DeclaresCWorkspaceand them_isSpecialWorkspaceflagsrc/desktop/Workspace.cpp— Handles construction, initialization, and animation selection for special workspacessrc/state/WorkspaceState.cpp— Orchestrates workspace creation with proper special status detectionsrc/state/WorkspaceQueryCore.cpp— Implements ID-based special workspace detection viaisSpecial()src/state/WorkspacePlacementController.cpp— Excludes special workspaces from layout calculationssrc/render/Renderer.cpp— Manages rendering visibility for scratchpad windowssrc/desktop/view/Window.cpp— Handles window visibility transitions for special workspacessrc/protocols/ExtWorkspace.cpp— Processes protocol commands for activating and deactivating scratchpads
Summary
- Special workspaces use negative ID ranges (
SPECIAL_WORKSPACE_STARTto-2) to distinguish themselves from normal workspaces - The
m_isSpecialWorkspaceflag inCWorkspacecontrols lifecycle, rendering, and placement behavior throughout the compositor - Activation stores scratchpads in
Monitor::m_activeSpecialWorkspacewithout 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →