This commit is contained in:
Lysec
2026-01-28 19:05:28 +01:00
6 changed files with 101 additions and 44 deletions
+23 -7
View File
@@ -17,7 +17,6 @@ Item {
required property int characterCount
required property real textRatio
required property bool showLabelsOnlyWhenOccupied
required property var colorMap
required property string focusedColor
required property string occupiedColor
required property string emptyColor
@@ -30,6 +29,23 @@ Item {
// Fixed dimension (cross-axis) for visual pill
readonly property real fixedDimension: Style.toOdd(capsuleHeight * baseDimensionRatio)
// Helper to safely get colors with proper reactivity
// Accesses Color singleton directly to ensure fresh values
function getColorPair(colorKey) {
switch (colorKey) {
case "primary":
return [Color.mPrimary, Color.mOnPrimary];
case "secondary":
return [Color.mSecondary, Color.mOnSecondary];
case "tertiary":
return [Color.mTertiary, Color.mOnTertiary];
case "onSurface":
return [Color.mOnSurface, Color.mSurface];
default:
return [Color.mPrimary, Color.mOnPrimary];
}
}
// Animated pill dimensions (for visual pill, not container)
property real pillWidth: isVertical ? fixedDimension : getWorkspaceWidth(workspace, false)
property real pillHeight: isVertical ? getWorkspaceHeight(workspace, false) : fixedDimension
@@ -86,12 +102,12 @@ Item {
if (pillMouseArea.containsMouse)
return Color.mHover;
if (workspace.isFocused)
return colorMap[focusedColor][0];
return getColorPair(focusedColor)[0];
if (workspace.isUrgent)
return Color.mError;
if (workspace.isOccupied)
return colorMap[occupiedColor][0];
return Qt.alpha(colorMap[emptyColor][0], 0.3);
return getColorPair(occupiedColor)[0];
return Qt.alpha(getColorPair(emptyColor)[0], 0.3);
}
Loader {
@@ -126,12 +142,12 @@ Item {
if (pillMouseArea.containsMouse)
return Color.mOnHover;
if (workspace.isFocused)
return colorMap[focusedColor][1];
return getColorPair(focusedColor)[1];
if (workspace.isUrgent)
return Color.mOnError;
if (workspace.isOccupied)
return colorMap[occupiedColor][1];
return colorMap[emptyColor][1];
return getColorPair(occupiedColor)[1];
return getColorPair(emptyColor)[1];
}
Behavior on color {
+4 -3
View File
@@ -49,6 +49,7 @@ Item {
readonly property string barPosition: Settings.getBarPositionForScreen(screenName)
readonly property bool isVerticalBar: barPosition === "left" || barPosition === "right"
readonly property real barHeight: Style.getBarHeightForScreen(screenName)
readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screenName)
readonly property real barFontSize: Style.getBarFontSizeForScreen(screenName)
readonly property bool hasFocusedWindow: CompositorService.getFocusedWindow() !== null
@@ -58,9 +59,9 @@ Item {
readonly property int iconSize: Style.toOdd(capsuleHeight * 0.75)
readonly property int verticalSize: Style.toOdd(capsuleHeight * 0.85)
// For horizontal bars, height is always capsuleHeight (no animation needed)
// For horizontal bars, height is always barHeight (no animation needed)
// For vertical bars, collapse to 0 when hidden
implicitHeight: isVerticalBar ? (((!hasFocusedWindow) && hideMode === "hidden") ? 0 : verticalSize) : capsuleHeight
implicitHeight: isVerticalBar ? (((!hasFocusedWindow) && hideMode === "hidden") ? 0 : verticalSize) : barHeight
implicitWidth: isVerticalBar ? (((!hasFocusedWindow) && hideMode === "hidden") ? 0 : verticalSize) : (((!hasFocusedWindow) && hideMode === "hidden") ? 0 : dynamicWidth)
// "visible": Always Visible, "hidden": Hide When Empty, "transparent": Transparent When Empty
@@ -194,7 +195,7 @@ Item {
x: isVerticalBar ? Style.pixelAlignCenter(parent.width, width) : 0
y: isVerticalBar ? 0 : Style.pixelAlignCenter(parent.height, height)
width: isVerticalBar ? ((!hasFocusedWindow) && hideMode === "hidden" ? 0 : verticalSize) : ((!hasFocusedWindow) && (hideMode === "hidden") ? 0 : dynamicWidth)
height: isVerticalBar ? ((!hasFocusedWindow) && hideMode === "hidden" ? 0 : verticalSize) : capsuleHeight
height: isVerticalBar ? ((!hasFocusedWindow) && hideMode === "hidden" ? 0 : verticalSize) : barHeight
radius: Style.radiusM
color: Style.capsuleColor
border.color: Style.capsuleBorderColor
+13 -6
View File
@@ -596,7 +596,7 @@ Item {
if (!visible)
return 0;
if (isVerticalBar)
return capsuleHeight;
return barHeight;
var calculatedWidth = showTitle ? taskbarLayout.implicitWidth : taskbarLayout.implicitWidth + Style.marginXL;
@@ -607,7 +607,7 @@ Item {
return Math.round(calculatedWidth);
}
readonly property real contentHeight: visible ? (isVerticalBar ? Math.round(taskbarLayout.implicitHeight + Style.marginXL) : capsuleHeight) : 0
readonly property real contentHeight: visible ? (isVerticalBar ? Math.round(taskbarLayout.implicitHeight + Style.marginS * 2) : barHeight) : 0
implicitWidth: contentWidth
implicitHeight: contentHeight
@@ -659,8 +659,8 @@ Item {
readonly property color titleBgColor: (isHovered || isFocused) ? Color.mHover : Style.capsuleColor
readonly property color titleFgColor: (isHovered || isFocused) ? Color.mOnHover : Color.mOnSurface
Layout.preferredWidth: root.showTitle ? Math.round(contentWidth + Style.marginXL) : Math.round(contentWidth) // Add margins for both pinned and running apps
Layout.preferredHeight: root.itemSize
Layout.preferredWidth: root.isVerticalBar ? root.barHeight : (root.showTitle ? Math.round(contentWidth + Style.marginXL) : Math.round(contentWidth)) // Add margins for both pinned and running apps
Layout.preferredHeight: root.isVerticalBar ? root.itemSize : root.barHeight
Layout.alignment: Qt.AlignCenter
// Ensure dragged item is on top
@@ -786,7 +786,7 @@ Item {
visible: shouldShowTitle
anchors.centerIn: parent
width: parent.width
height: root.height
height: root.barHeight
color: titleBgColor
radius: Style.radiusM
@@ -840,8 +840,15 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
width: Style.toOdd(root.itemSize * 0.25)
height: 4
color: taskbarItem.isFocused ? Color.mPrimary : "transparent"
color: taskbarItem.isFocused ? Color.mPrimary : (taskbarItem.isHovered ? Color.mHover : "transparent")
radius: Math.min(Style.radiusXXS, width / 2)
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
}
}
+36 -9
View File
@@ -68,6 +68,7 @@ Item {
property bool hidePassive: widgetSettings.hidePassive !== undefined ? widgetSettings.hidePassive : true // Hide passive status items
property var filteredItems: [] // Items to show inline (pinned)
property var dropdownItems: [] // Items to show in drawer (unpinned)
property int hoveredItemIndex: -1 // Track hovered item for dot indicator
Timer {
id: updateDebounceTimer
@@ -288,11 +289,12 @@ Item {
}
// Content dimensions for implicit sizing
readonly property real capsuleWidth: isVertical ? capsuleHeight : Math.round(trayFlow.implicitWidth)
readonly property real capsuleContentHeight: isVertical ? Math.round(trayFlow.implicitHeight) : capsuleHeight
readonly property real capsulePadding: Style.marginXS
readonly property real capsuleWidth: isVertical ? capsuleHeight : Math.round(trayFlow.implicitWidth + capsulePadding * 2)
readonly property real capsuleContentHeight: isVertical ? Math.round(trayFlow.implicitHeight + capsulePadding * 2) : capsuleHeight
implicitWidth: isVertical ? barHeight : Math.round(trayFlow.implicitWidth)
implicitHeight: isVertical ? Math.round(trayFlow.implicitHeight) : barHeight
implicitWidth: isVertical ? barHeight : Math.round(trayFlow.implicitWidth + capsulePadding * 2)
implicitHeight: isVertical ? Math.round(trayFlow.implicitHeight + capsulePadding * 2) : barHeight
visible: filteredItems.length > 0 || dropdownItems.length > 0
opacity: (filteredItems.length > 0 || dropdownItems.length > 0) ? 1.0 : 0.0
@@ -311,12 +313,12 @@ Item {
Flow {
id: trayFlow
spacing: Style.marginXS
spacing: 0
flow: isVertical ? Flow.TopToBottom : Flow.LeftToRight
// Position at edge for full click area
x: isVertical ? 0 : 0
y: isVertical ? 0 : 0
// Position with padding from capsule edges
x: isVertical ? 0 : capsulePadding
y: isVertical ? capsulePadding : 0
// Drawer opener (before items if opposite direction)
NIconButton {
@@ -357,9 +359,12 @@ Item {
delegate: Item {
id: trayDelegate
required property var modelData
required property int index
width: isVertical ? barHeight : capsuleHeight
height: isVertical ? capsuleHeight : barHeight
visible: modelData
readonly property bool isHovered: root.hoveredItemIndex === index
// Tooltip anchor representing the visual area (for proper tooltip positioning)
Item {
@@ -406,6 +411,24 @@ Item {
}
}
Rectangle {
id: hoverIndicator
anchors.bottom: trayIcon.bottom
anchors.bottomMargin: -2
anchors.horizontalCenter: trayIcon.horizontalCenter
width: Style.toOdd(iconSize * 0.25)
height: 4
color: trayDelegate.isHovered ? Color.mHover : "transparent"
radius: Math.min(Style.radiusXXS, width / 2)
Behavior on color {
ColorAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
@@ -480,9 +503,13 @@ Item {
if (popupMenuWindow) {
popupMenuWindow.close();
}
root.hoveredItemIndex = trayDelegate.index;
TooltipService.show(tooltipAnchor, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection(root.screen?.name));
}
onExited: TooltipService.hide()
onExited: {
root.hoveredItemIndex = -1;
TooltipService.hide();
}
}
}
}
+21 -13
View File
@@ -63,11 +63,21 @@ Item {
readonly property string emptyColor: (widgetSettings.emptyColor !== undefined) ? widgetSettings.emptyColor : widgetMetadata.emptyColor
readonly property bool showBadge: (widgetSettings.showBadge !== undefined) ? widgetSettings.showBadge : widgetMetadata.showBadge
readonly property var colorMap: {
"primary": [Color.mPrimary, Color.mOnPrimary],
"secondary": [Color.mSecondary, Color.mOnSecondary],
"tertiary": [Color.mTertiary, Color.mOnTertiary],
"onSurface": [Color.mOnSurface, Color.mSurface]
// Helper to safely get colors with proper reactivity
// Accesses Color singleton directly to ensure fresh values
function getColorPair(colorKey) {
switch (colorKey) {
case "primary":
return [Color.mPrimary, Color.mOnPrimary];
case "secondary":
return [Color.mSecondary, Color.mOnSecondary];
case "tertiary":
return [Color.mTertiary, Color.mOnTertiary];
case "onSurface":
return [Color.mOnSurface, Color.mSurface];
default:
return [Color.mPrimary, Color.mOnPrimary];
}
}
// Only for grouped mode / show apps
@@ -557,7 +567,6 @@ Item {
characterCount: root.characterCount
textRatio: root.textRatio
showLabelsOnlyWhenOccupied: root.showLabelsOnlyWhenOccupied
colorMap: root.colorMap
focusedColor: root.focusedColor
occupiedColor: root.occupiedColor
emptyColor: root.emptyColor
@@ -592,7 +601,6 @@ Item {
characterCount: root.characterCount
textRatio: root.textRatio
showLabelsOnlyWhenOccupied: root.showLabelsOnlyWhenOccupied
colorMap: root.colorMap
focusedColor: root.focusedColor
occupiedColor: root.occupiedColor
emptyColor: root.emptyColor
@@ -792,13 +800,13 @@ Item {
color: {
if (groupedContainer.workspaceModel.isFocused)
return root.colorMap[root.focusedColor][0];
return root.getColorPair(root.focusedColor)[0];
if (groupedContainer.workspaceModel.isUrgent)
return Color.mError;
if (groupedContainer.hasWindows)
return root.colorMap[root.occupiedColor][0];
return root.getColorPair(root.occupiedColor)[0];
return root.colorMap[root.emptyColor][0];
return root.getColorPair(root.emptyColor)[0];
}
scale: groupedContainer.workspaceModel.isActive ? 1.0 : 0.8
@@ -861,13 +869,13 @@ Item {
color: {
if (groupedContainer.workspaceModel.isFocused)
return root.colorMap[root.focusedColor][1];
return root.getColorPair(root.focusedColor)[1];
if (groupedContainer.workspaceModel.isUrgent)
return Color.mOnError;
if (groupedContainer.hasWindows)
return root.colorMap[root.occupiedColor][1];
return root.getColorPair(root.occupiedColor)[1];
return root.colorMap[root.emptyColor][1];
return root.getColorPair(root.emptyColor)[1];
}
Behavior on opacity {
@@ -137,19 +137,17 @@ ColumnLayout {
spacing: Style.marginS
NText {
anchors.verticalCenter: parent.verticalCenter
text: model.rule
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
Layout.fillWidth: true
}
NIconButton {
width: 16
height: 16
anchors.verticalCenter: parent.verticalCenter
icon: "close"
baseSize: 8
baseSize: 12 * Style.uiScaleRatio
colorBg: Color.mSurfaceVariant
colorFg: Color.mOnSurface
colorFg: Color.mOnSurfaceVariant
colorBgHover: Color.mError
colorFgHover: Color.mOnError
onClicked: {