diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/flake.nix b/flake.nix index 05b9746..d5d5d62 100644 --- a/flake.nix +++ b/flake.nix @@ -15,9 +15,9 @@ (system: fn system nixpkgs.legacyPackages.${system}); in { packages = forEachSystem (system: pkgs: rec { - default = dots; - dots = pkgs.stdenv.mkDerivation { - pname = "dots"; + default = minmat; + minmat = pkgs.stdenv.mkDerivation { + pname = "minmat"; version = "0.1.0"; src = ./shell; diff --git a/shell/bar/Bar.qml b/shell/bar/Bar.qml index e8f1ab7..9c8eb04 100644 --- a/shell/bar/Bar.qml +++ b/shell/bar/Bar.qml @@ -74,9 +74,12 @@ Variants { } // VolumeIndicator { - // bar: root + // id: volumeIndicator + // popup: root.popup // Layout.preferredWidth: this.height // Layout.fillHeight: true + // Layout.topMargin: 2 + // Layout.bottomMargin: 2 // } PowerMenu { diff --git a/shell/bar/systray/SysTray.qml b/shell/bar/systray/SysTray.qml index a4ffc74..47dfbe2 100644 --- a/shell/bar/systray/SysTray.qml +++ b/shell/bar/systray/SysTray.qml @@ -5,8 +5,8 @@ import QtQuick.Layouts import Quickshell import Quickshell.Widgets import Quickshell.Services.SystemTray -import qs.bar -import qs.widgets +import "../../widgets" +import ".." // TODO: // 1. Get rid of leftItem/rightItem properties on menu diff --git a/shell/bar/volume/DeviceMixer.qml b/shell/bar/volume/DeviceMixer.qml index e7076dc..ed37a83 100644 --- a/shell/bar/volume/DeviceMixer.qml +++ b/shell/bar/volume/DeviceMixer.qml @@ -3,9 +3,8 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import Quickshell.Services.Pipewire -import Quickshell.Widgets -import qs -import qs.widgets +import "../../widgets/" as Widgets +import "../.." ColumnLayout { id: root @@ -14,7 +13,7 @@ ColumnLayout { // don't load until the node is not null Loader { id: sinkLoader - active: sink !== null + active: sink !== null Layout.preferredWidth: 350 Layout.preferredHeight: 45 @@ -23,11 +22,11 @@ ColumnLayout { sourceComponent: VolumeCard { id: sinkCard node: sinkLoader.sink - button: StyledMouseArea { - property bool checked: !sinkCard.node.audio.muted - - // IconImage {} - + button: Widgets.FontIconButton { + hoverEnabled: false + iconName: sinkCard.node.audio.muted ? "volume_off" : "volume_up" + checked: !sinkCard.node.audio.muted + inactiveColor: ShellSettings.colors["surface_container_highest"] onClicked: { sinkCard.node.audio.muted = !sinkCard.node.audio.muted; } @@ -40,7 +39,7 @@ ColumnLayout { // microphone, same as above Loader { id: sourceLoader - active: source !== null + active: source !== null Layout.preferredWidth: 350 Layout.preferredHeight: 45 @@ -49,11 +48,11 @@ ColumnLayout { sourceComponent: VolumeCard { id: sourceCard node: sourceLoader.source - button: StyledMouseArea { - property bool checked: !sourceCard.node.audio.muted - - // IconImage {} - + button: Widgets.FontIconButton { + hoverEnabled: false + iconName: sourceCard.node.audio.muted ? "mic_off" : "mic" + checked: !sourceCard.node.audio.muted + inactiveColor: ShellSettings.colors["surface_container_highest"] onClicked: { sourceCard.node.audio.muted = !sourceCard.node.audio.muted; } diff --git a/shell/bar/volume/VolumeCard.qml b/shell/bar/volume/VolumeCard.qml index ea085de..32ff535 100644 --- a/shell/bar/volume/VolumeCard.qml +++ b/shell/bar/volume/VolumeCard.qml @@ -1,80 +1,50 @@ -pragma ComponentBehavior: Bound - import QtQuick import QtQuick.Layouts -import QtQuick.Controls import Quickshell.Widgets import Quickshell.Services.Pipewire -import qs -import qs.widgets +import "../../widgets/" as Widgets +import "../.." -Loader { +WrapperRectangle { id: root - active: node !== null + color: ShellSettings.colors["surface_container"] + radius: width / 2 + margin: 6 required property PwNode node + property string text + property Component button + property Component icon - sourceComponent: WrapperRectangle { - id: comp - color: ShellSettings.colors.surface_container_translucent - radius: 12 - margin: 6 - - border { - width: 1 - color: ShellSettings.colors.active_translucent - } - - // property string text - // property Component button - // property Component icon - - PwObjectTracker { - id: tracker - objects: [root.node] - } - - RowLayout { - Slider { - value: root.node.audio.volume ?? 0 - // text: root.text - // icon: root.icon - - onValueChanged: { - // only allow changes when the node is ready other wise you will combust - if (!root.node.ready) - return; - - root.node.audio.volume = value; - } - - Layout.fillWidth: true - Layout.fillHeight: true - } - - // Loader { - // id: buttonLoader - // sourceComponent: root.button - // - // Layout.preferredWidth: this.height - // Layout.fillHeight: true - // } - } + PwObjectTracker { + id: tracker + objects: [root.node] } - // sourceComponent: VolumeCard { - // id: sinkCard - // node: sinkLoader.sink - // button: StyledMouseArea { - // property bool checked: !sinkCard.node.audio.muted - // - // // IconImage {} - // - // onClicked: { - // sinkCard.node.audio.muted = !sinkCard.node.audio.muted; - // } - // } - // - // anchors.fill: parent - // } + RowLayout { + Widgets.MaterialSlider { + value: root.node.audio.volume ?? 0 + text: root.text + icon: root.icon + + onValueChanged: { + // only allow changes when the node is ready other wise you will combust + if (!root.node.ready) + return; + + root.node.audio.volume = value; + } + + Layout.fillWidth: true + Layout.fillHeight: true + } + + Loader { + id: buttonLoader + sourceComponent: root.button + + Layout.preferredWidth: this.height + Layout.fillHeight: true + } + } } diff --git a/shell/bar/volume/VolumeControl.qml b/shell/bar/volume/VolumeControl.qml index bcb4f48..4423de1 100644 --- a/shell/bar/volume/VolumeControl.qml +++ b/shell/bar/volume/VolumeControl.qml @@ -3,34 +3,32 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import Quickshell.Widgets -import qs.widgets +import "../../widgets/" as Widgets -DeviceMixer {} +WrapperItem { + id: root + visible: false -// WrapperItem { -// id: root -// -// ColumnLayout { -// spacing: 10 -// -// // TabBar { -// // id: tabBar -// // model: ["headphones", "tune"] -// // Layout.fillWidth: true -// // Layout.preferredHeight: 35 -// // } -// -// -// // StackLayout { -// // id: page -// // currentIndex: tabBar.currentIndex -// // Layout.fillWidth: true -// // Layout.preferredHeight: currentItem ? currentItem.implicitHeight : 0 -// // -// // readonly property Item currentItem: children[currentIndex] -// // -// // DeviceMixer {} -// // ApplicationMixer {} -// // } -// } -// } + ColumnLayout { + spacing: 10 + + Widgets.TabBar { + id: tabBar + model: ["headphones", "tune"] + Layout.fillWidth: true + Layout.preferredHeight: 35 + } + + StackLayout { + id: page + currentIndex: tabBar.currentIndex + Layout.fillWidth: true + Layout.preferredHeight: currentItem ? currentItem.implicitHeight : 0 + + readonly property Item currentItem: children[currentIndex] + + DeviceMixer {} + ApplicationMixer {} + } + } +} diff --git a/shell/bar/volume/VolumeIndicator.qml b/shell/bar/volume/VolumeIndicator.qml index c251c4e..66f7a6e 100644 --- a/shell/bar/volume/VolumeIndicator.qml +++ b/shell/bar/volume/VolumeIndicator.qml @@ -1,65 +1,27 @@ -pragma ComponentBehavior: Bound - import QtQuick -import QtQuick.Layouts -import Quickshell.Widgets -import Quickshell.Services.Pipewire -import qs.widgets -import qs.bar +import "../../widgets/" as Widgets -StyledMouseArea { +Item { id: root - onClicked: showMenu = !showMenu - required property var bar - property bool showMenu: false + required property var popup - IconImage { - id: icon - source: "root:resources/volume/volume-full.svg" + Widgets.FontIconButton { + id: button + iconName: "volume_up" + anchors.fill: parent + onClicked: { + if (root.popup.content == volumeMenu) { + root.popup.hide(); + return; + } - anchors { - fill: parent - margins: 2 + root.popup.set(this, volumeMenu); + root.popup.show(); } } - property PopupItem menu: PopupItem { - id: menu - owner: root - popup: root.bar.popup - show: root.showMenu - onClosed: root.showMenu = false - - implicitWidth: 300 - implicitHeight: container.implicitHeight + (2 * 8) - - // implicitWidth: volumeMenu.implicitWidth - // implicitHeight: volumeMenu.implicitHeight - - // VolumeControl { - // id: volumeMenu - // } - - ColumnLayout { - id: container - - anchors { - fill: parent - margins: 8 - } - - VolumeCard { - node: Pipewire.defaultAudioSink - Layout.fillWidth: true - Layout.preferredHeight: 45 - } - - VolumeCard { - node: Pipewire.defaultAudioSource - Layout.fillWidth: true - Layout.preferredHeight: 45 - } - } + VolumeControl { + id: volumeMenu } } diff --git a/shell/launcher/Controller.qml b/shell/launcher/Controller.qml index e56f366..3a24e00 100644 --- a/shell/launcher/Controller.qml +++ b/shell/launcher/Controller.qml @@ -7,8 +7,7 @@ import Quickshell import Quickshell.Io import Quickshell.Wayland import Quickshell.Widgets -import qs -import qs.widgets +import ".." Singleton { PersistentProperties { @@ -34,50 +33,46 @@ Singleton { LazyLoader { id: loader - // activeAsync: persist.launcherOpen - active: persist.launcherOpen + activeAsync: persist.launcherOpen PanelWindow { + implicitWidth: 500 + implicitHeight: 7 + searchContainer.implicitHeight + list.topMargin * 2 + list.delegateHeight * 10 color: "transparent" - exclusiveZone: 0 WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive // WlrLayershell.namespace: "shell:launcher" - anchors { - top: true - bottom: true - left: true - right: true - } - - WrapperRectangle { - clip: true - radius: 12 + Rectangle { + id: container color: ShellSettings.colors.surface_translucent - margin: 6 - - border { - width: 1 - color: ShellSettings.colors.active_translucent - } + radius: 12 anchors { - horizontalCenter: parent.horizontalCenter - top: parent.top - topMargin: screen.height / 2.75 + fill: parent + margins: 10 + } + + Behavior on height { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } } ColumnLayout { - id: column - anchors.centerIn: parent + anchors.fill: parent + anchors.margins: 7 + anchors.topMargin: 10 + anchors.bottomMargin: 0 + spacing: 0 - StyledRectangle { + Rectangle { id: searchContainer + Layout.fillWidth: true implicitHeight: searchbox.implicitHeight + 15 radius: 6 - - // Width is largely determined by size of the searchContainer - Layout.preferredWidth: 500 + color: ShellSettings.colors.surface_container_translucent + border.color: ShellSettings.colors.border_translucent RowLayout { id: searchbox @@ -86,8 +81,8 @@ Singleton { TextInput { id: search - color: ShellSettings.colors.highlight Layout.fillWidth: true + color: ShellSettings.colors.highlight focus: true Keys.forwardTo: [list] @@ -120,114 +115,97 @@ Singleton { ListView { id: list - visible: Layout.preferredHeight > 1 + Layout.fillWidth: true + Layout.fillHeight: true clip: true cacheBuffer: 0 // works around QTBUG-131106 //reuseItems: true - - Layout.fillWidth: true - Layout.preferredHeight: Math.min(matchesLength * delegateHeight, 500) - - Behavior on Layout.preferredHeight { - NumberAnimation { - duration: 200 - easing.type: Easing.OutCubic - } - } - - property var matchesLength: model.values.length - model: ScriptModel { - values: { + values: DesktopEntries.applications.values.map(object => { const stxt = search.text.toLowerCase(); + const ntxt = object.name.toLowerCase(); + let si = 0; + let ni = 0; - if (stxt === '') - return []; + let matches = []; + let startMatch = -1; - return DesktopEntries.applications.values.map(object => { - // const stxt = search.text.toLowerCase(); + for (let si = 0; si != stxt.length; ++si) { + const sc = stxt[si]; - const ntxt = object.name.toLowerCase(); - let si = 0; - let ni = 0; + while (true) { + // Drop any entries with letters that don't exist in order + if (ni == ntxt.length) + return null; - let matches = []; - let startMatch = -1; + const nc = ntxt[ni++]; - for (let si = 0; si != stxt.length; ++si) { - const sc = stxt[si]; + if (nc == sc) { + if (startMatch == -1) + startMatch = ni; + break; + } else { + if (startMatch != -1) { + matches.push({ + index: startMatch, + length: ni - startMatch + }); - 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; - } + startMatch = -1; } } } + } - if (startMatch != -1) { - matches.push({ - index: startMatch, - length: ni - 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; + 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]; + 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; + s = bm.length - am.length; if (s != 0) return s; - s = a.object.name.length - b.object.name.length; + s = am.index - bm.index; if (s != 0) return s; - return a.object.name.localeCompare(b.object.name); - }).map(entry => entry.object); - } + ++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" @@ -293,7 +271,6 @@ Singleton { readonly property real delegateHeight: 44 delegate: MouseArea { - id: entryMouseArea required property DesktopEntry modelData implicitHeight: list.delegateHeight @@ -306,7 +283,6 @@ Singleton { RowLayout { id: delegateLayout - anchors { verticalCenter: parent.verticalCenter left: parent.left @@ -317,11 +293,10 @@ Singleton { Layout.alignment: Qt.AlignVCenter asynchronous: true implicitSize: 30 - source: Quickshell.iconPath(entryMouseArea.modelData.icon) + source: Quickshell.iconPath(modelData.icon) } - Text { - text: entryMouseArea.modelData.name + text: modelData.name color: ShellSettings.colors.active Layout.alignment: Qt.AlignVCenter } diff --git a/shell/notifications/ActiveToast.qml b/shell/notifications/ActiveToast.qml index 293ddaf..6f42c84 100644 --- a/shell/notifications/ActiveToast.qml +++ b/shell/notifications/ActiveToast.qml @@ -114,8 +114,8 @@ Item { font.bold: true elide: Text.ElideRight maximumLineCount: 1 - // Layout.preferredWidth: implicitWidth - // Layout.maximumWidth: topRow.width * 0.3 + Layout.preferredWidth: implicitWidth + Layout.maximumWidth: topRow.width * 0.3 } Text { diff --git a/shell/notifications/Controller.qml b/shell/notifications/Controller.qml index 8eed4d4..de7f5de 100644 --- a/shell/notifications/Controller.qml +++ b/shell/notifications/Controller.qml @@ -39,7 +39,7 @@ Scope { onVisibleCountChanged: visible = visibleCount != 0 color: "transparent" - implicitWidth: 500 + implicitWidth: 525 visible: false exclusionMode: ExclusionMode.Normal diff --git a/shell/resources/volume/volume-full.svg b/shell/resources/volume/volume-full.svg index 2c24be5..5126fca 100644 --- a/shell/resources/volume/volume-full.svg +++ b/shell/resources/volume/volume-full.svg @@ -1,9 +1,15 @@ - - - - - - - - - \ No newline at end of file + + + + volume-up-solid + + + + + + + + + + + diff --git a/shell/resources/volume/volume-mute.svg b/shell/resources/volume/volume-mute.svg index 4b67e0c..3604983 100644 --- a/shell/resources/volume/volume-mute.svg +++ b/shell/resources/volume/volume-mute.svg @@ -1,9 +1,16 @@ - - - - - - - - - \ No newline at end of file + + + + volume-off-solid + + + + + + + + + + + + diff --git a/shell/screencapture/SelectionRectangle.qml b/shell/screencapture/SelectionRectangle.qml index ff92c0e..71df1cf 100644 --- a/shell/screencapture/SelectionRectangle.qml +++ b/shell/screencapture/SelectionRectangle.qml @@ -17,8 +17,8 @@ Item { onVisibleChanged: { if (!visible) selectionRect.width -= borderSize; - selectionRect.height -= borderSize; - areaSelected(selectionRect); + selectionRect.height -= borderSize; + areaSelected(selectionRect); } MouseArea {