diff --git a/ags/config/bar/Bar.js b/ags/config/bar/Bar.js new file mode 100644 index 0000000..3526bdf --- /dev/null +++ b/ags/config/bar/Bar.js @@ -0,0 +1,46 @@ +import { GTK_ALIGN_CENTER, GTK_ALIGN_END, GTK_ALIGN_START } from "../constants.js" +import { Clock } from "./Clock.js" +import { SysTray } from "./Systray.js" + +function BarStart() { + return Widget.Box({ + halign: GTK_ALIGN_START, + children: [ + Widget.Label({ label: "Start" }), + Widget.Button({ label: "Button", onClicked: () => App.ToggleWindow("media2") }), + ], + }) +} +function BarCenter() { + return Widget.Box({ + halign: GTK_ALIGN_CENTER, + children: [ + Clock(), + ], + }) +} +function BarEnd() { + return Widget.Box({ + halign: GTK_ALIGN_END, + children: [ + SysTray(), + ], + }) +} + +export function Bar(monitor = 0) { + return Widget.Window({ + monitor, + exclusivity: "exclusive", + className: "bar", + margins: [5, 5, 0, 5], + name: `bar${monitor}`, + anchor: ["left", "top", "right"], + child: Widget.CenterBox({ + vertical: false, + startWidget: BarStart(), + centerWidget: BarCenter(), + endWidget: BarEnd(), + }) + }) +} diff --git a/ags/config/bar/Clock.js b/ags/config/bar/Clock.js new file mode 100644 index 0000000..3660cc1 --- /dev/null +++ b/ags/config/bar/Clock.js @@ -0,0 +1,24 @@ +const time = Variable("", { + poll: [1000, 'date "+%H:%M"'], +}) + +const date = Variable("", { + poll: [1000, 'date "+%Y-%m-%d"'], +}) + +export function Clock() { + return Widget.Box({ + className: "clock", + vertical: true, + children: [ + Widget.Label({ + className: "time", + label: time.bind(), + }), + Widget.Label({ + className: "date", + label: date.bind(), + }), + ], + }) +} diff --git a/ags/config/bar/Systray.js b/ags/config/bar/Systray.js new file mode 100644 index 0000000..6d30e93 --- /dev/null +++ b/ags/config/bar/Systray.js @@ -0,0 +1,16 @@ +const systemtray = await Service.import("systemtray") + +export function SysTray() { + const items = systemtray.bind("items") + .as(items => items.map(item => Widget.Button({ + child: Widget.Icon({ icon: item.bind("icon") }), + on_primary_click: (_, event) => item.activate(event), + on_secondary_click: (_, event) => item.openMenu(event), + tooltip_markup: item.bind("tooltip_markup"), + }))) + + return Widget.Box({ + className: "systray", + children: items, + }) +} diff --git a/ags/config/colors.css b/ags/config/colors.css new file mode 100644 index 0000000..3e3f215 --- /dev/null +++ b/ags/config/colors.css @@ -0,0 +1,35 @@ +@define-color ctp-rosewater #f5e0dc; +@define-color ctp-flamingo #f2cdcd; +@define-color ctp-pink #f5c2e7; +@define-color ctp-mauve #cba6f7; +@define-color ctp-red #f38ba8; +@define-color ctp-maroon #eba0ac; +@define-color ctp-peach #fab387; +@define-color ctp-yellow #f9e2af; +@define-color ctp-green #a6e3a1; +@define-color ctp-teal #94e2d5; +@define-color ctp-sky #89dceb; +@define-color ctp-sapphire #74c7ec; +@define-color ctp-blue #89b4fa; +@define-color ctp-lavender #b4befe; +@define-color ctp-text #cdd6f4; +@define-color ctp-subtext1 #bac2de; +@define-color ctp-subtext0 #a6adc8; +@define-color ctp-overlay2 #9399b2; +@define-color ctp-overlay1 #7f849c; +@define-color ctp-overlay0 #6c7086; +@define-color ctp-surface2 #585b70; +@define-color ctp-surface1 #45475a; +@define-color ctp-surface0 #313244; +@define-color ctp-base #1e1e2e; +@define-color ctp-mantle #181825; +@define-color ctp-crust #11111b; + +button { + background: @ctp-surface0; + border: none; +} + +button:active, button:hover, button:focus { + background: @ctp-surface1; +} diff --git a/ags/config/config.js b/ags/config/config.js new file mode 100644 index 0000000..5999848 --- /dev/null +++ b/ags/config/config.js @@ -0,0 +1,14 @@ +import { Media } from "./media/Media.js"; +import { Bar } from "./bar/Bar.js"; +import { Notifications } from "./notifications/Notifications.js"; + + +App.config({ + style: "./style.css", + windows: [ + Bar(2), + Media(2), + Notifications(2), + ] +}) + diff --git a/ags/config/constants.js b/ags/config/constants.js new file mode 100644 index 0000000..3824349 --- /dev/null +++ b/ags/config/constants.js @@ -0,0 +1,5 @@ +export const GTK_ALIGN_FILL = 0; +export const GTK_ALIGN_START = 1; +export const GTK_ALIGN_END = 2; +export const GTK_ALIGN_CENTER = 3; +export const GTK_ALIGN_BASELINE = 4; diff --git a/ags/config/media/Media.js b/ags/config/media/Media.js new file mode 100644 index 0000000..1b5e445 --- /dev/null +++ b/ags/config/media/Media.js @@ -0,0 +1,50 @@ +const mpris = await Service.import("mpris") +const players = mpris.bind("players") + +const FALLBACK_ICON = "audio-x-generic-symbolic" +const PLAY_ICON = "media-playback-start-symbolic" +const PAUSE_ICON = "media-playback-pause-symbolic" +const PREV_ICON = "media-skip-backward-symbolic" +const NEXT_ICON = "media-skip-forward-symbolic" + +/** @param {number} length */ +function lengthStr(length) { + const min = Math.floor(length / 60) + const sec = Math.floor(length % 60) + const sec0 = sec < 10 ? "0" : "" + return `${min}:${sec0}${sec}` +} + +/** @param {import('types/service/mpris').MprisPlayer} player */ +function Player(player) { + return Widget.Label({ label: `${player.name}: ${player.cover_path}` }) + // return Widget.Overlay({ + // child: Widget.Box({ + // class_name: "img", + // vpack: "start", + // css: player.bind("cover_path").transform(p => `background-image: url('${p}');`), + // }), + // overlays: [ + // Widget.Label({ label: player.name }), + // ], + // }) +} + +function MediaContent() { + return Widget.Box({ + children: players.as(p => p.map(Player)), + }) +} + +export function Media(monitor = 0) { + return Widget.Window({ + monitor, + visible: false, + exclusivity: "normal", + className: "media", + margins: [10, 10, 0, 10], + name: `media${monitor}`, + anchor: ["left", "top"], + child: MediaContent(), + }) +} diff --git a/ags/config/notifications/Notifications.js b/ags/config/notifications/Notifications.js new file mode 100644 index 0000000..7c5366b --- /dev/null +++ b/ags/config/notifications/Notifications.js @@ -0,0 +1,129 @@ +const notifications = await Service.import("notifications") + +/** @param {import('resource:///com/github/Aylur/ags/service/notifications.js').Notification} n */ +function NotificationIcon({ app_entry, app_icon, image }) { + if (image) { + return Widget.Box({ + css: `background-image: url("${image}");` + + "background-size: contain;" + + "background-repeat: no-repeat;" + + "background-position: center;", + }) + } + + let icon = "dialog-information-symbolic" + if (Utils.lookUpIcon(app_icon)) + icon = app_icon + + if (app_entry && Utils.lookUpIcon(app_entry)) + icon = app_entry + + return Widget.Box({ + child: Widget.Icon(icon), + }) +} + +/** @param {import('resource:///com/github/Aylur/ags/service/notifications.js').Notification} n */ +function Notification(n) { + const icon = Widget.Box({ + vpack: "start", + class_name: "icon", + child: NotificationIcon(n), + }) + + const title = Widget.Label({ + class_name: "title", + xalign: 0, + justification: "left", + hexpand: true, + max_width_chars: 24, + label: n.summary, + use_markup: true, + }) + + const body = Widget.Label({ + class_name: "body", + hexpand: true, + use_markup: true, + xalign: 0, + justification: "left", + label: n.body, + wrap: true, + }) + + const content = Widget.Box({ + className: "content", + children: [ + icon, + Widget.Box({ + vertical: true, + children: [ + title, + body, + ] + }), + ], + }) + + const actions = Widget.Box({ + className: "actions", + children: n.actions.map(({ id, label }) => Widget.Button({ + className: "action", + on_clicked: () => { + n.invoke(id) + n.dismiss() + }, + hexpand: true, + child: Widget.Label(label), + })), + }) + + + return Widget.EventBox({ + attribute: { id: n.id }, + onPrimaryClick: n.dismiss, + child: Widget.Box({ + classNames: ["notification", n.urgency], + vertical: true, + children: [ + content, + actions, + ], + }), + }) +} + +function NotificationList() { + const list = Widget.Box({ + css: "min-width: 2px; min-height: 2px;", + vertical: true, + spacing: 10, + children: notifications.popups.map(Notification), + }) + + function onNotified(_, /** @type {number} */ id) { + const n = notifications.getNotification(id) + if (n) + list.children = [Notification(n), ...list.children] + } + + function onDismissed(_, /** @type {number} */ id) { + list.children.find(n => n.attribute.id === id)?.destroy() + } + + list.hook(notifications, onNotified, "notified") + .hook(notifications, onDismissed, "dismissed") + return list +} + +export function Notifications(monitor = 0) { + return Widget.Window({ + monitor, + exclusivity: "normal", + className: "notifications", + margins: [10, 10, 10, 10], + name: `notifications${monitor}`, + anchor: ["left", "top"], + child: NotificationList(), + }) +} diff --git a/ags/config/notifications/style.css b/ags/config/notifications/style.css new file mode 100644 index 0000000..aa5b3a9 --- /dev/null +++ b/ags/config/notifications/style.css @@ -0,0 +1,59 @@ +.notification { + min-width: 300px; + padding: 10px; + background-color: alpha(@ctp-base, 0.7); + border-radius: 5px; + + border: 1px solid; + border-left: 5px solid; + border-color: @ctp-overlay1; +} + +.notification.low { + border-color: @ctp-base; +} + +.notification.critical { + border-color: @ctp-red; +} + +.notification .icon { + min-width: 68px; + min-height: 68px; + margin-right: 1em; +} + +.notification .icon image { + font-size: 58px; + /* to center the icon */ + margin: 5px; + color: @ctp-text; +} + +.notification .icon box { + min-width: 68px; + min-height: 68px; + border-radius: 7px; +} + +.notification .actions .action { + margin: 0 .4em; + margin-top: .8em; +} + +.notification .actions .action:first-child { + margin-left: 0; +} + +.notification .actions .action:last-child { + margin-right: 0; +} + +.notification .title { + color: @ctp-text; + font-size: 1.4em; +} + +.notification .body { + color: @ctp-subtext0; +} diff --git a/ags/config/style.css b/ags/config/style.css new file mode 100644 index 0000000..8671537 --- /dev/null +++ b/ags/config/style.css @@ -0,0 +1,29 @@ +@import url("colors.css"); +@import url("notifications/style.css"); + + +.bar > box { + padding: 10px; + border-radius: 5px; + + background-color: alpha(@ctp-base, 0.95); + color: @ctp-text; +} + + +.clock .time { + font-weight: bold; + font-size: 1em; +} + +.clock .date { + font-size: 0.8em; +} + +.media > box { + padding: 10px; + border-radius: 5px; + + background-color: alpha(@ctp-base, 0.95); + color: @ctp-text; +} diff --git a/ags/config/tsconfig.json b/ags/config/tsconfig.json new file mode 100644 index 0000000..f03f2d1 --- /dev/null +++ b/ags/config/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "lib": [ + "ES2022" + ], + "allowJs": true, + "checkJs": true, + "strict": true, + "noImplicitAny": false, + "baseUrl": ".", + "typeRoots": [ + "./types" + ], + "skipLibCheck": true + } +} \ No newline at end of file diff --git a/ags/config/types b/ags/config/types new file mode 120000 index 0000000..b7f3cac --- /dev/null +++ b/ags/config/types @@ -0,0 +1 @@ +/home/kalle/.local/share/com.github.Aylur.ags/types \ No newline at end of file diff --git a/ags/default.nix b/ags/default.nix new file mode 100644 index 0000000..fff16ab --- /dev/null +++ b/ags/default.nix @@ -0,0 +1,15 @@ +{ inputs +, lib +, config +, pkgs +, ... +}: + +{ + imports = [ inputs.ags.homeManagerModules.default ]; + programs.ags = { + enable = true; + configDir = ./config; + }; +} + diff --git a/eww/default.nix b/eww/default.nix index bc5df7d..f1e435c 100644 --- a/eww/default.nix +++ b/eww/default.nix @@ -8,7 +8,6 @@ { programs.eww = { enable = true; - package = pkgs.eww-wayland; configDir = ./config; }; diff --git a/flake.lock b/flake.lock index c5f60ad..77d10f9 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,59 @@ { "nodes": { + "ags": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1721306136, + "narHash": "sha256-VKPsIGf3/a+RONBipx4lEE4LXG2sdMNkWQu22LNQItg=", + "owner": "Aylur", + "repo": "ags", + "rev": "344ea72cd3b8d4911f362fec34bce7d8fb37028c", + "type": "github" + }, + "original": { + "owner": "Aylur", + "repo": "ags", + "type": "github" + } + }, + "aquamarine": { + "inputs": { + "hyprutils": [ + "hyprland", + "hyprutils" + ], + "hyprwayland-scanner": [ + "hyprland", + "hyprwayland-scanner" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1721571743, + "narHash": "sha256-hat7wggtDISBJD8kTo5MTrT+IsY/Ha2MwgjmqqijoCA=", + "owner": "hyprwm", + "repo": "aquamarine", + "rev": "601f6cf95cbe4fef02dc7faf34bba58566c914e9", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "aquamarine", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -7,11 +61,11 @@ ] }, "locked": { - "lastModified": 1708988456, - "narHash": "sha256-RCz7Xe64tN2zgWk+MVHkzg224znwqknJ1RnB7rVqUWw=", + "lastModified": 1721534365, + "narHash": "sha256-XpZOkaSJKdOsz1wU6JfO59Rx2fqtcarQ0y6ndIOKNpI=", "owner": "nix-community", "repo": "home-manager", - "rev": "1d085ea4444d26aa52297758b333b449b2aa6fca", + "rev": "635563f245309ef5320f80c7ebcb89b2398d2949", "type": "github" }, "original": { @@ -21,23 +75,79 @@ "type": "github" } }, - "hyprland-protocols": { + "hyprcursor": { "inputs": { + "hyprlang": [ + "hyprland", + "hyprlang" + ], "nixpkgs": [ - "xdg-desktop-portal-hyprland", + "hyprland", "nixpkgs" ], "systems": [ - "xdg-desktop-portal-hyprland", + "hyprland", "systems" ] }, "locked": { - "lastModified": 1691753796, - "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", + "lastModified": 1721330371, + "narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=", + "owner": "hyprwm", + "repo": "hyprcursor", + "rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprcursor", + "type": "github" + } + }, + "hyprland": { + "inputs": { + "aquamarine": "aquamarine", + "hyprcursor": "hyprcursor", + "hyprlang": "hyprlang", + "hyprutils": "hyprutils", + "hyprwayland-scanner": "hyprwayland-scanner", + "nixpkgs": "nixpkgs", + "systems": "systems_2", + "xdph": "xdph" + }, + "locked": { + "lastModified": 1721668777, + "narHash": "sha256-QNKSZDkZ5+0a+g0wZoZfcWuH1Fy3ZvIeKg0grNdwnHc=", + "owner": "hyprwm", + "repo": "hyprland", + "rev": "4c3b03516209a49244a8f044143c1162752b8a7a", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland", + "type": "github" + } + }, + "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "hyprland", + "xdph", + "nixpkgs" + ], + "systems": [ + "hyprland", + "xdph", + "systems" + ] + }, + "locked": { + "lastModified": 1718746314, + "narHash": "sha256-HUklK5u86w2Yh9dOkk4FdsL8eehcOZ95jPhLixGDRQY=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "rev": "1b61f0093afff20ab44d88ad707aed8bf2215290", "type": "github" }, "original": { @@ -48,18 +158,25 @@ }, "hyprlang": { "inputs": { + "hyprutils": [ + "hyprland", + "hyprutils" + ], "nixpkgs": [ - "xdg-desktop-portal-hyprland", + "hyprland", "nixpkgs" ], - "systems": "systems" + "systems": [ + "hyprland", + "systems" + ] }, "locked": { - "lastModified": 1708681732, - "narHash": "sha256-ULZZLZ9C33G13IaXLuAc4oTzHUvnATI8Fj2u6gzMfT0=", + "lastModified": 1721324361, + "narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "f4466367ef0a92a6425d482050dc2b8840c0e644", + "rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086", "type": "github" }, "original": { @@ -68,13 +185,79 @@ "type": "github" } }, + "hyprutils": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1721324102, + "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "962582a090bc233c4de9d9897f46794280288989", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprwayland-scanner": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1721324119, + "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1709150264, - "narHash": "sha256-HofykKuisObPUfj0E9CJVfaMhawXkYx3G8UIFR/XQ38=", + "lastModified": 1721379653, + "narHash": "sha256-8MUgifkJ7lkZs3u99UDZMB4kbOxvMEXQZ31FO3SopZ0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1d9c2c9b3e71b9ee663d11c5d298727dace8d374", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1721379653, + "narHash": "sha256-8MUgifkJ7lkZs3u99UDZMB4kbOxvMEXQZ31FO3SopZ0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9099616b93301d5cf84274b184a3a5ec69e94e08", + "rev": "1d9c2c9b3e71b9ee663d11c5d298727dace8d374", "type": "github" }, "original": { @@ -103,11 +286,11 @@ "plugin-rainbow-delimiters-nvim": { "flake": false, "locked": { - "lastModified": 1709163331, - "narHash": "sha256-QETHqUrqY9acAUxRgROGI3Qopy+P6tW36uVqHCemj10=", + "lastModified": 1720388982, + "narHash": "sha256-6+MSV9pkudhf/xVdofU6syYCzViHltvDWkYvbeuEfLs=", "owner": "HiPhish", "repo": "rainbow-delimiters.nvim", - "rev": "4902de74335ba0c4816cb67c5d5052c0c5fc7e56", + "rev": "b29da4a6061a88270e875b38367d82c04c856128", "type": "gitlab" }, "original": { @@ -134,12 +317,13 @@ }, "root": { "inputs": { + "ags": "ags", "home-manager": "home-manager", - "nixpkgs": "nixpkgs", + "hyprland": "hyprland", + "nixpkgs": "nixpkgs_2", "plugin-harpoon1": "plugin-harpoon1", "plugin-rainbow-delimiters-nvim": "plugin-rainbow-delimiters-nvim", - "plugin-undotree-nvim": "plugin-undotree-nvim", - "xdg-desktop-portal-hyprland": "xdg-desktop-portal-hyprland" + "plugin-undotree-nvim": "plugin-undotree-nvim" } }, "systems": { @@ -172,21 +356,28 @@ "type": "github" } }, - "xdg-desktop-portal-hyprland": { + "xdph": { "inputs": { "hyprland-protocols": "hyprland-protocols", - "hyprlang": "hyprlang", + "hyprlang": [ + "hyprland", + "hyprlang" + ], "nixpkgs": [ + "hyprland", "nixpkgs" ], - "systems": "systems_2" + "systems": [ + "hyprland", + "systems" + ] }, "locked": { - "lastModified": 1708954916, - "narHash": "sha256-GUbIMXUrcb6Pxmz9lQ3j6XMFLsQaSwTvViNKYNSMdd0=", + "lastModified": 1721648131, + "narHash": "sha256-cyyxu/oj4QEFp3CVx2WeXa9T4OAUyynuBJHGkBZSxJI=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "15fd76cb6ebb0e3c3b2c3a3daf452e7b781c6e8a", + "rev": "663be9cad424b170b28b9fa8a61042d721007f3b", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index fffdf6d..37c3e5b 100644 --- a/flake.nix +++ b/flake.nix @@ -9,6 +9,10 @@ home-manager.url = "github:nix-community/home-manager/master"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; + # AGS + ags.url = "github:Aylur/ags"; + ags.inputs.nixpkgs.follows = "nixpkgs"; + # Neovim plugins not in nixpkgs plugin-rainbow-delimiters-nvim.url = "gitlab:HiPhish/rainbow-delimiters.nvim"; plugin-rainbow-delimiters-nvim.flake = false; @@ -19,10 +23,7 @@ plugin-harpoon1.url = "github:ThePrimeagen/harpoon"; plugin-harpoon1.flake = false; - # Track hyprland xdg desktop portal master until screenshots get released again - xdg-desktop-portal-hyprland.url = "github:hyprwm/xdg-desktop-portal-hyprland"; - xdg-desktop-portal-hyprland.inputs.nixpkgs.follows = "nixpkgs"; - + hyprland.url = "github:hyprwm/hyprland"; }; outputs = diff --git a/home-manager/kalle-pc/kalle.nix b/home-manager/kalle-pc/kalle.nix index 37df292..e609b26 100644 --- a/home-manager/kalle-pc/kalle.nix +++ b/home-manager/kalle-pc/kalle.nix @@ -19,6 +19,7 @@ ../../eww ../../hyprland ../../hyprland/hyprpaper.nix + ../../ags ]; hyprland = @@ -28,7 +29,6 @@ mod = mod; primaryMonitor = "DP-2"; - monitors = [ { name = "DP-2"; @@ -72,27 +72,11 @@ sensitivity = 0.1; - keyboard = { - layout = "us"; - variant = ""; - options = ""; - }; - - inner_gaps = 5; - outer_gaps = 10; - - border = { - size = 1; - active = "rgba(33ccffee) rgba(00ff99ee) 45deg"; - inactive = "rgba(595959aa)"; - }; - layout = "dwindle"; - rounding = 5; - layerRules = { "gtk-layer-shell" = [ "blur" "ignorezero" ]; + "notifications2" = [ "noanim" "blur" "ignorezero"]; }; windowRules = { @@ -257,22 +241,46 @@ pavucontrol difftastic sops - obsidian + (obsidian.override { + electron = pkgs.electron_29-bin; + }) + unzip + vlc cachix ]; programs.home-manager.enable = true; - + gtk = { + enable = true; theme = { - package = pkgs.libsForQt5.breeze-gtk; - name = "Breeze-Dark"; + name = "Adwaita-dark"; + package = pkgs.gnome-themes-extra; }; iconTheme = { - package = pkgs.libsForQt5.breeze-icons; name = "breeze-dark"; + package = pkgs.kdePackages.breeze-icons; + }; + + cursorTheme = { + name = "breeze_cursors"; + package = pkgs.libsForQt5.breeze-qt5; + }; + }; + + qt = { + enable = true; + style.name = "breeze-dark"; + }; + + dconf = { + enable = true; + settings = { + "org/gnome/desktop/interface" = { + color-scheme = "prefer-dark"; + }; }; }; @@ -286,7 +294,7 @@ # Replace some commands with better versions ssh = "kitty +kitten ssh"; - diff = "${pkgs.difftastic}/bin/difftastic"; + diff = "${pkgs.difftastic}/bin/difft"; }; initExtra = '' function open() { @@ -301,6 +309,7 @@ settings = { background_opacity = "0.8"; allow_remote_control = true; + enable_audio_bell = false; }; }; diff --git a/hyprland/default.nix b/hyprland/default.nix index 8a79d3e..c52a014 100644 --- a/hyprland/default.nix +++ b/hyprland/default.nix @@ -85,7 +85,7 @@ variant = mkOption { type = types.str; - default = "qwerty"; + default = ""; }; options = mkOption { @@ -94,101 +94,7 @@ }; }; - inner_gaps = mkOption { type = types.int; }; - - outer_gaps = mkOption { type = types.int; }; - - border = { - size = mkOption { type = types.int; }; - active = mkOption { type = types.str; }; - inactive = mkOption { type = types.str; }; - }; - - animations = { - enable = mkOption { - type = types.bool; - default = true; - }; - - beziers = mkOption { - type = types.listOf types.str; - default = [ - "myBezier, 0.05, 0.9, 0.1, 1.05" - ]; - }; - - windows = mkOption { - type = types.str; - default = "1, 3, myBezier"; - }; - - windowsOut = mkOption { - type = types.str; - default = "1, 3, default, popin 80%"; - }; - - border = mkOption { - type = types.str; - default = "1, 5, default"; - }; - - borderangle = mkOption { - type = types.str; - default = "1, 4, default"; - }; - - fade = mkOption { - type = types.str; - default = "1, 3, default"; - }; - - workspaces = mkOption { - type = types.str; - default = "1, 2, default"; - }; - }; - layout = mkOption { type = types.str; }; - rounding = mkOption { type = types.int; }; - - blur = { - enable = mkOption { - type = types.bool; - default = true; - }; - - size = mkOption { - type = types.int; - default = 3; - }; - - passes = mkOption { - type = types.int; - default = 1; - }; - }; - - shadow = { - enable = mkOption { - type = types.bool; - default = true; - }; - - range = mkOption { - type = types.int; - default = 4; - }; - - strength = mkOption { - type = types.int; - default = 3; - }; - - color = mkOption { - type = types.str; - default = "rgba(1a1a1aee)"; - }; - }; layerRules = mkOption { type = types.attrsOf (types.listOf types.str); @@ -205,16 +111,6 @@ default = { }; }; - generateWorkspaceBinds = mkOption { - type = types.bool; - default = true; - }; - - generateWindowManagementBinds = mkOption { - type = types.bool; - default = true; - }; - binds = mkOption { type = types.attrsOf types.str; default = { }; @@ -280,12 +176,12 @@ }; general = { - gaps_in = cfg.inner_gaps; - gaps_out = cfg.outer_gaps; + gaps_in = 5; + gaps_out = 10; - border_size = cfg.border.size; - "col.active_border" = cfg.border.active; - "col.inactive_border" = cfg.border.inactive; + border_size = 1; + "col.active_border" = "rgba(33ccffee) rgba(00ff99ee) 45deg"; + "col.inactive_border" = "rgba(595959aa)"; layout = cfg.layout; }; @@ -295,28 +191,19 @@ }; decoration = { - rounding = cfg.rounding; + rounding = 5; blur = { - enabled = if cfg.blur.enable then "yes" else "no"; - size = cfg.blur.size; - passes = cfg.blur.passes; + enabled = "yes"; + size = 3; + passes = 1; new_optimizations = "on"; }; - drop_shadow = if cfg.shadow.enable then "yes" else "no"; - shadow_range = cfg.shadow.range; - shadow_render_power = cfg.shadow.strength; - "col.shadow" = cfg.shadow.color; - }; - - dwindle = { - pseudotile = "yes"; - preserve_split = "yes"; - }; - - master = { - new_is_master = true; + drop_shadow = "yes"; + shadow_range = 4; + shadow_render_power = 3; + "col.shadow" = "rgba(1a1a1aee)"; }; gestures = { @@ -324,19 +211,21 @@ }; animations = { - enabled = if cfg.animations.enable then "yes" else "no"; + enabled = "yes"; # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more - bezier = cfg.animations.beziers; + bezier = [ + "myBezier, 0.05, 0.9, 0.1, 1.05" + ]; animation = [ - "windows, ${cfg.animations.windows}" - "windowsOut, ${cfg.animations.windowsOut}" - "border, ${cfg.animations.border}" - "borderangle, ${cfg.animations.borderangle}" - "fade, ${cfg.animations.fade}" - "workspaces, ${cfg.animations.workspaces}" + "windows, 1, 3, myBezier" + "windowsOut, 1, 3, default, popin 80%" + "border, 1, 5, default" + "borderangle, 1, 4, default" + "fade, 1, 3, default" + "workspaces, 1, 2, default" ]; }; @@ -352,7 +241,7 @@ let # Create one work space for each non primary monitor perMonitorWorkspaces = map - (m: "${m.name}, name:${m.name}") + (m: "name:${m.name}, monitor:${m.name}") (lib.filter (m: m.name != cfg.primaryMonitor) cfg.monitors @@ -368,32 +257,26 @@ let # Create binds to switch workspaces and move windows between them workspaceBinds = - if cfg.generateWorkspaceBinds then - lib.flatten - (map - (i: - let - k = if i == 10 then 0 else i; - in - [ - "${cfg.mod}, ${toString k}, workspace, ${toString i}" - "${cfg.mod} SHIFT, ${toString k}, movetoworkspace, ${toString i}" - ] - ) - (lib.range 1 10) + lib.flatten + (map + (i: + let + k = if i == 10 then 0 else i; + in + [ + "${cfg.mod}, ${toString k}, workspace, ${toString i}" + "${cfg.mod} SHIFT, ${toString k}, movetoworkspace, ${toString i}" + ] ) - else - [ ]; + (lib.range 1 10) + ); # Create binds to manage wiwdows - windowManagementBinds = - if cfg.generateWindowManagementBinds then [ - "${cfg.mod} SHIFT, Q, killactive" - "${cfg.mod}, F, togglefloating" - "${cfg.mod} SHIFT, F, fullscreen" - ] - else - [ ]; + windowManagementBinds = [ + "${cfg.mod} SHIFT, Q, killactive" + "${cfg.mod}, F, togglefloating" + "${cfg.mod} SHIFT, F, fullscreen" + ]; configBinds = lib.mapAttrsToList (k: v: "${k}, ${v}") cfg.binds; in @@ -401,13 +284,10 @@ bindm = let - windowManagementBinds = - if cfg.generateWindowManagementBinds then [ + windowManagementBinds = [ "${cfg.mod}, mouse:272, movewindow" "${cfg.mod}, mouse:273, resizewindow" - ] - else - [ ]; + ]; configBinds = lib.mapAttrsToList (k: v: "${k}, ${v}") cfg.mouseBinds; diff --git a/nixos/kalle-pc/configuration.nix b/nixos/kalle-pc/configuration.nix index 7315478..4642b63 100644 --- a/nixos/kalle-pc/configuration.nix +++ b/nixos/kalle-pc/configuration.nix @@ -17,6 +17,10 @@ experimental-features = "nix-command flakes"; # Deduplicate and optimize nix store auto-optimise-store = true; + # Allow me to use cachix + trusted-users = [ "root" "kalle" ]; + substituters = ["https://hyprland.cachix.org"]; + trusted-public-keys = ["hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="]; }; services.btrfs.autoScrub.enable = true; @@ -42,15 +46,10 @@ }; # Enable the X11 windowing system. + services.displayManager.sddm.enable = true; services.xserver = { enable = true; - - displayManager.sddm.enable = true; - - # Configure keymap in X11 xkb.layout = "us"; - # xkbVariant = "dvorak"; - # xkbOptions = "eurosign:e,caps:escape"; }; # Allow flashing ZSA keyboards @@ -58,7 +57,7 @@ programs.hyprland = { enable = true; - portalPackage = inputs.xdg-desktop-portal-hyprland.packages.x86_64-linux.xdg-desktop-portal-hyprland; + # package = inputs.hyprland.packages.x86_64-linux.hyprland; }; xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; @@ -138,6 +137,8 @@ }; }; + services.gvfs.enable = true; + # Enable the OpenSSH daemon. services.openssh.enable = true; diff --git a/nvim/default.nix b/nvim/default.nix index ea36a11..73f7818 100644 --- a/nvim/default.nix +++ b/nvim/default.nix @@ -19,16 +19,19 @@ vimdiffAlias = true; extraPackages = with pkgs; [ - nodejs_21 # Required for copilot-vim + nodejs_22 # Required for copilot-vim ripgrep # Required for telescope wl-clipboard # Required for clipboard sync # Language servers clang-tools lua-language-server - rnix-lsp nodePackages.typescript-language-server + typescript tailwindcss-language-server + gopls + vhdl-ls + nixd ]; plugins = with pkgs.vimPlugins; [ @@ -93,7 +96,6 @@ config = toLuaFile ./plugin/cmp.lua; } - { plugin = nvim-lspconfig; config = toLuaFile ./plugin/lsp.lua; diff --git a/nvim/plugin/lsp.lua b/nvim/plugin/lsp.lua index 980a7c6..13c2ae6 100644 --- a/nvim/plugin/lsp.lua +++ b/nvim/plugin/lsp.lua @@ -100,7 +100,7 @@ require('lspconfig').lua_ls.setup { } } -require('lspconfig').rnix.setup { +require('lspconfig').nixd.setup { on_attach = on_attach, capabilities = capabilities, } @@ -108,6 +108,11 @@ require('lspconfig').rnix.setup { require('lspconfig').tsserver.setup { on_attach = on_attach, capabilities = capabilities, + init_options = { + tsserver = { + fallbackPath = string.gsub(vim.fn.system("dirname `which tsserver`"), '^%s*(.-)%s*$', '%1') .. "/../lib/node_modules/typescript/lib", + }, + }, } require('lspconfig').tailwindcss.setup { @@ -120,6 +125,16 @@ require('lspconfig').clangd.setup { capabilities = capabilities, } +require('lspconfig').gopls.setup { + on_attach = on_attach, + capabilities = capabilities, +} + +require('lspconfig').vhdl_ls.setup { + on_attach = on_attach, + capabilities = capabilities, +} + require('rust-tools').setup({ server = { on_attach = on_attach,