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 insrc/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:
- Request — A client invokes
setFullscreenthrough XDG or XWayland protocols. - Controller update —
CFullscreenController::setFullscreenModesets the window’s internal mode toFSMODE_FULLSCREENand optionally updates the client mode. - Handler synchronization — The handler returned by
getFsHandler(window)callssyncFullscreenTargetsto align its internal state. - Rendering — In
src/render/Renderer.cppline 267, the renderer checksFullscreen::controller()->isFullscreen(pWindow)and skips drawing non-covering windows on the same monitor. - IPC event — The controller posts a
fullscreenevent so external scripts andhyprctlcan 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
CFullscreenControllersingleton insrc/managers/fullscreen/, which tracks internal and client fullscreen states. - Three modes exist—
FSMODE_NONE,FSMODE_MAXIMIZED, andFSMODE_FULLSCREEN—queried through helpers likeisFullscreen(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.cppline 267 skips non-covering windows whenisFullscreen(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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →