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:
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberAnimation {
|
Connections {
|
||||||
to: 0.02
|
target: root
|
||||||
duration: Theme.extraLongDuration
|
function on_BgColorChanged() { barShape.requestPaint() }
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.lineTo(0, RT)
|
||||||
|
ctx.arcTo(0, 0, RT, 0, RT)
|
||||||
|
|
||||||
|
ctx.closePath()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.fillStyle = root._bgColor
|
||||||
|
outline()
|
||||||
|
ctx.fill()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.effect: MultiEffect {
|
Canvas {
|
||||||
shadowEnabled: true
|
id: barTint
|
||||||
shadowHorizontalOffset: 0
|
anchors.fill: parent
|
||||||
shadowVerticalOffset: 4
|
antialiasing: true
|
||||||
shadowBlur: 0.5 // radius/32, adjusted for visual match
|
renderTarget: Canvas.FramebufferObject
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.15)
|
|
||||||
shadowOpacity: 0.15
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1035,8 +1114,8 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user