init commit

This commit is contained in:
2026-06-11 11:01:51 +05:30
commit 72e90c145e
36 changed files with 2380 additions and 0 deletions

16
hypr/environment.lua Normal file
View File

@@ -0,0 +1,16 @@
-- Use NVIDIA GBM + Vulkan for wlroots
hl.env("WLR_RENDERER", "vulkan")
hl.env("GBM_BACKEND", "nvidia-drm")
hl.env("__GLX_VENDOR_LIBRARY_NAME", "nvidia")
-- Ensure Hyprland runs fully on the NVIDIA GPU
hl.env("__NV_PRIME_RENDER_OFFLOAD", "1")
hl.env("__VK_LAYER_NV_optimus", "NVIDIA_only")
hl.env("__NV_PRIME_RENDER_OFFLOAD_PROVIDER", "NVIDIA-G0")
-- Fix cursor and presentation glitches
hl.env("WLR_NO_HARDWARE_CURSORS", "1")
hl.env("WLR_DRM_DEVICES", "/dev/dri/card1")
-- Fix hyprquickframe preview rendering
hl.env("QSG_RHI_BACKEND", "vulkan")

479
hypr/hy3-usage.md Normal file
View File

@@ -0,0 +1,479 @@
<img align="right" style="width: 256px" src="assets/logo.svg">
# hy3
<a href="https://matrix.to/#/#hy3:outfoxxed.me"><img src="https://img.shields.io/badge/Join%20the%20matrix%20room-%23hy3:outfoxxed.me-0dbd8b?logo=matrix&style=flat-square"></a>
i3 / sway like layout for [hyprland](https://github.com/hyprwm/hyprland).
[Installation](#installation), [Configuration](#configuration)
_Check the [changelog](./CHANGELOG.md) for a list of new features and improvements_
### Features
- [x] i3 like tiling
- [x] Node based window manipulation (you can interact with multiple windows at once)
- [x] Greatly improved tabbed node groups over base hyprland
- [x] Optional autotiling
Additional features may be suggested in the repo issues or the [matrix room](https://matrix.to/#/#hy3:outfoxxed.me).
### Demo
<video width="640" height="360" controls="controls" src="https://github.com/user-attachments/assets/ed2fe78d-8c31-47d8-a91d-e89aed42189c"></video>
---
In addition to hy3, I maintain [Quickshell](https://quickshell.outfoxxed.me/?utm_source=hy3-readme),
a toolkit for creating custom bars, widgets, lockscreens, and other desktop shell components
with first class support for Hyprland.
If that sounds interesting, check out the [website](https://quickshell.outfoxxed.me/?utm_source=hy3-readme).
---
### Stability
hy3 has a tagged release for each hyprland update, and master tracks hyprland's main branch.
If you are running a release version of hyprland then use the matching tagged hy3 version.
If you are running an untagged hyprland release then use the `master` branch of hy3.
Commits are tested before pushing and will build against the hyprland release **in the flake.lock file**.
There may be a mismatch with hyprland's main branch. If hy3 fails to build against hyprland's main branch
please make an issue or ping me in the [hy3 matrix room](https://matrix.to/#/#hy3-support:outfoxxed.me).
Tagged hy3 versions are always checked against the corresponding hyprland tag.
If you encounter any bugs, please report them in the issue tracker.
When reporting bugs, please include:
- Commit hash of the version you are running.
- Steps to reproduce the bug (if you can figure them out)
- backtrace of the crash (if applicable)
## Installation
> [!IMPORTANT]
> The master branch of hy3 follows the master branch of hyprland.
> Attempting to use a mismatched hyprland release will result in failure when building or loading hy3.
>
> To use hy3 against a release version of hyprland,
> check out the matching hy3 tag for the hyprland version.
> hy3 tags are formatted as `hl{version}` where `{version}` matches the release version of hyprland.
### Nix
#### Hyprland home manager module
Assuming you use hyprland's home manager module, you can easily integrate hy3 by adding it to the plugins array.
```nix
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprland.url = "git+https://github.com/hyprwm/Hyprland?submodules=1&ref={version}";
# where {version} is the hyprland release version
# or "github:hyprwm/Hyprland?submodules=1" to follow the development branch
hy3 = {
url = "github:outfoxxed/hy3?ref=hl{version}"; # where {version} is the hyprland release version
# or "github:outfoxxed/hy3" to follow the development branch.
# (you may encounter issues if you dont do the same for hyprland)
inputs.hyprland.follows = "hyprland";
};
};
outputs = { nixpkgs, home-manager, hyprland, hy3, ... }: {
homeConfigurations."user@hostname" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
hyprland.homeManagerModules.default
{
wayland.windowManager.hyprland = {
enable = true;
plugins = [ hy3.packages.x86_64-linux.hy3 ];
};
}
];
};
};
}
```
#### Manual (Nix)
hy3's binary is availible as `${hy3.packages.<system>.hy3}/lib/libhy3.so`, so you can also
directly use it in your hyprland config like so:
```nix
# ...
wayland.windowManager.hyprland = {
# ...
extraConfig = ''
plugin = ${hy3.packages.x86_64-linux.hy3}/lib/libhy3.so
'';
};
```
### hyprpm
Hyprland now has a dedicated plugin manager, which should be used when your package manager
isn't capable of locking hy3 builds to the correct hyprland version.
> [!IMPORTANT]
> Make sure hyprpm is activated by putting
>
> ```conf
> exec-once = hyprpm reload -n
> ```
>
> in your hyprland.conf. (See [the wiki](https://wiki.hyprland.org/Plugins/Using-Plugins/) for details.)
To install hy3 via hyprpm run
```sh
hyprpm add https://github.com/outfoxxed/hy3
```
To update hy3 (and all other plugins), run
```sh
hyprpm update
```
Sometimes the headers from hyprland are not updated, if this happens run (See [issue #109](https://github.com/outfoxxed/hy3/issues/109) for an example of where this happened)
```sh
hyprpm update -f
```
(See [the wiki](https://wiki.hyprland.org/Plugins/Using-Plugins/) for details.)
> [!WARNING]
> When you are running a tagged hyprland version hyprpm (0.34.0+) will build against hy3's
> corrosponding release. However if you are running an untagged build (aka `-git`) hyprpm
> will build against hy3's _latest_ commit. This means **if you are running an out of date
> untagged build of hyprland, hyprpm may pick an incompatible revision of hy3**.
>
> To fix this problem you will either need to update hyprland or manually build the correct
> version of hy3.
### Manual
Install hyprland, including its headers and pkg-config file, then run the following commands:
```sh
cmake -DCMAKE_BUILD_TYPE=Release -B build
cmake --build build
```
The plugin will be located at `build/libhy3.so`, and you can load it normally
(See [the hyprland wiki](https://wiki.hyprland.org/Plugins/Using-Plugins/#installing--using-plugins) for details.)
Note that the hyprland headers and pkg-config file **MUST be installed correctly, for the target version of hyprland**.
### Arch (AUR)
> [!NOTE]
> This method of installation is deprecated and you should use _hyprpm_ instead,
> as it is simpler and less error prone.
> [!CAUTION]
> Pacman is not very reliable when it comes to building packages in the correct order.
> If you get a notification saying _hy3 was compiled for a different version of hyprland_
> then your packages likely updated in the wrong order, or you have hyprland headers in `/usr/local`.
>
> To fix this, remove `/usr/include/hyprland`, `/usr/local/include/hyprland`, `/usr/share/pkgconfig/hyprland.pc` and `/usr/local/share/pkgconfig/hyprland.pc`,
> then reinstall hyprland and hy3.
>
> If you know how to fix this please open an issue or pr, or message `@outfoxxed:outfoxxed.me` in the [matrix room](https://matrix.to/#/#hy3-support:outfoxxed.me).
hy3 stable (for arch's `hyprland` package) is availible on the AUR as [hy3](https://aur.archlinux.org/packages/hy3).
hy3-git (for `hyprland-git` on the AUR, unofficial package) is availible on the AUR as [hy3-git](https://aur.archlinux.org/packages/hy3-git).
Both packages install hy3 as `/usr/lib/libhy3.so`.
You can enable it in your hyprland configuration by adding the following line anywhere in your `hyprland.conf`
```conf
plugin = /usr/lib/libhy3.so
```
## Configuration
> [!IMPORTANT]
> The configuration listed below is for the current hy3 commit.
> If you are using a release version of hy3 then make sure you are
> reading the tagged revision of this readme.
Set your `general:layout` to `hy3` in hyprland.conf.
hy3 requires using a few custom dispatchers for normal operation.
In your hyprland config replace the following dispatchers:
- `movefocus` -> `hy3:movefocus`
- `movewindow` -> `hy3:movewindow`
You can use `hy3:makegroup` to create a new split.
The [dispatcher list](#dispatcher-list) and [config fields](#config-fields) sections have all the
configuration options, and some explanation as to what they do.
[The hyprland config in my dots](https://git.outfoxxed.me/outfoxxed/nixnew/src/branch/master/modules/hyprland/hyprland.conf) can also be used as a reference.
### Config fields
```conf
plugin {
hy3 {
# policy controlling what happens when a node is removed from a group,
# leaving only a group
# 0 = remove the nested group
# 1 = keep the nested group
# 2 = keep the nested group only if its parent is a tab group
node_collapse_policy = <int> # default: 2
# offset from group split direction when only one window is in a group
group_inset = <int> # default: 10
# if a tab group will automatically be created for the first window spawned in a workspace
tab_first_window = <bool>
# tab group settings
tabs {
# height of the tab bar
height = <int> # default: 22
# padding between the tab bar and its focused node
padding = <int> # default: 6
# the tab bar should animate in/out from the top instead of below the window
from_top = <bool> # default: false
# radius of tab bar corners
radius = <int> # default: 6
# tab bar border width
border_width = <int> # default: 2
# render the window title on the bar
render_text = <bool> # default: true
# center the window title
text_center = <bool> # default: true
# font to render the window title with
text_font = <string> # default: Sans
# height of the window title
text_height = <int> # default: 8
# left padding of the window title
text_padding = <int> # default: 3
colors {
# active tab bar segment colors
active = <color> # default: rgba(33ccff40)
active_border = <color> # default: rgba(33ccffee)
active_text = <color> # default: rgba(ffffffff)
# active tab bar segment colors for bars on an unfocused monitor
active_alt_monitor = <color> # default: rgba(60606040)
active_alt_monitor_border = <color> # default: rgba(808080ee)
active_alt_monitor_text = <color> # default: rgba(ffffffff)
# focused tab bar segment colors (focused node in unfocused container)
focused = <color> # default: rgba(60606040)
focused_border = <color> # default: rgba(808080ee)
focused_text = <color> # default: rgba(ffffffff)
# inactive tab bar segment colors
inactive = <color> # default: rgba(30303020)
inactive_border = <color> # default: rgba(606060aa)
inactive_text = <color> # default: rgba(ffffffff)
# urgent tab bar segment colors
urgent = <color> # default: rgba(ff223340)
urgent_border = <color> # default: rgba(ff2233ee)
urgent_text = <color> # default: rgba(ffffffff)
# locked tab bar segment colors
locked = <color> # default: rgba(90903340)
locked_border = <color> # default: rgba(909033ee)
locked_text = <color> # default: rgba(ffffffff)
}
# if tab backgrounds should be blurred
# Blur is only visible when the above colors are not opaque.
blur = <bool> # default: true
# opacity multiplier for tabs
# Applies to blur as well as the given colors.
opacity = <float> # default: 1.0
}
# autotiling settings
autotile {
# enable autotile
enable = <bool> # default: false
# make autotile-created groups ephemeral
ephemeral_groups = <bool> # default: true
# if a window would be squished smaller than this width, a vertical split will be created
# -1 = never automatically split vertically
# 0 = always automatically split vertically
# <number> = pixel width to split at
trigger_width = <int> # default: 0
# if a window would be squished smaller than this height, a horizontal split will be created
# -1 = never automatically split horizontally
# 0 = always automatically split horizontally
# <number> = pixel height to split at
trigger_height = <int> # default: 0
# a space or comma separated list of workspace ids where autotile should be enabled
# it's possible to create an exception rule by prefixing the definition with "not:"
# workspaces = 1,2 # autotiling will only be enabled on workspaces 1 and 2
# workspaces = not:1,2 # autotiling will be enabled on all workspaces except 1 and 2
workspaces = <string> # default: all
}
}
}
```
### Dispatcher list
- `hy3:makegroup, <h | v | opposite | tab>, [toggle], [ephemeral | force_ephemeral]` - make a vertical / horizontal split or tab group
- `toggle` - if the focused node is the only child of its parent, which is of the type specified, the node's parent will be removed.
- `ephemeral` - the group will be removed once it contains only one node. does not affect existing groups.
- `force_ephemeral` - same as ephemeral, but converts existing single windows groups.
- `hy3:changegroup, <h | v | tab | untab | toggletab | opposite>` - change the group the node belongs to, to a different layout
- `untab` will untab the group if it was previously tabbed
- `toggletab` will untab if group is tabbed, and tab if group is untabbed
- `opposite` will toggle between horizontal and vertical layouts if the group is not tabbed.
- `hy3:setephemeral, <true | false>` - change the ephemerality of the group the node belongs to
- `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible], [warp | nowarp]` - move the focus left, up, down, or right
- `visible` - only move between visible nodes, not hidden tabs
- `warp` - warp the mouse to the selected window, even if `general:no_cursor_warps` is true.
- `nowarp` - does not warp the mouse to the selected window, even if `general:no_cursor_warps` is false.
- `hy3:warpcursor` - warp the cursor to the center of the focused node
- `hy3:movewindow, <l | u | d | r | left | down | up | right>, [once], [visible]` - move a window left, up, down, or right
- `once` - only move directly to the neighboring group, without moving into any of its subgroups
- `visible` - only move between visible nodes, not hidden tabs
- `hy3:movetoworkspace, <workspace>, [follow, [warp | nowarp]]` - move the active node to the given workspace
- `follow` - change focus to the given workspace when moving the selected node
- `warp` - warp the mouse to the selected window, even if `general:no_cursor_warps` is true.
- `nowarp` - does not warp the mouse to the selected window, even if `general:no_cursor_warps` is false.
- `hy3:killactive` - close all windows in the focused node
- `hy3:changefocus, <top | bottom | raise | lower | tab | tabnode>`
- `top` - focus all nodes in the workspace
- `bottom` - focus the single root selection window
- `raise` - raise focus one level
- `lower` - lower focus one level
- `tab` - raise focus to the nearest tab
- `tabnode` - raise focus to the nearest node under the tab
- `hy3:togglefocuslayer, [nowarp]` - toggle focus between tiled and floating layers
- `nowarp` - do not warp the mouse to the newly focused window
- `hy3:focustab, [l | r | left | right | index, <index>], [prioritize_hovered | require_hovered], [wrap]`
- `l | r | left | right` - direction to change focus towards
- `index, <index>` - select the `index`th tab
- `prioritize_hovered` - prioritize the tab group under the mouse when multiple are stacked. use the lowest group if none is under the mouse.
- `require_hovered` - affect the tab group under the mouse. do nothing if none are hovered.
- `wrap` - wrap to the opposite size of the tab bar if moving off the end
- `hy3:locktab, [lock | unlock]` - lock the current tab, makingg it behave like a node
- `hy3:debugnodes` - print the node tree into the hyprland log
- :warning: **ALPHA QUALITY** `hy3:setswallow, <true | false | toggle>` - set the containing node's window swallow state
- :warning: **ALPHA QUALITY** `hy3:expand, <expand | shrink | base>` - expand the current node to cover other nodes
- `expand` - expand by one node
- `shrink` - shrink by one node
- `base` - undo all expansions
- `hy3:equalize, [workspace]` - equalize window sizes in group
- no argument: equalizes immediate siblings of the focused window
- `workspace`: equalizes all windows across the entire workspace tree
### Lua dispatchers
When using Hyprland's Lua config, hy3 exposes dispatcher factories under `hl.plugin.hy3`.
The returned functions can be passed to `hl.bind(...)`.
```lua
local hy3 = hl.plugin.hy3
-- all factories return dispatcher functions and dispatchers return no values
-- option tables are optional except for focus_tab
hy3.make_group("h" | "v" | "tab" | "opposite", {
toggle = true | false, -- default: false
ephemeral = true | false | "force", -- default: false
})
hy3.change_group("h" | "v" | "tab" | "untab" | "toggletab" | "opposite")
hy3.set_ephemeral(true | false | "true" | "false")
hy3.move_focus("l" | "r" | "u" | "d" | "left" | "right" | "up" | "down", {
visible = true | false, -- default: false
warp = true | false, -- default: follows cursor:no_warps
})
hy3.toggle_focus_layer({
warp = true | false, -- default: true
})
hy3.warp_cursor()
hy3.move_window("l" | "r" | "u" | "d" | "left" | "right" | "up" | "down", {
once = true | false, -- default: false
visible = true | false, -- default: false
})
hy3.move_to_workspace("<workspace>", {
follow = true | false, -- default: false
warp = true | false, -- default: follows cursor:no_warps when follow = true
})
hy3.change_focus("top" | "bottom" | "raise" | "lower" | "tab" | "tabnode")
-- direction and index are mutually exclusive
hy3.focus_tab({
direction = "l" | "r" | "left" | "right",
mouse = "ignore" | "prioritize_hovered" | "require_hovered", -- default: "ignore"
wrap = true | false, -- default: false
})
hy3.focus_tab({
index = <number>,
mouse = "ignore" | "prioritize_hovered" | "require_hovered", -- default: "ignore"
wrap = true | false, -- default: false
})
hy3.set_swallow(true | false | "true" | "false" | "toggle")
hy3.kill_active()
hy3.expand("expand" | "shrink" | "base" | "maximize" | "fullscreen", {
fullscreen = "" | "intermediate_maximize" | "fullscreen_maximize" | "maximize_only",
})
hy3.lock_tab(nil | "" | "toggle" | "lock" | "unlock")
hy3.equalize({
scope = "" | "group" | "workspace", -- default: "group"
workspace = true | false, -- overrides scope if present
recursive = true | false, -- overrides workspace if present
})
hy3.debug_nodes()
```

346
hypr/hyprland.lua Normal file
View File

@@ -0,0 +1,346 @@
-- This is an example Hyprland Lua config file.
-- Refer to the wiki for more information.
-- https://wiki.hypr.land/Configuring/Start/
-- Please note not all available settings / options are set here.
-- For a full list, see the wiki
-- You can (and should!!) split this configuration into multiple files
-- Create your files separately and then require them like this:
-- require("myColors")
require("environment")
local colors = require("rose-pine")
------------------
---- MONITORS ----
------------------
-- See https://wiki.hypr.land/Configuring/Basics/Monitors/
hl.monitor({
output = "DP-1",
mode = "1920x1080@100",
position = "0x0",
scale = 1,
})
hl.monitor({
output = "HDMI-A-1",
mode = "1920x1080@60",
position = "1920x0",
scale = 1.25,
})
---------------------
---- MY PROGRAMS ----
---------------------
-- Set programs that you use
local terminal = "kitty"
local fileManager = "kitty"
local menu = "hyprlauncher"
local browser = "vivaldi-stable --enable-features=AcceleratedVideoEncoder"
local browserPrivate = "vivaldi --incognito --enable-features=AcceleratedVideoEncoder"
-------------------
---- AUTOSTART ----
-------------------
-- See https://wiki.hypr.land/Configuring/Basics/Autostart/
-- Autostart necessary processes (like notifications daemons, status bars, etc.)
-- Or execute your favorite apps at launch like this:
hl.on("hyprland.start", function()
hl.exec_cmd("swaybg -i /home/sortedcord/Pictures/Wallpapers/cliff.jpg -m fill")
hl.exec_cmd("wayle shell")
hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP")
hl.exec_cmd("quickshell")
hl.exec_cmd("hyprpm reload -n")
end)
-------------------------------
---- ENVIRONMENT VARIABLES ----
-------------------------------
-- See https://wiki.hypr.land/Configuring/Advanced-and-Cool/Environment-variables/
hl.env("XCURSOR_SIZE", "24")
hl.env("HYPRCURSOR_SIZE", "24")
hl.env("bitdepth", "10")
hl.env("XDG_DESKTOP_PORTAL_HYPRLAND_FORCE_SHM", "1")
-----------------------
----- PERMISSIONS -----
-----------------------
-- See https://wiki.hypr.land/Configuring/Advanced-and-Cool/Permissions/
-- Please note permission changes here require a Hyprland restart and are not applied on-the-fly
-- for security reasons
-- hl.config({
-- ecosystem = {
-- enforce_permissions = true,
-- },
-- })
-- hl.permission("/usr/(bin|local/bin)/grim", "screencopy", "allow")
-- hl.permission("/usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland", "screencopy", "allow")
-- hl.permission("/usr/(bin|local/bin)/hyprpm", "plugin", "allow")
-----------------------
---- LOOK AND FEEL ----
-----------------------
-- Refer to https://wiki.hypr.land/Configuring/Basics/Variables/
hl.config({
general = {
gaps_in = 3,
gaps_out = 3,
border_size = 2,
col = {
active_border = colors.rose,
inactive_border = colors.muted,
},
-- Set to true to enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false,
-- Please see https://wiki.hypr.land/Configuring/Advanced-and-Cool/Tearing/ before you turn this on
allow_tearing = false,
layout = "hy3",
},
decoration = {
rounding = 0,
rounding_power = 0,
-- Change transparency of focused and unfocused windows
active_opacity = 1.0,
inactive_opacity = 1.0,
shadow = {
enabled = false,
range = 4,
render_power = 3,
color = 0xee1a1a1a,
},
blur = {
enabled = false,
size = 3,
passes = 1,
vibrancy = 0.1696,
},
},
animations = {
enabled = false,
},
})
-- hy3 plugin settings for i3-like tabbing & container layout
hl.config({
plugin = {
hy3 = {
-- policy controlling what happens when a node is removed from a group,
-- leaving only a group
-- 0 = remove the nested group
-- 1 = keep the nested group
-- 2 = keep the nested group only if its parent is a tab group
node_collapse_policy = 2,
-- offset from group split direction when only one window is in a group
group_inset = 10,
-- if a tab group will automatically be created for the first window spawned in a workspace
tab_first_window = false,
-- tab group settings
tabs = {
-- height of the tab bar
height = 20,
-- padding between the tab bar and its focused node
padding = 3,
-- the tab bar should animate in/out from the top instead of below the window
from_top = false,
-- radius of tab bar corners
radius = 0,
-- tab bar border width
border_width = 2,
-- render the window title on the bar
render_text = true,
-- center the window title
text_center = true,
-- font to render the window title with
text_font = "Sans",
-- height of the window title
text_height = 10,
-- left padding of the window title
text_padding = 3,
colors = {
-- active tab bar segment colors (using Rose Pine colors, fully opaque)
active = colors.rose,
active_border = colors.rose,
active_text = colors.base,
-- active tab bar segment colors for bars on an unfocused monitor
active_alt_monitor = colors.subtle,
active_alt_monitor_border = colors.subtle,
active_alt_monitor_text = colors.base,
-- focused tab bar segment colors (focused node in unfocused container)
focused = colors.muted,
focused_border = colors.muted,
focused_text = colors.text,
-- inactive tab bar segment colors
inactive = colors.surface,
inactive_border = colors.overlay,
inactive_text = colors.muted,
-- urgent tab bar segment colors
urgent = colors.love,
urgent_border = colors.love,
urgent_text = colors.base,
-- locked tab bar segment colors
locked = colors.gold,
locked_border = colors.gold,
locked_text = colors.base,
},
-- if tab backgrounds should be blurred
blur = false,
-- opacity multiplier for tabs
opacity = 1.0,
},
-- autotiling settings
autotile = {
enable = false,
ephemeral_groups = true,
trigger_width = 0,
trigger_height = 0,
workspaces = "all",
},
},
},
})
-- Default curves and animations, see https://wiki.hypr.land/Configuring/Advanced-and-Cool/Animations/
-- Default springs
-- Ref https://wiki.hypr.land/Configuring/Basics/Workspace-Rules/
-- "Smart gaps" / "No gaps when only"
-- uncomment all if you wish to use that.
-- hl.workspace_rule({ workspace = "w[tv1]", gaps_out = 0, gaps_in = 0 })
-- hl.workspace_rule({ workspace = "f[1]", gaps_out = 0, gaps_in = 0 })
-- hl.window_rule({
-- name = "no-gaps-wtv1",
-- match = { float = false, workspace = "w[tv1]" },
-- border_size = 0,
-- rounding = 0,
-- })
-- hl.window_rule({
-- name = "no-gaps-f1",
-- match = { float = false, workspace = "f[1]" },
-- border_size = 0,
-- rounding = 0,
-- })
-- See https://wiki.hypr.land/Configuring/Layouts/Dwindle-Layout/ for more
hl.config({
dwindle = {
preserve_split = true, -- You probably want this
},
})
-- See https://wiki.hypr.land/Configuring/Layouts/Master-Layout/ for more
hl.config({
master = {
new_status = "master",
},
})
-- See https://wiki.hypr.land/Configuring/Layouts/Scrolling-Layout/ for more
hl.config({
scrolling = {
fullscreen_on_one_column = true,
},
})
----------------
---- MISC ----
----------------
hl.config({
misc = {
disable_hyprland_logo = true, -- If true disables the random hyprland logo / anime girl background. :(
},
})
---------------
---- INPUT ----
---------------
hl.config({
input = {
kb_layout = "us",
kb_variant = "",
kb_model = "",
kb_options = "",
kb_rules = "",
follow_mouse = 1,
sensitivity = 0, -- -1.0 - 1.0, 0 means no modification.
touchpad = {
natural_scroll = false,
},
},
})
hl.gesture({
fingers = 3,
direction = "horizontal",
action = "workspace",
})
-- Example per-device config
-- See https://wiki.hypr.land/Configuring/Advanced-and-Cool/Devices/ for more
hl.device({
name = "epic-mouse-v1",
sensitivity = -0.5,
})
---------------------
---- KEYBINDINGS ----
---------------------
require("keybinds").setup({
terminal = terminal,
menu = menu,
browser = browser,
browserPrivate = browserPrivate,
})
--------------------------------
---- WINDOWS AND WORKSPACES ----
--------------------------------
require("windowrules")

221
hypr/keybinds.lua Normal file
View File

@@ -0,0 +1,221 @@
local M = {}
function M.setup(opts)
local terminal = opts.terminal
local menu = opts.menu
local browser = opts.browser
local browserPrivate = opts.browserPrivate
-- Import and setup hy3 plugin helper
local hy3 = hl.plugin.hy3
if not hy3 then
hy3 = setmetatable({}, {
__index = function(_, k)
return function(...)
return function()
print("hy3 plugin is not loaded, cannot call " .. k)
end
end
end,
})
end
-- Track and write split state to /tmp/hy3_split for status bars like Wayle
local current_split = "H"
local function set_split(dir)
current_split = dir
local f = io.open("/tmp/hy3_split", "w")
if f then
f:write(dir)
f:close()
end
end
set_split("H") -- Initialize
local mainMod = "SUPER" -- Sets "Windows" key as main modifier
-- Example binds, see https://wiki.hypr.land/Configuring/Basics/Binds/ for more
hl.bind(mainMod .. " + Return", hl.dsp.exec_cmd(terminal))
hl.bind(mainMod .. " + Q", hl.dsp.window.close())
hl.bind(mainMod .. " + SHIFT + E", hl.dsp.exit())
hl.bind(mainMod .. " + SHIFT + R", function()
hl.exec_cmd("hyprctl reload && notify-send 'Hyprland config reloaded'")
end)
hl.bind(mainMod .. " + E", hl.dsp.exec_cmd(terminal .. " fish -c 'y; exec fish'"))
hl.bind(mainMod .. " + SPACE", hl.dsp.window.float({ action = "toggle" }))
hl.bind(mainMod .. " + F", hl.dsp.window.fullscreen())
hl.bind(mainMod .. " + D", hl.dsp.exec_cmd(menu))
hl.bind(mainMod .. " + B", hl.dsp.exec_cmd(browser))
hl.bind(mainMod .. " + SHIFT + B", hl.dsp.exec_cmd(browserPrivate))
hl.bind(mainMod .. " + P", hl.dsp.window.pseudo())
-- hl.bind(mainMod .. " + S", hl.dsp.exec_cmd("hyprquickframe"))
hl.bind(
mainMod .. " + S",
hl.dsp.exec_cmd(
' grim -g "$(slurp)" - | satty -f - --copy-command wl-copy -o "~/Pictures/Screenshots/%Y%m%d_%H%M%S.png"'
)
)
-- hl.bind(mainMod .. " + G", hl.dsp.exec_cmd("python /home/sortedcord/Projects/firecrawl-search/main.py"))
-- Move focus with mainMod + arrow keys (hy3 plugin aware)
hl.bind(mainMod .. " + left", hy3.move_focus("left"))
hl.bind(mainMod .. " + right", hy3.move_focus("right"))
hl.bind(mainMod .. " + up", hy3.move_focus("up"))
hl.bind(mainMod .. " + down", hy3.move_focus("down"))
-- Move focus with mainMod + hjkl (hy3 plugin aware)
hl.bind(mainMod .. " + H", hy3.move_focus("l"))
hl.bind(mainMod .. " + J", hy3.move_focus("d"))
hl.bind(mainMod .. " + K", hy3.move_focus("u"))
hl.bind(mainMod .. " + L", hy3.move_focus("r"))
hl.bind(mainMod .. " + W", hl.dsp.exec_cmd("rofi -show window"))
-- Move window with mainMod + SHIFT + hjkl (hy3 plugin aware)
hl.bind(mainMod .. " + SHIFT + H", hy3.move_window("l"))
hl.bind(mainMod .. " + SHIFT + J", hy3.move_window("d"))
hl.bind(mainMod .. " + SHIFT + K", hy3.move_window("u"))
hl.bind(mainMod .. " + SHIFT + L", hy3.move_window("r"))
-- i3-like container and layout controls
-- Toggle layout tabbed
hl.bind(mainMod .. " + SHIFT + T", function()
hl.dispatch(hy3.change_group("toggletab"))
if current_split == "T" then
set_split("H")
else
set_split("T")
end
end)
-- Split layout horizontal / vertical toggle
hl.bind(mainMod .. " + SHIFT + G", function()
hl.dispatch(hy3.change_group("opposite"))
if current_split == "H" then
set_split("V")
elseif current_split == "V" then
set_split("H")
end
end)
-- Pre-split vertical (V), horizontal (C), or tab (X)
hl.bind(mainMod .. " + V", function()
hl.dispatch(hy3.make_group("v", { toggle = true }))
set_split("V")
end)
hl.bind(mainMod .. " + C", function()
hl.dispatch(hy3.make_group("h", { toggle = true }))
set_split("H")
end)
hl.bind(mainMod .. " + X", function()
hl.dispatch(hy3.make_group("tab", { toggle = true }))
set_split("T")
end)
-- Focus parent (A) / focus child (SHIFT + A)
hl.bind(mainMod .. " + A", hy3.change_focus("raise"))
hl.bind(mainMod .. " + SHIFT + A", hy3.change_focus("lower"))
-- Cycle tabs with Super + Alt + Left/Right
hl.bind(mainMod .. " + ALT + left", hy3.focus_tab({ direction = "l", wrap = true }))
hl.bind(mainMod .. " + ALT + right", hy3.focus_tab({ direction = "r", wrap = true }))
-- Switch workspaces with mainMod + [0-9]
-- Move active window/container to a workspace with mainMod + SHIFT + [0-9] (hy3 plugin aware)
for i = 1, 10 do
local key = i % 10 -- 10 maps to key 0
hl.bind(mainMod .. " + " .. key, hl.dsp.focus({ workspace = i }))
hl.bind(mainMod .. " + SHIFT + " .. key, hy3.move_to_workspace(tostring(i)))
end
-- Move window to other monitor with mod+semicolon
hl.bind(mainMod .. " + semicolon", hl.dsp.window.move({ monitor = "+1" }))
-- Swap windows between monitors (mod+shift+semicolon)
-- Detect which monitor we're on and use the correct focus direction
hl.bind(mainMod .. " + SHIFT + semicolon", function()
local active_monitor = hl.get_active_monitor()
local focus_direction = "r"
-- If we're on the rightmost monitor (HDMI-A-1), focus left instead
if active_monitor.name == "HDMI-A-1" then
focus_direction = "l"
end
-- Move window to next monitor
hl.dispatch(hl.dsp.window.move({ monitor = "+1" }))
-- Focus a window on the current monitor using the correct direction (hy3 plugin aware)
hl.dispatch(hy3.move_focus(focus_direction))
-- Move the newly focused window back to original monitor
hl.dispatch(hl.dsp.window.move({ monitor = "-1" }))
end)
-- Example special workspace (scratchpad)
-- hl.bind(mainMod .. " + S", hl.dsp.workspace.toggle_special("magic"))
-- hl.bind(mainMod .. " + SHIFT + S", hl.dsp.window.move({ workspace = "special:magic" }))
-- Scroll through existing workspaces with mainMod + scroll
-- hl.bind(mainMod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }))
-- hl.bind(mainMod .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" }))
hl.bind(mainMod .. " + Y", hl.dsp.focus({ workspace = "e+1" }))
hl.bind(mainMod .. " + T", hl.dsp.focus({ workspace = "e-1" }))
-- Move/resize windows with mainMod + LMB/RMB and dragging
hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })
-- Laptop multimedia keys for volume and LCD brightness
hl.bind(
"XF86AudioRaiseVolume",
hl.dsp.exec_cmd("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"),
{ locked = true, repeating = true }
)
hl.bind(
"XF86AudioLowerVolume",
hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"),
{ locked = true, repeating = true }
)
hl.bind(
"XF86AudioMute",
hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"),
{ locked = true, repeating = true }
)
hl.bind(
"XF86AudioMicMute",
hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"),
{ locked = true, repeating = true }
)
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%+"), { locked = true, repeating = true })
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%-"), { locked = true, repeating = true })
-- Requires playerctl
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), { locked = true })
hl.bind("XF86AudioPause", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), { locked = true })
-- Cursor controls (simplified - submaps not supported in Lua API)
-- Jump cursor to a position
hl.bind("SUPER + G + A", hl.dsp.exec_cmd("hyprctl dispatch submap reset && wl-kbptr && hyprctl dispatch submap cursor"))
-- Cursor movement
hl.bind("SUPER + G + J", hl.dsp.exec_cmd("wlrctl pointer move 0 10"), { repeating = true })
hl.bind("SUPER + G + K", hl.dsp.exec_cmd("wlrctl pointer move 0 -10"), { repeating = true })
hl.bind("SUPER + G + L", hl.dsp.exec_cmd("wlrctl pointer move 10 0"), { repeating = true })
hl.bind("SUPER + G + H", hl.dsp.exec_cmd("wlrctl pointer move -10 0"), { repeating = true })
-- Left button
hl.bind("SUPER + G + S", hl.dsp.exec_cmd("wlrctl pointer click left"))
-- Middle button
hl.bind("SUPER + G + D", hl.dsp.exec_cmd("wlrctl pointer click middle"))
-- Right button
hl.bind("SUPER + G + F", hl.dsp.exec_cmd("wlrctl pointer click right"))
-- Scroll up and down
hl.bind("SUPER + G + E", hl.dsp.exec_cmd("wlrctl pointer scroll 10 0"), { repeating = true })
hl.bind("SUPER + G + R", hl.dsp.exec_cmd("wlrctl pointer scroll -10 0"), { repeating = true })
-- Scroll left and right
hl.bind("SUPER + G + T", hl.dsp.exec_cmd("wlrctl pointer scroll 0 -10"), { repeating = true })
hl.bind("SUPER + G + G", hl.dsp.exec_cmd("wlrctl pointer scroll 0 10"), { repeating = true })
end
return M

22
hypr/rose-pine.lua Normal file
View File

@@ -0,0 +1,22 @@
-- name: Rosé Pine
-- author: jishnurajendran
-- upstream: https://github.com/jishnurajendran/hyprland-rosepine/blob/main/rose-pine.conf
-- All natural pine, faux fur and a bit of soho vibes for the classy minimalist
return {
base = 0xff191724,
surface = 0xff1f1d2e,
overlay = 0xff26233a,
muted = 0xff6e6a86,
subtle = 0xff908caa,
text = 0xffe0def4,
love = 0xffeb6f92,
gold = 0xfff6c177,
rose = 0xffebbcba,
pine = 0xff31748f,
foam = 0xff9ccfd8,
iris = 0xffc4a7e7,
highlightLow = 0xff21202e,
highlightMed = 0xff403d52,
highlightHigh = 0xff524f67,
}

90
hypr/windowrules.lua Normal file
View File

@@ -0,0 +1,90 @@
-- Workspace to monitor mapping
for i = 1, 5 do
hl.workspace_rule({ workspace = i, monitor = "DP-1" })
end
for i = 6, 10 do
hl.workspace_rule({ workspace = i, monitor = "HDMI-A-1" })
end
-- See https://wiki.hypr.land/Configuring/Basics/Window-Rules/
-- and https://wiki.hypr.land/Configuring/Basics/Workspace-Rules/
-- Example window rules that are useful
local suppressMaximizeRule = hl.window_rule({
-- Ignore maximize requests from all apps. You'll probably like this.
name = "suppress-maximize-events",
match = { class = ".*" },
suppress_event = "maximize",
})
-- suppressMaximizeRule:set_enabled(false)
hl.window_rule({
-- Set Pegasus to fullscreen
name = "pegasus-fullscreen",
match = { class = "pegasus-frontend" },
fullscreen = true,
})
hl.window_rule({
-- Always float Bitwarden
name = "bitwarden-float",
match = { title = "Bitwarden - Vivaldi" },
float = true,
})
hl.window_rule({
-- Always float Game Splash Screen
name = "gsplash-float",
match = { class = "gsplash" },
float = true,
content = "game",
})
hl.window_rule({
-- SCREENCHEAT fullscreen
name = "screencheat-fullscreen",
match = { title = "SCREENCHEAT" },
fullscreen = true,
})
hl.window_rule({
-- Always float Satty
name = "satty-float",
match = { class = "com.gabm.satty" },
float = true,
})
hl.window_rule({
-- Fix some dragging issues with XWayland
name = "fix-xwayland-drags",
match = {
class = "^$",
title = "^$",
xwayland = true,
float = true,
fullscreen = false,
pin = false,
},
no_focus = true,
})
-- Layer rules also return a handle.
-- local overlayLayerRule = hl.layer_rule({
-- name = "no-anim-overlay",
-- match = { namespace = "^my-overlay$" },
-- no_anim = true,
-- })
-- overlayLayerRule:set_enabled(false)
-- Hyprland-run windowrule
hl.window_rule({
name = "move-hyprland-run",
match = { class = "hyprland-run" },
move = "20 monitor_h-120",
float = true,
})