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

> Understand Hyprland scratchpads with this deep dive into their source code. Learn how special workspaces use flags, IDs, and isolated rendering to function seamlessly.

- Repository: [Hypr Development/Hyprland](https://github.com/hyprwm/Hyprland)
- Tags: deep-dive
- Published: 2026-07-23

---

**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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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:

```conf
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:

```bash
hyprctl dispatch movetoworkspace special:scratchpad

```

Internally, this triggers the workspace creation logic in [`src/state/WorkspaceState.cpp`](https://github.com/hyprwm/Hyprland/blob/main/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:

```bash
hyprctl dispatch togglespecial scratchpad

```

This command interacts with [`src/protocols/ExtWorkspace.cpp`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/src/desktop/Workspace.hpp)** — Declares `CWorkspace` and the `m_isSpecialWorkspace` flag
- **[`src/desktop/Workspace.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/desktop/Workspace.cpp)** — Handles construction, initialization, and animation selection for special workspaces
- **[`src/state/WorkspaceState.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/state/WorkspaceState.cpp)** — Orchestrates workspace creation with proper special status detection
- **[`src/state/WorkspaceQueryCore.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/state/WorkspaceQueryCore.cpp)** — Implements ID-based special workspace detection via `isSpecial()`
- **[`src/state/WorkspacePlacementController.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/state/WorkspacePlacementController.cpp)** — Excludes special workspaces from layout calculations
- **[`src/render/Renderer.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/render/Renderer.cpp)** — Manages rendering visibility for scratchpad windows
- **[`src/desktop/view/Window.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/desktop/view/Window.cpp)** — Handles window visibility transitions for special workspaces
- **[`src/protocols/ExtWorkspace.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/protocols/ExtWorkspace.cpp)** — Processes protocol commands for activating and deactivating scratchpads

## 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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/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`](https://github.com/hyprwm/Hyprland/blob/main/src/desktop/Workspace.cpp), the `CWorkspace::init` method selects these animation properties when `m_isSpecialWorkspace` is true, allowing independent visual effects for scratchpad transitions.