From a0b1248d1ef2044cb04de613ed9ebecbdd9f1a56 Mon Sep 17 00:00:00 2001 From: Rosty Hnatyshyn Date: Wed, 5 Aug 2026 23:37:42 -0700 Subject: [PATCH] add fuzzel, hyprland, qmlls to lspconfig, blur to quickshell bar --- fuzzel/fuzzel.ini | 124 +++++++++++ hypr/awww_randomize.sh | 28 +++ hypr/hyprland.lua | 369 +++++++++++++++++++++++++++++++++ hypr/rules.lua | 21 ++ nvim/lua/plugins/lspconfig.lua | 3 +- quickshell/Bar.qml | 106 ++++++---- 6 files changed, 611 insertions(+), 40 deletions(-) create mode 100644 fuzzel/fuzzel.ini create mode 100755 hypr/awww_randomize.sh create mode 100644 hypr/hyprland.lua create mode 100644 hypr/rules.lua diff --git a/fuzzel/fuzzel.ini b/fuzzel/fuzzel.ini new file mode 100644 index 0000000..2f9dcd6 --- /dev/null +++ b/fuzzel/fuzzel.ini @@ -0,0 +1,124 @@ +# output= +# font=monospace +# dpi-aware=auto +use-bold=yes +# message= +# message-mode=wrap +# prompt="> " +placeholder="Choose an application from the list" +icon-theme=kora-grey +icons-enabled=yes +# hide-before-typing=no +# fields=filename,name,generic +# password-character=* +# filter-desktop=no +# match-mode=fzf +# sort-result=yes +# match-counter=no +# delayed-filter-ms=300 +# delayed-filter-limit=20000 +show-actions=no +# terminal=$TERMINAL -e # Note: you cannot actually use environment variables here +# launch-prefix= +# list-executables-in-path=no + +anchor=center +# x-margin=0 +# y-margin=0 +# lines=15 +# minimal-lines=no +width=45 +tabs=2 +# horizontal-pad=40 +# vertical-pad=8 +# inner-pad=0 + +# scaling-filter=box +# image-size-ratio=0.5 + +# gamma-correct-blending=no +# line-height= +# letter-spacing=0 + +# layer=overlay +# keyboard-focus=exclusive +# exit-on-keyboard-focus-loss=yes + +# cache= + +# render-workers= +# match-workers= + +# enable-mouse=yes + +[colors] +background=1e1e2edd +text=cdd6f4ff +prompt=bac2deff +placeholder=7f849cff +input=cdd6f4ff +match=f38ba8ff +selection-text=ff2400 +selection-match=f38ba8ff +counter=7f849cff +border=f38ba8ff + +[border] +width=0 +radius=10 + +[dmenu] +# mode=text # text|index +# exit-immediately-if-empty=no + +[key-bindings] +# cancel=Escape Control+g Control+c Control+bracketleft +# execute=Return KP_Enter Control+y +# execute-or-next=Tab +# execute-input=Shift+Return Shift+KP_Enter +# cursor-left=Left Control+b +# cursor-left-word=Control+Left Mod1+b +# cursor-right=Right Control+f +# cursor-right-word=Control+Right Mod1+f +# cursor-home=Home Control+a +# cursor-end=End Control+e +# delete-line=Control+Shift+BackSpace +# delete-prev=BackSpace Control+h +# delete-prev-word=Mod1+BackSpace Control+BackSpace Control+w +# delete-line-backward=Control+u +# delete-next=Delete KP_Delete Control+d +# delete-next-word=Mod1+d Control+Delete Control+KP_Delete +# delete-line-forward=Control+k +# prev=Up Control+p +# prev-with-wrap=ISO_Left_Tab +# prev-page=Page_Up KP_Page_Up +# next=Down Control+n +# next-with-wrap=none +# next-page=Page_Down KP_Page_Down +# expunge=Shift+Delete +# clipboard-paste=Control+v XF86Paste +# primary-paste=Shift+Insert Shift+KP_Insert + +# custom-N: *dmenu mode only*. Like execute, but with a non-zero +# exit-code; custom-1 exits with code 10, custom-2 with 11, custom-3 +# with 12, and so on. + +# custom-1=Mod1+1 +# custom-2=Mod1+2 +# custom-3=Mod1+3 +# custom-4=Mod1+4 +# custom-5=Mod1+5 +# custom-6=Mod1+6 +# custom-7=Mod1+7 +# custom-8=Mod1+8 +# custom-9=Mod1+9 +# custom-10=Mod1+0 +# custom-11=Mod1+exclam +# custom-12=Mod1+at +# custom-13=Mod1+numbersign +# custom-14=Mod1+dollar +# custom-15=Mod1+percent +# custom-16=Mod1+dead_circumflex +# custom-17=Mod1+ampersand +# custom-18=Mod1+asterix +# custom-19=Mod1+parentleft diff --git a/hypr/awww_randomize.sh b/hypr/awww_randomize.sh new file mode 100755 index 0000000..f557ff7 --- /dev/null +++ b/hypr/awww_randomize.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# Changes the wallpaper to a randomly chosen image in a given directory +# at a set interval. + +DEFAULT_INTERVAL=300 # In seconds + +if [ $# -lt 1 ] || [ ! -d "$1" ]; then + printf "Usage:\n\t\e[1m%s\e[0m \e[4mDIRECTORY\e[0m [\e[4mINTERVAL\e[0m]\n" "$0" + printf "\tChanges the wallpaper to a randomly chosen image in DIRECTORY every\n\tINTERVAL seconds (or every %d seconds if unspecified)." "$DEFAULT_INTERVAL" + exit 1 +fi + +# See awww-img(1) +RESIZE_TYPE="stretch" +export AWWW_TRANSITION_FPS="${AWWW_TRANSITION_FPS:-144}" +export AWWW_TRANSITION_STEP="${AWWW_TRANSITION_STEP:-2}" + +while true; do + find "$1" -type f \ + | while read -r img; do + echo "$(/dev/null 2>&1 && hyprshutdown || hyprctl dispatch 'hl.dsp.exit()'")) +hl.bind(mainMod .. " + SPACE", hl.dsp.window.float({ action = "toggle" })) + +hl.bind(mainMod .. " + F", hl.dsp.window.fullscreen_state({ internal="1", client="1", action = "toggle"})) +hl.bind(mainMod .. " + SHIFT + Q", hl.dsp.window.close()) + +-- change focus +hl.bind(mainMod .. " + left", hl.dsp.focus({ direction = "left" })) +hl.bind(mainMod .. " + right", hl.dsp.focus({ direction = "right" })) +hl.bind(mainMod .. " + up", hl.dsp.focus({ direction = "up" })) +hl.bind(mainMod .. " + down", hl.dsp.focus({ direction = "down" })) + +-- move workspaces +hl.bind(mainMod .. " + SHIFT + LEFT", hl.dsp.window.swap({ direction = "left"})) +hl.bind(mainMod .. " + SHIFT + RIGHT", hl.dsp.window.swap({ direction = "right"})) + +-- Switch workspaces with mainMod + [0-9] +-- Move active window to a workspace with mainMod + SHIFT + [0-9] +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, hl.dsp.window.move({ workspace = i })) +end + +hl.bind(mainMod .. " + MINUS", hl.dsp.workspace.toggle_special("magic")) +hl.bind(mainMod .. " + SHIFT + MINUS", 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" })) + +-- 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 }) + + +-------------------------------- +---- WINDOWS AND WORKSPACES ---- +-------------------------------- + +-- 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({ + -- 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, +}) + +require("rules") diff --git a/hypr/rules.lua b/hypr/rules.lua new file mode 100644 index 0000000..e25d479 --- /dev/null +++ b/hypr/rules.lua @@ -0,0 +1,21 @@ +hl.window_rule({match = {title = "^(Open File)(.*)$" }, center = true}) +hl.window_rule({match = {title = "^(Open File)(.*)$" }, float = true}) +hl.window_rule({match = {title = "^(Select a File)(.*)$" }, center = true}) +hl.window_rule({match = {title = "^(Select a File)(.*)$" }, float = true}) +hl.window_rule({match = {title = "^(Choose wallpaper)(.*)$" }, center = true}) +hl.window_rule({match = {title = "^(Choose wallpaper)(.*)$" }, float = true}) +hl.window_rule({match = {title = "^(Choose wallpaper)(.*)$" }, size = {"(monitor_w*0.60)", "(monitor_h*0.65)"} }) +hl.window_rule({match = {title = "^(Open Folder)(.*)$" }, center = true}) +hl.window_rule({match = {title = "^(Open Folder)(.*)$" }, float = true}) +hl.window_rule({match = {title = "^(Save As)(.*)$" }, center = true}) +hl.window_rule({match = {title = "^(Save As)(.*)$" }, float = true}) +hl.window_rule({match = {title = "^(Library)(.*)$" }, center = true}) +hl.window_rule({match = {title = "^(Library)(.*)$" }, float = true}) +hl.window_rule({match = {title = "^(File Upload)(.*)$" }, center = true}) +hl.window_rule({match = {title = "^(File Upload)(.*)$" }, float = true}) +hl.window_rule({match = {title = "^(.*)(wants to save)$" }, center = true}) +hl.window_rule({match = {title = "^(.*)(wants to save)$" }, float = true}) +hl.window_rule({match = {title = "^(.*)(wants to open)$" }, center = true}) +hl.window_rule({match = {title = "^(.*)(wants to open)$" }, float = true}) + +hl.window_rule({match = {title = "(.*)(Settings)(.*)$" },float = true}) diff --git a/nvim/lua/plugins/lspconfig.lua b/nvim/lua/plugins/lspconfig.lua index 69fcec8..9146a55 100644 --- a/nvim/lua/plugins/lspconfig.lua +++ b/nvim/lua/plugins/lspconfig.lua @@ -225,7 +225,8 @@ return { "rust_analyzer", "wgsl_analyzer", "julials", - "pyright" + "pyright", + "qmlls" }) end, }, diff --git a/quickshell/Bar.qml b/quickshell/Bar.qml index 03b20ac..483428c 100644 --- a/quickshell/Bar.qml +++ b/quickshell/Bar.qml @@ -7,14 +7,15 @@ import QtQuick.Layouts import Quickshell.Services.SystemTray import Quickshell.DBusMenu + Scope { id: root property string time - + property int cpuUsage: 0 property int memUsage: 0 property var lastCpuIdle: 0 - property var lastCpuTotal: 0 + property var lastCpuTotal: 0 SystemClock { id: sysClock @@ -26,15 +27,16 @@ Scope { command: ["sh", "-c", "head -1 /proc/stat"] stdout: SplitParser { onRead: data => { - if (!data) return - var p = data.trim().split(/\s+/) - var idle = parseInt(p[4]) + parseInt(p[5]) - var total = p.slice(1, 8).reduce((a, b) => a + parseInt(b), 0) + if (!data) + return; + var p = data.trim().split(/\s+/); + var idle = parseInt(p[4]) + parseInt(p[5]); + var total = p.slice(1, 8).reduce((a, b) => a + parseInt(b), 0); if (lastCpuTotal > 0) { - cpuUsage = Math.round(100 * (1 - (idle - lastCpuIdle) / (total - lastCpuTotal))) + cpuUsage = Math.round(100 * (1 - (idle - lastCpuIdle) / (total - lastCpuTotal))); } - lastCpuTotal = total - lastCpuIdle = idle + lastCpuTotal = total; + lastCpuIdle = idle; } } Component.onCompleted: running = true @@ -48,36 +50,36 @@ Scope { command: ["sh", "-c", "free | grep Mem"] stdout: SplitParser { onRead: data => { - if (!data) return - var parts = data.trim().split(/\s+/) - var total = parseInt(parts[1]) || 1 - var used = parseInt(parts[2]) || 0 - memUsage = Math.round(100 * used / total) + if (!data) + return; + var parts = data.trim().split(/\s+/); + var total = parseInt(parts[1]) || 1; + var used = parseInt(parts[2]) || 0; + memUsage = Math.round(100 * used / total); } } Component.onCompleted: running = true } - + Timer { interval: 1000 running: true repeat: true onTriggered: { - cpuProc.running = true - memProc.running = true + cpuProc.running = true; + memProc.running = true; } } Variants { model: Quickshell.screens - + PanelWindow { + id: barRoot required property var modelData screen: modelData readonly property HyprlandMonitor monitor: Hyprland.monitorFor(screen) - id: barRoot - // Theme property color colBg: "#150d16" property color colFg: "#f5dbc4" @@ -90,6 +92,10 @@ Scope { property string fontFamily: "Inter" property int fontSize: 16 + BackgroundEffect.blurRegion: Region { + item: barRoot.contentItem + } + anchors.bottom: true anchors.left: true anchors.right: true @@ -107,17 +113,21 @@ Scope { delegate: Loader { active: modelData.monitor && modelData.monitor.name === monitor.name && modelData.id != -98 - + sourceComponent: Text { - property bool isActive: Hyprland.focusedWorkspace?.id === modelData.id - text: modelData.id - + property bool isActive: Hyprland.focusedWorkspace?.id === modelData.id + text: modelData.id + color: isActive ? barRoot.colRed : barRoot.colFg - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - + font { + family: root.fontFamily + pixelSize: root.fontSize + bold: true + } + MouseArea { anchors.fill: parent - onClicked: ws.activate() + onClicked: ws.activate() } } } @@ -127,37 +137,56 @@ Scope { id: clock anchors.centerIn: parent property var timeFmt: "h:mm:ss AP" - property var timeStr: Qt.formatDateTime(sysClock.date, timeFmt) - + property var timeStr: Qt.formatDateTime(sysClock.date, timeFmt) + color: barRoot.colFg - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } - text: timeStr + font { + family: root.fontFamily + pixelSize: root.fontSize + bold: true + } + text: timeStr MouseArea { anchors.fill: parent - onClicked: { clock.timeFmt = (clock.timeFmt === "h:mm:ss AP") ? "ddd, MMM d - h:mm:ss AP" : "h:mm:ss AP" } + onClicked: { + clock.timeFmt = (clock.timeFmt === "h:mm:ss AP") ? "ddd, MMM d - h:mm:ss AP" : "h:mm:ss AP"; + } } } - Item { Layout.fillWidth: true } + Item { + Layout.fillWidth: true + } // CPU Text { text: "CPU: " + cpuUsage + "%" color: barRoot.colFg - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } + font { + family: root.fontFamily + pixelSize: root.fontSize + bold: true + } } - Rectangle { width: 1; height: 16; color: root.colMuted } + Rectangle { + width: 1 + height: 16 + color: root.colMuted + } // Memory Text { text: "Mem: " + memUsage + "%" color: barRoot.colFg - font { family: root.fontFamily; pixelSize: root.fontSize; bold: true } + font { + family: root.fontFamily + pixelSize: root.fontSize + bold: true + } } - Row { spacing: 5 Repeater { @@ -166,7 +195,7 @@ Scope { source: modelData.icon width: 16 height: 16 - + MouseArea { anchors.fill: parent onClicked: modelData.activate() @@ -174,7 +203,6 @@ Scope { } } } - } } }