Omarchy: Monitors and Workspaces

Omarchy ships with a default monitor layout that may work for you, but in my case I needed to adjust it. And its default workspace behaviour does not feel intuitive at all. Here's how I changed it.

Monitors

Hyprland workspace layout

Hyprland stores monitor configuration in ~/.config/hypr/monitors.conf. By default it contains:

env = GDK_SCALE,2
monitor=,preferred,auto,auto

On my machine that results in a laptop screen at too low a resolution and assumes the external display sits on the right. That suits my primary laptop but not the other.

Check what Hyprland currently detects:

hyprctl monitors all

Example output:

Monitor eDP-1 (ID 0):
    [email protected] at 0x0
    description: BOE 0x093E
    make: BOE
    model: 0x093E
    physical size (mm): 340x190
    [...]

Monitor HDMI-A-1 (ID 1):
    [email protected] at 1280x0
    description: Dell Inc. DELL P2717H 4P9HC6CCANHS
    make: Dell Inc.
    model: DELL P2717H
    physical size (mm): 600x340
    [...]

The laptop panel reports 1920x1080 while the HDMI monitor is positioned at 1280x0; that offset shows the effective resolution of the laptop at 1280x1024. I replace the defaults with explicit values:

env = GDK_SCALE,2
monitor=HDMI-A-1,1920x1080@60,1920x0,1
monitor=eDP-1,1920x1080@60,0x0,1

Hyprland applies the changes as soon as you save the file. No reload required.

On the other laptop I prefer the external display on the left, and the built-in panel uses a different resolution:

env = GDK_SCALE,2
monitor=HDMI-A-1,1920x1080@60,-1920x0,1
monitor=eDP-1,1366x768@60,0x0,1

Workspaces

Waybar workspaces

Workspaces are a handy way to organize your windows. For example, have your communication like Discord and Email on workspace 8, and your development tools on workspace 1. In my case, I like to have 4 workspaces per monitor.

By default, Omarchy displays 5 workspaces on both screens, each numbered from 1 to 5. They are linked, yet somehow also independent. I couldn't figure out the logic. Also, when I cycle through them using Super-Tab, it skips the empty ones, and on the monitor... well, let me stop. I can't explain it anyway 😛.

Let me show how I made it more logical using a plugin called 'split-monitor-workspaces'.

Execute the following commands:

sudo pacman -S cmake meson cpio
hyprpm update
hyprpm add https://github.com/Duckonaut/split-monitor-workspaces
hyprpm enable split-monitor-workspaces

Add these lines at the end of the file ~/.config/hypr/hyprland.conf:

# Plugins Configuration
source = ~/.config/hypr/plugin-split-monitor-workspace.conf

Create the file ~/.config/hypr/plugin-split-monitor-workspace.conf with the following content:

# Auto-load plugins on startup (recommended by Hyprland)
exec-once = hyprpm reload -n

# --- split-monitor-workspaces ---
plugin {
  split-monitor-workspaces {
    count = 4
    keep_focused = 1
    enable_persistent_workspaces = 1
    enable_notifications = 1
    enable_wrapping = 1
  }
}

# unbind Omarchy defaults without touching them
unbind = SUPER, code:10
unbind = SUPER, code:11
unbind = SUPER, code:12
unbind = SUPER, code:13
unbind = SUPER, code:14
unbind = SUPER, code:15
unbind = SUPER, code:16
unbind = SUPER, code:17
unbind = SUPER, code:18
unbind = SUPER, code:19

unbind = SUPER SHIFT, code:10
unbind = SUPER SHIFT, code:11
unbind = SUPER SHIFT, code:12
unbind = SUPER SHIFT, code:13
unbind = SUPER SHIFT, code:14
unbind = SUPER SHIFT, code:15
unbind = SUPER SHIFT, code:16
unbind = SUPER SHIFT, code:17
unbind = SUPER SHIFT, code:18
unbind = SUPER SHIFT, code:19

##### WORKSPACES (per monitor, via plugin) #####
# WS 1–4 on monitor 0
bindd = SUPER, code:10, WS1, exec, hyprctl dispatch focusmonitor 0; hyprctl dispatch split-workspace 1
bindd = SUPER, code:11, WS2, exec, hyprctl dispatch focusmonitor 0; hyprctl dispatch split-workspace 2
bindd = SUPER, code:12, WS3, exec, hyprctl dispatch focusmonitor 0; hyprctl dispatch split-workspace 3
bindd = SUPER, code:13, WS4, exec, hyprctl dispatch focusmonitor 0; hyprctl dispatch split-workspace 4

# WS 5–8 on monitor 1
bindd = SUPER, code:14, WS5, exec, hyprctl dispatch focusmonitor 1; hyprctl dispatch split-workspace 1
bindd = SUPER, code:15, WS6, exec, hyprctl dispatch focusmonitor 1; hyprctl dispatch split-workspace 2
bindd = SUPER, code:16, WS7, exec, hyprctl dispatch focusmonitor 1; hyprctl dispatch split-workspace 3
bindd = SUPER, code:17, WS8, exec, hyprctl dispatch focusmonitor 1; hyprctl dispatch split-workspace 4

# SUPER + SHIFT + [1..8] = move window to workspace (and move focus there)
# WS 1–4 on monitor 0
bindd = SUPER SHIFT, code:10, Move win to WS 1, exec, hyprctl dispatch movewindow mon:0; hyprctl dispatch focusmonitor 0; hyprctl dispatch split-movetoworkspace 1
bindd = SUPER SHIFT, code:11, Move win to WS 2, exec, hyprctl dispatch movewindow mon:0; hyprctl dispatch focusmonitor 0; hyprctl dispatch split-movetoworkspace 2
bindd = SUPER SHIFT, code:12, Move win to WS 3, exec, hyprctl dispatch movewindow mon:0; hyprctl dispatch focusmonitor 0; hyprctl dispatch split-movetoworkspace 3
bindd = SUPER SHIFT, code:13, Move win to WS 4, exec, hyprctl dispatch movewindow mon:0; hyprctl dispatch focusmonitor 0; hyprctl dispatch split-movetoworkspace 4

# WS 5–8 on monitor 1 → remap to local 1–4
bindd = SUPER SHIFT, code:14, Move win to WS 5, exec, hyprctl dispatch movewindow mon:1; hyprctl dispatch focusmonitor 1; hyprctl dispatch split-movetoworkspace 1
bindd = SUPER SHIFT, code:15, Move win to WS 6, exec, hyprctl dispatch movewindow mon:1; hyprctl dispatch focusmonitor 1; hyprctl dispatch split-movetoworkspace 2
bindd = SUPER SHIFT, code:16, Move win to WS 7, exec, hyprctl dispatch movewindow mon:1; hyprctl dispatch focusmonitor 1; hyprctl dispatch split-movetoworkspace 3
bindd = SUPER SHIFT, code:17, Move win to WS 8, exec, hyprctl dispatch movewindow mon:1; hyprctl dispatch focusmonitor 1; hyprctl dispatch split-movetoworkspace 4

# Cycle workspaces on current monitor
bindd = SUPER, TAB, Cycle WS next, split-cycleworkspaces, next
bindd = SUPER SHIFT, TAB, Cycle WS prev, split-cycleworkspaces, prev

# SUPER + SHIFT + LEFT/RIGHT = send window to prev/next monitor
bindd = SUPER SHIFT, LEFT, Send win to left mon, movewindow, mon:l
bindd = SUPER SHIFT, RIGHT, Send win to right mon, movewindow, mon:r

# Fix workspace cycling
unbind = SUPER, TAB
unbind = SUPER SHIFT, TAB

bind = SUPER, TAB, split-workspace, +1
bind = SUPER SHIFT, TAB, split-workspace, -1

Troubleshooting

If Hyprland refuses to launch after an Arch update, rebuild the plugin before reenabling it. See Omarchy: What if Hyprland is Broken? for a quick recovery checklist.

Waybar

Then change the top bar (waybar) to display the workspaces more clearly.

In the file .config/waybar/config.jsonc, replace the entire workspaces section by:

  "hyprland/workspaces": {
    "all-outputs": false,
    "sort-by-number": true,
    "disable-scroll": true,
    "on-click": "activate",
    "format": "{icon}",
    },

I recommend changing the CSS of waybar to make the current workspace stand out more clearly. Replace the workspaces styles by:

#workspaces button {
  all: initial;
  padding: 0 6px;
  margin: 0 1.5px;
  min-width: 9px;
  opacity: 0.5;
}

#workspaces button.visible,
#workspaces button.active {
  font-weight: bold;
  opacity: 1;
}

/* remove the existing button.empty rule */

Finally, reboot. These changes are too much for Omarchy to handle automatically 😀.