1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-31 00:42:50 -05:00

TopBar: add "goth" corners option for the swooping edge effect

This commit is contained in:
bbedward
2025-09-18 23:37:32 -04:00
parent 97f0acadb6
commit 542536455b
3 changed files with 159 additions and 61 deletions

View File

@@ -104,6 +104,7 @@ Singleton {
property real topBarInnerPadding: 8 property real topBarInnerPadding: 8
property bool topBarSquareCorners: false property bool topBarSquareCorners: false
property bool topBarNoBackground: false property bool topBarNoBackground: false
property bool topBarGothCornersEnabled: true
property bool lockScreenShowPowerActions: true property bool lockScreenShowPowerActions: true
property bool hideBrightnessSlider: false property bool hideBrightnessSlider: false
property int notificationTimeoutLow: 5000 property int notificationTimeoutLow: 5000
@@ -280,6 +281,7 @@ Singleton {
topBarInnerPadding = settings.topBarInnerPadding !== undefined ? settings.topBarInnerPadding : 8 topBarInnerPadding = settings.topBarInnerPadding !== undefined ? settings.topBarInnerPadding : 8
topBarSquareCorners = settings.topBarSquareCorners !== undefined ? settings.topBarSquareCorners : false topBarSquareCorners = settings.topBarSquareCorners !== undefined ? settings.topBarSquareCorners : false
topBarNoBackground = settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false topBarNoBackground = settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false
topBarGothCornersEnabled = settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : true
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true
hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({}) screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
@@ -382,6 +384,7 @@ Singleton {
"topBarInnerPadding": topBarInnerPadding, "topBarInnerPadding": topBarInnerPadding,
"topBarSquareCorners": topBarSquareCorners, "topBarSquareCorners": topBarSquareCorners,
"topBarNoBackground": topBarNoBackground, "topBarNoBackground": topBarNoBackground,
"topBarGothCornersEnabled": topBarGothCornersEnabled,
"lockScreenShowPowerActions": lockScreenShowPowerActions, "lockScreenShowPowerActions": lockScreenShowPowerActions,
"hideBrightnessSlider": hideBrightnessSlider, "hideBrightnessSlider": hideBrightnessSlider,
"notificationTimeoutLow": notificationTimeoutLow, "notificationTimeoutLow": notificationTimeoutLow,
@@ -962,6 +965,11 @@ Singleton {
saveSettings() saveSettings()
} }
function setTopBarGothCornersEnabled(enabled) {
topBarGothCornersEnabled = enabled
saveSettings()
}
function setLockScreenShowPowerActions(enabled) { function setLockScreenShowPowerActions(enabled) {
lockScreenShowPowerActions = enabled lockScreenShowPowerActions = enabled
saveSettings() saveSettings()

View File

@@ -866,6 +866,17 @@ Item {
checked) checked)
} }
} }
DankToggle {
width: parent.width
text: "Goth Corners"
description: "Add curved swooping tips at the bottom of the bar."
checked: SettingsData.topBarGothCornersEnabled
onToggled: checked => {
SettingsData.setTopBarGothCornersEnabled(
checked)
}
}
} }
} }

View File

@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Effects import QtQuick.Effects
import QtQuick.Shapes
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import Quickshell.Services.Mpris import Quickshell.Services.Mpris
@@ -22,6 +23,12 @@ PanelWindow {
property var modelData property var modelData
property var notepadVariants: null property var notepadVariants: null
property bool gothCornersEnabled: SettingsData.topBarGothCornersEnabled
property real wingtipsRadius: Theme.cornerRadius
readonly property real _wingR: Math.max(0, wingtipsRadius)
readonly property color _bgColor: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, topBarCore.backgroundTransparency)
readonly property color _tintColor: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
signal colorPickerRequested() signal colorPickerRequested()
function getNotepadInstanceForScreen() { function getNotepadInstanceForScreen() {
@@ -41,7 +48,7 @@ PanelWindow {
readonly property real widgetHeight: Math.max(20, 26 + SettingsData.topBarInnerPadding * 0.6) readonly property real widgetHeight: Math.max(20, 26 + SettingsData.topBarInnerPadding * 0.6)
screen: modelData screen: modelData
implicitHeight: effectiveBarHeight + SettingsData.topBarSpacing implicitHeight: effectiveBarHeight + SettingsData.topBarSpacing + (SettingsData.topBarGothCornersEnabled ? _wingR : 0)
color: "transparent" color: "transparent"
Component.onCompleted: { Component.onCompleted: {
const fonts = Qt.fontFamilies() const fonts = Qt.fontFamilies()
@@ -129,10 +136,10 @@ PanelWindow {
right: true right: true
} }
exclusiveZone: (!SettingsData.topBarVisible || topBarCore.autoHide) ? -1 : root.effectiveBarHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap exclusiveZone: (!SettingsData.topBarVisible || topBarCore.autoHide) ? -1 : root.effectiveBarHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2
mask: Region { mask: Region {
item: topBarMouseArea item: barShape
} }
Item { Item {
@@ -143,16 +150,9 @@ PanelWindow {
property real backgroundTransparency: SettingsData.topBarTransparency property real backgroundTransparency: SettingsData.topBarTransparency
property bool autoHide: SettingsData.topBarAutoHide property bool autoHide: SettingsData.topBarAutoHide
property bool reveal: { property bool reveal: {
// Handle Niri overview state first
if (CompositorService.isNiri && NiriService.inOverview) { if (CompositorService.isNiri && NiriService.inOverview) {
// If Show on Overview is enabled, show the bar return SettingsData.topBarOpenOnOverview
if (SettingsData.topBarOpenOnOverview) {
return true
} }
// If Show on Overview is disabled, hide the bar
return false
}
// Normal visibility logic when not in overview
return SettingsData.topBarVisible && (!autoHide || topBarMouseArea.containsMouse || hasActivePopout) return SettingsData.topBarVisible && (!autoHide || topBarMouseArea.containsMouse || hasActivePopout)
} }
@@ -210,13 +210,15 @@ PanelWindow {
MouseArea { MouseArea {
id: topBarMouseArea id: topBarMouseArea
height: parent.reveal ? root.effectiveBarHeight + SettingsData.topBarSpacing : 4 y: 0
height: topBarCore.reveal ? (root.effectiveBarHeight + SettingsData.topBarSpacing) : 4
anchors { anchors {
top: parent.top top: parent.top
left: parent.left left: parent.left
right: parent.right right: parent.right
} }
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.NoButton
Behavior on height { Behavior on height {
NumberAnimation { NumberAnimation {
@@ -231,7 +233,7 @@ PanelWindow {
transform: Translate { transform: Translate {
id: topBarSlide id: topBarSlide
y: topBarCore.reveal ? 0 : -(root.effectiveBarHeight - 4) y: Math.round(topBarCore.reveal ? 0 : -(root.effectiveBarHeight - 4))
Behavior on y { Behavior on y {
NumberAnimation { NumberAnimation {
@@ -242,63 +244,147 @@ PanelWindow {
} }
Item { Item {
id: barUnitInset
anchors.fill: parent anchors.fill: parent
anchors.topMargin: SettingsData.topBarSpacing
anchors.bottomMargin: 0
anchors.leftMargin: SettingsData.topBarSpacing anchors.leftMargin: SettingsData.topBarSpacing
anchors.rightMargin: SettingsData.topBarSpacing anchors.rightMargin: SettingsData.topBarSpacing
anchors.topMargin: SettingsData.topBarSpacing
Rectangle { Item {
id: barBackground
anchors.fill: parent anchors.fill: parent
radius: SettingsData.topBarSquareCorners ? 0 : Theme.cornerRadius anchors.bottomMargin: -(SettingsData.topBarGothCornersEnabled ? root._wingR : 0)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, topBarCore.backgroundTransparency)
layer.enabled: true
Rectangle { Canvas {
id: barShape
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04) antialiasing: true
radius: parent.radius renderTarget: Canvas.FramebufferObject
SequentialAnimation on opacity { property real h : height - (SettingsData.topBarGothCornersEnabled ? root._wingR : 0)
running: false property real rb : SettingsData.topBarGothCornersEnabled ? root._wingR : 0
loops: Animation.Infinite property real rt : SettingsData.topBarSquareCorners ? 0 : Theme.cornerRadius
NumberAnimation { onHChanged: requestPaint()
to: 0.08 onRbChanged: requestPaint()
duration: Theme.extraLongDuration onRtChanged: requestPaint()
easing.type: Theme.standardEasing
Connections {
target: root
function on_BgColorChanged() { barShape.requestPaint() }
} }
NumberAnimation { onPaint: {
to: 0.02 const ctx = getContext("2d")
duration: Theme.extraLongDuration const W = width, H = barShape.h, R = barShape.rb, RT = barShape.rt
easing.type: Theme.standardEasing
} ctx.reset()
} ctx.clearRect(0, 0, width, height)
function outline() {
ctx.beginPath()
ctx.moveTo(RT, 0)
ctx.lineTo(W - RT, 0)
ctx.arcTo(W, 0, W, RT, RT)
ctx.lineTo(W, H)
if (R > 0) {
ctx.lineTo(W, H + R)
ctx.arc(W - R, H + R, R, 0, -Math.PI / 2, true)
ctx.lineTo(R, H)
ctx.arc(R, H + R, R, -Math.PI / 2, -Math.PI, true)
ctx.lineTo(0, H + R)
} else {
ctx.lineTo(W, H - RT)
ctx.arcTo(W, H, W - RT, H, RT)
ctx.lineTo(RT, H)
ctx.arcTo(0, H, 0, H - RT, RT)
} }
layer.effect: MultiEffect { ctx.lineTo(0, RT)
shadowEnabled: true ctx.arcTo(0, 0, RT, 0, RT)
shadowHorizontalOffset: 0
shadowVerticalOffset: 4 ctx.closePath()
shadowBlur: 0.5 // radius/32, adjusted for visual match }
shadowColor: Qt.rgba(0, 0, 0, 0.15)
shadowOpacity: 0.15 ctx.fillStyle = root._bgColor
outline()
ctx.fill()
}
}
Canvas {
id: barTint
anchors.fill: parent
antialiasing: true
renderTarget: Canvas.FramebufferObject
Connections {
target: barShape
function onHChanged() { barTint.requestPaint() }
function onRbChanged() { barTint.requestPaint() }
function onRtChanged() { barTint.requestPaint() }
}
Connections {
target: root
function on_BgColorChanged() { barTint.requestPaint() }
}
onPaint: {
const ctx = getContext("2d")
const W = width, H = barShape.h, R = barShape.rb, RT = barShape.rt
ctx.reset()
ctx.clearRect(0, 0, width, height)
ctx.beginPath()
ctx.moveTo(RT, 0)
ctx.lineTo(W - RT, 0)
ctx.arcTo(W, 0, W, RT, RT)
ctx.lineTo(W, H)
if (R > 0) {
ctx.lineTo(W, H + R)
ctx.arc(W - R, H + R, R, 0, -Math.PI / 2, true)
ctx.lineTo(R, H)
ctx.arc(R, H + R, R, -Math.PI / 2, -Math.PI, true)
ctx.lineTo(0, H + R)
} else {
ctx.lineTo(W, H - RT)
ctx.arcTo(W, H, W - RT, H, RT)
ctx.lineTo(RT, H)
ctx.arcTo(0, H, 0, H - RT, RT)
}
ctx.lineTo(0, RT)
ctx.arcTo(0, 0, RT, 0, RT)
ctx.closePath()
ctx.fillStyle = root._tintColor
ctx.fill()
}
} }
} }
Item { Item {
id: topBarContent id: topBarContent
anchors.fill: parent
anchors.leftMargin: Math.max(Theme.spacingXS, SettingsData.topBarInnerPadding * 0.8)
anchors.rightMargin: Math.max(Theme.spacingXS, SettingsData.topBarInnerPadding * 0.8)
anchors.topMargin: SettingsData.topBarInnerPadding / 2
anchors.bottomMargin: SettingsData.topBarInnerPadding / 2
clip: true
readonly property int availableWidth: width readonly property int availableWidth: width
readonly property int launcherButtonWidth: 40 readonly property int launcherButtonWidth: 40
readonly property int workspaceSwitcherWidth: 120 // Approximate readonly property int workspaceSwitcherWidth: 120
readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference readonly property int focusedAppMaxWidth: 456
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2) readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2)
readonly property int rightSectionWidth: rightSection.width readonly property int rightSectionWidth: rightSection.width
readonly property int clockWidth: 120 // Approximate clock width readonly property int clockWidth: 120
readonly property int mediaMaxWidth: 280 // Normal max width readonly property int mediaMaxWidth: 280
readonly property int weatherWidth: 80 // Approximate weather width readonly property int weatherWidth: 80
readonly property bool validLayout: availableWidth > 100 && estimatedLeftSectionWidth > 0 && rightSectionWidth > 0 readonly property bool validLayout: availableWidth > 100 && estimatedLeftSectionWidth > 0 && rightSectionWidth > 0
readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2 readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2
readonly property int clockRightEdge: clockLeftEdge + clockWidth readonly property int clockRightEdge: clockLeftEdge + clockWidth
@@ -377,13 +463,6 @@ PanelWindow {
return componentMap[widgetId] || null return componentMap[widgetId] || null
} }
anchors.fill: parent
anchors.leftMargin: Math.max(Theme.spacingXS, SettingsData.topBarInnerPadding * 0.8)
anchors.rightMargin: Math.max(Theme.spacingXS, SettingsData.topBarInnerPadding * 0.8)
anchors.topMargin: SettingsData.topBarInnerPadding / 2
anchors.bottomMargin: SettingsData.topBarInnerPadding / 2
clip: true
Row { Row {
id: leftSection id: leftSection
@@ -686,7 +765,7 @@ PanelWindow {
dankDashPopoutLoader.active = true dankDashPopoutLoader.active = true
if (dankDashPopoutLoader.item) { if (dankDashPopoutLoader.item) {
dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible
dankDashPopoutLoader.item.currentTabIndex = 0 // Overview tab dankDashPopoutLoader.item.currentTabIndex = 0
} }
} }
} }
@@ -709,7 +788,7 @@ PanelWindow {
dankDashPopoutLoader.active = true dankDashPopoutLoader.active = true
if (dankDashPopoutLoader.item) { if (dankDashPopoutLoader.item) {
dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible
dankDashPopoutLoader.item.currentTabIndex = 1 // Media tab dankDashPopoutLoader.item.currentTabIndex = 1
} }
} }
} }
@@ -731,7 +810,7 @@ PanelWindow {
dankDashPopoutLoader.active = true dankDashPopoutLoader.active = true
if (dankDashPopoutLoader.item) { if (dankDashPopoutLoader.item) {
dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible dankDashPopoutLoader.item.dashVisible = !dankDashPopoutLoader.item.dashVisible
dankDashPopoutLoader.item.currentTabIndex = 2 // Weather tab dankDashPopoutLoader.item.currentTabIndex = 2
} }
} }
} }