Compare commits
12 commits
dc6aecdc31
...
73a34287f0
Author | SHA1 | Date | |
---|---|---|---|
73a34287f0 |
|||
1eaf307047 |
|||
b9e02538aa |
|||
ddd440d87c |
|||
d41e4a1d51 |
|||
26d5d7e24b |
|||
7535a6bb9e |
|||
5e9c4e8e4c |
|||
cbb594395a |
|||
5779ca210d |
|||
4b8775bab0 |
|||
fe40ebce25 |
30 changed files with 2143 additions and 133 deletions
154
flake.lock
generated
154
flake.lock
generated
|
@ -20,11 +20,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749155310,
|
||||
"narHash": "sha256-t0HfHg/1+TbSra5s6nNM0o4tnb3uqWedShSpZXsUMYY=",
|
||||
"lastModified": 1750372185,
|
||||
"narHash": "sha256-lVBKxd9dsZOH1fA6kSE5WNnt8e+09fN+NL/Q3BjTWHY=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "94981cf75a9f11da0b6dd6a1abbd7c50a36ab2d3",
|
||||
"rev": "7cef49d261cbbe537e8cb662485e76d29ac4cbca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -35,11 +35,11 @@
|
|||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1748970125,
|
||||
"narHash": "sha256-UDyigbDGv8fvs9aS95yzFfOKkEjx1LO3PL3DsKopohA=",
|
||||
"lastModified": 1750266157,
|
||||
"narHash": "sha256-tL42YoNg9y30u7zAqtoGDNdTyXTi8EALDeCB13FtbQA=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "323b5746d89e04b22554b061522dfce9e4c49b18",
|
||||
"rev": "e37c943371b73ed87faf33f7583860f81f1d5a48",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -111,6 +111,21 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_4": {
|
||||
"locked": {
|
||||
"lastModified": 1747046372,
|
||||
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
|
@ -341,11 +356,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749238452,
|
||||
"narHash": "sha256-8qiKEWcxUrjpUpK+WyFNg/72C8rp70LUuyTD23T+SdQ=",
|
||||
"lastModified": 1750371717,
|
||||
"narHash": "sha256-cNP+bVq8m5x2Rl6MTjwfQLCdwbVmKvTH7yqVc1SpiJM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "c7225d73755a6c4c7c72f4d4f3925ea426e325a8",
|
||||
"rev": "15c6f8f3a567fec9a0f732cd310a7ff456deef88",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -374,11 +389,11 @@
|
|||
"xdph": "xdph"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1750355078,
|
||||
"narHash": "sha256-vNTJaHBvasZuuwD0cYOqhpICaQ0SnQ7CqBhSZLjw3sc=",
|
||||
"lastModified": 1750959819,
|
||||
"narHash": "sha256-KZuCRu4PpqK0QrUJ2i/9+k+51ZO7prnjdH2WfR3wkuI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland",
|
||||
"rev": "b49d0ca20e4378db1e9abeb661d72f4c8c070db9",
|
||||
"rev": "3d6476c9021519995239ec93bbb11f0dce6c60a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -467,11 +482,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749155776,
|
||||
"narHash": "sha256-t1PM0wxQLQwv2F2AW23uA7pm5giwmcgYEWbNIRct9r4=",
|
||||
"lastModified": 1750371812,
|
||||
"narHash": "sha256-D868K1dVEACw17elVxRgXC6hOxY+54wIEjURztDWLk8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-qtutils",
|
||||
"rev": "396e8aa1c06274835b69da7f9a015fff9a9b7522",
|
||||
"rev": "b13c7481e37856f322177010bdf75fccacd1adc8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -496,11 +511,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749145882,
|
||||
"narHash": "sha256-qr0KXeczF8Sma3Ae7+dR2NHhvG7YeLBJv19W4oMu6ZE=",
|
||||
"lastModified": 1750371198,
|
||||
"narHash": "sha256-/iuJ1paQOBoSLqHflRNNGyroqfF/yvPNurxzcCT0cAE=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "1bfb84f54d50c7ae6558c794d3cfd5f6a7e6e676",
|
||||
"rev": "cee01452bca58d6cadb3224e21e370de8bc20f0b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -521,11 +536,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749819919,
|
||||
"narHash": "sha256-7F/KG8dwSH9JXdlpOVrEEArS+PJSn0iEnx5eVCk89/I=",
|
||||
"lastModified": 1750703126,
|
||||
"narHash": "sha256-zJHmLsiW6P8h9HaH5eMKhEh/gvym3k6/Ywr4UHKpJfc=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "57ab2a867d8b554ad89f29060c15efd11631db91",
|
||||
"rev": "d46bd32da554c370f98180a1e465f052b9584805",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -546,11 +561,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749145760,
|
||||
"narHash": "sha256-IHaGWpGrv7seFWdw/1A+wHtTsPlOGIKMrk1TUIYJEFI=",
|
||||
"lastModified": 1750371869,
|
||||
"narHash": "sha256-lGk4gLjgZQ/rndUkzmPYcgbHr8gKU5u71vyrjnwfpB4=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "817918315ea016cc2d94004bfb3223b5fd9dfcc6",
|
||||
"rev": "aa38edd6e3e277ae6a97ea83a69261a5c3aab9fd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -586,11 +601,11 @@
|
|||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1750168384,
|
||||
"narHash": "sha256-PBfJ7dGsR02im/RYN8wXII8yNPFhKxiPdq+JDfbvD2k=",
|
||||
"lastModified": 1750866260,
|
||||
"narHash": "sha256-fo5NvfutMEw9OV+5rGYuCKjlNNjcnD3cKMbOfzusO/E=",
|
||||
"owner": "nix-community",
|
||||
"repo": "lanzaboote",
|
||||
"rev": "38c2addd2e0cedcb03708de6e6c21fb1be86d410",
|
||||
"rev": "f40a3401f86d117affeeb8ca6f0ce5cd1ca3cc24",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -662,11 +677,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1750134718,
|
||||
"narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=",
|
||||
"lastModified": 1750776420,
|
||||
"narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c",
|
||||
"rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -704,6 +719,22 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1750339022,
|
||||
"narHash": "sha256-ws4nec55lgEwmz5LovtxnrFlCFuAQiY/TEcspY8KycY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8b1e1e1e0fd8215f26e074ae47a73cbb2b1a328e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
|
@ -760,11 +791,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1750335144,
|
||||
"narHash": "sha256-mEudA3XHHFPjR7XHad5Si6tag5M/tTSJIB6oDLifv60=",
|
||||
"lastModified": 1750880040,
|
||||
"narHash": "sha256-ZwQH4akrZf5BxOfXx9Skjw7UpWAj1/ITVRDZsS/AYLA=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "95d0af8113394b1fdb71c94ac5160c83b8b829cb",
|
||||
"revCount": 584,
|
||||
"rev": "d949f913479445e4f0ca3a95a183ee45d98dc359",
|
||||
"revCount": 596,
|
||||
"type": "git",
|
||||
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||
},
|
||||
|
@ -781,9 +812,11 @@
|
|||
"lix-module": "lix-module",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"quickshell": "quickshell",
|
||||
"rust-overlay": "rust-overlay_2",
|
||||
"schizofox": "schizofox",
|
||||
"systems": "systems_3",
|
||||
"watt": "watt"
|
||||
"watt": "watt",
|
||||
"zedless": "zedless"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
|
@ -794,11 +827,31 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749955444,
|
||||
"narHash": "sha256-CllTHvHX8KAdAZ+Lxzd23AmZTxO1Pfy+zC43/5tYkAE=",
|
||||
"lastModified": 1750560265,
|
||||
"narHash": "sha256-jQCojKl1/TzqE6ANOu6rP2qqxOcGK2xs6hpxZ77wrR8=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "539ba15741f0e6691a2448743dbc601d8910edce",
|
||||
"rev": "076fdb0d45a9de3f379a626f51a62c78afe7efb1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"rust-overlay_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1750905536,
|
||||
"narHash": "sha256-Mo7yXM5IvMGNvJPiNkFsVT2UERmnvjsKgnY6UyDdySQ=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "2fa7c0aabd15fa0ccc1dc7e675a4fcf0272ad9a1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -947,11 +1000,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749490041,
|
||||
"narHash": "sha256-R9Dn9IyUdPaJHD2Oqd7XJnnxpka6M6UYw4Ld0iA46HM=",
|
||||
"lastModified": 1750372504,
|
||||
"narHash": "sha256-VBeZb1oqZM1cqCAZnFz/WyYhO8aF/ImagI7WWg/Z3Og=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "3cf35e178bc192ee51e3fddfd69e531e2c106a30",
|
||||
"rev": "400308fc4f9d12e0a93e483c2e7a649e12af1a92",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -959,6 +1012,25 @@
|
|||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"zedless": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_4",
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1750898414,
|
||||
"narHash": "sha256-QuSbqvtgYIpEBriY/zTbsmOt+WXPuANSVAN4wnt6U1k=",
|
||||
"owner": "zedless-editor",
|
||||
"repo": "zed",
|
||||
"rev": "3ab1a186f16d5554c3b91e1963f4e4e4acfcc5e4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "zedless-editor",
|
||||
"repo": "zed",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
|
12
flake.nix
12
flake.nix
|
@ -20,7 +20,7 @@
|
|||
system: pkgs: {
|
||||
inherit
|
||||
(import ./packages {
|
||||
inherit pkgs;
|
||||
inherit inputs pkgs;
|
||||
})
|
||||
fish
|
||||
helix
|
||||
|
@ -83,5 +83,15 @@
|
|||
url = "https://git.lix.systems/lix-project/nixos-module/archive/2.93.0.tar.gz";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# The things rust is making me do...
|
||||
rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
zedless = {
|
||||
url = "github:zedless-editor/zed";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,32 @@
|
|||
{pkgs, ...}: {
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}:let
|
||||
|
||||
# a newer nil version, for pipes support.
|
||||
newer-nil = pkgs.nil.overrideAttrs (_: {
|
||||
version = "unstable-02-06-2025";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "oxalica";
|
||||
repo = "nil";
|
||||
rev = "577d160da311cc7f5042038456a0713e9863d09e";
|
||||
hash = "sha256-ggXU3RHv6NgWw+vc+HO4/9n0GPufhTIUjVuLci8Za8c=";
|
||||
};
|
||||
cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
|
||||
inherit (newer-nil) src;
|
||||
hash = "sha256-uZsLlFU9GKLvFllF7Kf5Q7HfN26KQojf4rvOb9p7Rjs=";
|
||||
};
|
||||
});
|
||||
|
||||
in {
|
||||
environment.systemPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
abook
|
||||
aerc
|
||||
alejandra
|
||||
aichat
|
||||
alsa-utils
|
||||
anki
|
||||
|
@ -79,5 +102,7 @@
|
|||
xournalpp
|
||||
zathura
|
||||
;
|
||||
inherit (inputs.zedless.packages.${pkgs.stdenv.system}) zed-editor;
|
||||
inherit newer-nil;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,15 +18,28 @@ in {
|
|||
tempDir = "/tmp/cups";
|
||||
|
||||
# Do not advertise shared printers.
|
||||
browsing = false;
|
||||
browsing = true;
|
||||
|
||||
# browsedConf = ''
|
||||
# BrowseDNSSDSubTypes _cups,_print
|
||||
# BrowseLocalProtocols all
|
||||
# BrowseRemoteProtocols all
|
||||
# CreateIPPPrinterQueues All
|
||||
|
||||
# BrowseProtocols all
|
||||
# '';
|
||||
|
||||
# Enable the CUPS webinterface, accessible at localhost:631.
|
||||
webInterface = true;
|
||||
|
||||
logLevel = "debug";
|
||||
|
||||
# Some local or network printers might need additional drivers.
|
||||
# These can be added into here.
|
||||
drivers = [
|
||||
pkgs.cups-kyocera-ecosys-m552x-p502x
|
||||
drivers = with pkgs; [
|
||||
gutenprint
|
||||
cups-kyocera-ecosys-m552x-p502x
|
||||
cups-filters
|
||||
];
|
||||
};
|
||||
|
||||
|
@ -35,6 +48,7 @@ in {
|
|||
avahi = {
|
||||
enable = true;
|
||||
nssmdns4 = true;
|
||||
nssmdns6 = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
|
|
103
modules/style/quickshell/shell/AudioPopup.qml
Normal file
103
modules/style/quickshell/shell/AudioPopup.qml
Normal file
|
@ -0,0 +1,103 @@
|
|||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import QtQuick.Layouts
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Services.Pipewire
|
||||
|
||||
Singleton {
|
||||
id: audioPopup
|
||||
property bool popupOpen: true
|
||||
|
||||
property var volume: sink.ready ? audioPopup.sink.audio.volume : 0
|
||||
|
||||
property var visible: volume
|
||||
|
||||
property PwNode sink: Pipewire.defaultAudioSink
|
||||
|
||||
// bind the node so we can read its properties
|
||||
PwObjectTracker {
|
||||
objects: [audioPopup.sink]
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 3000
|
||||
running: false
|
||||
repeat: false
|
||||
|
||||
onTriggered: audioPopup.visible = false
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: loader
|
||||
activeAsync: audioPopup.popupOpen
|
||||
|
||||
PanelWindow {
|
||||
id: popup
|
||||
width: 400
|
||||
height: 30
|
||||
visible: true
|
||||
|
||||
// Give the window an empty click mask so all clicks pass through it.
|
||||
mask: Region {}
|
||||
|
||||
// Use the wlroots specific layer property to ensure it displays over
|
||||
// fullscreen windows.
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
|
||||
color: "transparent"
|
||||
|
||||
anchors {
|
||||
bottom: true
|
||||
}
|
||||
|
||||
margins {
|
||||
bottom: 250
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rect
|
||||
Layout.fillWidth: true
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "white"
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
radius: 5
|
||||
opacity: 0
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: "black"
|
||||
height: 20
|
||||
radius: height / 2
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
topLeftRadius: 0
|
||||
bottomLeftRadius: 0
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width * audioPopup.sink.audio.volume
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
}
|
||||
}
|
46
modules/style/quickshell/shell/ClockWidget.qml
Normal file
46
modules/style/quickshell/shell/ClockWidget.qml
Normal file
|
@ -0,0 +1,46 @@
|
|||
import QtQuick
|
||||
import Quickshell
|
||||
|
||||
Rectangle {
|
||||
|
||||
|
||||
width: text.width
|
||||
implicitHeight: text.height
|
||||
// border.color: "black"
|
||||
border.width: 2
|
||||
radius: 0
|
||||
color: "transparent"
|
||||
|
||||
Behavior on implicitHeight {
|
||||
NumberAnimation {
|
||||
duration: 100
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: text.height
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
SystemClock {
|
||||
id: clock
|
||||
precision: SystemClock.Seconds
|
||||
}
|
||||
|
||||
Text {
|
||||
id: text
|
||||
anchors.centerIn: parent
|
||||
property var date: Date()
|
||||
|
||||
text: Qt.formatDateTime(clock.date, "hh mm")
|
||||
|
||||
font.family: "ComicShannsMono Nerd Font Mono"
|
||||
font.weight: Font.ExtraBold
|
||||
font.pointSize: 12
|
||||
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
310
modules/style/quickshell/shell/Launcher.qml
Normal file
310
modules/style/quickshell/shell/Launcher.qml
Normal file
|
@ -0,0 +1,310 @@
|
|||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
|
||||
import "./config"
|
||||
|
||||
Singleton {
|
||||
id: launcher
|
||||
property bool launcherOpen: false
|
||||
|
||||
IpcHandler {
|
||||
target: "launcher"
|
||||
|
||||
function open(): void {
|
||||
launcher.launcherOpen = true;
|
||||
}
|
||||
|
||||
function close(): void {
|
||||
launcher.launcherOpen = false;
|
||||
}
|
||||
|
||||
function toggle(): void {
|
||||
launcher.launcherOpen = !launcher.launcherOpen;
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: loader
|
||||
activeAsync: launcher.launcherOpen
|
||||
|
||||
PanelWindow {
|
||||
implicitWidth: 450
|
||||
implicitHeight: 7 + searchContainer.implicitHeight + list.topMargin * 2 + list.delegateHeight * 10
|
||||
color: "transparent"
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
||||
|
||||
Rectangle {
|
||||
|
||||
height: 7 + searchContainer.implicitHeight + list.topMargin + list.bottomMargin + Math.min(list.contentHeight, list.delegateHeight * 10)
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
width: 450
|
||||
color: Config.catppuccin.base
|
||||
radius: 5
|
||||
border.color: Config.catppuccin.mantle
|
||||
border.width: 2
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 7
|
||||
anchors.bottomMargin: 0
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
id: searchContainer
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: searchbox.implicitHeight + 10
|
||||
color: Config.catppuccin.base
|
||||
radius: 3
|
||||
border.color: Config.catppuccin.mantle
|
||||
|
||||
RowLayout {
|
||||
id: searchbox
|
||||
anchors.fill: parent
|
||||
anchors.margins: 5
|
||||
|
||||
TextInput {
|
||||
id: search
|
||||
Layout.fillWidth: true
|
||||
color: Config.catppuccin.text
|
||||
font.pointSize: 13
|
||||
|
||||
focus: true
|
||||
Keys.forwardTo: [list]
|
||||
Keys.onEscapePressed: launcher.launcherOpen = false
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
if (event.key == Qt.Key_J) {
|
||||
list.currentIndex = list.currentIndex == list.count - 1 ? 0 : list.currentIndex + 1;
|
||||
event.accepted = true;
|
||||
} else if (event.key == Qt.Key_K) {
|
||||
list.currentIndex = list.currentIndex == 0 ? list.count - 1 : list.currentIndex - 1;
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (list.currentItem) {
|
||||
list.currentItem.clicked(null);
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
list.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: list
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
cacheBuffer: 0 // works around QTBUG-131106
|
||||
//reuseItems: true
|
||||
model: ScriptModel {
|
||||
values: DesktopEntries.applications.values.map(object => {
|
||||
const stxt = search.text.toLowerCase();
|
||||
const ntxt = object.name.toLowerCase();
|
||||
let si = 0;
|
||||
let ni = 0;
|
||||
|
||||
let matches = [];
|
||||
let startMatch = -1;
|
||||
|
||||
for (let si = 0; si != stxt.length; ++si) {
|
||||
const sc = stxt[si];
|
||||
|
||||
while (true) {
|
||||
// Drop any entries with letters that don't exist in order
|
||||
if (ni == ntxt.length)
|
||||
return null;
|
||||
|
||||
const nc = ntxt[ni++];
|
||||
|
||||
if (nc == sc) {
|
||||
if (startMatch == -1)
|
||||
startMatch = ni;
|
||||
break;
|
||||
} else {
|
||||
if (startMatch != -1) {
|
||||
matches.push({
|
||||
index: startMatch,
|
||||
length: ni - startMatch
|
||||
});
|
||||
|
||||
startMatch = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startMatch != -1) {
|
||||
matches.push({
|
||||
index: startMatch,
|
||||
length: ni - startMatch + 1
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
object: object,
|
||||
matches: matches
|
||||
};
|
||||
}).filter(entry => entry !== null).sort((a, b) => {
|
||||
let ai = 0;
|
||||
let bi = 0;
|
||||
let s = 0;
|
||||
|
||||
while (ai != a.matches.length && bi != b.matches.length) {
|
||||
const am = a.matches[ai];
|
||||
const bm = b.matches[bi];
|
||||
|
||||
s = bm.length - am.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
s = am.index - bm.index;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
++ai;
|
||||
++bi;
|
||||
}
|
||||
|
||||
s = a.matches.length - b.matches.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
s = a.object.name.length - b.object.name.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
return a.object.name.localeCompare(b.object.name);
|
||||
}).map(entry => entry.object)
|
||||
|
||||
onValuesChanged: list.currentIndex = 0
|
||||
}
|
||||
|
||||
topMargin: 7
|
||||
bottomMargin: list.count == 0 ? 0 : 7
|
||||
|
||||
add: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 0
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
highlight: Rectangle {
|
||||
radius: 5
|
||||
color: "transparent"
|
||||
border.color: Config.catppuccin.lavender
|
||||
border.width: 2
|
||||
}
|
||||
keyNavigationEnabled: true
|
||||
keyNavigationWraps: true
|
||||
highlightMoveVelocity: -1
|
||||
highlightMoveDuration: 50
|
||||
preferredHighlightBegin: list.topMargin
|
||||
preferredHighlightEnd: list.height - list.bottomMargin
|
||||
highlightRangeMode: ListView.ApplyRange
|
||||
snapMode: ListView.SnapToItem
|
||||
|
||||
readonly property real delegateHeight: 44
|
||||
|
||||
delegate: MouseArea {
|
||||
required property DesktopEntry modelData
|
||||
|
||||
implicitHeight: list.delegateHeight
|
||||
implicitWidth: ListView.view.width
|
||||
|
||||
onClicked: {
|
||||
modelData.execute();
|
||||
launcher.launcherOpen = false;
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: delegateLayout
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
leftMargin: 5
|
||||
}
|
||||
|
||||
IconImage {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
asynchronous: true
|
||||
implicitSize: 30
|
||||
source: Quickshell.iconPath(modelData.icon)
|
||||
}
|
||||
Text {
|
||||
text: modelData.name
|
||||
color: Config.catppuccin.text
|
||||
font.family: "JetBrainsMono Nerd Font Mono"
|
||||
font.pointSize: 13
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function init() {
|
||||
}
|
||||
}
|
127
modules/style/quickshell/shell/ReloadPopup.qml
Normal file
127
modules/style/quickshell/shell/ReloadPopup.qml
Normal file
|
@ -0,0 +1,127 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
|
||||
Scope {
|
||||
id: root
|
||||
property bool failed
|
||||
property string errorString
|
||||
|
||||
// Connect to the Quickshell global to listen for the reload signals.
|
||||
Connections {
|
||||
target: Quickshell
|
||||
|
||||
function onReloadCompleted() {
|
||||
root.failed = false;
|
||||
popupLoader.loading = true;
|
||||
}
|
||||
|
||||
function onReloadFailed(error: string) {
|
||||
// Close any existing popup before making a new one.
|
||||
popupLoader.active = false;
|
||||
|
||||
root.failed = true;
|
||||
root.errorString = error;
|
||||
popupLoader.loading = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the popup in a loader because it isn't needed most of the timeand will take up
|
||||
// memory that could be used for something else.
|
||||
LazyLoader {
|
||||
id: popupLoader
|
||||
|
||||
PanelWindow {
|
||||
id: popup
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
right: true
|
||||
}
|
||||
|
||||
margins {
|
||||
top: 25
|
||||
left: 25
|
||||
}
|
||||
|
||||
width: rect.width
|
||||
height: rect.height
|
||||
|
||||
// color blending is a bit odd as detailed in the type reference.
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
id: rect
|
||||
color: root.failed ? "#40802020" : "#40009020"
|
||||
|
||||
implicitHeight: layout.implicitHeight + 50
|
||||
implicitWidth: layout.implicitWidth + 30
|
||||
|
||||
// Fills the whole area of the rectangle, making any clicks go to it,
|
||||
// which dismiss the popup.
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: popupLoader.active = false
|
||||
|
||||
// makes the mouse area track mouse hovering, so the hide animation
|
||||
// can be paused when hovering.
|
||||
hoverEnabled: true
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 20
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.failed ? "Reloaing failed." : "Reloading completed!"
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.errorString
|
||||
color: "white"
|
||||
// When visible is false, it also takes up no space.
|
||||
visible: root.errorString != ""
|
||||
}
|
||||
}
|
||||
|
||||
// A progress bar on the bottom of the screen, showing how long until the
|
||||
// popup is removed.
|
||||
Rectangle {
|
||||
id: bar
|
||||
color: "#20ffffff"
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
height: 20
|
||||
|
||||
PropertyAnimation {
|
||||
id: anim
|
||||
target: bar
|
||||
property: "width"
|
||||
from: rect.width
|
||||
to: 0
|
||||
duration: failed ? 10000 : 800
|
||||
onFinished: popupLoader.active = false
|
||||
|
||||
// Pause the animation when the mouse is hovering over the popup,
|
||||
// so it stays onscreen while reading. This updates reactively
|
||||
// when the mouse moves on and off the popup.
|
||||
paused: mouseArea.containsMouse
|
||||
}
|
||||
}
|
||||
|
||||
// We could set `running: true` inside the animation, but the width of the
|
||||
// rectangle might not be calculated yet, due to the layout.
|
||||
// In the `Component.onCompleted` event handler, all of the component's
|
||||
// properties and children have been initialized.
|
||||
Component.onCompleted: anim.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
modules/style/quickshell/shell/SysTray.qml
Normal file
57
modules/style/quickshell/shell/SysTray.qml
Normal file
|
@ -0,0 +1,57 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Services.SystemTray
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
required property var bar
|
||||
|
||||
width: parent.width
|
||||
height: column.height + 10
|
||||
color: "#30c0ffff"
|
||||
radius: 5
|
||||
border.color: "black"
|
||||
border.width: 2
|
||||
|
||||
RowLayout {
|
||||
id: column
|
||||
spacing: 10
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
Repeater {
|
||||
model: SystemTray.items
|
||||
|
||||
Item {
|
||||
id: item
|
||||
|
||||
required property SystemTrayItem modelData
|
||||
|
||||
height: 35
|
||||
width: 35
|
||||
|
||||
Image {
|
||||
source: item.modelData.icon
|
||||
anchors.fill: parent
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
item.modelData.activate();
|
||||
}
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
if (item.modelData.hasMenu) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
modules/style/quickshell/shell/config/Config.qml
Normal file
50
modules/style/quickshell/shell/config/Config.qml
Normal file
|
@ -0,0 +1,50 @@
|
|||
pragma Singleton
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
readonly property QtObject bar: QtObject {
|
||||
readonly property int width: 50
|
||||
readonly property var colors: QtObject {
|
||||
readonly property color bar: "#1e1e2e"
|
||||
readonly property color barOutline: "#50ffffff"
|
||||
readonly property color widget: "#25ceffff"
|
||||
readonly property color widgetActive: "#80ceffff"
|
||||
readonly property color widgetOutline: "#40ffffff"
|
||||
readonly property color widgetOutlineSeparate: "#20ffffff"
|
||||
readonly property color separator: "#60ffffff"
|
||||
}
|
||||
}
|
||||
|
||||
readonly property QtObject border: QtObject {
|
||||
readonly property int thickness: 8
|
||||
readonly property color color: "#1e1e2e"
|
||||
readonly property int rounding: 25
|
||||
}
|
||||
|
||||
readonly property QtObject catppuccin: QtObject {
|
||||
readonly property color base: "#1e1e2e"
|
||||
readonly property color mantle: "#181825"
|
||||
readonly property color surface0: "#313244"
|
||||
readonly property color surface1: "#45475a"
|
||||
readonly property color surface2: "#585b70"
|
||||
readonly property color text: "#cdd6f4"
|
||||
readonly property color rosewater: "#f5e0dc"
|
||||
readonly property color lavender: "#b4befe"
|
||||
readonly property color red: "#f38ba8"
|
||||
readonly property color peach: "#fab387"
|
||||
readonly property color yellow: "#f9e2af"
|
||||
readonly property color green: "#a6e3a1"
|
||||
readonly property color teal: "#a6e3a1"
|
||||
readonly property color blue: "#89b4fa"
|
||||
readonly property color mauve: "#cba6f7"
|
||||
readonly property color flamingo: "#f2cdcd"
|
||||
}
|
||||
readonly property QtObject volumeslider: QtObject {
|
||||
readonly property int width: 50
|
||||
}
|
||||
|
||||
}
|
50
modules/style/quickshell/shell/modules/bar/Bar.qml
Normal file
50
modules/style/quickshell/shell/modules/bar/Bar.qml
Normal file
|
@ -0,0 +1,50 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
|
||||
import "../../config"
|
||||
import "components"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property ShellScreen screen
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
implicitWidth: Config.bar.width
|
||||
|
||||
Item {
|
||||
id: child
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
implicitWidth: Math.max(clock.implicitWidth, workspaces.implicitWidth)
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 2
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
margins: 0
|
||||
}
|
||||
Clock {
|
||||
id: clock
|
||||
}
|
||||
Workspaces {
|
||||
id: workspaces
|
||||
screen: root.screen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import QtQuick
|
||||
import Quickshell
|
||||
|
||||
import "../../../config"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
width: text.width + 5
|
||||
height: text.height + 5
|
||||
implicitWidth: width
|
||||
border.color: Config.catppuccin.rosewater
|
||||
border.width: 0
|
||||
radius: 5
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
id: text
|
||||
anchors.centerIn: parent
|
||||
property var date: Date()
|
||||
|
||||
text: Qt.formatDateTime(clock.date, "hh mm")
|
||||
|
||||
font.family: "JetBrainsMono NF Mono"
|
||||
font.pointSize: 15
|
||||
|
||||
color: Config.catppuccin.text
|
||||
}
|
||||
|
||||
SystemClock {
|
||||
id: clock
|
||||
precision: SystemClock.Seconds
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import QtQuick.Layouts
|
||||
|
||||
import "../../../services/niri"
|
||||
import "../../../config"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
required property ShellScreen screen
|
||||
property var workspaces: Niri.workspaces
|
||||
property var wsCount: Niri.workspaces.length
|
||||
property var activeWorkspace: Niri.activeWorkspace
|
||||
property var activeWorkspaceIndex: Niri.activeWorkspaceIndex
|
||||
|
||||
property int wsItemHeight: 15
|
||||
|
||||
signal workspaceAdded(workspace: var)
|
||||
function onWorkspaceAdded(workspace: var) {
|
||||
root.workspaces.push(workspace);
|
||||
}
|
||||
|
||||
// property bool _: log()
|
||||
// function log() {
|
||||
// console.log(workspaces.values);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// Works
|
||||
height: 300
|
||||
|
||||
// Gives warning
|
||||
// height: workspaces.length * root.wsItemHeight
|
||||
implicitWidth: list.implicitWidth
|
||||
color: "transparent"
|
||||
border.color: Config.catppuccin.rosewater
|
||||
border.width: 0
|
||||
radius: 7
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
ListView {
|
||||
id: list
|
||||
model: root.workspaces
|
||||
implicitHeight: contentHeight
|
||||
implicitWidth: contentItem.childrenRect.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
// anchors.fill: parent
|
||||
|
||||
delegate: Item {
|
||||
id: wsItem
|
||||
// Name of the workspace
|
||||
property string name: "VOID"
|
||||
// ID of the workspace
|
||||
required property string id
|
||||
|
||||
required property string output
|
||||
|
||||
property bool isActive: (id - 1 == root.activeWorkspaceIndex)
|
||||
|
||||
property real animActive: isActive ? 1 : 0.65
|
||||
Behavior on animActive {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
|
||||
// property bool isCorrectScreen: log()
|
||||
// function log() {
|
||||
// console.log("Screen name: " + root.screen.name);
|
||||
// console.log(wsItem.output);
|
||||
// console.log(wsItem.id);
|
||||
|
||||
// let isCorrect = root.screen.name == wsItem.output;
|
||||
// console.log("isCorrect: ", isCorrect);
|
||||
// return root.screen.name == wsItem.output;
|
||||
// }
|
||||
|
||||
implicitHeight: root.wsItemHeight
|
||||
implicitWidth: 50
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
height: wsItem.height - 5
|
||||
width: parent.width * wsItem.animActive
|
||||
radius: height / 2
|
||||
border.color: Config.catppuccin.mantle
|
||||
border.width: 0
|
||||
color: Config.catppuccin.blue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Niri.workspaces.forEach(workspace => {
|
||||
root.workspaceAdded(workspace);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Shapes
|
||||
|
||||
import "../notifications" as Notifications
|
||||
|
||||
Rectangle {
|
||||
required property Item bar
|
||||
}
|
55
modules/style/quickshell/shell/modules/drawers/Border.qml
Normal file
55
modules/style/quickshell/shell/modules/drawers/Border.qml
Normal file
|
@ -0,0 +1,55 @@
|
|||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
|
||||
import "../../config"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property Item bar
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
id: rect
|
||||
|
||||
// Parent has a mask applied that cuts out all except the border and the bar.
|
||||
anchors.fill: parent
|
||||
color: Config.border.color
|
||||
visible: false
|
||||
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 150
|
||||
easing.type: Easing.BezierSpline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: mask
|
||||
|
||||
anchors.fill: parent
|
||||
layer.enabled: true
|
||||
visible: false
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Config.border.thickness
|
||||
anchors.leftMargin: root.bar.implicitWidth
|
||||
radius: Config.border.rounding
|
||||
}
|
||||
}
|
||||
|
||||
MultiEffect {
|
||||
anchors.fill: parent
|
||||
maskEnabled: true
|
||||
maskInverted: true
|
||||
maskSource: mask
|
||||
source: rect
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
}
|
104
modules/style/quickshell/shell/modules/drawers/Drawers.qml
Normal file
104
modules/style/quickshell/shell/modules/drawers/Drawers.qml
Normal file
|
@ -0,0 +1,104 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Services.Notifications
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
|
||||
import "../bar"
|
||||
import "../volume"
|
||||
import "../notifications"
|
||||
|
||||
import "../../services"
|
||||
import "../../config"
|
||||
|
||||
Variants {
|
||||
model: Quickshell.screens
|
||||
|
||||
Scope {
|
||||
id: scope
|
||||
required property ShellScreen modelData
|
||||
|
||||
Exclusions {
|
||||
screen: scope.modelData
|
||||
bar: bar
|
||||
}
|
||||
|
||||
PanelWindow {
|
||||
id: win
|
||||
|
||||
screen: scope.modelData
|
||||
color: "transparent"
|
||||
|
||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
|
||||
// Clickthrough mask.
|
||||
// Clickable areas of the window are determined by the provided region.
|
||||
mask: Region {
|
||||
// Start at the bottom left; right of the bar and on top of the border
|
||||
x: bar.implicitWidth
|
||||
y: Config.border.thickness
|
||||
|
||||
// Width is the window width - the bar's width - the border thickness
|
||||
width: win.width - bar.implicitWidth - Config.border.thickness
|
||||
|
||||
// Height is window width - the border thickness x2 —top border and bottom border.
|
||||
height: win.height - Config.border.thickness * 2
|
||||
|
||||
// Setting the intersection mode to Xor will invert the mask and make everything in the mask region not clickable and pass through clicks inside it through the window.
|
||||
intersection: Intersection.Xor
|
||||
Region {
|
||||
item: volume
|
||||
intersection: Intersection.Subtract
|
||||
}
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
bottom: true
|
||||
left: true
|
||||
right: true
|
||||
}
|
||||
|
||||
Item {
|
||||
id: background
|
||||
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
|
||||
Border {
|
||||
bar: bar
|
||||
}
|
||||
|
||||
Backgrounds {
|
||||
bar: bar
|
||||
}
|
||||
}
|
||||
|
||||
MultiEffect {
|
||||
anchors.fill: source
|
||||
source: background
|
||||
shadowEnabled: true
|
||||
blurMax: 15
|
||||
}
|
||||
|
||||
Bar {
|
||||
id: bar
|
||||
screen: scope.modelData
|
||||
}
|
||||
|
||||
// VolumeSlider {
|
||||
// id: volume
|
||||
// screen: scope.modelData
|
||||
// }
|
||||
|
||||
// Hover {
|
||||
// id: hover
|
||||
// screen: scope.modelData
|
||||
// bar: bar
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
pragma ComponentBehavior: Bound
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
|
||||
import "../../config"
|
||||
|
||||
Scope {
|
||||
id: root
|
||||
required property ShellScreen screen
|
||||
required property Item bar
|
||||
|
||||
ExclusionZone {
|
||||
anchors.left: true
|
||||
exclusiveZone: root.bar.implicitWidth
|
||||
}
|
||||
|
||||
ExclusionZone {
|
||||
anchors.top: true
|
||||
}
|
||||
|
||||
ExclusionZone {
|
||||
anchors.right: true
|
||||
}
|
||||
|
||||
ExclusionZone {
|
||||
anchors.bottom: true
|
||||
}
|
||||
|
||||
component ExclusionZone: PanelWindow {
|
||||
screen: root.screen
|
||||
color: "transparent"
|
||||
exclusiveZone: Config.border.thickness
|
||||
implicitHeight: Config.border.thickness
|
||||
implicitWidth: Config.border.thickness
|
||||
mask: Region {}
|
||||
}
|
||||
}
|
319
modules/style/quickshell/shell/modules/launcher/Launcher.qml
Normal file
319
modules/style/quickshell/shell/modules/launcher/Launcher.qml
Normal file
|
@ -0,0 +1,319 @@
|
|||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
|
||||
Singleton {
|
||||
id: launcher
|
||||
property bool launcherOpen: false
|
||||
|
||||
IpcHandler {
|
||||
target: "launcher"
|
||||
|
||||
function open(): void {
|
||||
launcher.launcherOpen = true;
|
||||
}
|
||||
|
||||
function close(): void {
|
||||
launcher.launcherOpen = false;
|
||||
}
|
||||
|
||||
function toggle(): void {
|
||||
launcher.launcherOpen = !launcher.launcherOpen;
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: loader
|
||||
activeAsync: launcher.launcherOpen
|
||||
|
||||
PanelWindow {
|
||||
width: 450
|
||||
height: 7 + searchContainer.implicitHeight + list.topMargin * 2 + list.delegateHeight * 10
|
||||
color: "transparent"
|
||||
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
||||
WlrLayershell.namespace: "shell:launcher"
|
||||
|
||||
Rectangle {
|
||||
|
||||
height: 7 + searchContainer.implicitHeight + list.topMargin + list.bottomMargin + Math.min(list.contentHeight, list.delegateHeight * 10)
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
width: 450
|
||||
color: "#30c0afaf"
|
||||
radius: 5
|
||||
border.color: "black"
|
||||
border.width: 2
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 7
|
||||
anchors.bottomMargin: 0
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
id: searchContainer
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: searchbox.implicitHeight + 10
|
||||
color: "#30c0ffff"
|
||||
radius: 3
|
||||
border.color: "#50ffffff"
|
||||
|
||||
RowLayout {
|
||||
id: searchbox
|
||||
anchors.fill: parent
|
||||
anchors.margins: 5
|
||||
|
||||
IconImage {
|
||||
implicitSize: parent.height
|
||||
source: "root:icons/magnifying-glass.svg"
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: search
|
||||
Layout.fillWidth: true
|
||||
color: "black"
|
||||
|
||||
focus: true
|
||||
Keys.forwardTo: [list]
|
||||
Keys.onEscapePressed: launcher.launcherOpen = false
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
if (event.key == Qt.Key_J) {
|
||||
list.currentIndex = list.currentIndex == list.count - 1 ? 0 : list.currentIndex + 1;
|
||||
event.accepted = true;
|
||||
} else if (event.key == Qt.Key_K) {
|
||||
list.currentIndex = list.currentIndex == 0 ? list.count - 1 : list.currentIndex - 1;
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (list.currentItem) {
|
||||
list.currentItem.clicked(null);
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
list.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: list
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
cacheBuffer: 0 // works around QTBUG-131106
|
||||
//reuseItems: true
|
||||
model: ScriptModel {
|
||||
values: DesktopEntries.applications.values.map(object => {
|
||||
const stxt = search.text.toLowerCase();
|
||||
const ntxt = object.name.toLowerCase();
|
||||
let si = 0;
|
||||
let ni = 0;
|
||||
|
||||
let matches = [];
|
||||
let startMatch = -1;
|
||||
|
||||
for (let si = 0; si != stxt.length; ++si) {
|
||||
const sc = stxt[si];
|
||||
|
||||
while (true) {
|
||||
// Drop any entries with letters that don't exist in order
|
||||
if (ni == ntxt.length)
|
||||
return null;
|
||||
|
||||
const nc = ntxt[ni++];
|
||||
|
||||
if (nc == sc) {
|
||||
if (startMatch == -1)
|
||||
startMatch = ni;
|
||||
break;
|
||||
} else {
|
||||
if (startMatch != -1) {
|
||||
matches.push({
|
||||
index: startMatch,
|
||||
length: ni - startMatch
|
||||
});
|
||||
|
||||
startMatch = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startMatch != -1) {
|
||||
matches.push({
|
||||
index: startMatch,
|
||||
length: ni - startMatch + 1
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
object: object,
|
||||
matches: matches
|
||||
};
|
||||
}).filter(entry => entry !== null).sort((a, b) => {
|
||||
let ai = 0;
|
||||
let bi = 0;
|
||||
let s = 0;
|
||||
|
||||
while (ai != a.matches.length && bi != b.matches.length) {
|
||||
const am = a.matches[ai];
|
||||
const bm = b.matches[bi];
|
||||
|
||||
s = bm.length - am.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
s = am.index - bm.index;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
++ai;
|
||||
++bi;
|
||||
}
|
||||
|
||||
s = a.matches.length - b.matches.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
s = a.object.name.length - b.object.name.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
return a.object.name.localeCompare(b.object.name);
|
||||
}).map(entry => entry.object)
|
||||
|
||||
onValuesChanged: list.currentIndex = 0
|
||||
}
|
||||
|
||||
topMargin: 7
|
||||
bottomMargin: list.count == 0 ? 0 : 7
|
||||
|
||||
add: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 0
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
highlight: Rectangle {
|
||||
radius: 5
|
||||
color: "#20e0ffff"
|
||||
border.color: "#30ffffff"
|
||||
border.width: 1
|
||||
}
|
||||
keyNavigationEnabled: true
|
||||
keyNavigationWraps: true
|
||||
highlightMoveVelocity: -1
|
||||
highlightMoveDuration: 50
|
||||
preferredHighlightBegin: list.topMargin
|
||||
preferredHighlightEnd: list.height - list.bottomMargin
|
||||
highlightRangeMode: ListView.ApplyRange
|
||||
snapMode: ListView.SnapToItem
|
||||
|
||||
readonly property real delegateHeight: 44
|
||||
|
||||
delegate: MouseArea {
|
||||
required property DesktopEntry modelData
|
||||
|
||||
implicitHeight: list.delegateHeight
|
||||
implicitWidth: ListView.view.width
|
||||
|
||||
onClicked: {
|
||||
modelData.execute();
|
||||
launcher.launcherOpen = false;
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: delegateLayout
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
leftMargin: 5
|
||||
}
|
||||
|
||||
IconImage {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
asynchronous: true
|
||||
implicitSize: 30
|
||||
source: Quickshell.iconPath(modelData.icon)
|
||||
}
|
||||
Text {
|
||||
text: modelData.name
|
||||
color: "black"
|
||||
font.family: "ComicShannsMono Nerd Font Mono"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function init() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import QtQuick
|
||||
import QtQuick.Shapes
|
||||
|
||||
import "../../config"
|
||||
import "../../services"
|
||||
|
||||
Shape {
|
||||
id: root
|
||||
anchors.top: parent.top
|
||||
// anchors.right: parent.right
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
readonly property real rounding: Config.border.rounding
|
||||
|
||||
implicitWidth: 1000
|
||||
implicitHeight: 300
|
||||
ShapePath {
|
||||
fillColor: Config.catppuccin.base
|
||||
strokeWidth: -1
|
||||
|
||||
PathArc {
|
||||
relativeX: root.rounding
|
||||
relativeY: root.rounding
|
||||
radiusX: root.rounding
|
||||
radiusY: root.rounding
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: 100
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 300
|
||||
relativeY: 0
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: -100
|
||||
}
|
||||
PathArc {
|
||||
relativeX: root.rounding
|
||||
relativeY: -root.rounding
|
||||
radiusX: root.rounding
|
||||
radiusY: root.rounding
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: 500
|
||||
easing.type: Easing.BezierSpline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "This is a test"
|
||||
color: "white"
|
||||
font.pointSize: 15
|
||||
font.bold: true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Shapes
|
||||
import "../../config"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
required property ShellScreen screen
|
||||
readonly property real rounding: Config.border.rounding
|
||||
color: "transparent"
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
implicitWidth: Config.volumeslider.width
|
||||
implicitHeight: screen.height / 3
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
color: "green"
|
||||
implicitWidth: hover.hovered ? Config.volumeslider.width : Config.border.thickness
|
||||
|
||||
implicitHeight: root.screen.height / 3
|
||||
|
||||
HoverHandler {
|
||||
id: hover
|
||||
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
|
||||
}
|
||||
|
||||
Behavior on implicitWidth {
|
||||
NumberAnimation {
|
||||
duration: 400
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shape {
|
||||
implicitWidth: hover.hovered ? Config.volumeslider.width : Config.border.thickness
|
||||
implicitHeight: root.screen.height / 3
|
||||
ShapePath {
|
||||
fillColor: Config.catppuccin.base
|
||||
strokeWidth: -1
|
||||
PathArc {
|
||||
relativeX: -root.rounding
|
||||
relativeY: root.rounding
|
||||
radiusX: root.rounding
|
||||
radiusY: root.rounding
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeY: root.screen.height / 3
|
||||
relativeX: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: root.rounding
|
||||
// relativeX: 50
|
||||
relativeY: -root.rounding
|
||||
radiusX: root.rounding
|
||||
radiusY: root.rounding
|
||||
// direction: PathArc.Counterclockwise
|
||||
// useLargeArc: true
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 50
|
||||
relativeY: 0
|
||||
}
|
||||
PathLine {
|
||||
relativeY: -root.screen.height / 3
|
||||
relativeX: 0
|
||||
}
|
||||
PathLine {
|
||||
relativeX: -50
|
||||
relativeY: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
modules/style/quickshell/shell/services/Hover.qml
Normal file
49
modules/style/quickshell/shell/services/Hover.qml
Normal file
|
@ -0,0 +1,49 @@
|
|||
import Quickshell
|
||||
import QtQuick
|
||||
import "../config"
|
||||
|
||||
MouseArea {
|
||||
id: root
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
required property ShellScreen screen
|
||||
// required property Panels panels
|
||||
required property Item bar
|
||||
|
||||
property bool showVolumeMenu: false
|
||||
property bool isInRightPanel: false
|
||||
|
||||
// function withinPanelHeight(panel: Item, x: real, y: real): bool {
|
||||
// const panelY = Config.border.thickness + panel.y;
|
||||
// return y >= panelY - Config.border.rounding && y <= panelY + panel.height + Config.border.rounding;
|
||||
// }
|
||||
|
||||
// function inLeftBorder(x: real, y: real): bool {
|
||||
// return x <= Config.border.thickness;
|
||||
// }
|
||||
|
||||
function inRightPanel(x: real, y: real): bool {
|
||||
// Cursor is in middle veritcal third of screen
|
||||
// Cursor is in the right border
|
||||
return y >= root.screen.height / 3 && y <= (root.screen.height / 3) * 2 && x >= root.screen.width - Config.border.thickness;
|
||||
}
|
||||
|
||||
// Update on mouse cursor movement
|
||||
onPositionChanged: event => {
|
||||
const x = event.x;
|
||||
const y = event.y;
|
||||
|
||||
root.isInRightPanel = inRightPanel(x, y);
|
||||
|
||||
console.log("In right panel: " + root.isInRightPanel);
|
||||
|
||||
console.log("x:" + x + " y: " + y);
|
||||
}
|
||||
onContainsMouseChanged: {
|
||||
if (!containsMouse) {
|
||||
root.isInRightPanel = false;
|
||||
}
|
||||
}
|
||||
}
|
20
modules/style/quickshell/shell/services/Notification.qml
Normal file
20
modules/style/quickshell/shell/services/Notification.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Services.Notifications
|
||||
|
||||
/**
|
||||
* Provides extra features not in Quickshell.Services.Notifications:
|
||||
* - Persistent storage
|
||||
* - Popup notifications, with timeout
|
||||
* - Notification groups by app
|
||||
*/
|
||||
Singleton {
|
||||
id: root
|
||||
NotificationServer {
|
||||
|
||||
}
|
||||
}
|
94
modules/style/quickshell/shell/services/niri/Niri.qml
Normal file
94
modules/style/quickshell/shell/services/niri/Niri.qml
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Kind thanks to https://github.com/MapoMagpie/nixos-flakes/blob/main/home/ui/quickshell/config/Data/Niri.qml
|
||||
// This file was taken from there and further modified.
|
||||
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
// property var data
|
||||
property var workspaces: []
|
||||
property var activeWorkspace: "VOID"
|
||||
property var activeWorkspaceIndex: 0
|
||||
property var windows: []
|
||||
// property var activedWindowId: 0
|
||||
|
||||
Process {
|
||||
id: proc
|
||||
command: ["niri", "msg", "-j", "event-stream"]
|
||||
|
||||
running: true
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
var event = JSON.parse(data);
|
||||
let workspaces = [];
|
||||
if (event.WorkspacesChanged) {
|
||||
root.workspaces = event.WorkspacesChanged.workspaces;
|
||||
root.workspaces = root.workspaces.sort((a, b) => a.id - b.id);
|
||||
root.activeWorkspaceIndex = root.workspaces.findIndex(w => w.is_focused);
|
||||
if (root.activeWorkspaceIndex < 0) {
|
||||
root.activeWorkspaceIndex = 0;
|
||||
}
|
||||
root.activeWorkspace = root.workspaces[root.activeWorkspaceIndex].name;
|
||||
}
|
||||
if (event.WindowsChanged) {
|
||||
root.windows = [...event.WindowsChanged.windows].sort((a, b) => a.id - b.id);
|
||||
}
|
||||
if (event.WindowOpenedOrChanged) {
|
||||
const window = event.WindowOpenedOrChanged.window;
|
||||
const index = root.windows.findIndex(w => w.id === window.id);
|
||||
// console.log("window opened or changed: ", index, ", win id: ", window.id);
|
||||
if (index >= 0) {
|
||||
// console.log("replace window, old: ", root.windows[index].id, ", new: ", window.id);
|
||||
root.windows[index] = window;
|
||||
} else {
|
||||
// console.log("push window, new: ", window.id);
|
||||
root.windows.push(window);
|
||||
}
|
||||
root.windows = [...root.windows.sort((a, b) => a.id - b.id)];
|
||||
}
|
||||
if (event.WindowClosed) {
|
||||
const index = root.windows.findIndex(w => w.id === event.WindowClosed.id);
|
||||
// console.log("window closed: ", index, ", win id: ", event.WindowClosed.id);
|
||||
if (index >= 0) {
|
||||
root.windows.splice(index, 1);
|
||||
}
|
||||
root.windows = [...root.windows.sort((a, b) => a.id - b.id)];
|
||||
}
|
||||
if (event.WorkspaceActivated) {
|
||||
root.activeWorkspaceIndex = root.workspaces.findIndex(w => w.id === event.WorkspaceActivated.id);
|
||||
if (root.activeWorkspaceIndex < 0) {
|
||||
root.activeWorkspaceIndex = 0;
|
||||
}
|
||||
root.activeWorkspace = root.workspaces[root.activeWorkspaceIndex].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// component Workspace: QtObject {
|
||||
// required property int id
|
||||
// property int idx
|
||||
// property string name: "VOID"
|
||||
// required property string output
|
||||
// property bool is_active
|
||||
// property bool is_focused
|
||||
// property int active_window_id
|
||||
// }
|
||||
}
|
||||
|
||||
// {
|
||||
// "workspaces": [
|
||||
// {
|
||||
// "id": 5,
|
||||
// "idx": 4,
|
||||
// "name": "GAME",
|
||||
// "output": "DP-3",
|
||||
// "is_active": false,
|
||||
// "is_focused": false,
|
||||
// "active_window_id": null
|
||||
// },
|
||||
// ]
|
||||
// }
|
|
@ -0,0 +1,21 @@
|
|||
//@ pragma Env QS_NO_RELOAD_POPUP=1
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
|
||||
import "modules"
|
||||
import "modules/drawers"
|
||||
import "services"
|
||||
|
||||
// import "modules/background"
|
||||
|
||||
ShellRoot {
|
||||
id: shellroot
|
||||
|
||||
Component.onCompleted: [Launcher.init()]
|
||||
|
||||
Drawers {}
|
||||
// Background {}Popup
|
||||
//
|
||||
|
||||
}
|
|
@ -33,73 +33,176 @@ in {
|
|||
enable = true;
|
||||
# sample config from https://github.com/NotAShelf/watt#sample-configuration
|
||||
settings = {
|
||||
charger = {
|
||||
# CPU governor to use
|
||||
governor = "performance";
|
||||
# Turbo boost setting: "always", "auto", or "never"
|
||||
turbo = "auto";
|
||||
|
||||
# Enable or disable automatic turbo management (when turbo = "auto")
|
||||
enable_auto_turbo = true;
|
||||
# Custom thresholds for auto turbo management
|
||||
turbo_auto_settings = {
|
||||
load_threshold_high = 70.0;
|
||||
load_threshold_low = 30.0;
|
||||
temp_threshold_high = 75.0;
|
||||
initial_turbo_state = false; # whether turbo should be initially enabled (false = disabled)
|
||||
};
|
||||
# Energy Performance Preference
|
||||
epp = "performance";
|
||||
# Energy Performance Bias (0-15 scale or named value)
|
||||
epb = "balance_performance";
|
||||
# Platform profile (if supported)
|
||||
platform_profile = "performance";
|
||||
# Min/max frequency in MHz (optional)
|
||||
min_freq_mhz = 800;
|
||||
max_freq_mhz = 3500;
|
||||
# Optional: Profile-specific battery charge thresholds (overrides global setting)
|
||||
# battery_charge_thresholds = [40, 80] # Start at 40%, stop at 80%
|
||||
};
|
||||
|
||||
battery = {
|
||||
governor = "powersave";
|
||||
turbo = "auto";
|
||||
|
||||
# More conservative auto turbo settings on battery
|
||||
enable_auto_turbo = true;
|
||||
turbo_auto_settings = {
|
||||
load_threshold_high = 80.0;
|
||||
load_threshold_low = 40.0;
|
||||
temp_threshold_high = 70.0;
|
||||
# start with turbo disabled on battery for power savings
|
||||
initial_turbo_state = false;
|
||||
};
|
||||
epp = "power";
|
||||
epb = "balance_power";
|
||||
platform_profile = "low-power";
|
||||
|
||||
# Global battery charging thresholds (applied to both profiles unless overridden)
|
||||
# Start charging at 40%, stop at 80% - extends battery lifespan
|
||||
# take precedence over this global setting
|
||||
battery_charge_thresholds = [40 90];
|
||||
min_freq_mhz = 800;
|
||||
max_freq_mhz = 2500;
|
||||
};
|
||||
|
||||
daemon = {
|
||||
# Base polling interval in seconds
|
||||
poll_interval_sec = 5;
|
||||
# Enable adaptive polling that changes with system state
|
||||
adaptive_interval = true;
|
||||
# Minimum polling interval for adaptive polling (seconds)
|
||||
min_poll_interval_sec = 1;
|
||||
# Maximum polling interval for adaptive polling (seconds)
|
||||
max_poll_interval_sec = 30;
|
||||
# Double the polling interval when on battery to save power
|
||||
throttle_on_battery = true;
|
||||
# Logging level: Error, Warning, Info, Debug
|
||||
log_level = "Info";
|
||||
};
|
||||
rule = [
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "power";
|
||||
frequency-mhz-maximum = 2000;
|
||||
governor = "powersave";
|
||||
turbo = false;
|
||||
};
|
||||
"if" = {
|
||||
is-more-than = 85;
|
||||
value = "$cpu-temperature";
|
||||
};
|
||||
priority = 100;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "power";
|
||||
frequency-mhz-maximum = 800;
|
||||
governor = "powersave";
|
||||
turbo = false;
|
||||
};
|
||||
"if" = {
|
||||
all = [
|
||||
"?discharging"
|
||||
{
|
||||
is-less-than = 0.3;
|
||||
value = "%power-supply-charge";
|
||||
}
|
||||
];
|
||||
};
|
||||
power = {platform-profile = "low-power";};
|
||||
priority = 90;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "performance";
|
||||
governor = "performance";
|
||||
turbo = true;
|
||||
};
|
||||
"if" = {
|
||||
all = [
|
||||
{
|
||||
is-more-than = 0.8;
|
||||
value = "%cpu-usage";
|
||||
}
|
||||
{
|
||||
is-less-than = 30;
|
||||
value = "$cpu-idle-seconds";
|
||||
}
|
||||
{
|
||||
is-less-than = 75;
|
||||
value = "$cpu-temperature";
|
||||
}
|
||||
];
|
||||
};
|
||||
priority = 80;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-bias = "balance_performance";
|
||||
energy-performance-preference = "performance";
|
||||
governor = "performance";
|
||||
turbo = true;
|
||||
};
|
||||
"if" = {
|
||||
all = [
|
||||
{not = "?discharging";}
|
||||
{
|
||||
is-more-than = 0.1;
|
||||
value = "%cpu-usage";
|
||||
}
|
||||
{
|
||||
is-less-than = 80;
|
||||
value = "$cpu-temperature";
|
||||
}
|
||||
];
|
||||
};
|
||||
priority = 70;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "balance_performance";
|
||||
governor = "schedutil";
|
||||
};
|
||||
"if" = {
|
||||
all = [
|
||||
{
|
||||
is-more-than = 0.4;
|
||||
value = "%cpu-usage";
|
||||
}
|
||||
{
|
||||
is-less-than = 0.8;
|
||||
value = "%cpu-usage";
|
||||
}
|
||||
];
|
||||
};
|
||||
priority = 60;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "power";
|
||||
governor = "powersave";
|
||||
turbo = false;
|
||||
};
|
||||
"if" = {
|
||||
all = [
|
||||
{
|
||||
is-less-than = 0.2;
|
||||
value = "%cpu-usage";
|
||||
}
|
||||
{
|
||||
is-more-than = 60;
|
||||
value = "$cpu-idle-seconds";
|
||||
}
|
||||
];
|
||||
};
|
||||
priority = 50;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "power";
|
||||
frequency-mhz-maximum = 1600;
|
||||
governor = "powersave";
|
||||
turbo = false;
|
||||
};
|
||||
"if" = {
|
||||
is-more-than = 300;
|
||||
value = "$cpu-idle-seconds";
|
||||
};
|
||||
priority = 40;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "power";
|
||||
frequency-mhz-maximum = 2000;
|
||||
governor = "powersave";
|
||||
turbo = false;
|
||||
};
|
||||
"if" = {
|
||||
all = [
|
||||
"?discharging"
|
||||
{
|
||||
is-less-than = 0.5;
|
||||
value = "%power-supply-charge";
|
||||
}
|
||||
];
|
||||
};
|
||||
power = {platform-profile = "low-power";};
|
||||
priority = 30;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-bias = "balance_power";
|
||||
energy-performance-preference = "power";
|
||||
frequency-mhz-maximum = 1800;
|
||||
frequency-mhz-minimum = 200;
|
||||
governor = "powersave";
|
||||
turbo = false;
|
||||
};
|
||||
"if" = "?discharging";
|
||||
priority = 20;
|
||||
}
|
||||
{
|
||||
cpu = {
|
||||
energy-performance-preference = "balance_performance";
|
||||
governor = "schedutil";
|
||||
};
|
||||
priority = 0;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
services = {
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
in {
|
||||
system = {
|
||||
# faster rebuilds
|
||||
switch = {
|
||||
enable = false;
|
||||
enableNg = true;
|
||||
};
|
||||
# our state version
|
||||
# switch = {
|
||||
# enable = false;
|
||||
# };
|
||||
|
||||
# My state version.
|
||||
stateVersion = "23.11";
|
||||
};
|
||||
environment.etc."machine-id".text = "${machine-id}\n";
|
||||
|
|
|
@ -148,10 +148,12 @@ in {
|
|||
# Substituters to pull from.
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://cache.privatevoid.net"
|
||||
];
|
||||
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"cache.privatevoid.net:SErQ8bvNWANeAvtsOESUwVYr2VJynfuc9JRwlzTTkVg="
|
||||
];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
config,
|
||||
inputs,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
|
@ -9,6 +10,27 @@
|
|||
|
||||
inherit (config.modules.system) isGraphical;
|
||||
cfg = config.modules.desktops.niri;
|
||||
|
||||
latestNightly = (inputs.rust-overlay.lib.mkRustBin {} pkgs).nightly.latest.default;
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
rustc = latestNightly;
|
||||
cargo = latestNightly;
|
||||
stdenv = pkgs.clangStdenv;
|
||||
};
|
||||
|
||||
new-swww = (pkgs.swww.override {inherit rustPlatform;}).overrideAttrs (prev: {
|
||||
src = pkgs.fetchFromGitHub {
|
||||
inherit (prev.src) owner repo;
|
||||
rev = "398a4048e389341dfd55285c53518a8ea3930ec4";
|
||||
hash = "sha256-ZAC5TbkshztW2IeDorhaxUmVCHf2tJCSGIGHSNl91Ns";
|
||||
};
|
||||
doInstallCheck = false;
|
||||
|
||||
cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
|
||||
inherit (new-swww) src;
|
||||
hash = "sha256-YH2gcy/8EtUmTHzwt38bBOFX3saN1wHIGQ5/eWqvSeM=";
|
||||
};
|
||||
});
|
||||
in {
|
||||
options.modules.desktops.niri.enable = mkEnableOption "Niri, a scolling tiling wayland compositor";
|
||||
|
||||
|
@ -28,6 +50,7 @@ in {
|
|||
|
||||
environment.systemPackages = builtins.attrValues {
|
||||
inherit (pkgs) xwayland-satellite avizo;
|
||||
inherit new-swww;
|
||||
};
|
||||
|
||||
xdg.portal = {
|
||||
|
@ -35,11 +58,15 @@ in {
|
|||
xdgOpenUsePortal = true;
|
||||
extraPortals = [
|
||||
pkgs.xdg-desktop-portal-gtk
|
||||
pkgs.xdg-desktop-portal-gnome
|
||||
];
|
||||
config = {
|
||||
common.default = ["*"];
|
||||
hyprland.default = ["gtk"];
|
||||
};
|
||||
configPackages = [
|
||||
pkgs.niri
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
{pkgs}: let
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
}: let
|
||||
inherit (pkgs) lib;
|
||||
helix = pkgs.callPackage ./helix {};
|
||||
helix = let
|
||||
latestNightly = (inputs.rust-overlay.lib.mkRustBin {} pkgs).nightly.latest.default;
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
rustc = latestNightly;
|
||||
cargo = latestNightly;
|
||||
stdenv = pkgs.clangStdenv;
|
||||
};
|
||||
in
|
||||
pkgs.callPackage ./helix {inherit rustPlatform;};
|
||||
kakoune = pkgs.callPackage ./kakoune.nix {};
|
||||
fish = pkgs.callPackage ./fish {inherit lib;};
|
||||
in {
|
||||
|
|
|
@ -41,20 +41,28 @@
|
|||
}: let
|
||||
inherit (lib.meta) getExe;
|
||||
|
||||
custom-helix = helix.overrideAttrs (_: rec {
|
||||
version = "25.06.1";
|
||||
src = fetchzip {
|
||||
url = "https://github.com/bloxx12/helix/releases/download/${version}/helix-${version}-source.tar.xz";
|
||||
hash = "sha256-941moaBUF+aGsbFapK1cp5+NFdecSfRCTdnVUtkDQps=";
|
||||
stripRoot = false;
|
||||
};
|
||||
custom-helix =
|
||||
(helix.override {inherit rustPlatform;}).overrideAttrs
|
||||
(_: let
|
||||
inherit (custom-helix) version;
|
||||
in {
|
||||
version = "25.06.1";
|
||||
src = fetchzip {
|
||||
url = "https://github.com/bloxx12/helix/releases/download/${version}/helix-${version}-source.tar.xz";
|
||||
hash = "sha256-941moaBUF+aGsbFapK1cp5+NFdecSfRCTdnVUtkDQps=";
|
||||
stripRoot = false;
|
||||
};
|
||||
|
||||
doInstallCheck = false;
|
||||
cargoDeps = rustPlatform.fetchCargoVendor {
|
||||
inherit (custom-helix) src;
|
||||
hash = "sha256-w07ZV1tR3lzYz4N+hI9alvFp0AHCcsItPRhVt9Sluo8=";
|
||||
};
|
||||
});
|
||||
cargoBuildFeatures = ["unicode-lines"];
|
||||
RUSTFLAGS = "-Ctarget-cpu=native -Clto=fat";
|
||||
|
||||
doInstallCheck = false;
|
||||
|
||||
cargoDeps = rustPlatform.fetchCargoVendor {
|
||||
inherit (custom-helix) src;
|
||||
hash = "sha256-w07ZV1tR3lzYz4N+hI9alvFp0AHCcsItPRhVt9Sluo8=";
|
||||
};
|
||||
});
|
||||
|
||||
toml = formats.toml {};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue