Optimization: Dock get loaded only on assigned screens instead of being invisble.

This commit is contained in:
LemmyCook 2025-08-25 21:42:27 -04:00
parent 18b79913bd
commit fcedb65119

View file

@ -9,287 +9,286 @@ import qs.Commons
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Loader { Variants {
active: (Settings.data.dock.monitors.length > 0) model: Quickshell.screens
sourceComponent: Component {
Variants {
model: Quickshell.screens
PanelWindow { Loader {
id: dockWindow
required property ShellScreen modelData required property ShellScreen modelData
readonly property real scaling: ScalingService.scale(screen) readonly property real scaling: ScalingService.scale(modelData)
screen: modelData
// Auto-hide properties - make reactive to settings changes active: modelData ? Settings.data.dock.monitors.includes(modelData.name) : false
property bool autoHide: Settings.data.dock.autoHide || (Settings.data.bar.position === "bottom")
property bool hidden: autoHide
property int hideDelay: 500
property int showDelay: 100
property int hideAnimationDuration: Style.animationFast
property int showAnimationDuration: Style.animationFast
property int peekHeight: 2
property int fullHeight: dockContainer.height
property int iconSize: 36
// Track hover state sourceComponent: PanelWindow {
property bool dockHovered: false id: dockWindow
property bool anyAppHovered: false
// Dock is only shown if explicitely toggled screen: modelData
visible: modelData ? Settings.data.dock.monitors.includes(modelData.name) : false
exclusionMode: ExclusionMode.Ignore // Auto-hide properties - make reactive to settings changes
property bool autoHide: Settings.data.dock.autoHide || (Settings.data.bar.position === "bottom")
property bool hidden: autoHide
property int hideDelay: 500
property int showDelay: 100
property int hideAnimationDuration: Style.animationFast
property int showAnimationDuration: Style.animationFast
property int peekHeight: 2
property int fullHeight: dockContainer.height
property int iconSize: 36
anchors.bottom: true // Track hover state
anchors.left: true property bool dockHovered: false
anchors.right: true property bool anyAppHovered: false
focusable: false
color: Color.transparent
implicitHeight: iconSize * 1.4 * scaling
// Watch for autoHide setting changes // Dock is only shown if explicitely toggled
onAutoHideChanged: { exclusionMode: ExclusionMode.Ignore
if (!autoHide) {
// If auto-hide is disabled, show the dock anchors.bottom: true
hidden = false anchors.left: true
hideTimer.stop() anchors.right: true
showTimer.stop() focusable: false
} else { color: Color.transparent
// If auto-hide is enabled, start hidden implicitHeight: iconSize * 1.4 * scaling
// Watch for autoHide setting changes
onAutoHideChanged: {
if (!autoHide) {
// If auto-hide is disabled, show the dock
hidden = false
hideTimer.stop()
showTimer.stop()
} else {
// If auto-hide is enabled, start hidden
hidden = true
}
}
// Timer for auto-hide delay
Timer {
id: hideTimer
interval: hideDelay
onTriggered: {
if (autoHide && !dockHovered && !anyAppHovered) {
hidden = true hidden = true
} }
} }
}
// Timer for auto-hide delay // Timer for show delay
Timer { Timer {
id: hideTimer id: showTimer
interval: hideDelay interval: showDelay
onTriggered: { onTriggered: hidden = false
if (autoHide && !dockHovered && !anyAppHovered) { }
hidden = true
} // Behavior for smooth hide/show animations
Behavior on margins.bottom {
NumberAnimation {
duration: hidden ? hideAnimationDuration : showAnimationDuration
easing.type: Easing.InOutQuad
}
}
MouseArea {
id: screenEdgeMouseArea
x: 0
y: modelData && modelData.geometry ? modelData.geometry.height - (fullHeight + 10 * scaling) : 0
width: screen.width
height: fullHeight + 10 * scaling
hoverEnabled: true
propagateComposedEvents: true
onEntered: {
if (autoHide && hidden) {
showTimer.start()
} }
} }
onExited: {
// Timer for show delay if (autoHide && !hidden && !dockHovered && !anyAppHovered) {
Timer { hideTimer.start()
id: showTimer
interval: showDelay
onTriggered: hidden = false
}
// Behavior for smooth hide/show animations
Behavior on margins.bottom {
NumberAnimation {
duration: hidden ? hideAnimationDuration : showAnimationDuration
easing.type: Easing.InOutQuad
} }
} }
}
margins.bottom: hidden ? -(fullHeight - peekHeight) : 0
Rectangle {
id: dockContainer
width: dock.width + 48 * scaling
height: iconSize * 1.4 * scaling
color: Color.mSurface
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
topLeftRadius: Style.radiusL * scaling
topRightRadius: Style.radiusL * scaling
MouseArea { MouseArea {
id: screenEdgeMouseArea id: dockMouseArea
x: 0 anchors.fill: parent
y: modelData && modelData.geometry ? modelData.geometry.height - (fullHeight + 10 * scaling) : 0
width: screen.width
height: fullHeight + 10 * scaling
hoverEnabled: true hoverEnabled: true
propagateComposedEvents: true propagateComposedEvents: true
onEntered: { onEntered: {
if (autoHide && hidden) { dockHovered = true
showTimer.start() if (autoHide) {
showTimer.stop()
hideTimer.stop()
hidden = false
} }
} }
onExited: { onExited: {
if (autoHide && !hidden && !dockHovered && !anyAppHovered) { dockHovered = false
// Only start hide timer if we're not hovering over any app
if (autoHide && !anyAppHovered) {
hideTimer.start() hideTimer.start()
} }
} }
} }
margins.bottom: hidden ? -(fullHeight - peekHeight) : 0 Item {
id: dock
width: runningAppsRow.width
height: parent.height - (20 * scaling)
anchors.centerIn: parent
Rectangle { NTooltip {
id: dockContainer id: appTooltip
width: dock.width + 48 * scaling visible: false
height: iconSize * 1.4 * scaling positionAbove: true
color: Color.mSurface
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
topLeftRadius: Style.radiusL * scaling
topRightRadius: Style.radiusL * scaling
MouseArea {
id: dockMouseArea
anchors.fill: parent
hoverEnabled: true
propagateComposedEvents: true
onEntered: {
dockHovered = true
if (autoHide) {
showTimer.stop()
hideTimer.stop()
hidden = false
}
}
onExited: {
dockHovered = false
// Only start hide timer if we're not hovering over any app
if (autoHide && !anyAppHovered) {
hideTimer.start()
}
}
} }
Item { function getAppIcon(toplevel: Toplevel): string {
id: dock if (!toplevel)
width: runningAppsRow.width return ""
height: parent.height - (20 * scaling) return Icons.iconForAppId(toplevel.appId?.toLowerCase())
}
Row {
id: runningAppsRow
spacing: Style.marginL * scaling
height: parent.height
anchors.centerIn: parent anchors.centerIn: parent
NTooltip { Repeater {
id: appTooltip model: ToplevelManager ? ToplevelManager.toplevels : null
visible: false
positionAbove: true
}
function getAppIcon(toplevel: Toplevel): string { delegate: Rectangle {
if (!toplevel) id: appButton
return "" width: iconSize * scaling
return Icons.iconForAppId(toplevel.appId?.toLowerCase()) height: iconSize * scaling
} color: Color.transparent
radius: Style.radiusM * scaling
Row { property bool isActive: ToplevelManager.activeToplevel && ToplevelManager.activeToplevel === modelData
id: runningAppsRow property bool hovered: appMouseArea.containsMouse
spacing: Style.marginL * scaling property string appId: modelData ? modelData.appId : ""
height: parent.height property string appTitle: modelData ? modelData.title : ""
anchors.centerIn: parent
Repeater { // Hover background
model: ToplevelManager ? ToplevelManager.toplevels : null Rectangle {
id: hoverBackground
anchors.fill: parent
color: appButton.hovered ? Color.mSurfaceVariant : Color.transparent
radius: parent.radius
opacity: appButton.hovered ? 0.8 : 0
delegate: Rectangle { Behavior on opacity {
id: appButton NumberAnimation {
duration: Style.animationFast
easing.type: Easing.OutQuad
}
}
}
// The icon
Image {
id: appIcon
width: iconSize * scaling width: iconSize * scaling
height: iconSize * scaling height: iconSize * scaling
color: Color.transparent anchors.centerIn: parent
radius: Style.radiusM * scaling source: dock.getAppIcon(modelData)
visible: source.toString() !== ""
smooth: true
mipmap: false
antialiasing: false
fillMode: Image.PreserveAspectFit
property bool isActive: ToplevelManager.activeToplevel && ToplevelManager.activeToplevel === modelData scale: appButton.hovered ? 1.1 : 1.0
property bool hovered: appMouseArea.containsMouse
property string appId: modelData ? modelData.appId : ""
property string appTitle: modelData ? modelData.title : ""
// Hover background Behavior on scale {
Rectangle { NumberAnimation {
id: hoverBackground duration: Style.animationFast
anchors.fill: parent easing.type: Easing.OutBack
color: appButton.hovered ? Color.mSurfaceVariant : Color.transparent }
radius: parent.radius }
opacity: appButton.hovered ? 0.8 : 0 }
Behavior on opacity { // Fall back if no icon
NumberAnimation { NText {
duration: Style.animationFast anchors.centerIn: parent
easing.type: Easing.OutQuad visible: !appIcon.visible
} text: "question_mark"
font.family: "Material Symbols Rounded"
font.pointSize: iconSize * 0.7 * scaling
color: appButton.isActive ? Color.mPrimary : Color.mOnSurfaceVariant
scale: appButton.hovered ? 1.1 : 1.0
Behavior on scale {
NumberAnimation {
duration: Style.animationFast
easing.type: Easing.OutBack
}
}
}
MouseArea {
id: appMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
onEntered: {
anyAppHovered = true
const appName = appButton.appTitle || appButton.appId || "Unknown"
appTooltip.text = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
appTooltip.target = appButton
appTooltip.isVisible = true
if (autoHide) {
showTimer.stop()
hideTimer.stop()
hidden = false
} }
} }
// The icon onExited: {
Image { anyAppHovered = false
id: appIcon appTooltip.hide()
width: iconSize * scaling // Only start hide timer if we're not hovering over the dock
height: iconSize * scaling if (autoHide && !dockHovered) {
anchors.centerIn: parent hideTimer.start()
source: dock.getAppIcon(modelData)
visible: source.toString() !== ""
smooth: true
mipmap: false
antialiasing: false
fillMode: Image.PreserveAspectFit
scale: appButton.hovered ? 1.1 : 1.0
Behavior on scale {
NumberAnimation {
duration: Style.animationFast
easing.type: Easing.OutBack
}
} }
} }
// Fall back if no icon onClicked: function (mouse) {
NText { if (mouse.button === Qt.MiddleButton && modelData?.close) {
anchors.centerIn: parent modelData.close()
visible: !appIcon.visible }
text: "question_mark" if (mouse.button === Qt.LeftButton && modelData?.activate) {
font.family: "Material Symbols Rounded" modelData.activate()
font.pointSize: iconSize * 0.7 * scaling
color: appButton.isActive ? Color.mPrimary : Color.mOnSurfaceVariant
scale: appButton.hovered ? 1.1 : 1.0
Behavior on scale {
NumberAnimation {
duration: Style.animationFast
easing.type: Easing.OutBack
}
} }
} }
}
MouseArea { Rectangle {
id: appMouseArea visible: isActive
anchors.fill: parent width: iconSize * 0.75
hoverEnabled: true height: 4 * scaling
cursorShape: Qt.PointingHandCursor color: Color.mPrimary
acceptedButtons: Qt.LeftButton | Qt.MiddleButton radius: Style.radiusXS
anchors.top: parent.bottom
onEntered: { anchors.horizontalCenter: parent.horizontalCenter
anyAppHovered = true anchors.topMargin: Style.marginXXS * scaling
const appName = appButton.appTitle || appButton.appId || "Unknown"
appTooltip.text = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
appTooltip.target = appButton
appTooltip.isVisible = true
if (autoHide) {
showTimer.stop()
hideTimer.stop()
hidden = false
}
}
onExited: {
anyAppHovered = false
appTooltip.hide()
// Only start hide timer if we're not hovering over the dock
if (autoHide && !dockHovered) {
hideTimer.start()
}
}
onClicked: function (mouse) {
if (mouse.button === Qt.MiddleButton && modelData?.close) {
modelData.close()
}
if (mouse.button === Qt.LeftButton && modelData?.activate) {
modelData.activate()
}
}
}
Rectangle {
visible: isActive
width: iconSize * 0.75
height: 4 * scaling
color: Color.mPrimary
radius: Style.radiusXS
anchors.top: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: Style.marginXXS * scaling
}
} }
} }
} }