Hyprland Fullscreen Mode Configuration: A Complete Guide to Controllers, Handlers, and Layout Rules

Hyprland fullscreen mode configuration is governed by the CFullscreenController singleton, protocol handlers, and per-window layout rules defined in src/managers/fullscreen/.

Configuring fullscreen behavior in the hyprwm/Hyprland compositor requires understanding how the CFullscreenController class tracks both internal enforcement and client-requested states. Hyprland fullscreen mode configuration is exposed through the Lua-based config system and implemented in the dedicated fullscreen subsystem under src/managers/fullscreen/, allowing granular control over window rules, workspace rules, and scrolling layouts.

Fullscreen States and Modes

The CFullscreenController singleton, accessed via Fullscreen::controller(), maintains fullscreen state for every window, workspace, and monitor. It distinguishes between an internal mode—what Hyprland enforces—and a client mode representing what the application requested.

The Three Fullscreen Modes

In src/managers/fullscreen/FullscreenController.hpp, the enum eFullscreenMode defines three possible states:

  • FSMODE_NONE — The window is not fullscreen.
  • FSMODE_MAXIMIZED — The window covers the work area but remains a maximized state rather than true fullscreen.
  • FSMODE_FULLSCREEN — True fullscreen where the window occupies the entire output.

The controller exposes query helpers such as isFullscreen(window), getFullscreenModes(window), and hasFullscreen(workspace) to inspect these states.

Fullscreen Handlers and Layout Integration

Handler selection is delegated through the IFullscreenHandler interface. The controller resolves the correct implementation via getFsHandler(window) and forwards queries such as isFullscreen and getFullscreenModes to it.

Handler Types

src/managers/fullscreen/FullscreenController.hpp defines three handler categories:

  • FULLSCREEN_HANDLER_DEFAULT — The generic handler used for most standard windows.
  • FULLSCREEN_HANDLER_LAYOUT — Layout-aware handlers that may treat fullscreen windows specially, such as in scrolling layouts.
  • FULLSCREEN_HANDLER_SCROLLING — A compound flag (1 << 2 | FULLSCREEN_HANDLER_LAYOUT) specifically for the scrolling layout in src/managers/fullscreen/handler/FullscreenHandler.hpp.

Each handler synchronizes its internal target list through syncFullscreenTargets whenever the controller updates a mode.

Protocol Support for XDG and XWayland

Client fullscreen requests enter the controller through two protocol paths before reaching CFullscreenController::setFullscreenMode.

XDG-Shell Handling

In src/protocols/XDGShell.cpp, CXDGToplevelResource::setFullscreen(bool) forwards the request to the window’s setFullscreen flag. This eventually routes to the controller’s mode setter and notifies the IPC system.

XWayland Handling

In src/managers/XWaylandManager.cpp, CHyprXWaylandManager::setWindowFullscreen updates both the XWayland surface and the XDG surface via XSurface::setFullscreen. Both paths converge on the controller to update the internal mode.

Key Configuration Options

Several configuration knobs in the Lua-based config control fullscreen behavior globally, per-layout, or per-window.

Allow Pinned Windows to Go Fullscreen

The binds:allow_pin_fullscreen option controls whether pinned windows can be forced into fullscreen. The controller checks this bind at src/managers/fullscreen/FullscreenController.cpp line 389 when handling pinned window state transitions.

Scrolling Layout Single-Column Fullscreen

For scrolling layouts, scrolling.fullscreen_on_one_column restricts a fullscreen window to a single column while keeping the rest of the layout visible. This is demonstrated in the example configuration at example/hyprland.lua lines 96–99.

Window and Workspace Rules

Per-window rules can force or prevent fullscreen on startup. The example config at example/hyprland.lua lines 32–36 uses fullscreen = false as an XWayland workaround. Workspace rules can also preset a workspace to launch with a fullscreen window.

-- Enable scrolling-layout fullscreen on a single column
hl.config({
    scrolling = {
        fullscreen_on_one_column = true,
    },
})

-- Global bind to allow pinned windows to go fullscreen
hl.bind("SUPER + F", hl.dsp.toggle_fullscreen({ allow_pin = true }))

-- Per-window rule: start a specific app not in fullscreen
hl.window_rule({
    name  = "myapp-no-fs",
    match = { class = "MyApp" },
    fullscreen = false,
})

-- Toggle fullscreen for the focused window (default bind)
hl.bind("SUPER + SHIFT + F", hl.dsp.window.fullscreen())

Internal Fullscreen Lifecycle

The fullscreen pipeline follows a strict sequence from client request to screen render:

  1. Request — A client invokes setFullscreen through XDG or XWayland protocols.
  2. Controller update — CFullscreenController::setFullscreenMode sets the window’s internal mode to FSMODE_FULLSCREEN and optionally updates the client mode.
  3. Handler synchronization — The handler returned by getFsHandler(window) calls syncFullscreenTargets to align its internal state.
  4. Rendering — In src/render/Renderer.cpp line 267, the renderer checks Fullscreen::controller()->isFullscreen(pWindow) and skips drawing non-covering windows on the same monitor.
  5. IPC event — The controller posts a fullscreen event so external scripts and hyprctl can react in real time.

Edge Cases and Safeguards

The controller includes several defensive mechanisms to prevent inconsistent states.

Error-Correction Loops

Many methods in FullscreenController.cpp contain error-correction lambdas. If isFullscreen or getFullscreenModes detects an inconsistency between the window and handler targets, the controller automatically re-invokes syncFullscreenTargets.

Covering Flag

Controller queries accept an optional covering argument to differentiate between any fullscreen window and the topmost covering one, preventing incorrect occlusion calculations.

Pinned Window Restrictions

Pinned windows receive special treatment in the controller logic. Unless binds:allow_pin_fullscreen is enabled, the controller blocks pinned windows from entering fullscreen to preserve their always-on-top semantics.

Summary

  • Hyprland fullscreen mode configuration centers on the CFullscreenController singleton in src/managers/fullscreen/, which tracks internal and client fullscreen states.
  • Three modes exist—FSMODE_NONE, FSMODE_MAXIMIZED, and FSMODE_FULLSCREEN—queried through helpers like isFullscreen(window).
  • Layout-specific handlers (IFullscreenHandler) delegate behavior for default, layout-aware, and scrolling contexts.
  • XDG and XWayland protocol requests both converge on CFullscreenController::setFullscreenMode.
  • User-facing options include binds:allow_pin_fullscreen, scrolling.fullscreen_on_one_column, and per-window or workspace rules in the Lua config.
  • The rendering path in src/render/Renderer.cpp line 267 skips non-covering windows when isFullscreen(pWindow) is true.

Frequently Asked Questions

How do I prevent a specific window from starting in fullscreen?

Use a per-window rule in your Hyprland configuration. According to the example config in example/hyprland.lua lines 32–36, set fullscreen = false inside a window_rule block matched to the window’s class or title. This forces the controller to initialize the window with FSMODE_NONE regardless of client requests.

What is the difference between maximized and fullscreen in Hyprland?

The eFullscreenMode enum in FullscreenController.hpp defines FSMODE_MAXIMIZED as covering the work area without taking over the full output, while FSMODE_FULLSCREEN makes the window occupy the entire monitor surface. The controller handles these as distinct internal states and reports them separately via getFullscreenModes(window).

Why does my scrolling layout still show other columns when a window is fullscreen?

The scrolling.fullscreen_on_one_column option controls this behavior. When set to true in example/hyprland.lua lines 96–99, the scrolling handler confines the fullscreen window to a single column rather than treating it as a true covering fullscreen across the entire output.

How does Hyprland handle pinned windows entering fullscreen?

The controller at FullscreenController.cpp line 389 checks the binds:allow_pin_fullscreen bind before permitting a pinned window to enter fullscreen. If the bind is disabled, pinned windows are blocked from fullscreen transitions to maintain their fixed-on-top status above normal windows.

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 →