mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'main' of https://github.com/noctalia-dev/noctalia-shell
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user