How to Create Custom Hyprland Rules for Specific Applications

Hyprland’s window-rule subsystem lets you automatically apply floating states, opacity, monitor placement, and decoration settings to windows matching specific class or title selectors using windowrule (static) and windowrulev2 (dynamic) syntax in your configuration file.

Creating custom Hyprland rules for specific applications allows you to enforce window behavior, visual effects, and workspace placement without manual intervention. In the hyprwm/Hyprland source code, this functionality is implemented through the CWindowRule and CWindowRuleApplicator classes located in the desktop rule subsystem. This guide explains the configuration syntax and internal implementation details you need to automate your window management.

Understanding the Hyprland Rule Engine Architecture

The rule engine is split between static and dynamic evaluation pipelines to optimize performance. According to the source code in src/desktop/rule/windowRule/WindowRule.hpp, a CWindowRule object (often paired with CRuleWithEffects) defines the selector criteria and the effects to apply, such as opacity, size, or border styles.

When Hyprland parses your configuration, each windowrule or windowrulev2 line instantiates a CWindowRule that is stored in the global rule manager. The CWindowRuleApplicator (defined in src/desktop/rule/windowRule/WindowRuleApplicator.hpp) attaches to each CWindow instance via the m_ruleApplicator pointer found in src/desktop/view/Window.hpp.

The applicator evaluates rules in two modes:

  • Static selectors – Checked once at window creation via matchesStaticSelector. These handle properties like class name or window title.
  • Dynamic selectors – Re-evaluated whenever window properties change (e.g., workspace switches). These use the windowrulev2 prefix and trigger applyDynamicRule.

All rendering decisions—such as decorate(), renderUnfocused(), and opaque()—query the applicator to determine final window state, ensuring rule changes apply instantly without restarting Hyprland.

Configuration Syntax: Static vs. Dynamic Rules

Hyprland distinguishes between one-time application rules and persistent conditional rules through different configuration keywords.

Static Rules with windowrule

Static rules evaluate when a window is first mapped. Use these for permanent attributes like initial floating state or monitor assignment.


# Syntax: windowrule = <effect>, <selector>

windowrule = floating, class:^Discord$
windowrule = monitor DP-1, class:^Discord$

Implementation: When the window is created, CWindowRuleApplicator::applyStaticRule is invoked. The floating effect calls CWindowRuleEffectContainer::setProperty(WINDOW_RULE_EFFECT_FLOATING, true), while monitor DP-1 triggers the workspace placement controller to move the window before it appears on screen.

Dynamic Rules with windowrulev2

Dynamic rules re-evaluate when window properties change. Use these for conditional behaviors based on workspace or focus state.

windowrulev2 = opacity 0.85, workspace:2 && class:^Alacritty$

Implementation: The workspace:2 selector creates a dynamic condition. CWindowRuleApplicator::applyDynamicRule runs whenever the window moves to a different workspace, updating opacity via CWindowRuleEffectContainer::setProperty(WINDOW_RULE_EFFECT_OPACITY, 0.85).

Practical Implementation Examples

These concrete examples demonstrate how to interact with the rule engine defined in src/desktop/view/Window.cpp and related files.

Force Floating Windows and Monitor Assignment

To force Discord to open floating and display on a specific monitor:

windowrule = floating, class:^Discord$
windowrule = monitor DP-1, class:^Discord$

Source reference: The monitor string is resolved by CWorkspacePlacementController::ensurePersistentWorkspacesPresent during rule application.

Workspace-Based Opacity Control

Reduce opacity for terminals on specific workspaces:

windowrulev2 = opacity 0.85, workspace:2 && class:^Alacritty$

Effect: The opacity is dynamically adjusted via the CWindowRuleEffectContainer whenever the window enters or leaves workspace 2.

Size Constraints and Performance Tuning

Set explicit dimensions or disable animations for games:


# Set initial size to 1024x768 pixels

windowrule = size 1024 768, class:^Alacritty$

# Disable animations and background dimming for games

windowrule = noanim, class:^SuperTuxKart$
windowrule = nodimaround, class:^SuperTuxKart$

Implementation: The size rule invokes CWindowRuleEffectContainer::setSize, which calls CWindow::resize during the mapping phase. The noanim and nodimaround effects set boolean flags checked by the renderer in src/render/Renderer.cpp before drawing frames.

Launch-Time Rules with exec-once

Apply rules to applications launched via exec-once using the embedded rule syntax parsed by src/config/supplementary/executor/Executor.hpp:

exec-once = alacritty, class:^Alacritty$, monitor:DP-1, floating

Implementation: The executor parses parameters after the command using buildFromExecString to create a temporary CWindowRule attached to the new PID, ensuring the rule applies before the window surfaces.

Core Source Files for Rule Customization

File Path Role in Rule System
src/desktop/rule/windowRule/WindowRule.hpp Defines CWindowRule, CRuleWithEffects, and parsing helpers including buildFromExecString.
src/desktop/rule/windowRule/WindowRuleApplicator.hpp Implements CWindowRuleApplicator which evaluates static and dynamic rules per-window.
src/desktop/view/Window.hpp Declares CWindow with the m_ruleApplicator member for querying rule effects.
src/desktop/view/Window.cpp Contains rule evaluation logic triggered on window map and property changes.
src/config/supplementary/executor/Executor.hpp Handles exec-once commands that embed temporary window rules.
example/hyprland.lua Reference configuration demonstrating windowrule syntax placement.

Summary

  • Hyprland rules automate window behavior through the CWindowRule and CWindowRuleApplicator classes in the desktop rule subsystem.
  • Use windowrule for static, one-time application at window creation (class, title matching).
  • Use windowrulev2 for dynamic re-evaluation when properties like workspace or floating state change.
  • Rule effects modify rendering decisions via CWindowRuleEffectContainer properties checked by CWindow methods like decorate() and opaque().
  • Changes to rules take effect immediately without restarting the compositor.
  • The exec-once command supports inline rule application parsed by the executor in src/config/supplementary/executor/Executor.hpp.

Frequently Asked Questions

What is the difference between windowrule and windowrulev2?

windowrule applies effects once when a window is created and matches against static properties like class or title. windowrulev2 creates dynamic rules that re-evaluate when window properties change, such as when moving between workspaces or toggling floating state. According to the source in src/desktop/rule/windowRule/WindowRuleApplicator.hpp, static rules use applyStaticRule while dynamic rules rely on applyDynamicRule.

How do I match applications by class name in Hyprland?

Use the class: selector with a regular expression pattern. For example, class:^Discord$ matches windows where the WM_CLASS property exactly equals "Discord". The matching logic resides in matchesStaticSelector within the rule applicator implementation.

Can I apply rules to already running windows?

Rules defined in your configuration apply to new windows automatically. For existing windows, you must reload the configuration (which updates the rule manager) or use dynamic windowrulev2 rules that re-evaluate on property changes. The rule engine in src/desktop/view/Window.cpp queries the applicator on every relevant property update, ensuring dynamic conditions are checked continuously.

Where are window rules evaluated in the Hyprland source code?

Rule evaluation occurs in src/desktop/view/Window.cpp when windows are mapped, and in CWindowRuleApplicator methods for static and dynamic checking. Rendering decisions in src/render/Renderer.cpp and input handling in src/managers/input/InputManager.cpp query the m_ruleApplicator pointer attached to each CWindow to determine final behavior.

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 →