Add Hyprland with hy3 plugin for XMonad-like tiling
Configure Hyprland to use the hy3 plugin for dynamic tiling similar to XMonad. Uses official Hyprland and hy3 flakes pinned to v0.53.0 for proper plugin compatibility (nixpkgs packaging had header issues). Key changes: - Add hyprland and hy3 flake inputs with version pinning - Rewrite hyprland.conf with hy3 layout and XMonad-like keybindings - Add helper scripts for window management (bring, replace, gather, etc.) - WASD directional navigation using hy3:movefocus/movewindow - Tab groups, horizontal/vertical splits via hy3:makegroup - Scratchpads via Hyprland special workspaces Also removes org-agenda-api flake integration (moved elsewhere). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,25 +1,38 @@
|
||||
# Hyprland Configuration
|
||||
# XMonad-like dynamic tiling using hy3 plugin
|
||||
# Based on XMonad configuration from xmonad.hs
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Monitors/
|
||||
# =============================================================================
|
||||
# PLUGINS (Hyprland pinned to 0.53.0 to match hy3)
|
||||
# =============================================================================
|
||||
exec-once = hyprctl plugin load /run/current-system/sw/lib/libhy3.so
|
||||
# hyprexpo disabled - header compatibility issue
|
||||
# exec-once = hyprctl plugin load /run/current-system/sw/lib/libhyprexpo.so
|
||||
|
||||
# =============================================================================
|
||||
# MONITORS
|
||||
# =============================================================================
|
||||
monitor=,preferred,auto,auto
|
||||
|
||||
# Source a file (multi-file configs)
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
|
||||
# Set programs that you use
|
||||
# =============================================================================
|
||||
# PROGRAMS
|
||||
# =============================================================================
|
||||
$terminal = alacritty
|
||||
$fileManager = dolphin
|
||||
$menu = rofi -show drun -show-icons
|
||||
$runMenu = rofi -show run
|
||||
|
||||
# Environment variables
|
||||
# =============================================================================
|
||||
# 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 CONFIGURATION
|
||||
# =============================================================================
|
||||
input {
|
||||
kb_layout = us
|
||||
kb_variant =
|
||||
@@ -33,100 +46,213 @@ input {
|
||||
natural_scroll = no
|
||||
}
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
sensitivity = 0
|
||||
}
|
||||
|
||||
# General settings
|
||||
# =============================================================================
|
||||
# GENERAL SETTINGS
|
||||
# =============================================================================
|
||||
general {
|
||||
gaps_in = 5
|
||||
gaps_out = 20
|
||||
gaps_out = 10
|
||||
border_size = 2
|
||||
col.active_border = rgba(edb443ee) rgba(33ccffee) 45deg
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
layout = master
|
||||
# Use hy3 layout for XMonad-like dynamic tiling
|
||||
layout = hy3
|
||||
|
||||
allow_tearing = false
|
||||
}
|
||||
|
||||
# Decoration
|
||||
# =============================================================================
|
||||
# DECORATION
|
||||
# =============================================================================
|
||||
decoration {
|
||||
rounding = 10
|
||||
|
||||
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
|
||||
# =============================================================================
|
||||
animations {
|
||||
enabled = yes
|
||||
|
||||
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||
bezier = linear, 0, 0, 1, 1
|
||||
|
||||
animation = windows, 1, 7, myBezier
|
||||
animation = windowsOut, 1, 7, default, popin 80%
|
||||
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, 7, default
|
||||
animation = workspaces, 1, 6, default
|
||||
}
|
||||
|
||||
# Layout configuration
|
||||
dwindle {
|
||||
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
preserve_split = yes # you probably want this
|
||||
animation = fade, 1, 4, default
|
||||
animation = workspaces, 1, 4, default
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MASTER LAYOUT CONFIGURATION
|
||||
# =============================================================================
|
||||
master {
|
||||
mfact = 0.25
|
||||
new_status = slave
|
||||
mfact = 0.5
|
||||
orientation = left
|
||||
# Smart gaps - no gaps when only one window
|
||||
no_gaps_when_only = 1
|
||||
}
|
||||
|
||||
# Misc
|
||||
# Dwindle layout (alternative - binary tree like i3)
|
||||
dwindle {
|
||||
pseudotile = yes
|
||||
preserve_split = yes
|
||||
no_gaps_when_only = 1
|
||||
}
|
||||
|
||||
# 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)
|
||||
}
|
||||
}
|
||||
|
||||
# hyprexpo disabled - header compatibility issue
|
||||
# hyprexpo {
|
||||
# columns = 3
|
||||
# gap_size = 5
|
||||
# bg_col = rgba(000000ff)
|
||||
# workspace_method = first 1
|
||||
# enable_gesture = true
|
||||
# gesture_fingers = 3
|
||||
# gesture_distance = 300
|
||||
# gesture_positive = false
|
||||
# }
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MISC
|
||||
# =============================================================================
|
||||
misc {
|
||||
force_default_wallpaper = 0
|
||||
disable_hyprland_logo = true
|
||||
}
|
||||
|
||||
# Scratchpad-like windows
|
||||
windowrule = float, title:^(htop)$
|
||||
windowrule = size 80% 80%, title:^(htop)$
|
||||
# =============================================================================
|
||||
# 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)$
|
||||
|
||||
# Chrome specific rules
|
||||
windowrule = float, class:^(chrome)$,title:^(.*@gmail.com.*Gmail.*)$
|
||||
windowrule = float, class:^(chrome)$,title:^(Messages)$
|
||||
windowrule = size 90% 90%, class:^(chrome)$,title:^(.*@gmail.com.*Gmail.*)$
|
||||
windowrule = size 90% 90%, class:^(chrome)$,title:^(Messages)$
|
||||
# Scratchpad windows - float and size
|
||||
windowrulev2 = float, class:^(htop-scratch)$
|
||||
windowrulev2 = size 90% 90%, class:^(htop-scratch)$
|
||||
windowrulev2 = center, class:^(htop-scratch)$
|
||||
|
||||
# ===== KEY BINDINGS =====
|
||||
# Based on XMonad configuration
|
||||
windowrulev2 = float, class:^(pavucontrol)$
|
||||
windowrulev2 = size 90% 90%, class:^(pavucontrol)$
|
||||
windowrulev2 = center, class:^(pavucontrol)$
|
||||
|
||||
# Main modifier key (Super/Windows key equivalent to mod4Mask)
|
||||
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
|
||||
|
||||
# Mod+Alt combination (equivalent to modalt in XMonad)
|
||||
$modAlt = SUPER_ALT
|
||||
|
||||
# Hyper key (equivalent to mod3Mask in XMonad)
|
||||
$hyper = ALT_R
|
||||
|
||||
# Program launching
|
||||
# -----------------------------------------------------------------------------
|
||||
# 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,
|
||||
bind = $mainMod, E, exec, emacsclient -c
|
||||
bind = $mainMod, V, exec, xclip -o | xdotool type --file -
|
||||
# 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 launching (equivalent to bindBringAndRaise)
|
||||
bind = $modAlt, C, exec, google-chrome-stable
|
||||
# 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
|
||||
|
||||
# Scratchpad equivalents (toggle special workspaces)
|
||||
# -----------------------------------------------------------------------------
|
||||
# SCRATCHPADS (Special Workspaces)
|
||||
# -----------------------------------------------------------------------------
|
||||
# Toggle scratchpads
|
||||
bind = $modAlt, E, togglespecialworkspace, element
|
||||
bind = $modAlt, G, togglespecialworkspace, gmail
|
||||
bind = $modAlt, H, togglespecialworkspace, htop
|
||||
@@ -136,7 +262,7 @@ bind = $modAlt, S, togglespecialworkspace, spotify
|
||||
bind = $modAlt, T, togglespecialworkspace, transmission
|
||||
bind = $modAlt, V, togglespecialworkspace, volume
|
||||
|
||||
# Move windows to special workspaces
|
||||
# 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
|
||||
@@ -146,56 +272,109 @@ bind = $modAlt SHIFT, S, movetoworkspace, special:spotify
|
||||
bind = $modAlt SHIFT, T, movetoworkspace, special:transmission
|
||||
bind = $modAlt SHIFT, V, movetoworkspace, special:volume
|
||||
|
||||
# Directional navigation (WASD keys as in XMonad)
|
||||
bind = $mainMod, W, movefocus, u
|
||||
bind = $mainMod, S, movefocus, d
|
||||
bind = $mainMod, A, movefocus, l
|
||||
bind = $mainMod, D, movefocus, r
|
||||
# Hidden workspace (like XMonad's NSP)
|
||||
bind = $mainMod, X, movetoworkspace, special:NSP
|
||||
bind = $mainMod SHIFT, X, togglespecialworkspace, NSP
|
||||
|
||||
# Move windows directionally
|
||||
bind = $mainMod SHIFT, W, movewindow, u
|
||||
bind = $mainMod SHIFT, S, movewindow, d
|
||||
bind = $mainMod SHIFT, A, movewindow, l
|
||||
bind = $mainMod SHIFT, D, movewindow, r
|
||||
# -----------------------------------------------------------------------------
|
||||
# DIRECTIONAL NAVIGATION (WASD - like XMonad Navigation2D)
|
||||
# Using hy3 dispatchers for proper tree-based navigation
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Resize windows
|
||||
bind = $mainMod CTRL, W, resizeactive, 0 -50
|
||||
bind = $mainMod CTRL, S, resizeactive, 0 50
|
||||
bind = $mainMod CTRL, A, resizeactive, -50 0
|
||||
bind = $mainMod CTRL, D, resizeactive, 50 0
|
||||
# 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
|
||||
|
||||
# Layout control
|
||||
bind = $mainMod, Space, exec, hyprctl dispatch layoutmsg cyclenext
|
||||
bind = $mainMod CTRL, Space, fullscreen, 0
|
||||
bind = $mainMod, slash, exec, hyprctl dispatch layoutmsg orientationcycle left top
|
||||
# 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
|
||||
bind = $mainMod SHIFT, bracketright, hy3:movetab, r
|
||||
bind = $mainMod SHIFT, bracketleft, hy3:movetab, l
|
||||
|
||||
# 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,
|
||||
bind = $mainMod SHIFT, Y, pseudo, # dwindle pseudotile
|
||||
bind = $mainMod, J, togglesplit, # dwindle split direction
|
||||
bind = $mainMod, comma, exec, hyprctl dispatch splitratio -0.05
|
||||
bind = $mainMod, period, exec, hyprctl dispatch splitratio +0.05
|
||||
bind = $mainMod, N, exec, hyprctl dispatch layoutmsg addmaster
|
||||
bind = $mainMod SHIFT, N, exec, hyprctl dispatch layoutmsg removemaster
|
||||
|
||||
# Focus manipulation
|
||||
bind = $mainMod, Tab, exec, hyprctl dispatch focuswindow "class:$(hyprctl activewindow -j | jq -r '.class')"
|
||||
bind = $mainMod, M, exec, hyprctl dispatch focuswindow "class:master"
|
||||
# Resize split ratio (hy3 uses resizeactive for splits)
|
||||
binde = $mainMod, comma, resizeactive, -50 0
|
||||
binde = $mainMod, period, resizeactive, 50 0
|
||||
|
||||
# Monitor/Screen control
|
||||
bind = $mainMod, Z, focusmonitor, +1
|
||||
bind = $mainMod SHIFT, Z, movewindow, mon:+1
|
||||
# Kill group - removes the focused window from its group
|
||||
bind = $mainMod, N, hy3:killactive
|
||||
|
||||
# Window management
|
||||
bind = $mainMod, G, exec, hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class)"' | rofi -dmenu -i -p "Go to window" | head -1 | xargs -I {} hyprctl dispatch focuswindow "title:{}"
|
||||
bind = $mainMod, B, exec, SELECTION=$(hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class) [\(.address)]"' | rofi -dmenu -i -p "Bring window"); if [ -n "$SELECTION" ]; then ADDRESS=$(echo "$SELECTION" | sed 's/.*\[\(.*\)\]/\1/'); hyprctl dispatch movetoworkspace "$(hyprctl activeworkspace -j | jq -r '.id')",address:"$ADDRESS"; fi
|
||||
bind = $mainMod SHIFT, B, exec, hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class)"' | rofi -dmenu -i -p "Replace window" | head -1 | xargs -I {} hyprctl dispatch swapwindow "title:{}"
|
||||
bind = $mainMod, M, exec, hyprctl dispatch togglespecialworkspace minimized
|
||||
bind = $mainMod SHIFT, M, exec, hyprctl dispatch movetoworkspace special:minimized
|
||||
bind = $mainMod SHIFT, H, exec, EMPTY_WS=$(hyprctl workspaces -j | jq -r 'map(select(.windows == 0)) | .[0].id // empty'); if [ -z "$EMPTY_WS" ]; then EMPTY_WS=$(hyprctl workspaces -j | jq -r 'max_by(.id).id + 1'); fi; hyprctl dispatch movetoworkspace $EMPTY_WS && hyprctl dispatch workspace $EMPTY_WS
|
||||
bind = $mainMod, X, exec, hyprctl dispatch movetoworkspace special:NSP
|
||||
# hy3:setswallow - set a window to swallow newly spawned windows
|
||||
bind = $mainMod, M, hy3:setswallow, toggle
|
||||
|
||||
# Workspace switching
|
||||
# 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
|
||||
@@ -207,7 +386,7 @@ bind = $mainMod, 8, workspace, 8
|
||||
bind = $mainMod, 9, workspace, 9
|
||||
bind = $mainMod, 0, workspace, 10
|
||||
|
||||
# Move windows to workspaces
|
||||
# Move window to workspace
|
||||
bind = $mainMod SHIFT, 1, movetoworkspace, 1
|
||||
bind = $mainMod SHIFT, 2, movetoworkspace, 2
|
||||
bind = $mainMod SHIFT, 3, movetoworkspace, 3
|
||||
@@ -219,27 +398,73 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||
|
||||
# Move and follow to workspace
|
||||
bind = $mainMod CTRL, 1, movetoworkspace, 1
|
||||
bind = $mainMod CTRL, 2, movetoworkspace, 2
|
||||
bind = $mainMod CTRL, 3, movetoworkspace, 3
|
||||
bind = $mainMod CTRL, 4, movetoworkspace, 4
|
||||
bind = $mainMod CTRL, 5, movetoworkspace, 5
|
||||
bind = $mainMod CTRL, 6, movetoworkspace, 6
|
||||
bind = $mainMod CTRL, 7, movetoworkspace, 7
|
||||
bind = $mainMod CTRL, 8, movetoworkspace, 8
|
||||
bind = $mainMod CTRL, 9, movetoworkspace, 9
|
||||
bind = $mainMod CTRL, 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
|
||||
|
||||
# Media keys and volume control
|
||||
bind = , XF86AudioRaiseVolume, exec, set_volume --unmute --change-volume +5
|
||||
bind = , XF86AudioLowerVolume, exec, set_volume --unmute --change-volume -5
|
||||
# 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
|
||||
bind = $mainMod, I, exec, set_volume --unmute --change-volume +5
|
||||
bind = $mainMod, K, exec, set_volume --unmute --change-volume -5
|
||||
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
|
||||
# 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
|
||||
@@ -248,47 +473,67 @@ bind = , XF86AudioNext, exec, playerctl next
|
||||
bind = $mainMod, J, exec, playerctl previous
|
||||
bind = , XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
# Brightness control
|
||||
bind = , XF86MonBrightnessUp, exec, brightness.sh 5
|
||||
bind = , XF86MonBrightnessDown, exec, brightness.sh -5
|
||||
# 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
|
||||
|
||||
# Utility bindings
|
||||
bind = $hyper, V, exec, rofi_clipit.sh
|
||||
bind = $hyper, Y, exec, rofi-pass
|
||||
bind = $hyper, H, exec, rofi_shutter
|
||||
# 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, dm-tool lock
|
||||
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, slash, exec, toggle_taffybar
|
||||
bind = $hyper, Space, exec, skippy-xd
|
||||
# Overview - show all windows (Hyper+Space)
|
||||
# hyprexpo disabled - using rofi window switcher as fallback
|
||||
bind = $hyper, Space, exec, rofi -show window -show-icons
|
||||
bind = $hyper, I, exec, rofi_select_input.hs
|
||||
bind = $hyper, O, exec, rofi_paswitch
|
||||
bind = $mainMod, apostrophe, exec, load_default_map
|
||||
bind = $modAlt, apostrophe, exec, load_xkb_map
|
||||
|
||||
# Reload config
|
||||
bind = $mainMod, R, exec, hyprctl reload
|
||||
|
||||
# Workspace cycling
|
||||
bind = $mainMod, backslash, workspace, previous
|
||||
bind = $mainMod, Tab, workspace, previous
|
||||
# -----------------------------------------------------------------------------
|
||||
# MOUSE BINDINGS
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Mouse bindings
|
||||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
# Scroll through workspaces
|
||||
bind = $mainMod, mouse_down, workspace, e+1
|
||||
bind = $mainMod, mouse_up, workspace, e-1
|
||||
|
||||
# Special workspaces for "scratchpad" applications
|
||||
# =============================================================================
|
||||
# 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 --title htop -e htop
|
||||
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
|
||||
|
||||
30
dotfiles/config/hypr/scripts/bring-window.sh
Executable file
30
dotfiles/config/hypr/scripts/bring-window.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bring window to current workspace (like XMonad's bringWindow)
|
||||
# Uses rofi to select a window and moves it to the current workspace
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Get current workspace
|
||||
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
|
||||
|
||||
# Get all windows and format for rofi
|
||||
WINDOWS=$(hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0 and .workspace.id != '"$CURRENT_WS"') | "\(.title) [\(.class)] - WS:\(.workspace.id) |\(.address)"')
|
||||
|
||||
if [ -z "$WINDOWS" ]; then
|
||||
notify-send "Bring Window" "No windows on other workspaces"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Show rofi menu
|
||||
SELECTION=$(echo "$WINDOWS" | rofi -dmenu -i -p "Bring window" -format 's')
|
||||
|
||||
if [ -n "$SELECTION" ]; then
|
||||
# Extract the window address (after the last |)
|
||||
ADDRESS=$(echo "$SELECTION" | sed 's/.*|//')
|
||||
|
||||
# Move window to current workspace
|
||||
hyprctl dispatch movetoworkspace "$CURRENT_WS,address:$ADDRESS"
|
||||
|
||||
# Focus the window
|
||||
hyprctl dispatch focuswindow "address:$ADDRESS"
|
||||
fi
|
||||
15
dotfiles/config/hypr/scripts/cycle-layout.sh
Executable file
15
dotfiles/config/hypr/scripts/cycle-layout.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Cycle between master and dwindle layouts
|
||||
# Like XMonad's NextLayout
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CURRENT=$(hyprctl getoption general:layout -j | jq -r '.str')
|
||||
|
||||
if [ "$CURRENT" = "master" ]; then
|
||||
hyprctl keyword general:layout dwindle
|
||||
notify-send "Layout" "Switched to Dwindle (binary tree)"
|
||||
else
|
||||
hyprctl keyword general:layout master
|
||||
notify-send "Layout" "Switched to Master (XMonad-like)"
|
||||
fi
|
||||
48
dotfiles/config/hypr/scripts/focus-next-class.sh
Executable file
48
dotfiles/config/hypr/scripts/focus-next-class.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Focus next window of a different class (like XMonad's focusNextClass)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Get focused window class
|
||||
FOCUSED_CLASS=$(hyprctl activewindow -j | jq -r '.class')
|
||||
FOCUSED_ADDR=$(hyprctl activewindow -j | jq -r '.address')
|
||||
|
||||
if [ "$FOCUSED_CLASS" = "null" ] || [ -z "$FOCUSED_CLASS" ]; then
|
||||
# No focused window, just focus any window
|
||||
hyprctl dispatch cyclenext
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get all unique classes
|
||||
ALL_CLASSES=$(hyprctl clients -j | jq -r '[.[] | select(.workspace.id >= 0) | .class] | unique | .[]')
|
||||
|
||||
# Get sorted list of classes
|
||||
CLASSES_ARRAY=()
|
||||
while IFS= read -r class; do
|
||||
CLASSES_ARRAY+=("$class")
|
||||
done <<< "$ALL_CLASSES"
|
||||
|
||||
# Find current class index and get next class
|
||||
CURRENT_INDEX=-1
|
||||
for i in "${!CLASSES_ARRAY[@]}"; do
|
||||
if [ "${CLASSES_ARRAY[$i]}" = "$FOCUSED_CLASS" ]; then
|
||||
CURRENT_INDEX=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $CURRENT_INDEX -eq -1 ] || [ ${#CLASSES_ARRAY[@]} -le 1 ]; then
|
||||
# Only one class or class not found
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get next class (wrapping around)
|
||||
NEXT_INDEX=$(( (CURRENT_INDEX + 1) % ${#CLASSES_ARRAY[@]} ))
|
||||
NEXT_CLASS="${CLASSES_ARRAY[$NEXT_INDEX]}"
|
||||
|
||||
# Find first window of next class
|
||||
NEXT_WINDOW=$(hyprctl clients -j | jq -r ".[] | select(.class == \"$NEXT_CLASS\" and .workspace.id >= 0) | .address" | head -1)
|
||||
|
||||
if [ -n "$NEXT_WINDOW" ]; then
|
||||
hyprctl dispatch focuswindow "address:$NEXT_WINDOW"
|
||||
fi
|
||||
30
dotfiles/config/hypr/scripts/gather-class.sh
Executable file
30
dotfiles/config/hypr/scripts/gather-class.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# Gather all windows of the same class as focused window (like XMonad's gatherThisClass)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Get focused window class
|
||||
FOCUSED_CLASS=$(hyprctl activewindow -j | jq -r '.class')
|
||||
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
|
||||
|
||||
if [ "$FOCUSED_CLASS" = "null" ] || [ -z "$FOCUSED_CLASS" ]; then
|
||||
notify-send "Gather Class" "No focused window"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Find all windows with same class on other workspaces
|
||||
WINDOWS=$(hyprctl clients -j | jq -r ".[] | select(.class == \"$FOCUSED_CLASS\" and .workspace.id != $CURRENT_WS and .workspace.id >= 0) | .address")
|
||||
|
||||
if [ -z "$WINDOWS" ]; then
|
||||
notify-send "Gather Class" "No other windows of class '$FOCUSED_CLASS'"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Move each window to current workspace
|
||||
COUNT=0
|
||||
for ADDR in $WINDOWS; do
|
||||
hyprctl dispatch movetoworkspace "$CURRENT_WS,address:$ADDR"
|
||||
((COUNT++))
|
||||
done
|
||||
|
||||
notify-send "Gather Class" "Gathered $COUNT windows of class '$FOCUSED_CLASS'"
|
||||
19
dotfiles/config/hypr/scripts/raise-or-run.sh
Executable file
19
dotfiles/config/hypr/scripts/raise-or-run.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
# Raise existing window or run command (like XMonad's raiseNextMaybe)
|
||||
# Usage: raise-or-run.sh <class-pattern> <command>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CLASS_PATTERN="$1"
|
||||
COMMAND="$2"
|
||||
|
||||
# Find windows matching the class pattern
|
||||
MATCHING=$(hyprctl clients -j | jq -r ".[] | select(.class | test(\"$CLASS_PATTERN\"; \"i\")) | .address" | head -1)
|
||||
|
||||
if [ -n "$MATCHING" ]; then
|
||||
# Window exists, focus it
|
||||
hyprctl dispatch focuswindow "address:$MATCHING"
|
||||
else
|
||||
# No matching window, run the command
|
||||
exec $COMMAND
|
||||
fi
|
||||
33
dotfiles/config/hypr/scripts/replace-window.sh
Executable file
33
dotfiles/config/hypr/scripts/replace-window.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
# Replace focused window with selected window (like XMonad's myReplaceWindow)
|
||||
# Swaps the positions of focused window and selected window
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Get current workspace and focused window
|
||||
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
|
||||
FOCUSED=$(hyprctl activewindow -j | jq -r '.address')
|
||||
|
||||
if [ "$FOCUSED" = "null" ] || [ -z "$FOCUSED" ]; then
|
||||
notify-send "Replace Window" "No focused window"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get all windows except focused
|
||||
WINDOWS=$(hyprctl clients -j | jq -r ".[] | select(.workspace.id >= 0 and .address != \"$FOCUSED\") | \"\(.title) [\(.class)] - WS:\(.workspace.id) |\(.address)\"")
|
||||
|
||||
if [ -z "$WINDOWS" ]; then
|
||||
notify-send "Replace Window" "No other windows available"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Show rofi menu
|
||||
SELECTION=$(echo "$WINDOWS" | rofi -dmenu -i -p "Replace with" -format 's')
|
||||
|
||||
if [ -n "$SELECTION" ]; then
|
||||
# Extract the window address
|
||||
ADDRESS=$(echo "$SELECTION" | sed 's/.*|//')
|
||||
|
||||
# Swap windows using hy3
|
||||
hyprctl dispatch hy3:movewindow "address:$ADDRESS"
|
||||
fi
|
||||
30
dotfiles/config/hypr/scripts/shift-to-empty-on-screen.sh
Executable file
30
dotfiles/config/hypr/scripts/shift-to-empty-on-screen.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# Shift window to empty workspace on screen in given direction
|
||||
# Like XMonad's shiftToEmptyOnScreen
|
||||
# Usage: shift-to-empty-on-screen.sh <direction: u|d|l|r>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DIRECTION="$1"
|
||||
|
||||
# First, move focus to the screen in that direction
|
||||
hyprctl dispatch focusmonitor "$DIRECTION"
|
||||
|
||||
# Get the monitor we're now on
|
||||
MONITOR=$(hyprctl activeworkspace -j | jq -r '.monitor')
|
||||
|
||||
# Find an empty workspace or create one
|
||||
# First check if there's an empty workspace on this monitor
|
||||
EMPTY_WS=$(hyprctl workspaces -j | jq -r ".[] | select(.windows == 0 and .monitor == \"$MONITOR\") | .id" | head -1)
|
||||
|
||||
if [ -z "$EMPTY_WS" ]; then
|
||||
# No empty workspace, find next available workspace number
|
||||
MAX_WS=$(hyprctl workspaces -j | jq -r 'map(.id) | max')
|
||||
EMPTY_WS=$((MAX_WS + 1))
|
||||
fi
|
||||
|
||||
# Go back to original monitor and move the window
|
||||
hyprctl dispatch focusmonitor "$DIRECTION" # This actually toggles back
|
||||
|
||||
# Move window to the empty workspace and follow
|
||||
hyprctl dispatch movetoworkspace "$EMPTY_WS"
|
||||
Reference in New Issue
Block a user