diff --git a/dotfiles/config/hypr/hyprland.conf b/dotfiles/config/hypr/hyprland.conf deleted file mode 120000 index 3a5aacd2..00000000 --- a/dotfiles/config/hypr/hyprland.conf +++ /dev/null @@ -1 +0,0 @@ -/nix/store/k2dsag6qk1zhq12k4hgpkpnvs3w98hv3-home-manager-files/.config/hypr/hyprland.conf \ No newline at end of file diff --git a/dotfiles/config/hypr/hyprland.conf b/dotfiles/config/hypr/hyprland.conf new file mode 100644 index 00000000..ad03147f --- /dev/null +++ b/dotfiles/config/hypr/hyprland.conf @@ -0,0 +1,532 @@ +# Hyprland Configuration +# XMonad-like dynamic tiling using hy3 plugin +# Based on XMonad configuration from xmonad.hs + +# ============================================================================= +# PLUGINS (Hyprland pinned to 0.53.0 to match hy3) +# ============================================================================= +# Load the plugin before parsing keybinds/layouts that depend on it +plugin = /run/current-system/sw/lib/libhy3.so + +# ============================================================================= +# MONITORS +# ============================================================================= +monitor=,preferred,auto,auto + +# ============================================================================= +# PROGRAMS +# ============================================================================= +$terminal = alacritty +$fileManager = dolphin +$menu = rofi -show drun -show-icons +$runMenu = rofi -show run + +# ============================================================================= +# ENVIRONMENT VARIABLES +# ============================================================================= +env = XCURSOR_SIZE,24 +env = QT_QPA_PLATFORMTHEME,qt5ct +env = GDK_DPI_SCALE,1.25 +env = QT_FONT_DPI,120 + +# ============================================================================= +# INPUT CONFIGURATION +# ============================================================================= +input { + kb_layout = us + kb_variant = + kb_model = + kb_options = + kb_rules = + + follow_mouse = 1 + + touchpad { + natural_scroll = no + } + + sensitivity = 0 +} + +# Cursor warping behavior +cursor { + persistent_warps = true +} + +# ============================================================================= +# GENERAL SETTINGS +# ============================================================================= +general { + gaps_in = 5 + gaps_out = 10 + border_size = 2 + col.active_border = rgba(edb443ee) rgba(33ccffee) 45deg + col.inactive_border = rgba(595959aa) + + # Use hy3 layout for XMonad-like dynamic tiling + layout = hy3 + + allow_tearing = false +} + +# ============================================================================= +# DECORATION +# ============================================================================= +decoration { + rounding = 5 + + blur { + enabled = true + size = 3 + passes = 1 + } + + # Fade inactive windows (like XMonad's fadeInactive) + active_opacity = 1.0 + inactive_opacity = 0.9 +} + +# ============================================================================= +# ANIMATIONS +# ============================================================================= +animations { + enabled = yes + + bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + bezier = linear, 0, 0, 1, 1 + + animation = windows, 1, 4, myBezier + animation = windowsOut, 1, 4, default, popin 80% + animation = border, 1, 10, default + animation = borderangle, 1, 8, default + animation = fade, 1, 4, default + animation = workspaces, 1, 4, default +} + +# ============================================================================= +# MASTER LAYOUT CONFIGURATION +# ============================================================================= +master { + new_status = slave + mfact = 0.5 + orientation = left +} + +# Dwindle layout (alternative - binary tree like i3) +dwindle { + pseudotile = yes + preserve_split = yes +} + +# ============================================================================= +# WORKSPACE RULES (SMART GAPS) +# ============================================================================= +# Replace no_gaps_when_only (removed in newer Hyprland) +# Remove gaps when there's only one visible tiled window (ignore special workspaces) +workspace = w[tv1]s[false], gapsout:0, gapsin:0 +workspace = f[1]s[false], gapsout:0, gapsin:0 + +# Group/tabbed window configuration (built-in alternative to hy3 tabs) +group { + col.border_active = rgba(edb443ff) + col.border_inactive = rgba(091f2eff) + + groupbar { + enabled = true + font_size = 12 + height = 22 + col.active = rgba(edb443ff) + col.inactive = rgba(091f2eff) + text_color = rgba(091f2eff) + } +} + +# ============================================================================= +# HY3/HYPREXPO PLUGIN CONFIG +# ============================================================================= +plugin { + hy3 { + # Disable autotile to get XMonad-like manual control + autotile { + enable = false + } + + # Tab configuration + tabs { + height = 22 + padding = 6 + render_text = true + text_font = "Sans" + text_height = 10 + text_padding = 3 + col.active = rgba(edb443ff) + col.inactive = rgba(091f2eff) + col.urgent = rgba(ff0000ff) + col.text.active = rgba(091f2eff) + col.text.inactive = rgba(ffffffff) + col.text.urgent = rgba(ffffffff) + } + } + +} + +# ============================================================================= +# MISC +# ============================================================================= +misc { + force_default_wallpaper = 0 + disable_hyprland_logo = true +} + +# ============================================================================= +# WINDOW RULES +# ============================================================================= +# Float dialogs +windowrulev2 = float, class:^()$,title:^()$ +windowrulev2 = float, title:^(Picture-in-Picture)$ +windowrulev2 = float, title:^(Open File)$ +windowrulev2 = float, title:^(Save File)$ +windowrulev2 = float, title:^(Confirm)$ + +# Scratchpad windows - float and size +windowrulev2 = float, class:^(htop-scratch)$ +windowrulev2 = size 90% 90%, class:^(htop-scratch)$ +windowrulev2 = center, class:^(htop-scratch)$ + +windowrulev2 = float, class:^(pavucontrol)$ +windowrulev2 = size 90% 90%, class:^(pavucontrol)$ +windowrulev2 = center, class:^(pavucontrol)$ + +windowrulev2 = float, class:^(Spotify)$ +windowrulev2 = size 90% 90%, class:^(Spotify)$ +windowrulev2 = center, class:^(Spotify)$ + +windowrulev2 = float, class:^(Element)$ +windowrulev2 = size 90% 90%, class:^(Element)$ +windowrulev2 = center, class:^(Element)$ + +windowrulev2 = float, class:^(Slack)$ +windowrulev2 = size 90% 90%, class:^(Slack)$ +windowrulev2 = center, class:^(Slack)$ + +windowrulev2 = float, class:^(transmission-gtk)$ +windowrulev2 = size 90% 90%, class:^(transmission-gtk)$ +windowrulev2 = center, class:^(transmission-gtk)$ + +# Gmail and Messages (Chrome windows) +windowrulev2 = float, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$ +windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$ +windowrulev2 = center, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$ + +windowrulev2 = float, class:^(google-chrome)$,title:^(Messages.*)$ +windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(Messages.*)$ +windowrulev2 = center, class:^(google-chrome)$,title:^(Messages.*)$ + +# ============================================================================= +# KEY BINDINGS +# ============================================================================= + +# Modifier keys +$mainMod = SUPER +$modAlt = SUPER ALT +$hyper = SUPER CTRL ALT + +# ----------------------------------------------------------------------------- +# Program Launching +# ----------------------------------------------------------------------------- +bind = $mainMod, P, exec, $menu +bind = $mainMod SHIFT, P, exec, $runMenu +bind = $mainMod SHIFT, Return, exec, $terminal +bind = $mainMod, Q, killactive, +bind = $mainMod SHIFT, C, killactive, +bind = $mainMod SHIFT, Q, exit, +# Emacs-everywhere (like XMonad's emacs-everywhere) +bind = $mainMod, E, exec, emacsclient --eval '(emacs-everywhere)' +bind = $mainMod, V, exec, wl-paste | xdotool type --file - + +# Chrome/Browser (raise or spawn like XMonad's bindBringAndRaise) +bind = $modAlt, C, exec, ~/.config/hypr/scripts/raise-or-run.sh google-chrome google-chrome-stable + +# ----------------------------------------------------------------------------- +# SCRATCHPADS (Special Workspaces) +# ----------------------------------------------------------------------------- +# Toggle scratchpads +bind = $modAlt, E, togglespecialworkspace, element +bind = $modAlt, G, togglespecialworkspace, gmail +bind = $modAlt, H, togglespecialworkspace, htop +bind = $modAlt, M, togglespecialworkspace, messages +bind = $modAlt, K, togglespecialworkspace, slack +bind = $modAlt, S, togglespecialworkspace, spotify +bind = $modAlt, T, togglespecialworkspace, transmission +bind = $modAlt, V, togglespecialworkspace, volume + +# Move windows to scratchpads +bind = $modAlt SHIFT, E, movetoworkspace, special:element +bind = $modAlt SHIFT, G, movetoworkspace, special:gmail +bind = $modAlt SHIFT, H, movetoworkspace, special:htop +bind = $modAlt SHIFT, M, movetoworkspace, special:messages +bind = $modAlt SHIFT, K, movetoworkspace, special:slack +bind = $modAlt SHIFT, S, movetoworkspace, special:spotify +bind = $modAlt SHIFT, T, movetoworkspace, special:transmission +bind = $modAlt SHIFT, V, movetoworkspace, special:volume + +# Hidden workspace (like XMonad's NSP) +bind = $mainMod, X, movetoworkspace, special:NSP +bind = $mainMod SHIFT, X, togglespecialworkspace, NSP + +# ----------------------------------------------------------------------------- +# DIRECTIONAL NAVIGATION (WASD - like XMonad Navigation2D) +# Using hy3 dispatchers for proper tree-based navigation +# ----------------------------------------------------------------------------- + +# Focus movement (Mod + WASD) - hy3:movefocus navigates the tree +bind = $mainMod, W, hy3:movefocus, u +bind = $mainMod, S, hy3:movefocus, d +bind = $mainMod, A, hy3:movefocus, l +bind = $mainMod, D, hy3:movefocus, r + +# Move windows (Mod + Shift + WASD) - hy3:movewindow with once=true for swapping +bind = $mainMod SHIFT, W, hy3:movewindow, u, once +bind = $mainMod SHIFT, S, hy3:movewindow, d, once +bind = $mainMod SHIFT, A, hy3:movewindow, l, once +bind = $mainMod SHIFT, D, hy3:movewindow, r, once + +# Resize windows (Mod + Ctrl + WASD) +binde = $mainMod CTRL, W, resizeactive, 0 -50 +binde = $mainMod CTRL, S, resizeactive, 0 50 +binde = $mainMod CTRL, A, resizeactive, -50 0 +binde = $mainMod CTRL, D, resizeactive, 50 0 + +# Screen/Monitor focus (Hyper + WASD) +bind = $hyper, W, focusmonitor, u +bind = $hyper, S, focusmonitor, d +bind = $hyper, A, focusmonitor, l +bind = $hyper, D, focusmonitor, r + +# Move window to monitor and follow (Hyper + Shift + WASD) +bind = $hyper SHIFT, W, movewindow, mon:u +bind = $hyper SHIFT, S, movewindow, mon:d +bind = $hyper SHIFT, A, movewindow, mon:l +bind = $hyper SHIFT, D, movewindow, mon:r + +# Shift to empty workspace on screen direction (Hyper + Ctrl + WASD) +# Like XMonad's shiftToEmptyOnScreen +bind = $hyper CTRL, W, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh u +bind = $hyper CTRL, S, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh d +bind = $hyper CTRL, A, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh l +bind = $hyper CTRL, D, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh r + +# ----------------------------------------------------------------------------- +# LAYOUT CONTROL (XMonad-like with hy3) +# ----------------------------------------------------------------------------- + +# Create groups with different orientations (like XMonad layouts) +# hy3:makegroup creates a split/tab group from focused window +bind = $mainMod, Space, hy3:changegroup, toggletab +bind = $mainMod SHIFT, Space, hy3:changegroup, opposite + +# Create specific group types +bind = $mainMod, H, hy3:makegroup, h +bind = $mainMod SHIFT, V, hy3:makegroup, v +bind = $mainMod CTRL, Space, hy3:makegroup, tab + +# Change group type (cycle h -> v -> tab) +bind = $mainMod, slash, hy3:changegroup, h +bind = $mainMod SHIFT, slash, hy3:changegroup, v + +# Tab navigation (like XMonad's focus next/prev in tabbed) +bind = $mainMod, bracketright, hy3:focustab, r, wrap +bind = $mainMod, bracketleft, hy3:focustab, l, wrap + +# Move window within tab group (hy3 has no movetab dispatcher) +bind = $mainMod SHIFT, bracketright, hy3:movewindow, r, visible +bind = $mainMod SHIFT, bracketleft, hy3:movewindow, l, visible + +# Expand focus to parent group (like XMonad's focus parent) +bind = $mainMod, grave, hy3:expand, expand +bind = $mainMod SHIFT, grave, hy3:expand, base + +# Fullscreen (like XMonad's NBFULL toggle) +bind = $mainMod, F, fullscreen, 0 +bind = $mainMod SHIFT, F, fullscreen, 1 + +# Toggle floating +bind = $mainMod, T, togglefloating, + +# Resize split ratio (hy3 uses resizeactive for splits) +binde = $mainMod, comma, resizeactive, -50 0 +binde = $mainMod, period, resizeactive, 50 0 + +# Kill group - removes the focused window from its group +bind = $mainMod, N, hy3:killactive + +# hy3:setswallow - set a window to swallow newly spawned windows +bind = $mainMod, M, hy3:setswallow, toggle + +# Minimize to special workspace (like XMonad's minimizeWindow) +bind = $mainMod SHIFT, M, movetoworkspace, special:minimized +# Restore last minimized +bind = $modAlt, Return, togglespecialworkspace, minimized + +# ----------------------------------------------------------------------------- +# WORKSPACE CONTROL +# ----------------------------------------------------------------------------- + +# Switch workspaces (1-9, 0=10) +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 +bind = $mainMod, 0, workspace, 10 + +# Move window to workspace +bind = $mainMod SHIFT, 1, movetoworkspace, 1 +bind = $mainMod SHIFT, 2, movetoworkspace, 2 +bind = $mainMod SHIFT, 3, movetoworkspace, 3 +bind = $mainMod SHIFT, 4, movetoworkspace, 4 +bind = $mainMod SHIFT, 5, movetoworkspace, 5 +bind = $mainMod SHIFT, 6, movetoworkspace, 6 +bind = $mainMod SHIFT, 7, movetoworkspace, 7 +bind = $mainMod SHIFT, 8, movetoworkspace, 8 +bind = $mainMod SHIFT, 9, movetoworkspace, 9 +bind = $mainMod SHIFT, 0, movetoworkspace, 10 + +# Move and follow to workspace (like XMonad's shiftThenView) +bind = $mainMod CTRL, 1, movetoworkspacesilent, 1 +bind = $mainMod CTRL, 1, workspace, 1 +bind = $mainMod CTRL, 2, movetoworkspacesilent, 2 +bind = $mainMod CTRL, 2, workspace, 2 +bind = $mainMod CTRL, 3, movetoworkspacesilent, 3 +bind = $mainMod CTRL, 3, workspace, 3 +bind = $mainMod CTRL, 4, movetoworkspacesilent, 4 +bind = $mainMod CTRL, 4, workspace, 4 +bind = $mainMod CTRL, 5, movetoworkspacesilent, 5 +bind = $mainMod CTRL, 5, workspace, 5 +bind = $mainMod CTRL, 6, movetoworkspacesilent, 6 +bind = $mainMod CTRL, 6, workspace, 6 +bind = $mainMod CTRL, 7, movetoworkspacesilent, 7 +bind = $mainMod CTRL, 7, workspace, 7 +bind = $mainMod CTRL, 8, movetoworkspacesilent, 8 +bind = $mainMod CTRL, 8, workspace, 8 +bind = $mainMod CTRL, 9, movetoworkspacesilent, 9 +bind = $mainMod CTRL, 9, workspace, 9 +bind = $mainMod CTRL, 0, movetoworkspacesilent, 10 +bind = $mainMod CTRL, 0, workspace, 10 + +# Workspace cycling (like XMonad's cycleWorkspaceOnCurrentScreen) +bind = $mainMod, backslash, workspace, previous + +# Go to next empty workspace (like XMonad's moveTo Next emptyWS) +bind = $hyper, E, workspace, empty + +# Move to next screen (like XMonad's shiftToNextScreenX) +bind = $mainMod, Z, focusmonitor, +1 +bind = $mainMod SHIFT, Z, movewindow, mon:+1 + +# Shift to empty workspace and view (like XMonad's shiftToEmptyAndView) +bind = $mainMod SHIFT, H, movetoworkspace, empty + +# ----------------------------------------------------------------------------- +# WINDOW MANAGEMENT +# ----------------------------------------------------------------------------- + +# Go to window (rofi window switcher) +bind = $mainMod, G, exec, rofi -show window -show-icons + +# Bring window (move to current workspace) +bind = $mainMod, B, exec, ~/.config/hypr/scripts/bring-window.sh + +# Replace window (swap focused with selected - like XMonad's myReplaceWindow) +bind = $mainMod SHIFT, B, exec, ~/.config/hypr/scripts/replace-window.sh + +# Gather windows of same class (like XMonad's gatherThisClass) +bind = $hyper, G, exec, ~/.config/hypr/scripts/gather-class.sh + +# Focus next window of different class (like XMonad's focusNextClass) +bind = $mainMod, Tab, exec, ~/.config/hypr/scripts/focus-next-class.sh + +# ----------------------------------------------------------------------------- +# MEDIA KEYS +# ----------------------------------------------------------------------------- + +# Volume control (matching XMonad: Mod+I=up, Mod+K=down, Mod+U=mute) +binde = , XF86AudioRaiseVolume, exec, set_volume --unmute --change-volume +5 +binde = , XF86AudioLowerVolume, exec, set_volume --unmute --change-volume -5 +bind = , XF86AudioMute, exec, set_volume --toggle-mute +binde = $mainMod, I, exec, set_volume --unmute --change-volume +5 +binde = $mainMod, K, exec, set_volume --unmute --change-volume -5 +bind = $mainMod, U, exec, set_volume --toggle-mute + +# Media player controls (matching XMonad: Mod+;=play, Mod+L=next, Mod+J=prev) +bind = $mainMod, semicolon, exec, playerctl play-pause +bind = , XF86AudioPlay, exec, playerctl play-pause +bind = , XF86AudioPause, exec, playerctl play-pause +bind = $mainMod, L, exec, playerctl next +bind = , XF86AudioNext, exec, playerctl next +bind = $mainMod, J, exec, playerctl previous +bind = , XF86AudioPrev, exec, playerctl previous + +# Mute current window (like XMonad's toggle_mute_current_window) +bind = $hyper SHIFT, Q, exec, toggle_mute_current_window.sh +bind = $hyper CTRL, Q, exec, toggle_mute_current_window.sh only + +# Brightness control +binde = , XF86MonBrightnessUp, exec, brightness.sh up +binde = , XF86MonBrightnessDown, exec, brightness.sh down + +# ----------------------------------------------------------------------------- +# UTILITY BINDINGS +# ----------------------------------------------------------------------------- + +bind = $hyper, V, exec, cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy +bind = $hyper, P, exec, rofi-pass +bind = $hyper, H, exec, grim -g "$(slurp)" - | swappy -f - +bind = $hyper, C, exec, shell_command.sh +bind = $hyper, X, exec, rofi_command.sh +bind = $hyper SHIFT, L, exec, hyprlock +bind = $hyper, K, exec, rofi_kill_process.sh +bind = $hyper SHIFT, K, exec, rofi_kill_all.sh +bind = $hyper, R, exec, rofi-systemd +bind = $hyper, 9, exec, start_synergy.sh +bind = $hyper, I, exec, rofi_select_input.hs +bind = $hyper, O, exec, rofi_paswitch + +# Reload config +bind = $mainMod, R, exec, hyprctl reload + +# ----------------------------------------------------------------------------- +# MOUSE BINDINGS +# ----------------------------------------------------------------------------- + +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow + +# Scroll through workspaces +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 + +# ============================================================================= +# AUTOSTART +# ============================================================================= + +# Scratchpad applications (start in special workspaces) +exec-once = [workspace special:element silent] element-desktop +exec-once = [workspace special:gmail silent] google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox +exec-once = [workspace special:htop silent] alacritty --class htop-scratch --title htop -e htop +exec-once = [workspace special:messages silent] google-chrome-stable --new-window https://messages.google.com/web/conversations +exec-once = [workspace special:slack silent] slack +exec-once = [workspace special:spotify silent] spotify +exec-once = [workspace special:transmission silent] transmission-gtk +exec-once = [workspace special:volume silent] pavucontrol + +# Clipboard history daemon +exec-once = wl-paste --type text --watch cliphist store +exec-once = wl-paste --type image --watch cliphist store + +# Night light (optional - comment out if not needed) +# exec-once = wlsunset -l 37.7 -L -122.4