Refactor: Panels and Bar background are now drawn separately with Shapes.

This commit is contained in:
ItsLemmy
2025-11-06 10:41:48 -05:00
parent 76a182a90c
commit e29c6ee1a6
109 changed files with 2381 additions and 2192 deletions
@@ -0,0 +1,161 @@
import QtQuick
import QtQuick.Shapes
import QtQuick.Effects
import qs.Commons
/**
* AllBackgrounds - Unified Shape container for all bar and panel backgrounds
*
* Unified shadow system. This component contains a single Shape
* with multiple ShapePath children (one for bar, one for each panel type).
*
* Benefits:
* - Single GPU-accelerated rendering pass for all backgrounds
* - Unified shadow system (one MultiEffect for everything)
*/
Item {
id: root
// Reference Bar
required property var bar
// Reference to MainScreen (for panel access)
required property var windowRoot
anchors.fill: parent
// The unified Shape container
Shape {
id: backgroundsShape
anchors.fill: parent
// Use curve renderer for smooth corners
preferredRendererType: Shape.CurveRenderer
// CRITICAL: Shape must not block mouse input!
// ShapePaths inside will render, but the Shape container itself should be transparent to input
enabled: false // Disable mouse input on the Shape itself
Component.onCompleted: {
Logger.d("AllBackgrounds", "AllBackgrounds initialized")
Logger.d("AllBackgrounds", " bar:", root.bar)
Logger.d("AllBackgrounds", " windowRoot:", root.windowRoot)
}
/**
* Bar
*/
BarBackground {
bar: root.bar
shapeContainer: backgroundsShape
}
/**
* Panels
*/
// Audio
PanelBackground {
panel: root.windowRoot.audioPanel
shapeContainer: backgroundsShape
}
// Battery
PanelBackground {
panel: root.windowRoot.batteryPanel
shapeContainer: backgroundsShape
}
// Bluetooth
PanelBackground {
panel: root.windowRoot.bluetoothPanel
shapeContainer: backgroundsShape
}
// Calendar
PanelBackground {
panel: root.windowRoot.calendarPanel
shapeContainer: backgroundsShape
}
// Control Center
PanelBackground {
panel: root.windowRoot.controlCenterPanel
shapeContainer: backgroundsShape
}
// Launcher
PanelBackground {
panel: root.windowRoot.launcherPanel
shapeContainer: backgroundsShape
}
// Notification History
PanelBackground {
panel: root.windowRoot.notificationHistoryPanel
shapeContainer: backgroundsShape
}
// Session Menu
PanelBackground {
panel: root.windowRoot.sessionMenuPanel
shapeContainer: backgroundsShape
}
// Settings
PanelBackground {
panel: root.windowRoot.settingsPanel
shapeContainer: backgroundsShape
}
// Setup Wizard
PanelBackground {
panel: root.windowRoot.setupWizardPanel
shapeContainer: backgroundsShape
}
// TrayDropdown
PanelBackground {
panel: root.windowRoot.trayDropdownPanel
shapeContainer: backgroundsShape
}
// TrayMenu
PanelBackground {
panel: root.windowRoot.trayMenuPanel
shapeContainer: backgroundsShape
}
// Wallpaper
PanelBackground {
panel: root.windowRoot.wallpaperPanel
shapeContainer: backgroundsShape
}
// WiFi
PanelBackground {
panel: root.windowRoot.wifiPanel
shapeContainer: backgroundsShape
}
// // Tray Dropdown
// PanelBackground {
// panel: root.windowRoot.trayDropdownPanel
// shapeContainer: backgroundsShape
// }
}
// Unified shadow system (one MultiEffect for all backgrounds)
MultiEffect {
source: backgroundsShape
anchors.fill: backgroundsShape
shadowEnabled: true
shadowBlur: Style.shadowBlur
shadowColor: Color.black
shadowHorizontalOffset: Settings.data.general.shadowOffsetX
shadowVerticalOffset: Settings.data.general.shadowOffsetY
}
}
@@ -0,0 +1,152 @@
import QtQuick
import QtQuick.Shapes
import qs.Commons
/**
* BarBackground - ShapePath component for rendering the bar background
*
* Unified shadow system. This component is a ShapePath that will be
* a child of the unified AllBackgrounds Shape container.
*
* Uses 4-state per-corner system for flexible corner rendering:
* - State -1: No radius (flat/square corner)
* - State 0: Normal (inner curve)
* - State 1: Horizontal inversion (outer curve on X-axis)
* - State 2: Vertical inversion (outer curve on Y-axis)
*/
ShapePath {
id: root
// Required reference to the bar component
required property var bar
// Required reference to AllBackgrounds shapeContainer
required property var shapeContainer
// Corner radius (from Style)
readonly property real radius: Style.radiusL
// Bar position - since bar's parent fills the screen and Shape also fills the screen,
// we can use bar.x and bar.y directly (they're already in screen coordinates)
readonly property point barMappedPos: bar ? Qt.point(bar.x, bar.y) : Qt.point(0, 0)
// Flatten corners if bar is too small (handle null bar)
readonly property bool shouldFlatten: bar ? (bar.width < radius * 2 || bar.height < radius * 2) : false
readonly property real effectiveRadius: shouldFlatten ? (bar ? Math.min(bar.width / 2, bar.height / 2) : 0) : radius
// Helper functions (inlined from ShapeCornerHelper)
function getMultX(cornerState) {
return cornerState === 1 ? -1 : 1
}
function getMultY(cornerState) {
return cornerState === 2 ? -1 : 1
}
function getArcDirection(multX, multY) {
return ((multX < 0) !== (multY < 0)) ? PathArc.Counterclockwise : PathArc.Clockwise
}
function getCornerRadius(cornerState) {
// State -1 = no radius (flat corner)
if (cornerState === -1)
return 0
// All other states use effectiveRadius
return effectiveRadius
}
// Per-corner multipliers and radii based on bar's corner states (handle null bar)
readonly property real tlMultX: bar ? getMultX(bar.topLeftCornerState) : 1
readonly property real tlMultY: bar ? getMultY(bar.topLeftCornerState) : 1
readonly property real tlRadius: bar ? getCornerRadius(bar.topLeftCornerState) : 0
readonly property real trMultX: bar ? getMultX(bar.topRightCornerState) : 1
readonly property real trMultY: bar ? getMultY(bar.topRightCornerState) : 1
readonly property real trRadius: bar ? getCornerRadius(bar.topRightCornerState) : 0
readonly property real brMultX: bar ? getMultX(bar.bottomRightCornerState) : 1
readonly property real brMultY: bar ? getMultY(bar.bottomRightCornerState) : 1
readonly property real brRadius: bar ? getCornerRadius(bar.bottomRightCornerState) : 0
readonly property real blMultX: bar ? getMultX(bar.bottomLeftCornerState) : 1
readonly property real blMultY: bar ? getMultY(bar.bottomLeftCornerState) : 1
readonly property real blRadius: bar ? getCornerRadius(bar.bottomLeftCornerState) : 0
// ShapePath configuration
strokeWidth: -1 // No stroke, fill only
fillColor: Qt.alpha(Color.mSurface, Settings.data.bar.backgroundOpacity)
// Starting position (top-left corner, after the arc)
// Use mapped coordinates relative to the Shape container
startX: barMappedPos.x + tlRadius * tlMultX
startY: barMappedPos.y
// Smooth color animation
Behavior on fillColor {
ColorAnimation {
duration: Style.animationFast
}
}
// ========== PATH DEFINITION ==========
// Draws a rectangle with potentially inverted corners
// All coordinates are relative to startX/startY
// Top edge (moving right)
PathLine {
relativeX: (bar ? bar.width : 0) - root.tlRadius * root.tlMultX - root.trRadius * root.trMultX
relativeY: 0
}
// Top-right corner arc
PathArc {
relativeX: root.trRadius * root.trMultX
relativeY: root.trRadius * root.trMultY
radiusX: root.trRadius
radiusY: root.trRadius
direction: root.getArcDirection(root.trMultX, root.trMultY)
}
// Right edge (moving down)
PathLine {
relativeX: 0
relativeY: (bar ? bar.height : 0) - root.trRadius * root.trMultY - root.brRadius * root.brMultY
}
// Bottom-right corner arc
PathArc {
relativeX: -root.brRadius * root.brMultX
relativeY: root.brRadius * root.brMultY
radiusX: root.brRadius
radiusY: root.brRadius
direction: root.getArcDirection(root.brMultX, root.brMultY)
}
// Bottom edge (moving left)
PathLine {
relativeX: -((bar ? bar.width : 0) - root.brRadius * root.brMultX - root.blRadius * root.blMultX)
relativeY: 0
}
// Bottom-left corner arc
PathArc {
relativeX: -root.blRadius * root.blMultX
relativeY: -root.blRadius * root.blMultY
radiusX: root.blRadius
radiusY: root.blRadius
direction: root.getArcDirection(root.blMultX, root.blMultY)
}
// Left edge (moving up) - closes the path back to start
PathLine {
relativeX: 0
relativeY: -((bar ? bar.height : 0) - root.blRadius * root.blMultY - root.tlRadius * root.tlMultY)
}
// Top-left corner arc (back to start)
PathArc {
relativeX: root.tlRadius * root.tlMultX
relativeY: -root.tlRadius * root.tlMultY
radiusX: root.tlRadius
radiusY: root.tlRadius
direction: root.getArcDirection(root.tlMultX, root.tlMultY)
}
}
@@ -0,0 +1,174 @@
import QtQuick
import QtQuick.Shapes
import qs.Commons
/**
* PanelBackground - ShapePath component for rendering a single background
*
* Unified shadow system. This component is a ShapePath that will
* be a child of the unified AllBackgrounds Shape container.
*
* Uses 4-state per-corner system for flexible corner rendering:
* - State -1: No radius (flat/square corner)
* - State 0: Normal (inner curve)
* - State 1: Horizontal inversion (outer curve on X-axis)
* - State 2: Vertical inversion (outer curve on Y-axis)
*/
ShapePath {
id: root
// Required reference to the panel component (e.g., windowRoot.controlCenterPanel)
required property var panel
// Required reference to AllBackgrounds shapeContainer
required property var shapeContainer
// Corner radius (from Style)
readonly property real radius: Style.radiusL
// Get the actual panelBackground Item from SmartPanel
// Only access panelRegion if panel exists and is visible
readonly property var panelBg: (panel && panel.visible) ? panel.panelRegion : null
// Panel position - panelBg is in screen coordinates already
readonly property real panelX: panelBg ? panelBg.x : 0
readonly property real panelY: panelBg ? panelBg.y : 0
readonly property real panelWidth: panelBg ? panelBg.width : 0
readonly property real panelHeight: panelBg ? panelBg.height : 0
// Flatten corners if panel is too small
readonly property bool shouldFlatten: panelBg ? (panelWidth < radius * 2 || panelHeight < radius * 2) : false
readonly property real effectiveRadius: shouldFlatten ? Math.min(panelWidth / 2, panelHeight / 2) : radius
// Helper functions (inlined from ShapeCornerHelper)
function getMultX(cornerState) {
return cornerState === 1 ? -1 : 1
}
function getMultY(cornerState) {
return cornerState === 2 ? -1 : 1
}
function getArcDirection(multX, multY) {
return ((multX < 0) !== (multY < 0)) ? PathArc.Counterclockwise : PathArc.Clockwise
}
function getCornerRadius(cornerState) {
// State -1 = no radius (flat corner)
if (cornerState === -1)
return 0
// All other states use effectiveRadius
return effectiveRadius
}
// Per-corner multipliers and radii based on panelBg's corner states
readonly property real tlMultX: panelBg ? getMultX(panelBg.topLeftCornerState) : 1
readonly property real tlMultY: panelBg ? getMultY(panelBg.topLeftCornerState) : 1
readonly property real tlRadius: panelBg ? getCornerRadius(panelBg.topLeftCornerState) : 0
readonly property real trMultX: panelBg ? getMultX(panelBg.topRightCornerState) : 1
readonly property real trMultY: panelBg ? getMultY(panelBg.topRightCornerState) : 1
readonly property real trRadius: panelBg ? getCornerRadius(panelBg.topRightCornerState) : 0
readonly property real brMultX: panelBg ? getMultX(panelBg.bottomRightCornerState) : 1
readonly property real brMultY: panelBg ? getMultY(panelBg.bottomRightCornerState) : 1
readonly property real brRadius: panelBg ? getCornerRadius(panelBg.bottomRightCornerState) : 0
readonly property real blMultX: panelBg ? getMultX(panelBg.bottomLeftCornerState) : 1
readonly property real blMultY: panelBg ? getMultY(panelBg.bottomLeftCornerState) : 1
readonly property real blRadius: panelBg ? getCornerRadius(panelBg.bottomLeftCornerState) : 0
// DEBUG: Log panel state changes
onPanelChanged: {
Logger.d("PanelBackground", "=== panel changed:", panel)
Logger.d("PanelBackground", " panel.visible:", panel ? panel.visible : "null")
Logger.d("PanelBackground", " panel.panelRegion:", panel ? panel.panelRegion : "null")
}
onPanelBgChanged: {
Logger.d("PanelBackground", "=== panelBg changed:", panelBg)
if (panelBg) {
Logger.d("PanelBackground", " Geometry:", panelX, panelY, panelWidth, "x", panelHeight)
Logger.d("PanelBackground", " startX:", startX, "startY:", startY)
Logger.d("PanelBackground", " fillColor:", fillColor)
}
}
// ShapePath configuration
strokeWidth: -1 // No stroke, fill only
// Starting position (top-left corner, after the arc)
startX: panelX + tlRadius * tlMultX
startY: panelY
fillColor: Color.mSurface
// Smooth color animation
Behavior on fillColor {
ColorAnimation {
duration: Style.animationFast
}
}
// ========== PATH DEFINITION ==========
// Draws a rectangle with potentially inverted corners
// All coordinates are relative to startX/startY
// Top edge (moving right)
PathLine {
relativeX: root.panelWidth - root.tlRadius * root.tlMultX - root.trRadius * root.trMultX
relativeY: 0
}
// Top-right corner arc
PathArc {
relativeX: root.trRadius * root.trMultX
relativeY: root.trRadius * root.trMultY
radiusX: root.trRadius
radiusY: root.trRadius
direction: root.getArcDirection(root.trMultX, root.trMultY)
}
// Right edge (moving down)
PathLine {
relativeX: 0
relativeY: root.panelHeight - root.trRadius * root.trMultY - root.brRadius * root.brMultY
}
// Bottom-right corner arc
PathArc {
relativeX: -root.brRadius * root.brMultX
relativeY: root.brRadius * root.brMultY
radiusX: root.brRadius
radiusY: root.brRadius
direction: root.getArcDirection(root.brMultX, root.brMultY)
}
// Bottom edge (moving left)
PathLine {
relativeX: -(root.panelWidth - root.brRadius * root.brMultX - root.blRadius * root.blMultX)
relativeY: 0
}
// Bottom-left corner arc
PathArc {
relativeX: -root.blRadius * root.blMultX
relativeY: -root.blRadius * root.blMultY
radiusX: root.blRadius
radiusY: root.blRadius
direction: root.getArcDirection(root.blMultX, root.blMultY)
}
// Left edge (moving up) - closes the path back to start
PathLine {
relativeX: 0
relativeY: -(root.panelHeight - root.blRadius * root.blMultY - root.tlRadius * root.tlMultY)
}
// Top-left corner arc (back to start)
PathArc {
relativeX: root.tlRadius * root.tlMultX
relativeY: -root.tlRadius * root.tlMultY
radiusX: root.tlRadius
radiusY: root.tlRadius
direction: root.getArcDirection(root.tlMultX, root.tlMultY)
}
}