Multi-head workspace setup in Omarchy

November 6, 2025

source

Hello, I compiled some defaults for a better multi-head setup in Omarchy. I understand that @dhh and a lot of folks enjoy the single head setup.

I do like it too, but sometimes, I want to plug my notebook to my big monitor, or to have a portrait monitor for writing docs or reading. Whatever the case might be, the Omarchy defaults for a multi-head are not very good.
Workspaces get messy as which one is in which monitor and no keybinds to (for example) move a window to a empty monitor workspace. So, I wrote a small guide to what I think is a better setup in Omarchy for a multi-head workspace setup.

Goal

Updated Keybidings

SUPER + CTRL to handle monitor interaction. To focus desired monitor:
SUPER + CTRL + < monitor index >
SUPER + CTRL + LEFT/RIGHT To move a window to the a monitor:
(even if the current workspace is empty)
SUPER + CTRL + SHIFT + < monitor index >
SUPER + CTRL + SHIFT + LEFT/RIGHT

Plugin

split-monitor-workspaces

Dependencies

sudo pacman -S cpio

Update headers

hyprpm update

Install

   hyprpm add https://github.com/Duckonaut/split-monitor-workspaces
   hyprpm enable split-monitor-workspaces
   hyprpm reload -n

Configuration

Add in ~/.config/hypr/hyprland.conf:

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

Create ~/.config/hypr/plugin-split-monitor-workspace.conf:

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

# --- split-monitor-workspaces ---
plugin {
  split-monitor-workspaces {
    count = 10
    keep_focused = 1
    enable_persistent_workspaces = 0
    enable_notifications = 0
  }
}

# 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) #####
# SUPER + [1..0] = switch workspace on current monitor
bindd = SUPER, code:10, Switch WS 1, split-workspace, 1
bindd = SUPER, code:11, Switch WS 2, split-workspace, 2
bindd = SUPER, code:12, Switch WS 3, split-workspace, 3
bindd = SUPER, code:13, Switch WS 4, split-workspace, 4
bindd = SUPER, code:14, Switch WS 5, split-workspace, 5
bindd = SUPER, code:15, Switch WS 6, split-workspace, 6
bindd = SUPER, code:16, Switch WS 7, split-workspace, 7
bindd = SUPER, code:17, Switch WS 8, split-workspace, 8
bindd = SUPER, code:18, Switch WS 9, split-workspace, 9
bindd = SUPER, code:19, Switch WS 0, split-workspace, 10

# SUPER + SHIFT + [1..0] = move window to workspace (keep focus here)
bindd = SUPER SHIFT, code:10, Move win to WS 1, split-movetoworkspace, 1
bindd = SUPER SHIFT, code:11, Move win to WS 2, split-movetoworkspace, 2
bindd = SUPER SHIFT, code:12, Move win to WS 3, split-movetoworkspace, 3
bindd = SUPER SHIFT, code:13, Move win to WS 4, split-movetoworkspace, 4
bindd = SUPER SHIFT, code:14, Move win to WS 5, split-movetoworkspace, 5
bindd = SUPER SHIFT, code:15, Move win to WS 6, split-movetoworkspace, 6
bindd = SUPER SHIFT, code:16, Move win to WS 7, split-movetoworkspace, 7
bindd = SUPER SHIFT, code:17, Move win to WS 8, split-movetoworkspace, 8
bindd = SUPER SHIFT, code:18, Move win to WS 9, split-movetoworkspace, 9
bindd = SUPER SHIFT, code:19, Move win to WS 0, split-movetoworkspace, 10

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

##### ABSOLUTE MONITOR FOCUS (SUPER + CTRL + <position>)
bindd = SUPER CTRL, code:10, Focus mon 0, focusmonitor, 0
bindd = SUPER CTRL, code:11, Focus mon 1, focusmonitor, 1
bindd = SUPER CTRL, code:12, Focus mon 2, focusmonitor, 2
bindd = SUPER CTRL, code:13, Focus mon 3, focusmonitor, 3
bindd = SUPER CTRL, code:14, Focus mon 4, focusmonitor, 4

##### MOVE WINDOW TO MONITOR (by ID, keep focus here)
# SUPER+CTRL+SHIFT+[1..3]
bindd = SUPER CTRL SHIFT, code:10, Send win to mon 0, movewindow, mon:0
bindd = SUPER CTRL SHIFT, code:11, Send win to mon 1, movewindow, mon:1
bindd = SUPER CTRL SHIFT, code:12, Send win to mon 2, movewindow, mon:2
bindd = SUPER CTRL SHIFT, code:13, Send win to mon 3, movewindow, mon:3
bindd = SUPER CTRL SHIFT, code:14, Send win to mon 4, movewindow, mon:4

##### ARROW NAV (relative; monitor-agnostic) #####
# SUPER + LEFT/RIGHT = focus monitor left/right
bindd = SUPER CTRL, LEFT, Focus monitor left, focusmonitor, l
bindd = SUPER CTRL, RIGHT, Focus monitor right, focusmonitor, r

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

Waybar

Update Waybar to better reflect it in ~/.config/waybar/style.css:

...
  "hyprland/workspaces": {
    "all-outputs": false,            // per-monitor list
    "sort-by-number": true,
    "disable-scroll": true,          // avoid scroll jumps
    "format": "{icon}",

    // Dots: filled = active here, ring = active elsewhere, hollow = has windows, dim = empty
    "format-icons": {
      "urgent":  "",
      "active":  "",  // current monitor's focused WS
      "visible": "",  // focused WS on another monitor
      "default": "",  // has windows
      "empty":   "·"   // created by split-monitor-workspaces but empty
    }
  },
...  

jpSkipper Sep 25, 2025

-

Thank you very much. One small thing, i was a little bit confused by: …Waybar
Update Waybar to better reflect it in ~/.config/waybar/style.css:

I guess you mean the ~/.config/waybar/config.jsonc instead of the css file.

opajanvv Sep 26, 2025

-

A few comments:

Anyway, thanks a lot for this walkthrough! Really helpful. Without it, I would have ditched Omarchy because of the lack of good workspace management in a dual-screen setup. I changed the setup to my own preferences:

It took me a few hours to get this working properly, so I’ll share my source files. `plugin-split-monitor-workspace.conf

# 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 CTRL SHIFT, LEFT, Send win to left mon, movewindow, mon:l
bindd = SUPER CTRL 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

waybar/config.jsonc

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

waybar/style.css

#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;
}

  

heart 7

brombirium Oct 13, 2025


opajanvv Oct 13, 2025

-

Thanks.
I’m gathering all my experiences with Omarchy in a blog, mainly for my own reference, so I can see why I made certain decisions. But of course, others can also use it to get ideas for their own configuration. It’s not complete yet, so feel free to check back from time to time to see if I’ve published a new blog post.
See https://opa.janvv.nl/tag:omarchy.

NawwafHusain Oct 24, 2025

-

Thank you guys, this has helped a lot! I want to extend the functionality a bit, but unsure where to even begin/if it possible. Currently I am running @opajanvv ’s set up, with wp 1-4 on my laptop and 5-8 on my monitor. What I want to achieve is, when no monitors are connected to the laptop, for the laptop to have 8 workspaces. When connected, the workspaces “move” to the new monitor. The reason I’m emphasizing move not create new ones, is that in my current set up, if i have a window in wp 5 and disconnect my HDMI, that window is “lost”, weirdly enough, when I reconnect, the window is still there in the same state.

@opajanvv

opajanvv Oct 24, 2025

-

Hey @NawwafHusain, that’s exactly what I was looking for. I already have a bash script that switches between three modes: laptop only, dual screen, and laptop mirrored (for presentations). It also requires a few other config files. I’m planning to document this in a blog article today or tomorrow. I still want to add keyboard shortcuts for it. Stay tuned.

@opajanvv

opajanvv Oct 24, 2025

-

@NawwafHusain new blog post is published. Hope it works for you. See the link in the previous post.

patroza Oct 26, 2025

-

im trying this with a virtual monitor connected to through vnc, but the whole separate workspaces per desktop is not really working as expected for me on latest omarchy.

opajanvv Oct 27, 2025

-

I don’t have experience with virtual monitors.
What’s the output of hyprctl monitors all?

patroza Oct 27, 2025

-

here it is, however, actually since switching my studio display from thunderbolt to split displayport+usb, it seems like it’s working well (also revealing the audio input/output and camera :)), I now have 5-8 on display 2. and 1-4 on display 1.

Monitor DP-1 (ID 0):
    5120x2880@60.00000 at 0x0
    description: Apple Computer Inc StudioDisplay 0x44030964
    make: Apple Computer Inc
    model: StudioDisplay
    physical size (mm): 600x330
    serial: 0x44030964
    active workspace: 4 (4)
    special workspace: 0 ()
    reserved: 0 26 0 0
    scale: 2.00
    transform: 0
    focused: yes
    dpmsStatus: 1
    vrr: false
    solitary: 0
    solitaryBlockedBy: windowed mode,missing candidate
    activelyTearing: false
    tearingBlockedBy: next frame is not torn,user settings,missing candidate
    directScanoutTo: 0
    directScanoutBlockedBy: user settings,screen record/screenshot,software renders/cursors,missing candidate
    disabled: false
    currentFormat: XRGB8888
    mirrorOf: none
    availableModes: 5120x2880@60.00Hz 3840x2160@60.00Hz 2560x2880@60.00Hz 2560x1440@60.00Hz 1920x1080@60.00Hz

Monitor HEADLESS-66 (ID 1):
    3456x2234@60.00000 at 2560x450
    description:
    make:
    model:
    physical size (mm): 0x0
    serial:
    active workspace: 5 (5)
    special workspace: 0 ()
    reserved: 0 26 0 0
    scale: 2.00
    transform: 0
    focused: no
    dpmsStatus: 1
    vrr: false
    solitary: 0
    solitaryBlockedBy: windowed mode,missing candidate
    activelyTearing: false
    tearingBlockedBy: next frame is not torn,user settings,not supported by monitor,missing candidate
    directScanoutTo: 0
    directScanoutBlockedBy: user settings,screen record/screenshot,software renders/cursors,missing candidate
    disabled: false
    currentFormat: XRGB8888
    mirrorOf: none
    availableModes: 1920x1080@0.06Hz
  

opajanvv Oct 27, 2025

-

Super. Glad you got it working.

Contributors:

@rsd @patroza @tonimarmol @brombirium @NawwafHusain @jpSkipper @opajanvv

Reply via email

© 2026 rcanzlovar.com | About | Contact | Privacy Policy | RSS Feed