diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b6959d0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.rumdl_cache
diff --git a/README.md b/README.md
index 0157b44..513f406 100644
--- a/README.md
+++ b/README.md
@@ -1,295 +1,72 @@
-# Quickshell Overview for Hyprland
+# Overzicht
-
+Standalone Quickshell workspace overview for Hyprland.
-A standalone workspace overview module for Hyprland using Quickshell - shows all workspaces with live window previews, drag-and-drop support, and Super+Tab keybind.
+## Overview
-
-
-
-
+Overzicht shows a full-screen grid of your workspaces with live window previews.
+It is controlled over Quickshell IPC and is designed for keyboard-first workflow.
+- Toggle: `overzicht ipc call overview toggle`
+- Open: `overzicht ipc call overview open`
+- Close: `overzicht ipc call overview close`
-
+`WlrLayershell.namespace` is `quickshell:overzicht`.
----
-
-## 📸 Preview
+## Preview

https://github.com/user-attachments/assets/9c3d2488-1c24-4cdd-84cd-87c4397d02a8
-> *Workspace overview showing live window previews with drag-and-drop support*
-
----
-
-## ✨ Features
-
-- 🖼️ Visual workspace overview showing all workspaces and windows
-- 🖥️ Multi-monitor support with proper scaling and vertical/rotated monitors [in experimental branch]
-- 📐 Smart row hiding - optionally hide empty workspace rows
-- 🎯 Click windows to focus them
-- 🖱️ Middle-click windows to close them
-- 🔄 Drag and drop windows between workspaces
-- ⌨️ Keyboard navigation (Arrow keys, vim keys, number shortcuts)
-- 💡 Hover tooltips showing window information
-- 🎨 Material Design 3 theming
-- ⚡ Smooth animations and transitions
-
-## 📦 Installation
-
-### Arch Linux (AUR)
-
-For Arch Linux users, you can install directly from the AUR:
-
-```bash
-# Using yay
-yay -S quickshell-overview-git
-
-# Using paru
-paru -S quickshell-overview-git
-```
-
-Then add the keybind and auto-start to your Hyprland config (see Setup steps 2-4 below).
+## Support Policy
-### Prerequisites
+Nix is the only supported installation path.
-- **Hyprland** compositor
-- **Quickshell** ([installation guide](https://quickshell.org/docs/v0.1.0/guide/install-setup/))
-- **Qt 6** with modules: QtQuick, QtQuick.Controls
+- No AUR package.
+- No manual non-Nix installer.
-### Setup
+## Flake Outputs
-1. **Clone this repository** to your Quickshell config directory:
- ```bash
- git clone https://github.com/Shanu-Kumawat/quickshell-overview ~/.config/quickshell/overview
- ```
+- `packages..overzicht`
+- `packages..default`
+- `overlays.default`
+- `homeModules.default`
+- `nixosModules.default`
-2. **Add keybind** to your Hyprland config (`~/.config/hypr/hyprland.conf`):
- ```conf
- bind = Super, TAB, exec, qs ipc -c overview call overview toggle
- ```
+## Home Manager Module
-3. **Auto-start** the overview (add to Hyprland config):
- ```conf
- exec-once = qs -c overview
- ```
+Option namespace: `programs.overzicht`.
-4. **Reload Hyprland**:
- ```bash
- hyprctl reload
- ```
+- `enable`
+- `systemd.enable`
+- `package`
+- `settings`
+- `colors`
-### Manual Start (if needed)
+Runtime files generated by the module:
-```bash
-qs -c overview &
-```
+- `~/.config/overzicht/settings.json`
+- `~/.config/overzicht/colors.json`
-### NixOS
+`settings.json` controls layout and behavior.
+`colors.json` controls the full `m3*` palette used in `common/Appearance.qml`.
-For NixOS users, ensure Quickshell has access to required Qt6 modules:
+Minimal Home Manager example:
```nix
-# In your configuration.nix or home-manager config
-environment.systemPackages = with pkgs; [
- quickshell
- qt6.qtwayland
-];
-```
-
-If you're using home-manager:
-
-```nix
-home.packages = with pkgs; [
- quickshell
- qt6.qtwayland
-];
-```
-
-## 🎮 Usage
-
-| Action | Description |
-|--------|-------------|
-| **Super + Tab** | Toggle the overview |
-| **Arrow Keys / h/l** | Navigate left/right within current row* |
-| **Up/Down / j/k** | Navigate between workspace rows |
-| **1-9, 0** | Jump to Nth workspace in current group (0 = 10th) |
-| **Escape / Enter** | Close the overview |
-| **Click workspace** | Switch to that workspace |
-| **Click window** | Focus that window |
-| **Middle-click window** | Close that window |
-| **Drag window** | Move window to different workspace |
-
-> *When `hideEmptyRows` is enabled, left/right navigation wraps within the current visible row for better UX
-
----
-
-## ⚙️ Configuration
-
-> **⚠️ Want to change the size, position, or number of workspaces?**
-> Edit `~/.config/quickshell/overview/common/Config.qml` - it's all there!
-
-### Workspace Grid
-
-Edit `~/.config/quickshell/overview/common/Config.qml`:
-
-```qml
-property QtObject overview: QtObject {
- property int rows: 2 // Number of workspace rows
- property int columns: 5 // Number of workspace columns (10 total workspaces)
- property real scale: 0.16 // Overview scale factor (0.1-0.3, smaller = more compact)
- property bool enable: true
- property bool hideEmptyRows: true // Hide workspace rows with no windows (recommended!)
-}
-```
-
-**Common adjustments:**
-- **Too small?** Increase `scale` (try 0.20 or 0.25)
-- **Too big?** Decrease `scale` (try 0.12 or 0.14)
-- **More workspaces?** Change `rows` and `columns` (e.g., 3 rows × 4 columns = 12 workspaces)
-
-**Hide empty workspace rows:**
-- Set `hideEmptyRows: true` to automatically hide rows that have no windows
-- Keeps your overview clean by only showing rows with active workspaces
-- The current workspace row is always visible, even if empty
-- Arrow key navigation (left/right) stays within the current row when enabled
-- Great for 2-row setups where you rarely use workspaces 6-10
-
-### Position
-
-Edit `~/.config/quickshell/overview/modules/overview/Overview.qml` (line ~111):
-
-```qml
-anchors {
- horizontalCenter: parent.horizontalCenter
- top: parent.top
- topMargin: 100 // Change this value to move up/down
-}
-```
-
-### Theme & Colors
-
-Edit `~/.config/quickshell/overview/common/Appearance.qml` to customize:
-- Colors (m3colors and colors objects)
-- Font families and sizes
-- Animation curves and durations
-- Border radius values
-
-### Matugen (Dynamic Colors from Wallpaper)
-
-[Matugen](https://github.com/InioX/matugen) lets you generate Material You colors from your wallpaper and apply them to the overview automatically.
-
-**1. Install matugen** - follow [matugen's install guide](https://github.com/InioX/matugen?tab=readme-ov-file#installation)
-
-**2. Copy the template** from this repo to matugen's templates folder:
-```bash
-mkdir -p ~/.config/matugen/templates
-cp ~/.config/quickshell/overview/quickshell-overview.qml ~/.config/matugen/templates/
-```
-
-**3. Add this to `~/.config/matugen/config.toml`** (create the file if it doesn't exist):
-```toml
-[templates.quickshell_overview]
-input_path = "./templates/quickshell-overview.qml"
-output_path = "~/.config/quickshell/overview/common/Appearance.colors.qml"
-```
-
-**4. Enable it** in `~/.config/quickshell/overview/common/Config.qml`:
-```qml
-property QtObject appearance: QtObject {
- property bool useMatugenColors: true // change from false to true
+{
+ programs.overzicht = {
+ enable = true;
+ systemd.enable = true;
+ };
}
```
-**5. Run matugen** with your wallpaper to generate colors:
-```bash
-matugen image /path/to/your/wallpaper.jpg
-```
-
-This generates `Appearance.colors.qml` which the overview loads automatically. Re-run step 5 whenever you change your wallpaper.
-
----
-
-## 📋 Requirements
-
-- **Hyprland** compositor (tested on latest versions)
-- **Quickshell** (Qt6-based shell framework)
-- **Qt 6** with the following modules:
- - QtQuick
- - QtQuick.Controls
- - QtQuick.Layouts
- - Quickshell.Wayland
- - Quickshell.Hyprland
-
-## 🚫 Removed Features (from original illogical-impulse)
-
-The following features were removed to make it standalone:
-
-- App search functionality
-- Emoji picker
-- Clipboard history integration
-- Search widget
-- Integration with the full illogical-impulse shell ecosystem
-
-## 📁 File Structure
-
-```
-~/.config/quickshell/overview/
-├── shell.qml # Main entry point
-├── README.md # This file
-├── hyprland-config.conf # Configuration reference
-├── common/
-│ ├── Appearance.qml # Theme and styling
-│ ├── Config.qml # Configuration options
-│ ├── functions/
-│ │ └── ColorUtils.qml # Color manipulation utilities
-│ └── widgets/
-│ ├── StyledText.qml # Styled text component
-│ ├── StyledRectangularShadow.qml
-│ ├── StyledToolTip.qml
-│ └── StyledToolTipContent.qml
-├── services/
-│ ├── GlobalStates.qml # Global state management
-│ └── HyprlandData.qml # Hyprland data provider
-└── modules/
- └── overview/
- ├── Overview.qml # Main overview component
- ├── OverviewWidget.qml # Workspace grid widget
- └── OverviewWindow.qml # Individual window preview
-```
-
-## 🎯 IPC Commands
-
-```bash
-# Toggle overview
-qs ipc -c overview call overview toggle
-
-# Open overview
-qs ipc -c overview call overview open
-
-# Close overview
-qs ipc -c overview call overview close
-```
-
-## 🐛 Known Issues
-
-- Window icons may fallback to generic icon if app class name doesn't match icon theme
-- Potential crashes during rapid window state changes due to Wayland screencopy buffer management
-
-## Credits
-
-Extracted from the overview feature in [illogical-impulse](https://github.com/end-4/dots-hyprland) by [end-4](https://github.com/end-4).
-
-Adapted as a standalone component for Hyprland + Quickshell users who want just the overview functionality.
-
----
-
-
-
-**Note:** Maintenance will be limited due to time constraints, but **PRs and code improvements are welcome!** Feel free to contribute or fork for your own needs.
+## NixOS Module
-Made with ❤️ for the Hyprland community
+Option namespace: `services.overzicht`.
-
+- `enable`
+- `package`
+- `target`
diff --git a/common/Appearance.qml b/common/Appearance.qml
index e8c6c2a..50f7cb9 100644
--- a/common/Appearance.qml
+++ b/common/Appearance.qml
@@ -2,15 +2,44 @@ pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
+import QtCore
import Quickshell
+import Quickshell.Io
import "functions"
-import "." as Common
Singleton {
id: root
- property QtObject m3colors: Common.Config.options.appearance.useMatugenColors && matugenLoader.item
- ? matugenLoader.item
- : defaultColors
+ function themeValue(path, fallback = undefined) {
+ let current = root.themeData;
+
+ for (let i = 0; i < path.length; i++) {
+ if (current === null || current === undefined)
+ return fallback;
+
+ current = current[path[i]];
+ }
+
+ return current === undefined || current === null ? fallback : current;
+ }
+
+ function parseThemeData() {
+ try {
+ const content = themeFile.text();
+
+ if (!content || content.trim().length === 0)
+ return ({});
+
+ return JSON.parse(content);
+ } catch (error) {
+ console.warn(`Failed to parse theme json: ${error}`);
+ return ({});
+ }
+ }
+
+ property string configDirectory: StandardPaths.standardLocations(StandardPaths.ConfigLocation)[0]
+ property var themeData: ({})
+
+ property QtObject m3colors
property QtObject animation
property QtObject animationCurves
property QtObject colors
@@ -18,37 +47,45 @@ Singleton {
property QtObject font
property QtObject sizes
- Loader {
- id: matugenLoader
- active: Common.Config.options.appearance.useMatugenColors
- source: "Appearance.colors.qml"
+ FileView {
+ id: themeFile
+ path: `${root.configDirectory}/overzicht/colors.json`
+ blockLoading: true
+ watchChanges: true
+ onLoadedChanged: if (loaded)
+ root.themeData = root.parseThemeData()
+ onFileChanged: {
+ reload();
+ root.themeData = root.parseThemeData();
+ }
}
- property QtObject defaultColors: QtObject {
- property bool darkmode: true
- property color m3primary: "#E5B6F2"
- property color m3onPrimary: "#452152"
- property color m3primaryContainer: "#5D386A"
- property color m3onPrimaryContainer: "#F9D8FF"
- property color m3secondary: "#D5C0D7"
- property color m3onSecondary: "#392C3D"
- property color m3secondaryContainer: "#534457"
- property color m3onSecondaryContainer: "#F2DCF3"
- property color m3background: "#161217"
- property color m3onBackground: "#EAE0E7"
- property color m3surface: "#161217"
- property color m3surfaceContainerLow: "#1F1A1F"
- property color m3surfaceContainer: "#231E23"
- property color m3surfaceContainerHigh: "#2D282E"
- property color m3surfaceContainerHighest: "#383339"
- property color m3onSurface: "#EAE0E7"
- property color m3surfaceVariant: "#4C444D"
- property color m3onSurfaceVariant: "#CFC3CD"
- property color m3inverseSurface: "#EAE0E7"
- property color m3inverseOnSurface: "#342F34"
- property color m3outline: "#988E97"
- property color m3outlineVariant: "#4C444D"
- property color m3shadow: "#000000"
+ Component.onCompleted: themeData = parseThemeData()
+
+ m3colors: QtObject {
+ property color m3primary: root.themeValue(["m3primary"], "#E5B6F2")
+ property color m3onPrimary: root.themeValue(["m3onPrimary"], "#452152")
+ property color m3primaryContainer: root.themeValue(["m3primaryContainer"], "#5D386A")
+ property color m3onPrimaryContainer: root.themeValue(["m3onPrimaryContainer"], "#F9D8FF")
+ property color m3onSecondary: root.themeValue(["m3onSecondary"], "#392C3D")
+ property color m3secondaryContainer: root.themeValue(["m3secondaryContainer"], "#534457")
+ property color m3onSecondaryContainer: root.themeValue(["m3onSecondaryContainer"], "#F2DCF3")
+ property color m3onBackground: root.themeValue(["m3onBackground"], "#EAE0E7")
+ property color m3surface: root.themeValue(["m3surface"], "#161217")
+ property color m3surfaceContainerHigh: root.themeValue(["m3surfaceContainerHigh"], "#2D282E")
+ property color m3surfaceContainerHighest: root.themeValue(["m3surfaceContainerHighest"], "#383339")
+ property color m3surfaceVariant: root.themeValue(["m3surfaceVariant"], "#4C444D")
+ property color m3background: root.themeValue(["m3background"], "#161217")
+ property color m3secondary: root.themeValue(["m3secondary"], "#D5C0D7")
+ property color m3surfaceContainerLow: root.themeValue(["m3surfaceContainerLow"], "#1F1A1F")
+ property color m3surfaceContainer: root.themeValue(["m3surfaceContainer"], "#231E23")
+ property color m3onSurface: root.themeValue(["m3onSurface"], "#EAE0E7")
+ property color m3onSurfaceVariant: root.themeValue(["m3onSurfaceVariant"], "#CFC3CD")
+ property color m3inverseSurface: root.themeValue(["m3inverseSurface"], "#EAE0E7")
+ property color m3inverseOnSurface: root.themeValue(["m3inverseOnSurface"], "#342F34")
+ property color m3outline: root.themeValue(["m3outline"], "#988E97")
+ property color m3outlineVariant: root.themeValue(["m3outlineVariant"], "#4C444D")
+ property color m3shadow: root.themeValue(["m3shadow"], "#000000")
}
colors: QtObject {
@@ -77,28 +114,28 @@ Singleton {
}
rounding: QtObject {
- property int unsharpen: 2
- property int verysmall: 8
- property int small: 12
- property int normal: 17
- property int large: 23
- property int full: 9999
- property int screenRounding: large
- property int windowRounding: 18
+ property int unsharpen: 0
+ property int verysmall: 0
+ property int small: 0
+ property int normal: 0
+ property int large: 0
+ property int full: 0
+ property int screenRounding: 0
+ property int windowRounding: 0
}
font: QtObject {
property QtObject family: QtObject {
- property string main: "sans-serif"
- property string title: "sans-serif"
- property string expressive: "sans-serif"
+ property string main: root.themeValue(["font", "family", "main"], "sans-serif")
+ property string title: root.themeValue(["font", "family", "title"], "sans-serif")
+ property string expressive: root.themeValue(["font", "family", "expressive"], "sans-serif")
}
property QtObject pixelSize: QtObject {
- property int smaller: 12
- property int small: 15
- property int normal: 16
- property int larger: 19
- property int huge: 22
+ property int smaller: root.themeValue(["font", "pixelSize", "smaller"], 12)
+ property int small: root.themeValue(["font", "pixelSize", "small"], 15)
+ property int normal: root.themeValue(["font", "pixelSize", "normal"], 16)
+ property int larger: root.themeValue(["font", "pixelSize", "larger"], 19)
+ property int huge: root.themeValue(["font", "pixelSize", "huge"], 22)
}
}
diff --git a/common/Config.qml b/common/Config.qml
index d1caa93..2b30420 100644
--- a/common/Config.qml
+++ b/common/Config.qml
@@ -2,26 +2,68 @@ pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
+import QtCore
import Quickshell
+import Quickshell.Io
Singleton {
id: root
-
- property QtObject options: QtObject {
- property QtObject appearance: QtObject {
- property bool useMatugenColors: false
+
+ function optionValue(path, fallback) {
+ let current = root.settingsData;
+
+ for (let i = 0; i < path.length; i++) {
+ if (current === null || current === undefined)
+ return fallback;
+
+ current = current[path[i]];
+ }
+
+ return current === undefined || current === null ? fallback : current;
+ }
+
+ function parseSettingsData() {
+ try {
+ const content = settingsFile.text();
+
+ if (!content || content.trim().length === 0)
+ return ({});
+
+ return JSON.parse(content);
+ } catch (error) {
+ console.warn(`Failed to parse overview settings json: ${error}`);
+ return ({});
}
+ }
+
+ property string configDirectory: StandardPaths.standardLocations(StandardPaths.ConfigLocation)[0]
+ property var settingsData: ({})
+ FileView {
+ id: settingsFile
+ path: `${root.configDirectory}/overzicht/settings.json`
+ blockLoading: true
+ watchChanges: true
+ onLoadedChanged: if (loaded)
+ root.settingsData = root.parseSettingsData()
+ onFileChanged: {
+ reload();
+ root.settingsData = root.parseSettingsData();
+ }
+ }
+
+ Component.onCompleted: settingsData = parseSettingsData()
+
+ property QtObject options: QtObject {
property QtObject overview: QtObject {
- property int rows: 2
- property int columns: 5
- property real scale: 0.16
- property bool enable: true
- property bool hideEmptyRows: true // Hide workspace rows with no windows
+ property int rows: root.optionValue(["overview", "rows"], 2)
+ property int columns: root.optionValue(["overview", "columns"], 4)
+ property real scale: root.optionValue(["overview", "scale"], 0.12)
+ property bool enable: root.optionValue(["overview", "enable"], true)
}
-
+
property QtObject hacks: QtObject {
- property int arbitraryRaceConditionDelay: 150
+ property int arbitraryRaceConditionDelay: root.optionValue(["hacks", "arbitraryRaceConditionDelay"], 150)
}
}
}
diff --git a/common/functions/ColorUtils.qml b/common/functions/ColorUtils.qml
index 6162df1..fa40753 100644
--- a/common/functions/ColorUtils.qml
+++ b/common/functions/ColorUtils.qml
@@ -47,12 +47,7 @@ Singleton {
function mix(color1, color2, percentage = 0.5) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
- return Qt.rgba(
- percentage * c1.r + (1 - percentage) * c2.r,
- percentage * c1.g + (1 - percentage) * c2.g,
- percentage * c1.b + (1 - percentage) * c2.b,
- percentage * c1.a + (1 - percentage) * c2.a
- );
+ return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a);
}
function transparentize(color, percentage = 1) {
diff --git a/common/widgets/StyledToolTip.qml b/common/widgets/StyledToolTip.qml
index 4d4678c..4214675 100644
--- a/common/widgets/StyledToolTip.qml
+++ b/common/widgets/StyledToolTip.qml
@@ -12,7 +12,7 @@ ToolTip {
background: null
visible: internalVisibleCondition
-
+
contentItem: StyledToolTipContent {
id: contentItem
text: root.text
diff --git a/common/widgets/StyledToolTipContent.qml b/common/widgets/StyledToolTipContent.qml
index b8c29c1..3a2c711 100644
--- a/common/widgets/StyledToolTipContent.qml
+++ b/common/widgets/StyledToolTipContent.qml
@@ -19,8 +19,8 @@ Item {
bottom: root.bottom
horizontalCenter: root.horizontalCenter
}
- color: Appearance?.colors.colTooltip ?? "#3C4043"
- radius: Appearance?.rounding.verysmall ?? 7
+ color: Appearance?.colors.colTooltip
+ radius: Appearance?.rounding.verysmall
opacity: shown ? 1 : 0
implicitWidth: shown ? (tooltipTextObject.implicitWidth + 2 * root.horizontalPadding) : 0
implicitHeight: shown ? (tooltipTextObject.implicitHeight + 2 * root.verticalPadding) : 0
@@ -45,5 +45,5 @@ Item {
color: Appearance?.colors.colOnTooltip ?? "#FFFFFF"
wrapMode: Text.Wrap
}
- }
+ }
}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..5af8dc8
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,17 @@
+{
+ description = "Quickshell overview.";
+
+ inputs = {
+ nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+ flake-parts.url = "github:hercules-ci/flake-parts";
+ import-tree.url = "github:vic/import-tree";
+ systems.url = "github:nix-systems/default";
+ treefmt-nix.url = "github:numtide/treefmt-nix";
+ };
+
+ outputs = inputs @ {flake-parts, ...}:
+ flake-parts.lib.mkFlake {inherit inputs;} {
+ systems = import inputs.systems;
+ imports = with inputs; [(import-tree ./parts)];
+ };
+}
diff --git a/modules/overview/Overview.qml b/modules/overview/Overview.qml
index 1b7b433..ea1cacb 100644
--- a/modules/overview/Overview.qml
+++ b/modules/overview/Overview.qml
@@ -22,7 +22,7 @@ Scope {
screen: modelData
visible: GlobalStates.overviewOpen
- WlrLayershell.namespace: "quickshell:overview"
+ WlrLayershell.namespace: "quickshell:overzicht"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
color: "transparent"
@@ -34,8 +34,8 @@ Scope {
anchors {
top: true
bottom: true
- left: !(Config?.options.overview.enable ?? true)
- right: !(Config?.options.overview.enable ?? true)
+ left: !(Config?.options.overview.enable ?? true)
+ right: !(Config?.options.overview.enable ?? true)
}
HyprlandFocusGrab {
@@ -92,42 +92,31 @@ Scope {
const currentGroup = Math.floor((currentId - 1) / workspacesPerGroup);
const minWorkspaceId = currentGroup * workspacesPerGroup + 1;
const maxWorkspaceId = minWorkspaceId + workspacesPerGroup - 1;
-
- // When hideEmptyRows is enabled, constrain navigation to current row
- const currentRow = Math.floor((currentId - minWorkspaceId) / Config.options.overview.columns);
- const rowMinId = minWorkspaceId + currentRow * Config.options.overview.columns;
- const rowMaxId = rowMinId + Config.options.overview.columns - 1;
let targetId = null;
// Arrow keys and vim-style hjkl
if (event.key === Qt.Key_Left || event.key === Qt.Key_H) {
targetId = currentId - 1;
- // Wrap within visible workspaces
- if (Config.options.overview.hideEmptyRows) {
- if (targetId < rowMinId) targetId = rowMaxId;
- } else {
- if (targetId < minWorkspaceId) targetId = maxWorkspaceId;
- }
+ if (targetId < minWorkspaceId)
+ targetId = maxWorkspaceId;
} else if (event.key === Qt.Key_Right || event.key === Qt.Key_L) {
targetId = currentId + 1;
- // Wrap within visible workspaces
- if (Config.options.overview.hideEmptyRows) {
- if (targetId > rowMaxId) targetId = rowMinId;
- } else {
- if (targetId > maxWorkspaceId) targetId = minWorkspaceId;
- }
+ if (targetId > maxWorkspaceId)
+ targetId = minWorkspaceId;
} else if (event.key === Qt.Key_Up || event.key === Qt.Key_K) {
targetId = currentId - Config.options.overview.columns;
- if (targetId < minWorkspaceId) targetId += workspacesPerGroup;
+ if (targetId < minWorkspaceId)
+ targetId += workspacesPerGroup;
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_J) {
targetId = currentId + Config.options.overview.columns;
- if (targetId > maxWorkspaceId) targetId -= workspacesPerGroup;
- }
+ if (targetId > maxWorkspaceId)
+ targetId -= workspacesPerGroup;
+ } else
// Number keys: jump to workspace within the current group
// 1-9 map to positions 1-9, 0 maps to position 10
- else if (event.key >= Qt.Key_1 && event.key <= Qt.Key_9) {
+ if (event.key >= Qt.Key_1 && event.key <= Qt.Key_9) {
const position = event.key - Qt.Key_0; // 1-9
if (position <= workspacesPerGroup) {
targetId = minWorkspaceId + position - 1;
@@ -149,11 +138,7 @@ Scope {
ColumnLayout {
id: columnLayout
visible: GlobalStates.overviewOpen
- anchors {
- horizontalCenter: parent.horizontalCenter
- top: parent.top
- topMargin: 100
- }
+ anchors.centerIn: parent
Loader {
id: overviewLoader
@@ -166,7 +151,7 @@ Scope {
}
}
}
-
+
IpcHandler {
target: "overview"
diff --git a/modules/overview/OverviewWidget.qml b/modules/overview/OverviewWidget.qml
index 64d2876..9ebd84b 100644
--- a/modules/overview/OverviewWidget.qml
+++ b/modules/overview/OverviewWidget.qml
@@ -24,12 +24,8 @@ Item {
property real scale: Config.options.overview.scale
property color activeBorderColor: Appearance.colors.colSecondary
- property real workspaceImplicitWidth: (monitorData?.transform % 2 === 1) ?
- ((monitor.height / monitor.scale - (monitorData?.reserved?.[0] ?? 0) - (monitorData?.reserved?.[2] ?? 0)) * root.scale) :
- ((monitor.width / monitor.scale - (monitorData?.reserved?.[0] ?? 0) - (monitorData?.reserved?.[2] ?? 0)) * root.scale)
- property real workspaceImplicitHeight: (monitorData?.transform % 2 === 1) ?
- ((monitor.width / monitor.scale - (monitorData?.reserved?.[1] ?? 0) - (monitorData?.reserved?.[3] ?? 0)) * root.scale) :
- ((monitor.height / monitor.scale - (monitorData?.reserved?.[1] ?? 0) - (monitorData?.reserved?.[3] ?? 0)) * root.scale)
+ property real workspaceImplicitWidth: (monitorData?.transform % 2 === 1) ? ((monitor.height / monitor.scale - (monitorData?.reserved?.[0] ?? 0) - (monitorData?.reserved?.[2] ?? 0)) * root.scale) : ((monitor.width / monitor.scale - (monitorData?.reserved?.[0] ?? 0) - (monitorData?.reserved?.[2] ?? 0)) * root.scale)
+ property real workspaceImplicitHeight: (monitorData?.transform % 2 === 1) ? ((monitor.width / monitor.scale - (monitorData?.reserved?.[1] ?? 0) - (monitorData?.reserved?.[3] ?? 0)) * root.scale) : ((monitor.height / monitor.scale - (monitorData?.reserved?.[1] ?? 0) - (monitorData?.reserved?.[3] ?? 0)) * root.scale)
property real workspaceNumberMargin: 80
property real workspaceNumberSize: 250 * monitor.scale
@@ -41,33 +37,6 @@ Item {
property int draggingFromWorkspace: -1
property int draggingTargetWorkspace: -1
- // Calculate which rows have windows or current workspace
- property var rowsWithContent: {
- if (!Config.options.overview.hideEmptyRows) return null;
-
- let rows = new Set();
- const firstWorkspace = root.workspaceGroup * root.workspacesShown + 1;
- const lastWorkspace = (root.workspaceGroup + 1) * root.workspacesShown;
-
- // Add row containing current workspace
- const currentWorkspace = monitor.activeWorkspace?.id ?? 1;
- if (currentWorkspace >= firstWorkspace && currentWorkspace <= lastWorkspace) {
- rows.add(Math.floor((currentWorkspace - firstWorkspace) / Config.options.overview.columns));
- }
-
- // Add rows with windows
- for (let addr in windowByAddress) {
- const win = windowByAddress[addr];
- const wsId = win?.workspace?.id;
- if (wsId >= firstWorkspace && wsId <= lastWorkspace) {
- const rowIndex = Math.floor((wsId - firstWorkspace) / Config.options.overview.columns);
- rows.add(rowIndex);
- }
- }
-
- return rows;
- }
-
implicitWidth: overviewBackground.implicitWidth + Appearance.sizes.elevationMargin * 2
implicitHeight: overviewBackground.implicitHeight + Appearance.sizes.elevationMargin * 2
@@ -85,7 +54,7 @@ Item {
implicitWidth: workspaceColumnLayout.implicitWidth + padding * 2
implicitHeight: workspaceColumnLayout.implicitHeight + padding * 2
- radius: Appearance.rounding.screenRounding * root.scale + padding
+ radius: Appearance.rounding.screenRounding
color: Appearance.colors.colLayer0
border.width: 1
border.color: Appearance.colors.colLayer0Border
@@ -102,11 +71,9 @@ Item {
id: row
property int rowIndex: index
spacing: workspaceSpacing
- visible: !Config.options.overview.hideEmptyRows ||
- (root.rowsWithContent && root.rowsWithContent.has(rowIndex))
- height: visible ? implicitHeight : 0
- Repeater { // Workspace repeater
+ Repeater {
+ // Workspace repeater
model: Config.options.overview.columns
Rectangle { // Workspace
id: workspace
@@ -120,7 +87,7 @@ Item {
implicitWidth: root.workspaceImplicitWidth
implicitHeight: root.workspaceImplicitHeight
color: hoveredWhileDragging ? hoveredWorkspaceColor : defaultWorkspaceColor
- radius: Appearance.rounding.screenRounding * root.scale
+ radius: Appearance.rounding.screenRounding
border.width: 2
border.color: hoveredWhileDragging ? hoveredBorderColor : "transparent"
@@ -143,8 +110,8 @@ Item {
acceptedButtons: Qt.LeftButton
onClicked: {
if (root.draggingTargetWorkspace === -1) {
- GlobalStates.overviewOpen = false
- Hyprland.dispatch(`workspace ${workspaceValue}`)
+ GlobalStates.overviewOpen = false;
+ Hyprland.dispatch(`workspace ${workspaceValue}`);
}
}
}
@@ -152,16 +119,17 @@ Item {
DropArea {
anchors.fill: parent
onEntered: {
- root.draggingTargetWorkspace = workspaceValue
- if (root.draggingFromWorkspace == root.draggingTargetWorkspace) return;
- hoveredWhileDragging = true
+ root.draggingTargetWorkspace = workspaceValue;
+ if (root.draggingFromWorkspace == root.draggingTargetWorkspace)
+ return;
+ hoveredWhileDragging = true;
}
onExited: {
- hoveredWhileDragging = false
- if (root.draggingTargetWorkspace == workspaceValue) root.draggingTargetWorkspace = -1
+ hoveredWhileDragging = false;
+ if (root.draggingTargetWorkspace == workspaceValue)
+ root.draggingTargetWorkspace = -1;
}
}
-
}
}
}
@@ -174,35 +142,36 @@ Item {
implicitWidth: workspaceColumnLayout.implicitWidth
implicitHeight: workspaceColumnLayout.implicitHeight
- Repeater { // Window repeater
+ Repeater {
+ // Window repeater
model: ScriptModel {
values: {
- return ToplevelManager.toplevels.values.filter((toplevel) => {
- const address = `0x${toplevel.HyprlandToplevel.address}`
- var win = windowByAddress[address]
- const inWorkspaceGroup = (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown)
+ return ToplevelManager.toplevels.values.filter(toplevel => {
+ const address = `0x${toplevel.HyprlandToplevel.address}`;
+ var win = windowByAddress[address];
+ const inWorkspaceGroup = (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown);
return inWorkspaceGroup;
}).sort((a, b) => {
// Proper stacking order based on Hyprland's window properties
- const addrA = `0x${a.HyprlandToplevel.address}`
- const addrB = `0x${b.HyprlandToplevel.address}`
- const winA = windowByAddress[addrA]
- const winB = windowByAddress[addrB]
-
+ const addrA = `0x${a.HyprlandToplevel.address}`;
+ const addrB = `0x${b.HyprlandToplevel.address}`;
+ const winA = windowByAddress[addrA];
+ const winB = windowByAddress[addrB];
+
// 1. Pinned windows are always on top
if (winA?.pinned !== winB?.pinned) {
- return winA?.pinned ? 1 : -1
+ return winA?.pinned ? 1 : -1;
}
-
+
// 2. Floating windows above tiled windows
if (winA?.floating !== winB?.floating) {
- return winA?.floating ? 1 : -1
+ return winA?.floating ? 1 : -1;
}
-
+
// 3. Within same category, sort by focus history
// Lower focusHistoryID = more recently focused = higher in stack
- return (winB?.focusHistoryID ?? 0) - (winA?.focusHistoryID ?? 0)
- })
+ return (winB?.focusHistoryID ?? 0) - (winA?.focusHistoryID ?? 0);
+ });
}
}
delegate: OverviewWindow {
@@ -215,21 +184,14 @@ Item {
windowData: windowByAddress[address]
toplevel: modelData
monitorData: monitor
-
+
// Calculate scale relative to window's source monitor
- property real sourceMonitorWidth: (monitor?.transform % 2 === 1) ?
- (monitor?.height ?? 1920) / (monitor?.scale ?? 1) - (monitor?.reserved?.[0] ?? 0) - (monitor?.reserved?.[2] ?? 0) :
- (monitor?.width ?? 1920) / (monitor?.scale ?? 1) - (monitor?.reserved?.[0] ?? 0) - (monitor?.reserved?.[2] ?? 0)
- property real sourceMonitorHeight: (monitor?.transform % 2 === 1) ?
- (monitor?.width ?? 1080) / (monitor?.scale ?? 1) - (monitor?.reserved?.[1] ?? 0) - (monitor?.reserved?.[3] ?? 0) :
- (monitor?.height ?? 1080) / (monitor?.scale ?? 1) - (monitor?.reserved?.[1] ?? 0) - (monitor?.reserved?.[3] ?? 0)
-
+ property real sourceMonitorWidth: (monitor?.transform % 2 === 1) ? (monitor?.height ?? 1920) / (monitor?.scale ?? 1) - (monitor?.reserved?.[0] ?? 0) - (monitor?.reserved?.[2] ?? 0) : (monitor?.width ?? 1920) / (monitor?.scale ?? 1) - (monitor?.reserved?.[0] ?? 0) - (monitor?.reserved?.[2] ?? 0)
+ property real sourceMonitorHeight: (monitor?.transform % 2 === 1) ? (monitor?.width ?? 1080) / (monitor?.scale ?? 1) - (monitor?.reserved?.[1] ?? 0) - (monitor?.reserved?.[3] ?? 0) : (monitor?.height ?? 1080) / (monitor?.scale ?? 1) - (monitor?.reserved?.[1] ?? 0) - (monitor?.reserved?.[3] ?? 0)
+
// Scale windows to fit the workspace size, accounting for different monitor sizes
- scale: Math.min(
- root.workspaceImplicitWidth / sourceMonitorWidth,
- root.workspaceImplicitHeight / sourceMonitorHeight
- )
-
+ scale: Math.min(root.workspaceImplicitWidth / sourceMonitorWidth, root.workspaceImplicitHeight / sourceMonitorHeight)
+
availableWorkspaceWidth: root.workspaceImplicitWidth
availableWorkspaceHeight: root.workspaceImplicitHeight
widgetMonitorId: root.monitor.id
@@ -247,8 +209,8 @@ Item {
repeat: false
running: false
onTriggered: {
- window.x = Math.round(Math.max((windowData?.at[0] - (monitor?.x ?? 0) - (monitorData?.reserved?.[0] ?? 0)) * root.scale, 0) + xOffset)
- window.y = Math.round(Math.max((windowData?.at[1] - (monitor?.y ?? 0) - (monitorData?.reserved?.[1] ?? 0)) * root.scale, 0) + yOffset)
+ window.x = Math.round(Math.max((windowData?.at[0] - (monitor?.x ?? 0) - (monitorData?.reserved?.[0] ?? 0)) * root.scale, 0) + xOffset);
+ window.y = Math.round(Math.max((windowData?.at[1] - (monitor?.y ?? 0) - (monitorData?.reserved?.[1] ?? 0)) * root.scale, 0) + yOffset);
}
}
@@ -263,38 +225,38 @@ Item {
onExited: hovered = false
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
drag.target: parent
- onPressed: (mouse) => {
- root.draggingFromWorkspace = windowData?.workspace.id
- window.pressed = true
- window.Drag.active = true
- window.Drag.source = window
- window.Drag.hotSpot.x = mouse.x
- window.Drag.hotSpot.y = mouse.y
+ onPressed: mouse => {
+ root.draggingFromWorkspace = windowData?.workspace.id;
+ window.pressed = true;
+ window.Drag.active = true;
+ window.Drag.source = window;
+ window.Drag.hotSpot.x = mouse.x;
+ window.Drag.hotSpot.y = mouse.y;
}
onReleased: {
- const targetWorkspace = root.draggingTargetWorkspace
- window.pressed = false
- window.Drag.active = false
- root.draggingFromWorkspace = -1
+ const targetWorkspace = root.draggingTargetWorkspace;
+ window.pressed = false;
+ window.Drag.active = false;
+ root.draggingFromWorkspace = -1;
if (targetWorkspace !== -1 && targetWorkspace !== windowData?.workspace.id) {
- Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace}, address:${window.windowData?.address}`)
- updateWindowPosition.restart()
- }
- else {
- window.x = window.initX
- window.y = window.initY
+ Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace}, address:${window.windowData?.address}`);
+ updateWindowPosition.restart();
+ } else {
+ window.x = window.initX;
+ window.y = window.initY;
}
}
- onClicked: (event) => {
- if (!windowData) return;
+ onClicked: event => {
+ if (!windowData)
+ return;
if (event.button === Qt.LeftButton) {
- GlobalStates.overviewOpen = false
- Hyprland.dispatch(`focuswindow address:${windowData.address}`)
- event.accepted = true
+ GlobalStates.overviewOpen = false;
+ Hyprland.dispatch(`focuswindow address:${windowData.address}`);
+ event.accepted = true;
} else if (event.button === Qt.MiddleButton) {
- Hyprland.dispatch(`closewindow address:${windowData.address}`)
- event.accepted = true
+ Hyprland.dispatch(`closewindow address:${windowData.address}`);
+ event.accepted = true;
}
}
@@ -318,7 +280,7 @@ Item {
width: root.workspaceImplicitWidth
height: root.workspaceImplicitHeight
color: "transparent"
- radius: Appearance.rounding.screenRounding * root.scale
+ radius: Appearance.rounding.screenRounding
border.width: 2
border.color: root.activeBorderColor
Behavior on x {
diff --git a/modules/overview/OverviewWindow.qml b/modules/overview/OverviewWindow.qml
index d225ba4..73b96ef 100644
--- a/modules/overview/OverviewWindow.qml
+++ b/modules/overview/OverviewWindow.qml
@@ -20,7 +20,7 @@ Item { // Window
property real xOffset: 0
property real yOffset: 0
property int widgetMonitorId: 0
-
+
property var targetWindowWidth: (windowData?.size[0] ?? 100) * scale
property var targetWindowHeight: (windowData?.size[1] ?? 100) * scale
property bool hovered: false
@@ -34,7 +34,7 @@ Item { // Window
property bool compactMode: Appearance.font.pixelSize.smaller * 4 > targetWindowHeight || Appearance.font.pixelSize.smaller * 4 > targetWindowWidth
property bool indicateXWayland: windowData?.xwayland ?? false
-
+
x: initX
y: initY
width: Math.min((windowData?.size[0] ?? 100) * root.scale, availableWorkspaceWidth)
@@ -64,12 +64,10 @@ Item { // Window
Rectangle {
anchors.fill: parent
- radius: Appearance.rounding.windowRounding * root.scale
- color: pressed ? ColorUtils.transparentize(Appearance.colors.colLayer2Active, 0.5) :
- hovered ? ColorUtils.transparentize(Appearance.colors.colLayer2Hover, 0.7) :
- ColorUtils.transparentize(Appearance.colors.colLayer2)
- border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.7)
- border.width : 1
+ radius: Appearance.rounding.windowRounding
+ color: pressed ? ColorUtils.transparentize(Appearance.colors.colLayer2Active, 0.5) : hovered ? ColorUtils.transparentize(Appearance.colors.colLayer2Hover, 0.7) : ColorUtils.transparentize(Appearance.colors.colLayer2)
+ border.color: ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.7)
+ border.width: 1
}
ColumnLayout {
diff --git a/nix/home-module.nix b/nix/home-module.nix
new file mode 100644
index 0000000..bc62d54
--- /dev/null
+++ b/nix/home-module.nix
@@ -0,0 +1,118 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ inherit
+ (lib)
+ mkEnableOption
+ mkOption
+ mkIf
+ getExe
+ types
+ literalExpression
+ ;
+ inherit (pkgs) callPackage;
+
+ cfg = config.programs.overzicht;
+ jsonFormat = pkgs.formats.json {};
+
+ generateJson = name: value:
+ if types.str.check value
+ then pkgs.writeText name value
+ else if types.path.check value || types.package.check value
+ then value
+ else jsonFormat.generate name value;
+in {
+ options.programs.overzicht = {
+ enable = mkEnableOption "quickshell overview shell";
+
+ systemd.enable = mkEnableOption "systemd user service for overzicht";
+
+ package = mkOption {
+ type = types.package;
+ default = callPackage ./package.nix {};
+ defaultText = literalExpression "callPackage ./package.nix {}";
+ description = "Package that provides the `overzicht` executable.";
+ };
+
+ settings = mkOption {
+ type = types.oneOf [jsonFormat.type types.str types.path];
+ default = {
+ overview = {
+ rows = 2;
+ columns = 4;
+ scale = 0.12;
+ enable = true;
+ };
+
+ hacks.arbitraryRaceConditionDelay = 150;
+ };
+ description = "Settings written to `~/.config/overzicht/settings.json`.";
+ };
+
+ colors = mkOption {
+ type = types.oneOf [jsonFormat.type types.str types.path];
+ default = {
+ m3primary = "#fb4934";
+ m3onPrimary = "#282828";
+ m3primaryContainer = "#3c3836";
+ m3onPrimaryContainer = "#fbf1c7";
+ m3onSecondary = "#282828";
+ m3secondaryContainer = "#3c3836";
+ m3onSecondaryContainer = "#fbf1c7";
+ m3onBackground = "#ebdbb2";
+ m3surface = "#282828";
+ m3surfaceContainerHigh = "#3c3836";
+ m3surfaceContainerHighest = "#504945";
+ m3surfaceVariant = "#504945";
+ m3background = "#3c3836";
+ m3secondary = "#b8bb26";
+ m3surfaceContainerLow = "#282828";
+ m3surfaceContainer = "#b8bb26";
+ m3onSurface = "#282828";
+ m3onSurfaceVariant = "#fbf1c7";
+ m3inverseSurface = "#504945";
+ m3inverseOnSurface = "#fbf1c7";
+ m3outline = "#fbf1c7";
+ m3outlineVariant = "#665c54";
+ m3shadow = "#282828";
+ };
+ description = "Colors written to `~/.config/overzicht/colors.json`.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [cfg.package];
+
+ xdg.configFile = {
+ "overzicht/settings.json".source = generateJson "overzicht-settings.json" cfg.settings;
+ "overzicht/colors.json".source = generateJson "overzicht-colors.json" cfg.colors;
+ };
+
+ systemd.user.services.overzicht = mkIf cfg.systemd.enable {
+ Unit = {
+ Description = "overzicht";
+ After = ["graphical-session-pre.target"];
+ PartOf = ["graphical-session.target"];
+ };
+
+ Service = {
+ ExecStart = getExe cfg.package;
+ Restart = "on-failure";
+ RestartSec = 1;
+ };
+
+ Install.WantedBy = ["graphical-session.target"];
+ };
+
+ assertions = [
+ {
+ assertion = cfg.package != null || !cfg.systemd.enable;
+ message = "programs.overzicht.package cannot be null when systemd is enabled.";
+ }
+ ];
+ };
+}
diff --git a/nix/nixos-module.nix b/nix/nixos-module.nix
new file mode 100644
index 0000000..d567bf4
--- /dev/null
+++ b/nix/nixos-module.nix
@@ -0,0 +1,54 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ inherit
+ (lib)
+ mkEnableOption
+ mkOption
+ literalExpression
+ mkIf
+ getExe
+ types
+ ;
+ inherit (pkgs) callPackage;
+
+ cfg = config.services.overzicht;
+in {
+ options.services.overzicht = {
+ enable = mkEnableOption "overzicht user service";
+
+ package = mkOption {
+ type = types.package;
+ default = callPackage ./package.nix {};
+ defaultText = literalExpression "callPackage ./package.nix {}";
+ description = "Package that provides the `overzicht` executable.";
+ };
+
+ target = mkOption {
+ type = types.str;
+ default = "graphical-session.target";
+ description = "User systemd target for overzicht.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = [cfg.package];
+
+ systemd.user.services.overzicht = {
+ description = "overzicht";
+ wantedBy = [cfg.target];
+ after = ["graphical-session-pre.target"];
+ partOf = [cfg.target];
+
+ serviceConfig = {
+ ExecStart = getExe cfg.package;
+ Restart = "on-failure";
+ RestartSec = 1;
+ };
+ };
+ };
+}
diff --git a/nix/package.nix b/nix/package.nix
new file mode 100644
index 0000000..0df0473
--- /dev/null
+++ b/nix/package.nix
@@ -0,0 +1,39 @@
+{
+ lib,
+ stdenvNoCC,
+ makeWrapper,
+ quickshell,
+}: let
+ inherit
+ (lib)
+ cleanSource
+ getExe
+ ;
+in
+ stdenvNoCC.mkDerivation {
+ pname = "overzicht";
+ version = "unstable";
+
+ src = cleanSource ../.;
+
+ nativeBuildInputs = [makeWrapper];
+
+ installPhase = ''
+ runHook preInstall
+
+ install -dm755 "$out/share/overzicht"
+ cp -r ./* "$out/share/overzicht/"
+
+ install -dm755 "$out/bin"
+ makeWrapper ${getExe quickshell} "$out/bin/overzicht" \
+ --add-flags "-p $out/share/overzicht"
+
+ runHook postInstall
+ '';
+
+ meta = with lib; {
+ description = "Quickshell-based workspace overview";
+ mainProgram = "overzicht";
+ platforms = platforms.linux;
+ };
+ }
diff --git a/parts/exports.nix b/parts/exports.nix
new file mode 100644
index 0000000..58b1bf4
--- /dev/null
+++ b/parts/exports.nix
@@ -0,0 +1,21 @@
+_: {
+ flake = {
+ overlays.default = final: _: {
+ overzicht = final.callPackage ../nix/package.nix {};
+ };
+
+ homeModules.default = import ../nix/home-module.nix;
+ nixosModules.default = import ../nix/nixos-module.nix;
+ };
+
+ perSystem = {
+ config,
+ pkgs,
+ ...
+ }: {
+ packages = {
+ overzicht = pkgs.callPackage ../nix/package.nix {};
+ default = config.packages.overzicht;
+ };
+ };
+}
diff --git a/parts/treefmt.nix b/parts/treefmt.nix
new file mode 100644
index 0000000..dc7f3c6
--- /dev/null
+++ b/parts/treefmt.nix
@@ -0,0 +1,23 @@
+{inputs, ...}:
+# Treefmt configuration for repository formatting.
+{
+ imports = [inputs.treefmt-nix.flakeModule];
+
+ perSystem = _: {
+ treefmt = {
+ projectRootFile = "flake.nix";
+
+ programs = {
+ alejandra.enable = true;
+ nixf-diagnose.enable = true;
+ deadnix.enable = true;
+ statix.enable = true;
+
+ qmlformat.enable = true;
+
+ rumdl-check.enable = true;
+ rumdl-format.enable = true;
+ };
+ };
+ };
+}
diff --git a/quickshell-overview.qml b/quickshell-overview.qml
deleted file mode 100644
index 95176b4..0000000
--- a/quickshell-overview.qml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-import QtQuick
-
-QtObject {
- id: m3
-
- property color m3primary: "{{colors.primary.default.hex}}"
- property color m3onPrimary: "{{colors.on_primary.default.hex}}"
-
- property color m3primaryContainer: "{{colors.primary_container.default.hex}}"
- property color m3onPrimaryContainer: "{{colors.on_primary_container.default.hex}}"
-
- property color m3secondary: "{{colors.secondary.default.hex}}"
- property color m3onSecondary: "{{colors.on_secondary.default.hex}}"
-
- property color m3secondaryContainer: "{{colors.secondary_container.default.hex}}"
- property color m3onSecondaryContainer: "{{colors.on_secondary_container.default.hex}}"
-
- property color m3background: "{{colors.background.default.hex}}"
- property color m3onBackground: "{{colors.on_background.default.hex}}"
-
- property color m3surface: "{{colors.surface.default.hex}}"
-
- property color m3surfaceContainerLow: "{{colors.surface_container_low.default.hex}}"
- property color m3surfaceContainer: "{{colors.surface_container.default.hex}}"
- property color m3surfaceContainerHigh: "{{colors.surface_container_high.default.hex}}"
- property color m3surfaceContainerHighest: "{{colors.surface_container_highest.default.hex}}"
-
- property color m3onSurface: "{{colors.on_surface.default.hex}}"
-
- property color m3surfaceVariant: "{{colors.surface_variant.default.hex}}"
- property color m3onSurfaceVariant: "{{colors.on_surface_variant.default.hex}}"
-
- property color m3inverseSurface: "{{colors.inverse_surface.default.hex}}"
- property color m3inverseOnSurface: "{{colors.inverse_on_surface.default.hex}}"
-
- property color m3outline: "{{colors.outline.default.hex}}"
- property color m3outlineVariant: "{{colors.outline_variant.default.hex}}"
-
- property color m3shadow: "#000000"
-}
diff --git a/services/HyprlandData.qml b/services/HyprlandData.qml
index e23472d..264f44e 100644
--- a/services/HyprlandData.qml
+++ b/services/HyprlandData.qml
@@ -62,7 +62,7 @@ Singleton {
target: Hyprland
function onRawEvent(event) {
- updateAll()
+ updateAll();
}
}
@@ -72,7 +72,7 @@ Singleton {
stdout: StdioCollector {
id: clientsCollector
onStreamFinished: {
- root.windowList = JSON.parse(clientsCollector.text)
+ root.windowList = JSON.parse(clientsCollector.text);
let tempWinByAddress = {};
for (var i = 0; i < root.windowList.length; ++i) {
var win = root.windowList[i];