Skip to main content
Version: v1.3.7

Dynamic Profile Modes Pattern

What are dynamic profile modes?

Dynamic profile modes allow a single profile to adapt its behavior based on context without creating multiple separate profiles. This is useful when you want different monitor configurations for the same physical setup depending on what you're doing (e.g., gaming, presenting, working).

Instead of creating home-gaming, home-presentation, and home-standard profiles, you can have one home profile that changes its configuration based on a mode variable.

When to use this pattern

Use dynamic profile modes when:

  • You have the same monitor setup but need different configurations for different activities
  • You want to quickly switch between configurations without disconnecting/reconnecting monitors
  • You need context-specific settings (refresh rates, scaling, positioning) for the same hardware

Examples:

  • Switch between high refresh rate for gaming and lower refresh rate for power saving
  • Mirror displays for presentations but extend them for regular work
  • Different scaling factors for reading vs. video editing

TUI Demo

Everything in this guide can be accomplished using the TUI: Ad-hoc


Prerequisites

This feature requires the hyprdynamicmonitors daemon to be running, as it monitors your configuration file for changes and automatically re-renders profiles when you switch modes:

hyprdynamicmonitors run

Or in your Hyprland config:

exec-once = hyprdynamicmonitors run

Setting up dynamic modes

Let's assume you have the following configuration:

~/.config/hyprdynamicmonitors/config.toml
[general]
destination = "$HOME/.config/hypr/config.d/99_autogenerated-monitors.conf"

[profiles.home]
config_file = "hyprconfigs/home.go.tmpl"
config_file_type = "template"

[[profiles.home.conditions.required_monitors]]
name = "eDP-1"
monitor_tag = "laptop"

[[profiles.home.conditions.required_monitors]]
name = "DP-11"
monitor_tag = "external"

With a simple template created by the TUI at hyprconfigs/home.go.tmpl:

hyprconfigs/home.go.tmpl
# <<<<< TUI AUTO START
monitor=desc:BOE NE135A1M-NY1,2880x1920@120.00000,0x0,2.00000000,transform,0,vrr,1
monitor=desc:LG Electronics LG SDQHD 301NTBKDU037,2560x2880@59.96700,-1800x0,1.60000000,transform,3,vrr,0
# <<<<< TUI AUTO END

The problem

Sometimes at home, you use the same setup differently - maybe to play games or run a presentation. You'd like the home profile to "specialize" depending on the context.

Since hyprdynamicmonitors monitors your configuration for changes, it's easy to combine the TUI and daemon to achieve this.

Step 1: Add a mode variable

First, add a mode static variable to your profile:

~/.config/hyprdynamicmonitors/config.toml
[profiles.home.static_template_values]
mode = "standard"

Your complete configuration now looks like this:

~/.config/hyprdynamicmonitors/config.toml
[general]
destination = "$HOME/.config/hypr/config.d/99_autogenerated-monitors.conf"

[profiles.home]
config_file = "hyprconfigs/home.go.tmpl"
config_file_type = "template"

[profiles.home.static_template_values]
mode = "standard"

[[profiles.home.conditions.required_monitors]]
name = "eDP-1"
monitor_tag = "laptop"

[[profiles.home.conditions.required_monitors]]
name = "DP-11"
monitor_tag = "external"

Step 2: Wrap the template in a conditional

Now adjust your template (hyprconfigs/home.go.tmpl) to use the mode variable:

hyprconfigs/home.go.tmpl
{{ if eq .mode "standard" }}
# <<<<< TUI AUTO START
monitor=desc:BOE NE135A1M-NY1,2880x1920@120.00000,0x0,2.00000000,transform,0,vrr,1
monitor=desc:LG Electronics LG SDQHD 301NTBKDU037,2560x2880@59.96700,-1800x0,1.60000000,transform,3,vrr,0
# <<<<< TUI AUTO END
{{ end }}

This means the monitor lines will only render when mode is set to "standard".

Step 3: Add additional modes

Now add a presentation mode. Edit your template to add a new conditional block:

hyprconfigs/home.go.tmpl
{{ if eq .mode "standard" }}
monitor=desc:BOE NE135A1M-NY1,2880x1920@120.00000,0x0,2.00000000,transform,0,vrr,1
monitor=desc:LG Electronics LG SDQHD 301NTBKDU037,2560x2880@59.96700,-1800x0,1.60000000,transform,3,vrr,0
{{ end }}

{{ if eq .mode "presentation" }}
# <<<<< TUI AUTO START
# <<<<< TUI AUTO END
{{ end }}

Important: We moved the TUI markers (# <<<<< TUI AUTO START/END) from the standard section to the presentation section. This tells the TUI which mode's configuration to update when you apply changes.

Understanding TUI markers:

The TUI markers tell hyprdynamicmonitors where to insert newly configured monitors. When you:

  1. Edit monitors in the TUI
  2. Press a in the Profile pane to apply

The configuration gets inserted between these markers. By placing the markers in the presentation block, we're saying "when I apply from the TUI, update the presentation mode configuration."

Step 4: Configure the presentation mode using the TUI

Now let's set up a different configuration for presentation mode. The workflow is:

4a) Switch to presentation mode in your config:

Edit ~/.config/hyprdynamicmonitors/config.toml:

~/.config/hyprdynamicmonitors/config.toml
[profiles.home.static_template_values]
mode = "presentation" # Changed from "standard"

The daemon will detect this change and switch to presentation mode.

4b) Configure monitors in the TUI:

Open the TUI:

hyprdynamicmonitors tui

Edit your monitors as needed for presentation mode (e.g., mirror displays, different refresh rates, etc.).

4c) Apply the configuration:

Press a in the Profile pane. This writes your configuration between the TUI markers in the presentation block.

Result:

Your template now has different configurations for each mode:

hyprconfigs/home.go.tmpl
{{ if eq .mode "standard" }}
monitor=desc:BOE NE135A1M-NY1,2880x1920@120.00000,0x0,2.00000000,transform,0,vrr,1
monitor=desc:LG Electronics LG SDQHD 301NTBKDU037,2560x2880@59.96700,-1800x0,1.60000000,transform,3,vrr,0
{{ end }}

{{ if eq .mode "presentation" }}
# <<<<< TUI AUTO START
# Mirror displays for presentation
monitor=desc:BOE NE135A1M-NY1,2880x1920@60.00000,0x0,1.60000000,transform,0,vrr,0
monitor=desc:LG Electronics LG SDQHD 301NTBKDU037,2560x2880@60.00000,0x0,1.60000000,transform,0,vrr,0
# <<<<< TUI AUTO END
{{ end }}

Note: The example above shows mirrored displays at 60Hz for presentation mode, while standard mode uses different positioning and 120Hz.

How it works

Here's what happens behind the scenes:

  1. The daemon watches your config file - When running, hyprdynamicmonitors monitors ~/.config/hyprdynamicmonitors/config.toml for changes

  2. You change the mode variable - When you edit mode = "presentation" in the config file, the daemon detects the change immediately

  3. Template is re-rendered - The daemon re-evaluates the template with the new mode value, so only the matching {{ if eq .mode "presentation" }} block is rendered

  4. Hyprland config is updated - The rendered output is written to your Hyprland config destination (e.g., 99_autogenerated-monitors.conf)

  5. Hyprland applies the changes - Hyprland automatically reloads the monitor configuration

All of this happens automatically without restarting anything!

Switching between modes

Now depending on the context, different configurations will be rendered by the daemon.

Manual switching

To switch modes, edit your config.toml and change the mode variable:

~/.config/hyprdynamicmonitors/config.toml
[profiles.home.static_template_values]
mode = "presentation"

The daemon will automatically detect the change and re-render the profile with the new mode. No need to restart anything!

Automated switching with scripts

You can create bash scripts to switch modes automatically. Here's an example:

Switch to presentation mode:

~/scripts/presentation-mode.sh
#!/bin/bash
# ~/scripts/presentation-mode.sh

CONFIG_FILE="$HOME/.config/hyprdynamicmonitors/config.toml"

# Use sed to change the mode value
sed -i 's/mode = ".*"/mode = "presentation"/' "$CONFIG_FILE"

echo "Switched to presentation mode"

Switch to standard mode:

~/scripts/standard-mode.sh
#!/bin/bash
# ~/scripts/standard-mode.sh

CONFIG_FILE="$HOME/.config/hyprdynamicmonitors/config.toml"

sed -i 's/mode = ".*"/mode = "standard"/' "$CONFIG_FILE"

echo "Switched to standard mode"

Make them executable:

chmod +x ~/scripts/presentation-mode.sh
chmod +x ~/scripts/standard-mode.sh

Bind to Hyprland keybindings:

# ~/.config/hypr/hyprland.conf
bind = $mainMod SHIFT, P, exec, ~/scripts/presentation-mode.sh
bind = $mainMod SHIFT, S, exec, ~/scripts/standard-mode.sh

Advanced: Mode-specific variables

You can also use different template variables for each mode:

~/.config/hyprdynamicmonitors/config.toml
[profiles.home.static_template_values]
mode = "standard"
gaming_refresh_rate = "144"
standard_refresh_rate = "60"

Then in your template:

hyprconfigs/home.go.tmpl
{{ if eq .mode "standard" }}
monitor=desc:BOE NE135A1M-NY1,2880x1920@{{ .standard_refresh_rate }},0x0,2.00000000
{{ end }}

{{ if eq .mode "gaming" }}
monitor=desc:BOE NE135A1M-NY1,2880x1920@{{ .gaming_refresh_rate }},0x0,2.00000000
{{ end }}

Complete workflow summary

Here's the full workflow for setting up and using dynamic modes:

  1. Initial setup:

    • Create a profile with a template
    • Add static_template_values with a mode variable
    • Wrap template sections in {{ if eq .mode "..." }} conditionals
  2. Adding a new mode:

    • Add a new conditional block in the template (e.g., {{ if eq .mode "gaming" }})
    • Place TUI markers in that block
    • Change mode in config.toml to the new mode
    • Configure monitors in TUI and press a to apply
  3. Switching modes:

    • Edit config.toml and change the mode value
    • Or run a script that modifies the mode value
    • The daemon automatically detects and applies the change
  4. Editing an existing mode:

    • Move TUI markers to the mode you want to edit
    • Change mode in config.toml to that mode
    • Open TUI, make changes, press a to apply

Dynamic modes vs. separate profiles

Use dynamic modes when:

  • Same physical monitor setup (same monitors connected)
  • Different configurations for different activities
  • Want quick switching via scripts/keybindings
  • Example: Home setup with gaming/work/presentation modes

Use separate profiles when:

  • Different physical setups (different monitors connected)
  • Different locations (home/office/mobile)
  • Different hardware conditions (docked/undocked, AC/battery, lid open/closed)
  • Example: Separate profiles for home (external monitor), office (dual monitors), and mobile (laptop only)

You can combine both approaches: Have separate profiles for different locations, and each profile can have dynamic modes for different activities at that location.

Tips

  • TUI marker placement: You can move the <<<<< TUI AUTO START/END markers to any mode section. The TUI will update whichever section contains the markers when you apply changes.

  • Multiple variables: Combine multiple variables (not just mode) to create even more flexible configurations:

    ~/.config/hyprdynamicmonitors/config.toml
    [profiles.home.static_template_values]
    mode = "standard"
    scaling = "2.0"
    vrr_enabled = "1"
  • Testing modes: Use --dry-run to test mode changes without applying them:

    hyprdynamicmonitors run --run-once --dry-run
  • Default mode: Always set a default mode in your config to ensure the profile works even if you forget to specify one.

  • Debugging: If a mode switch doesn't work, check the daemon logs with --debug to see which template block is being rendered.


Practical example: Gaming vs. productivity

Here's a real-world example with three modes for a home setup:

config.toml:

~/.config/hyprdynamicmonitors/config.toml
[general]
destination = "$HOME/.config/hypr/config.d/99_autogenerated-monitors.conf"

[profiles.home]
config_file = "hyprconfigs/home.go.tmpl"
config_file_type = "template"

[profiles.home.static_template_values]
mode = "productivity" # Default mode

[[profiles.home.conditions.required_monitors]]
name = "eDP-1"
monitor_tag = "laptop"

[[profiles.home.conditions.required_monitors]]
name = "DP-11"
monitor_tag = "gaming_monitor"

hyprconfigs/home.go.tmpl:

hyprconfigs/home.go.tmpl
{{ if eq .mode "productivity" }}
# Productivity: Extended displays, laptop on left, 60Hz for battery saving
monitor=desc:BOE NE135A1M-NY1,2880x1920@60,0x0,2.0,transform,0,vrr,0
monitor=desc:LG Electronics 27GL850,2560x1440@60,1440x0,1.0,transform,0,vrr,0
{{ end }}

{{ if eq .mode "gaming" }}
# Gaming: Disable laptop screen, gaming monitor only at 144Hz
monitor=desc:BOE NE135A1M-NY1,disable
monitor=desc:LG Electronics 27GL850,2560x1440@144,0x0,1.0,transform,0,vrr,1
{{ end }}

{{ if eq .mode "presentation" }}
# <<<<< TUI AUTO START
# Presentation: Mirror displays at same resolution
monitor=desc:BOE NE135A1M-NY1,1920x1080@60,0x0,1.5,transform,0,vrr,0
monitor=desc:LG Electronics 27GL850,1920x1080@60,0x0,1.0,transform,0,vrr,0
# <<<<< TUI AUTO END
{{ end }}

Switching scripts:

~/scripts/hdm-*.sh
# ~/scripts/hdm-gaming.sh
#!/bin/bash
sed -i 's/mode = ".*"/mode = "gaming"/' ~/.config/hyprdynamicmonitors/config.toml
notify-send "HDM" "Switched to gaming mode"

# ~/scripts/hdm-productivity.sh
#!/bin/bash
sed -i 's/mode = ".*"/mode = "productivity"/' ~/.config/hyprdynamicmonitors/config.toml
notify-send "HDM" "Switched to productivity mode"

# ~/scripts/hdm-presentation.sh
#!/bin/bash
sed -i 's/mode = ".*"/mode = "presentation"/' ~/.config/hyprdynamicmonitors/config.toml
notify-send "HDM" "Switched to presentation mode"

Hyprland keybindings:

bind = $mainMod SHIFT, G, exec, ~/scripts/hdm-gaming.sh
bind = $mainMod SHIFT, P, exec, ~/scripts/hdm-productivity.sh
bind = $mainMod SHIFT, M, exec, ~/scripts/hdm-presentation.sh

Now you can instantly switch between gaming (high refresh rate, single monitor), productivity (dual monitors, power saving), and presentation (mirrored displays) with a simple keybinding!