diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index bd19260..f68bc96 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -14,9 +14,9 @@ Variants { aboveWindows: true screen: modelData margins { - top: Settings.config.margins - left: Settings.config.margins - right: Settings.config.margins + top: Settings.config.floating ? Settings.config.margins : 0 + left: Settings.config.floating ? Settings.config.margins : 0 + right: Settings.config.floating ? Settings.config.margins : 0 } anchors { @@ -29,8 +29,8 @@ Variants { id: container implicitHeight: Settings.config.barHeight anchors.fill: parent - color: Colors.surface - radius: implicitHeight / 2 + color: Qt.rgba(Colors.surface.r, Colors.surface.g, Colors.surface.b, Settings.config.translucency) + radius: Settings.config.floating ? Settings.config.barHeight / 2 : 0 Row { id: leftStuff @@ -60,6 +60,7 @@ Variants { Volume {} Battery {} SysTray {} + SettingsIcon {} } } } diff --git a/modules/bar/Battery.qml b/modules/bar/Battery.qml index 483445a..4406296 100644 --- a/modules/bar/Battery.qml +++ b/modules/bar/Battery.qml @@ -15,7 +15,7 @@ Loader { sourceComponent: Rectangle { id: container radius: implicitHeight / 2 - color: clickHandler.containsMouse ? Colors.secondaryContainer : Colors.primaryContainer + color: clickHandler.containsMouse ? Colors.primary : Colors.surfaceContainer anchors.verticalCenter: parent.verticalCenter implicitWidth: root.implicitWidth + 20 implicitHeight: Settings.config.barHeight - 10 diff --git a/modules/bar/Clock.qml b/modules/bar/Clock.qml index 066e9f3..dcf5660 100644 --- a/modules/bar/Clock.qml +++ b/modules/bar/Clock.qml @@ -8,7 +8,7 @@ import qs.reusables Rectangle { id: container radius: implicitHeight / 2 - color: formatSwitch.containsMouse ? Colors.secondaryContainer : Colors.primaryContainer + color: formatSwitch.containsMouse ? Colors.primaryContainer : Colors.surfaceContainer anchors.verticalCenter: parent.verticalCenter implicitHeight: Settings.config.barHeight - 10 implicitWidth: root.implicitWidth + 20 diff --git a/modules/bar/Mpris.qml b/modules/bar/Mpris.qml index f79c89f..5047c19 100644 --- a/modules/bar/Mpris.qml +++ b/modules/bar/Mpris.qml @@ -8,7 +8,7 @@ Rectangle { id: container visible: root.spotify != null radius: implicitHeight / 2 - color: clickHandler.containsMouse ? Colors.secondaryContainer : Colors.primaryContainer + color: clickHandler.containsMouse ? Colors.primaryContainer : Colors.surfaceContainer implicitWidth: root.implicitWidth + 20 implicitHeight: Settings.config.barHeight - 10 Item { diff --git a/modules/bar/SettingsIcon.qml b/modules/bar/SettingsIcon.qml new file mode 100644 index 0000000..29d2bb7 --- /dev/null +++ b/modules/bar/SettingsIcon.qml @@ -0,0 +1,29 @@ +import QtQuick +import qs.modules.widgets.settingsapp +import qs.settings +import qs.reusables +import qs + +Rectangle { + id: root + radius: implicitHeight / 2 + color: pavuArea.containsMouse ? Colors.primaryContainer : Colors.surfaceContainer + anchors.verticalCenter: parent.verticalCenter + implicitWidth: volumeIcon.implicitWidth + 5 + implicitHeight: Settings.config.barHeight - 10 + CustomIcon { + id: volumeIcon + anchors.centerIn: parent + text: "settings" + } + MouseArea { + id: pavuArea + anchors.fill: root + onClicked: { + Settings.config.settingsShown = true; + } + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + } +} diff --git a/modules/bar/Title.qml b/modules/bar/Title.qml index a8d1fb0..85df49e 100644 --- a/modules/bar/Title.qml +++ b/modules/bar/Title.qml @@ -3,12 +3,11 @@ import Quickshell.Wayland import qs import qs.settings import qs.reusables -import QtQuick.Dialogs Rectangle { id: container radius: implicitHeight / 2 - color: Colors.primaryContainer + color: Colors.surfaceContainer anchors.verticalCenter: parent.verticalCenter implicitWidth: root.implicitWidth implicitHeight: Settings.config.barHeight - 10 @@ -24,29 +23,5 @@ Rectangle { text: root.activeWindow ? root.activeWindow.activated ? root.activeWindow.appId : "Desktop" : "Desktop" elide: Text.ElideRight } - MouseArea { - id: fontOpener - FontDialog { - id: fontPicker - title: "qs-fontpicker" - flags: FontDialog.NoButtons | FontDialog.MonospacedFonts - - onAccepted: { - Settings.config.font = selectedFont.family; - Settings.config.fontSize = selectedFont.pointSize; - } - onSelectedFontChanged: { - Settings.config.font = selectedFont.family; - Settings.config.fontSize = selectedFont.pointSize; - } - } - anchors.fill: parent - acceptedButtons: Qt.LeftButton - cursorShape: Qt.PointingHandCursor - onClicked: { - fontPicker.open(); - console.log(fontPicker.selectedFont.family); - } - } } } diff --git a/modules/bar/Volume.qml b/modules/bar/Volume.qml index a03f9b3..47945af 100644 --- a/modules/bar/Volume.qml +++ b/modules/bar/Volume.qml @@ -9,7 +9,7 @@ import qs Rectangle { id: container radius: implicitHeight / 2 - color: pavuArea.containsMouse ? Colors.secondaryContainer : Colors.primaryContainer + color: pavuArea.containsMouse ? Colors.primaryContainer : Colors.surfaceContainer anchors.verticalCenter: parent.verticalCenter implicitWidth: root.implicitWidth + 20 implicitHeight: Settings.config.barHeight - 10 diff --git a/modules/bar/Workspaces.qml b/modules/bar/Workspaces.qml index 739e160..82621f2 100644 --- a/modules/bar/Workspaces.qml +++ b/modules/bar/Workspaces.qml @@ -5,10 +5,13 @@ import qs import qs.settings import qs.reusables -Item { +Rectangle { id: root - implicitWidth: workspaceRow.implicitWidth - implicitHeight: workspaceRow.implicitHeight + color: Colors.surfaceContainer + + implicitWidth: workspaceRow.implicitWidth + 10 + implicitHeight: Settings.config.barHeight - 10 + radius: Settings.config.barHeight / 2 anchors.verticalCenter: parent.verticalCenter property var screen: screen Row { @@ -43,7 +46,8 @@ Item { CustomText { anchors.centerIn: workspaceNumber text: parent.modelData.id - color: workspaceNumber.modelData.focused ? Colors.onSecondaryContainerColor : Colors.surfaceVariant + color: Colors.onSurfaceColor + opacity: workspaceNumber.modelData.focused ? 1 : 0.5 } MouseArea { anchors.fill: parent diff --git a/modules/notifications/Notification.qml b/modules/notifications/Notification.qml index b86d4eb..4d2dac6 100644 --- a/modules/notifications/Notification.qml +++ b/modules/notifications/Notification.qml @@ -17,7 +17,7 @@ Variants { bottom: true } margins { - top: Settings.config.barHeight + Settings.config.margins + 10 + top: Settings.config.floating ? Settings.config.barHeight + Settings.config.margins + 10 : Settings.config.barHeight + 10 right: 10 left: 10 } diff --git a/modules/overlays/ScreenCorners.qml b/modules/overlays/ScreenCorners.qml new file mode 100644 index 0000000..74b0400 --- /dev/null +++ b/modules/overlays/ScreenCorners.qml @@ -0,0 +1,224 @@ +import QtQuick +import QtQuick.Shapes +import qs +import qs.settings + +/** +* ScreenCorners - Shape component for rendering screen corners +* +* Renders concave corners at the screen edges to create a rounded screen effect. +* Self-contained Shape component (no shadows). +*/ +Item { + id: root + + anchors.fill: parent + + // Wrapper with layer caching to reduce GPU tessellation overhead + Item { + anchors.fill: parent + + // Cache the Shape to a texture to prevent continuous re-tessellation + layer.enabled: true + + Shape { + id: cornersShape + + anchors.fill: parent + preferredRendererType: Shape.CurveRenderer + enabled: false // Disable mouse input + + ShapePath { + id: cornersPath + + // Corner configuration + readonly property color cornerColor: Qt.rgba(Colors.surface.r, Colors.surface.g, Colors.surface.b, Settings.config.translucency) + readonly property real cornerRadius: Settings.config.screenCornerRadius + readonly property real cornerSize: Settings.config.screenCornerRadius + + // Determine margins based on bar position + readonly property real topMargin: Settings.config.floating ? 0 : Settings.config.barHeight + readonly property real bottomMargin: 0 + readonly property real leftMargin: 0 + readonly property real rightMargin: 0 + + // Screen dimensions + readonly property real screenWidth: cornersShape.width + readonly property real screenHeight: cornersShape.height + + // Only show screen corners if enabled and appropriate conditions are met + readonly property bool shouldShow: Settings.config.showScreenCorners + + // ShapePath configuration + strokeWidth: -1 // No stroke, fill only + fillColor: shouldShow ? cornerColor : "transparent" + + // Smooth color animation (disabled during theme transitions to sync with Color.qml) + + // ========== PATH DEFINITION ========== + // Draws 4 separate corner squares at screen edges + // Each corner square has a concave arc on the inner diagonal + + // ========== TOP-LEFT CORNER ========== + // Arc is at the bottom-right of this square (inner diagonal) + // Start at top-left screen corner + startX: leftMargin + startY: topMargin + + // Top edge (moving right) + PathLine { + relativeX: cornersPath.cornerSize + relativeY: 0 + } + + // Right edge (moving down toward arc) + PathLine { + relativeX: 0 + relativeY: cornersPath.cornerSize - cornersPath.cornerRadius + } + + // Concave arc (bottom-right corner of square, curving inward toward screen center) + PathArc { + relativeX: -cornersPath.cornerRadius + relativeY: cornersPath.cornerRadius + radiusX: cornersPath.cornerRadius + radiusY: cornersPath.cornerRadius + direction: PathArc.Counterclockwise + } + + // Bottom edge (moving left) + PathLine { + relativeX: -(cornersPath.cornerSize - cornersPath.cornerRadius) + relativeY: 0 + } + + // Left edge (moving up) - closes back to start + PathLine { + relativeX: 0 + relativeY: -cornersPath.cornerSize + } + + // ========== TOP-RIGHT CORNER ========== + // Arc is at the bottom-left of this square (inner diagonal) + PathMove { + x: cornersPath.screenWidth - cornersPath.rightMargin - cornersPath.cornerSize + y: cornersPath.topMargin + } + + // Top edge (moving right) + PathLine { + relativeX: cornersPath.cornerSize + relativeY: 0 + } + + // Right edge (moving down) + PathLine { + relativeX: 0 + relativeY: cornersPath.cornerSize + } + + // Bottom edge (moving left toward arc) + PathLine { + relativeX: -(cornersPath.cornerSize - cornersPath.cornerRadius) + relativeY: 0 + } + + // Concave arc (bottom-left corner of square, curving inward toward screen center) + PathArc { + relativeX: -cornersPath.cornerRadius + relativeY: -cornersPath.cornerRadius + radiusX: cornersPath.cornerRadius + radiusY: cornersPath.cornerRadius + direction: PathArc.Counterclockwise + } + + // Left edge (moving up) - closes back to start + PathLine { + relativeX: 0 + relativeY: -(cornersPath.cornerSize - cornersPath.cornerRadius) + } + + // ========== BOTTOM-LEFT CORNER ========== + // Arc is at the top-right of this square (inner diagonal) + PathMove { + x: cornersPath.leftMargin + y: cornersPath.screenHeight - cornersPath.bottomMargin - cornersPath.cornerSize + } + + // Top edge (moving right toward arc) + PathLine { + relativeX: cornersPath.cornerSize - cornersPath.cornerRadius + relativeY: 0 + } + + // Concave arc (top-right corner of square, curving inward toward screen center) + PathArc { + relativeX: cornersPath.cornerRadius + relativeY: cornersPath.cornerRadius + radiusX: cornersPath.cornerRadius + radiusY: cornersPath.cornerRadius + direction: PathArc.Counterclockwise + } + + // Right edge (moving down) + PathLine { + relativeX: 0 + relativeY: cornersPath.cornerSize - cornersPath.cornerRadius + } + + // Bottom edge (moving left) + PathLine { + relativeX: -cornersPath.cornerSize + relativeY: 0 + } + + // Left edge (moving up) - closes back to start + PathLine { + relativeX: 0 + relativeY: -cornersPath.cornerSize + } + + // ========== BOTTOM-RIGHT CORNER ========== + // Arc is at the top-left of this square (inner diagonal) + // Start at bottom-right of square (different from other corners!) + PathMove { + x: cornersPath.screenWidth - cornersPath.rightMargin + y: cornersPath.screenHeight - cornersPath.bottomMargin + } + + // Bottom edge (moving left) + PathLine { + relativeX: -cornersPath.cornerSize + relativeY: 0 + } + + // Left edge (moving up toward arc) + PathLine { + relativeX: 0 + relativeY: -(cornersPath.cornerSize - cornersPath.cornerRadius) + } + + // Concave arc (top-left corner of square, curving inward toward screen center) + PathArc { + relativeX: cornersPath.cornerRadius + relativeY: -cornersPath.cornerRadius + radiusX: cornersPath.cornerRadius + radiusY: cornersPath.cornerRadius + direction: PathArc.Counterclockwise + } + + // Top edge (moving right) + PathLine { + relativeX: cornersPath.cornerSize - cornersPath.cornerRadius + relativeY: 0 + } + + // Right edge (moving down) - closes back to start + PathLine { + relativeX: 0 + relativeY: cornersPath.cornerSize + } + } + } + } +} diff --git a/modules/overlays/Wallpaper.qml b/modules/overlays/Wallpaper.qml index ba11b22..2191133 100644 --- a/modules/overlays/Wallpaper.qml +++ b/modules/overlays/Wallpaper.qml @@ -27,5 +27,6 @@ Variants { fillMode: Image.Stretch source: Settings.config.currentWall } + ScreenCorners {} } } diff --git a/modules/widgets/SettingsApp/Appearance.qml b/modules/widgets/SettingsApp/Appearance.qml deleted file mode 100644 index 912155b..0000000 --- a/modules/widgets/SettingsApp/Appearance.qml +++ /dev/null @@ -1,14 +0,0 @@ - - -import QtQuick -import qs -import qs.reusables - -Item { - id: root - implicitWidth: 300 - implicitHeight: 300 - CustomText { - text: "I am the Appearance page" - } -} diff --git a/modules/widgets/settingsapp/Appearance.qml b/modules/widgets/settingsapp/Appearance.qml new file mode 100644 index 0000000..d412654 --- /dev/null +++ b/modules/widgets/settingsapp/Appearance.qml @@ -0,0 +1,80 @@ +import QtQuick +import qs +import qs.reusables +import QtQuick.Layouts +import qs.settings +import Quickshell.Widgets +import QtQuick.Controls +import QtQuick.Dialogs + +ClippingWrapperRectangle { + id: root + FontDialog { + id: fontPicker + title: "qs-fontpicker" + flags: FontDialog.NoButtons | FontDialog.MonospacedFonts + + onAccepted: { + Settings.config.font = selectedFont.family; + Settings.config.fontSize = selectedFont.pointSize; + } + onSelectedFontChanged: { + Settings.config.font = selectedFont.family; + Settings.config.fontSize = selectedFont.pointSize; + } + } + anchors.centerIn: parent + clip: true + color: Colors.surfaceContainerLow + radius: 12 + margin: 20 + + ColumnLayout { + id: verticalLayout + Rectangle { + id: fontWrapper + radius: 14 + color: Colors.surfaceContainerHigh + implicitHeight: fontLayout.implicitHeight + 10 + implicitWidth: fontLayout.implicitWidth + 10 + RowLayout { + id: fontLayout + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + clip: true + spacing: 10 + CustomText { + id: fontText + font.bold: true + text: "current font: " + Settings.config.font + } + Rectangle { + id: fontSelector + Layout.rightMargin: 5 + implicitWidth: fontSelectorText.implicitWidth + 20 + implicitHeight: 20 + color: Colors.surfaceContainerHigh + border.width: 2 + border.color: Colors.outline + radius: 12 + CustomText { + id: fontSelectorText + anchors.centerIn: parent + text: "Pick Font" + } + MouseArea { + id: fontPickerOpener + anchors.fill: parent + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + onClicked: fontPicker.open() + } + } + } + } + Item { + id: spring + Layout.fillHeight: true + } + } +} diff --git a/modules/widgets/SettingsApp/MainWindow.qml b/modules/widgets/settingsapp/MainWindow.qml similarity index 91% rename from modules/widgets/SettingsApp/MainWindow.qml rename to modules/widgets/settingsapp/MainWindow.qml index 4bfcda1..f17a7e1 100644 --- a/modules/widgets/SettingsApp/MainWindow.qml +++ b/modules/widgets/settingsapp/MainWindow.qml @@ -10,6 +10,10 @@ import qs.reusables FloatingWindow { id: root + visible: Settings.config.settingsShown + onClosed: { + Settings.config.settingsShown = false; + } color: Colors.surface title: "qs-settings" implicitWidth: 800 @@ -35,13 +39,16 @@ FloatingWindow { } RowLayout { id: windowLayout + clip: true anchors.fill: parent + spacing: 10 ClippingWrapperRectangle { id: pageWrapper Layout.margins: 20 Layout.fillHeight: true Layout.preferredWidth: 200 + Layout.rightMargin: 0 margin: 20 color: Colors.surfaceContainerLow radius: 12 @@ -54,7 +61,7 @@ FloatingWindow { id: pageDelegate Rectangle { radius: 24 - color: ListView.isCurrentItem ? Colors.surfaceContainerHighest : "transparent" + color: ListView.isCurrentItem ? Colors.surfaceContainerHigh : "transparent" implicitHeight: 30 implicitWidth: pageWrapper.width - 50 required property var modelData @@ -82,6 +89,7 @@ FloatingWindow { } Loader { id: contentLoader + Layout.leftMargin: 0 Layout.fillHeight: true Layout.fillWidth: true Layout.margins: 20 diff --git a/modules/widgets/SettingsApp/Matugen.qml b/modules/widgets/settingsapp/Matugen.qml similarity index 100% rename from modules/widgets/SettingsApp/Matugen.qml rename to modules/widgets/settingsapp/Matugen.qml diff --git a/modules/widgets/SettingsApp/WelcomePage.qml b/modules/widgets/settingsapp/WelcomePage.qml similarity index 89% rename from modules/widgets/SettingsApp/WelcomePage.qml rename to modules/widgets/settingsapp/WelcomePage.qml index 495afbc..bad7084 100644 --- a/modules/widgets/SettingsApp/WelcomePage.qml +++ b/modules/widgets/settingsapp/WelcomePage.qml @@ -8,7 +8,7 @@ ClippingWrapperRectangle { id: root anchors.centerIn: parent clip: true - color: Colors.surfaceContainerHighest + color: Colors.surfaceContainerLow radius: 12 margin: 20 ColumnLayout { @@ -16,7 +16,7 @@ ClippingWrapperRectangle { spacing: 0 anchors.top: parent.top CustomText { - + topPadding: 10 text: "Welcome!" font.pixelSize: 24 font.bold: true diff --git a/modules/widgets/wallswitcher/WallSwitcher.qml b/modules/widgets/wallswitcher/WallSwitcher.qml index 4ca4be0..0ae305d 100644 --- a/modules/widgets/wallswitcher/WallSwitcher.qml +++ b/modules/widgets/wallswitcher/WallSwitcher.qml @@ -23,7 +23,7 @@ FloatingWindow { } Process { id: wallustRunner - property string cmd: "matugen image " + Settings.config.currentWall + " -t scheme-neutral" + property string cmd: "matugen image " + Settings.config.currentWall command: ["sh", "-c", cmd] } GlobalShortcut { @@ -46,9 +46,10 @@ FloatingWindow { Layout.bottomMargin: 0 radius: 14 implicitHeight: 30 - color: Colors.onPrimaryColor + color: Colors.surfaceContainerLow CustomText { id: titleText + font.bold: true anchors.centerIn: textWrapper text: "Wallpapers in " + Settings.config.wallDir } @@ -64,6 +65,7 @@ FloatingWindow { color: Colors.surfaceContainerLow GridView { id: gridRoot + anchors.margins: 20 property var columns: Math.floor(gridRoot.width / cellWidth) property var usedWidth: columns * cellWidth property var emptySpace: width - usedWidth @@ -78,7 +80,6 @@ FloatingWindow { anchors.fill: innerWindow anchors.centerIn: innerWindow leftMargin: emptySpace / 2 - topMargin: 20 model: folderModel delegate: fileDelegate FolderListModel { @@ -96,6 +97,7 @@ FloatingWindow { id: imageRounder implicitHeight: 80 implicitWidth: 120 + color: "transparent" required property string filePath radius: 12 child: Image { @@ -112,7 +114,7 @@ FloatingWindow { onClicked: { Settings.config.currentWall = imageRounder.filePath; if (Settings.config.generateScheme) { - wallustRunner.startDetached(); + wallustRunner.running = true; } } } diff --git a/settings/Settings.qml b/settings/Settings.qml index ba25888..ae5a6c9 100644 --- a/settings/Settings.qml +++ b/settings/Settings.qml @@ -7,34 +7,34 @@ import Quickshell.Io Singleton { id: root property alias config: settingsAdapter - property alias currentWall: settingsAdapter.currentWall - onConfigChanged: { - console.log('config change detected, writing adapter'); - settingsView.writeAdapter(); - } - + onConfigChanged: settingsView.writeAdapter() FileView { id: settingsView + path: "/home/lucy/.config/qs.json" + watchChanges: true onAdapterUpdated: writeAdapter() - path: "/home/lucy/.config/quickshell/settings/config.json" - watchChanges: false - + onFileChanged: reload() adapter: JsonAdapter { id: settingsAdapter - property var margins: 10 + property var margins: 20 property var currentWall: "" - property var barHeight: 28 + property var barHeight: 30 property var font: "" property var fontSize: 14 property var rounding: 10 property var wallDir: "file:///home/lucy/.walls/" - property bool floating: true + property bool floating: false property int paddingTop: 10 property int paddingSides: 10 property var generateScheme: true property bool wallSwitcherShown: false - property int fontWeight: 500 + property int fontWeight: 600 + property bool showScreenCorners: true + property int screenCornerRadius: 10 + property double translucency: 1 + property bool blackScreenCorners: true + property bool settingsShown: true } } } diff --git a/shell.qml b/shell.qml index 59936d8..678bf86 100644 --- a/shell.qml +++ b/shell.qml @@ -6,13 +6,14 @@ import qs.modules.bar import qs.modules.overlays import qs.modules.notifications import qs.modules.widgets.wallswitcher -import qs.modules.widgets.SettingsApp +import qs.modules.widgets.settingsapp ShellRoot { id: root - Ipc {} + Wallpaper {} Bar {} Notification {} - Wallpaper {} WallSwitcher {} + Ipc {} + MainWindow {} }