-- https://wiki.hypr.land/Configuring/Basics/Window-Rules/ -- launchers — float centred at cursor hl.window_rule({ name = "ulauncher-launcher", match = { class = "ulauncher" }, tag = "+launcher" }) hl.window_rule({ name = "vicinae-launcher", match = { class = "vicinae" }, tag = "+launcher" }) hl.window_rule({ name = "launcher", match = { tag = "launcher" }, float = true, pin = true, no_shadow = true, no_blur = true, border_size = 0, move = "(cursor_x-(window_w/2)) (cursor_y-(window_h/2))", }) hl.window_rule({ name = "vicinae-server", match = { class = "vicinae-server" }, pin = true, no_shadow = true, no_blur = true, border_size = 0, move = "(cursor_x-(window_w/2)) (cursor_y-(window_h/2))", }) -- firefox hl.window_rule({ name = "firefox", match = { class = "firefox" }, opaque = true, render_unfocused = true }) -- vesktop (Discord) hl.window_rule({ name = "vesktop", match = { class = "vesktop" }, render_unfocused = true, no_screen_share = true }) -- mixer tag — tag assignment hl.window_rule({ name = "nextcloud-mixer", match = { class = "com.nextcloud.desktopclient.nextcloud" }, tag = "+mixer" }) hl.window_rule({ name = "blueman-mixer", match = { class = "blueman-manager" }, tag = "+mixer" }) hl.window_rule({ name = "nm-mixer", match = { class = "nm-connection-editor" }, tag = "+mixer" }) -- mixer tag — behaviour hl.window_rule({ name = "mixer-float", match = { tag = "mixer" }, float = true, pin = true, move = "(monitor_w*0.7) (monitor_h*0.05)", size = "(monitor_w*0.2) (monitor_h*0.3)", }) -- centred large hl.window_rule({ name = "large-centered-L", match = { tag = "centered-L" }, float = true, move = "(monitor_w*0.1) (monitor_h*0.1)", size = "(monitor_w*0.8) (monitor_h*0.8)", }) -- centred medium hl.window_rule({ name = "large-centered", match = { tag = "centered" }, float = true, move = "(monitor_w*0.2) (monitor_h*0.2)", size = "(monitor_w*0.6) (monitor_h*0.6)", }) -- centred small hl.window_rule({ name = "centered-small", match = { tag = "centered-S" }, float = true, move = "(monitor_w*0.4) (monitor_h*0.4)", size = "(monitor_w*0.2) (monitor_h*0.2)", }) -- filepicker — float, fixed 760x460, centred on the cursor. -- The size and move must be kept in sync by hand: Hyprland evaluates `move` -- using the window's *natural* size and only then applies `size`, resizing -- from the top-left. Using cursor_x-(window_w/2) would therefore centre the -- natural (~1274x714) window and leave the shrunk one off-cursor, so the -- offsets below are hard-coded to half the final size (380x230). zenity's -- file chooser ignores --width/--height and has a ~738x363 GTK minimum, so -- 760x460 is about as small as it goes while landing exactly on the pointer. hl.window_rule({ name = "filepicker", match = { tag = "filepicker" }, float = true, size = "760 460", move = "(cursor_x-380) (cursor_y-230)", }) -- xdg portal dialogs — float, centred on the monitor (i.e. above the parent). -- The GTK portal backend (xdg-desktop-portal-gtk) serves native file/app/print -- choosers for portal-driven apps: Steam ("select library folder"), Chromium/ -- Electron, Flatpak apps, etc. It runs in its *own* process, so the dialog opens -- as a parentless top-level with no xdg-dialog/X11-dialog hint — Hyprland has no -- signal that it's a dialog and would otherwise tile it (unlike in-process xdg -- dialogs, which it auto-floats). Natural size is kept, so the centre offsets use -- the real window_w/window_h (no `size` to skew them; see the filepicker note). hl.window_rule({ name = "xdg-portal-dialog", match = { class = "xdg-desktop-portal-gtk" }, float = true, move = "(monitor_w/2 - window_w/2) (monitor_h/2 - window_h/2)", }) -- dialogs — float any dialog-like window at its natural (minimum) size, centred on -- the cursor: renaming dialogs, generic Save/Open/Confirm/Delete/Move/Copy/Replace/ -- Properties/Preferences dialogs, and Firefox "Opening " download prompts. -- Hyprland already auto-floats real in-process xdg/X11 dialogs; this catches the ones -- that tile because they carry no dialog hint, matched heuristically by title. No -- `size`, so the natural (minimum) size is kept and the cursor-centre offsets use the -- real window_w/h (see the filepicker note above re: move/size ordering). hl.window_rule({ name = "dialog-float", match = { title = "^(Rename|Save|Opening |Open |Confirm|Delete|Move|Copy|Replace|Properties|Preferences).*" }, float = true, move = "(cursor_x-(window_w/2)) (cursor_y-(window_h/2))", }) -- spotify floating hl.window_rule({ name = "spotify-float", match = { class = "spotify", float = true }, no_blur = true, opacity = "0.5 0.05", }) -- smart gaps hl.workspace_rule({ workspace = "w[tv1]s[false]", gaps_out = 0, gaps_in = 0 }) hl.workspace_rule({ workspace = "f[1]s[false]", gaps_out = 0, gaps_in = 0 }) hl.window_rule({ name = "smart-gaps-tiling-tv1", match = { float = false, workspace = "w[tv1]s[false]" }, border_size = 1, rounding = 3 }) hl.window_rule({ name = "smart-gaps-tiling-f1", match = { float = false, workspace = "f[1]s[false]" }, border_size = 0, rounding = 0 })