diff --git a/Modules/Bar/Widgets/ArchUpdater.qml b/Modules/Bar/Widgets/ArchUpdater.qml
index b86eb50..e405ecf 100644
--- a/Modules/Bar/Widgets/ArchUpdater.qml
+++ b/Modules/Bar/Widgets/ArchUpdater.qml
@@ -48,10 +48,10 @@ NIconButton {
let tooltip = header
if (pacmanTooltip !== "") {
- tooltip += "
" + pacmanTooltip
+ tooltip += "\n" + pacmanTooltip
}
if (aurTooltip !== "") {
- tooltip += "
" + aurTooltip
+ tooltip += "\n" + aurTooltip
}
return tooltip
}
diff --git a/Modules/Bar/Widgets/Battery.qml b/Modules/Bar/Widgets/Battery.qml
index e76a0a3..f149b9b 100644
--- a/Modules/Bar/Widgets/Battery.qml
+++ b/Modules/Bar/Widgets/Battery.qml
@@ -103,7 +103,7 @@ Item {
let lines = []
if (testMode) {
lines.push("Time left: " + Time.formatVagueHumanReadableDuration(12345))
- return lines.join("
")
+ return lines.join("\n")
}
if (!isReady || !battery.isLaptopBattery) {
return "No battery detected"
@@ -130,7 +130,7 @@ Item {
if (battery.healthPercentage !== undefined && battery.healthPercentage > 0) {
lines.push("Health: " + Math.round(battery.healthPercentage) + "%")
}
- return lines.join("
")
+ return lines.join("\n")
}
}
}
diff --git a/Modules/Bar/Widgets/Bluetooth.qml b/Modules/Bar/Widgets/Bluetooth.qml
index 0b8b4f9..7cb4186 100644
--- a/Modules/Bar/Widgets/Bluetooth.qml
+++ b/Modules/Bar/Widgets/Bluetooth.qml
@@ -21,6 +21,6 @@ NIconButton {
colorBorderHover: Color.transparent
icon: "bluetooth"
- tooltipText: "Bluetooth Devices"
+ tooltipText: "Bluetooth devices"
onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(screen, this)
}
diff --git a/Modules/Bar/Widgets/Brightness.qml b/Modules/Bar/Widgets/Brightness.qml
index 63a8c20..bc09dca 100644
--- a/Modules/Bar/Widgets/Brightness.qml
+++ b/Modules/Bar/Widgets/Brightness.qml
@@ -70,8 +70,8 @@ Item {
var monitor = getMonitor()
if (!monitor)
return ""
- return "Brightness: " + Math.round(monitor.brightness * 100) + "%
Method: " + monitor.method
- + "
Left click for advanced settings.
Scroll up/down to change brightness."
+ return "Brightness: " + Math.round(monitor.brightness * 100) + "%\nMethod: " + monitor.method
+ + "\nLeft click for advanced settings.\nScroll up/down to change brightness."
}
onWheel: function (angle) {
diff --git a/Modules/Bar/Widgets/KeyboardLayout.qml b/Modules/Bar/Widgets/KeyboardLayout.qml
index 0ee56e5..d655055 100644
--- a/Modules/Bar/Widgets/KeyboardLayout.qml
+++ b/Modules/Bar/Widgets/KeyboardLayout.qml
@@ -25,7 +25,7 @@ Row {
collapsedIconColor: Color.mOnSurface
autoHide: false // Important to be false so we can hover as long as we want
text: currentLayout
- tooltipText: "Keyboard Layout: " + currentLayout
+ tooltipText: "Keyboard layout: " + currentLayout
onClicked: {
diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml
index dbfe5cf..5607fe2 100644
--- a/Modules/Bar/Widgets/MediaMini.qml
+++ b/Modules/Bar/Widgets/MediaMini.qml
@@ -26,9 +26,8 @@ Row {
NText {
id: fullTitleMetrics
visible: false
- text: getTitle()
- font.pointSize: Style.fontSizeS * scaling
- font.weight: Style.fontWeightMedium
+ text: titleText.text
+ font: titleText.font
}
Rectangle {
@@ -50,37 +49,6 @@ Row {
width: 200 * scaling
}
- // Mouse area for hover detection - direct child of Rectangle
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
- onClicked: mouse => {
- if (mouse.button === Qt.LeftButton) {
- MediaService.playPause()
- } else if (mouse.button == Qt.RightButton) {
- MediaService.next()
- // Need to hide the tooltip instantly
- tooltip.visible = false
- } else if (mouse.button == Qt.MiddleButton) {
- MediaService.previous()
- // Need to hide the tooltip instantly
- tooltip.visible = false
- }
- }
-
- onEntered: {
- if (tooltip.text !== "") {
- tooltip.show()
- }
- }
- onExited: {
- tooltip.hide()
- }
- }
-
Item {
id: mainContainer
anchors.fill: parent
@@ -172,18 +140,18 @@ Row {
NText {
id: titleText
- // If hovered, show up to 400 pixels, otherwise show up to 120 pixels
- width: (mouseArea.containsMouse) ? Math.min(fullTitleMetrics.contentWidth + (Style.marginS * scaling),
- 400 * scaling) : Math.min(
- fullTitleMetrics.contentWidth + (Style.marginS * scaling), 120 * scaling)
+ // If hovered or just switched window, show up to 400 pixels
+ // If not hovered show up to 120 pixels
+ width: (mouseArea.containsMouse) ? Math.min(fullTitleMetrics.contentWidth,
+ 400 * scaling) : Math.min(fullTitleMetrics.contentWidth,
+ 120 * scaling)
text: getTitle()
font.pointSize: Style.fontSizeS * scaling
font.weight: Style.fontWeightMedium
- elide: mouseArea.containsMouse ? Text.ElideNone : Text.ElideRight
+ elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
color: Color.mTertiary
- clip: true
Behavior on width {
NumberAnimation {
@@ -193,6 +161,37 @@ Row {
}
}
}
+
+ // Mouse area for hover detection
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
+ onClicked: mouse => {
+ if (mouse.button === Qt.LeftButton) {
+ MediaService.playPause()
+ } else if (mouse.button == Qt.RightButton) {
+ MediaService.next()
+ // Need to hide the tooltip instantly
+ tooltip.visible = false
+ } else if (mouse.button == Qt.MiddleButton) {
+ MediaService.previous()
+ // Need to hide the tooltip instantly
+ tooltip.visible = false
+ }
+ }
+
+ onEntered: {
+ if (tooltip.text !== "") {
+ tooltip.show()
+ }
+ }
+ onExited: {
+ tooltip.hide()
+ }
+ }
}
}
@@ -201,14 +200,14 @@ Row {
text: {
var str = ""
if (MediaService.canGoNext) {
- str += "Right click for next
"
+ str += "Right click for next\n"
}
if (MediaService.canGoPrevious) {
- str += "Middle click for previous
"
+ str += "Middle click for previous\n"
}
return str
}
target: anchor
positionAbove: Settings.data.bar.position === "bottom"
}
-}
+}
\ No newline at end of file
diff --git a/Modules/Bar/Widgets/NightLight.qml b/Modules/Bar/Widgets/NightLight.qml
index 43e330e..f6eda83 100644
--- a/Modules/Bar/Widgets/NightLight.qml
+++ b/Modules/Bar/Widgets/NightLight.qml
@@ -21,7 +21,7 @@ NIconButton {
colorBorderHover: Color.transparent
icon: Settings.data.nightLight.enabled ? "bedtime" : "bedtime_off"
- tooltipText: `Night Light: ${Settings.data.nightLight.enabled ? "enabled" : "disabled"}
Left click to toggle.
Right click to access settings.`
+ tooltipText: `Night light: ${Settings.data.nightLight.enabled ? "enabled" : "disabled"}\nLeft click to toggle.\nRight click to access settings.`
onClicked: Settings.data.nightLight.enabled = !Settings.data.nightLight.enabled
onRightClicked: {
diff --git a/Modules/Bar/Widgets/NotificationHistory.qml b/Modules/Bar/Widgets/NotificationHistory.qml
index 8a1e8c3..ff0db05 100644
--- a/Modules/Bar/Widgets/NotificationHistory.qml
+++ b/Modules/Bar/Widgets/NotificationHistory.qml
@@ -15,7 +15,7 @@ NIconButton {
sizeRatio: 0.8
icon: "notifications"
- tooltipText: "Notification History"
+ tooltipText: "Notification history"
colorBg: Color.mSurfaceVariant
colorFg: Color.mOnSurface
colorBorder: Color.transparent
diff --git a/Modules/Bar/Widgets/ScreenRecorderIndicator.qml b/Modules/Bar/Widgets/ScreenRecorderIndicator.qml
index 38ed2c7..ce68391 100644
--- a/Modules/Bar/Widgets/ScreenRecorderIndicator.qml
+++ b/Modules/Bar/Widgets/ScreenRecorderIndicator.qml
@@ -12,7 +12,7 @@ NIconButton {
visible: ScreenRecorderService.isRecording
icon: "videocam"
- tooltipText: "Screen Recording Active\nClick To Stop Recording"
+ tooltipText: "Screen recording is active\nClick to stop recording"
sizeRatio: 0.8
colorBg: Color.mPrimary
colorFg: Color.mOnPrimary
diff --git a/Modules/Bar/Widgets/SidePanelToggle.qml b/Modules/Bar/Widgets/SidePanelToggle.qml
index 0a6e6b3..7020209 100644
--- a/Modules/Bar/Widgets/SidePanelToggle.qml
+++ b/Modules/Bar/Widgets/SidePanelToggle.qml
@@ -10,7 +10,7 @@ NIconButton {
property real scaling: ScalingService.scale(screen)
icon: "widgets"
- tooltipText: "Open Side Panel"
+ tooltipText: "Open side panel"
sizeRatio: 0.8
colorBg: Color.mSurfaceVariant
diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml
new file mode 100644
index 0000000..04da2e0
--- /dev/null
+++ b/Modules/Bar/Widgets/Taskbar.qml
@@ -0,0 +1,98 @@
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls
+import Quickshell
+import Quickshell.Widgets
+import Quickshell.Wayland
+import qs.Commons
+import qs.Services
+import qs.Widgets
+
+Rectangle {
+ id: root
+ property ShellScreen screen
+ property real scaling: ScalingService.scale(screen)
+
+ readonly property real itemSize: Style.baseWidgetSize * 0.8 * scaling
+
+ // Always visible when there are toplevels
+ implicitWidth: taskbarRow.width + Style.marginM * scaling * 2
+ implicitHeight: Math.round(Style.capsuleHeight * scaling)
+ radius: Math.round(Style.radiusM * scaling)
+ color: Color.mSurfaceVariant
+
+ Row {
+ id: taskbarRow
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: Style.marginXXS * root.scaling
+
+ Repeater {
+ model: ToplevelManager && ToplevelManager.toplevels ? ToplevelManager.toplevels : []
+ delegate: Item {
+ id: taskbarItem
+ required property Toplevel modelData
+ property Toplevel toplevel: modelData
+ property bool isActive: ToplevelManager.activeToplevel === modelData
+ width: root.itemSize
+ height: root.itemSize
+
+ Rectangle {
+ id: iconBackground
+ anchors.centerIn: parent
+ width: root.itemSize * 0.75
+ height: root.itemSize * 0.75
+ color: taskbarItem.isActive ? Color.mPrimary : root.color
+ border.width: 0
+ radius: Math.round(Style.radiusXS * root.scaling)
+ border.color: "transparent"
+ z: -1
+
+ IconImage {
+ id: appIcon
+ anchors.centerIn: parent
+ width: Style.marginL * root.scaling
+ height: Style.marginL * root.scaling
+ source: Icons.iconForAppId(taskbarItem.modelData.appId)
+ smooth: true
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+
+ onPressed: function(mouse) {
+ if (!taskbarItem.modelData) return
+
+ if (mouse.button === Qt.LeftButton) {
+ try {
+ taskbarItem.modelData.activate()
+ } catch (error) {
+ Logger.error("Taskbar", "Failed to activate toplevel: " + error)
+ }
+ } else if (mouse.button === Qt.RightButton) {
+ try {
+ taskbarItem.modelData.close()
+ } catch (error) {
+ Logger.error("Taskbar", "Failed to close toplevel: " + error)
+ }
+ }
+ }
+ onEntered: taskbarTooltip.show()
+ onExited: taskbarTooltip.hide()
+ }
+
+ NTooltip {
+ id: taskbarTooltip
+ text: taskbarItem.modelData.title || taskbarItem.modelData.appId || "Unknown App"
+ target: taskbarItem
+ positionAbove: Settings.data.bar.position === "bottom"
+ }
+ }
+ }
+ }
+}
diff --git a/Modules/Bar/Widgets/Volume.qml b/Modules/Bar/Widgets/Volume.qml
index 24a8492..8819cc9 100644
--- a/Modules/Bar/Widgets/Volume.qml
+++ b/Modules/Bar/Widgets/Volume.qml
@@ -59,7 +59,7 @@ Item {
autoHide: false // Important to be false so we can hover as long as we want
text: Math.floor(AudioService.volume * 100) + "%"
tooltipText: "Volume: " + Math.round(
- AudioService.volume * 100) + "%
Left click for advanced settings.
Scroll up/down to change volume."
+ AudioService.volume * 100) + "%\nLeft click for advanced settings.\nScroll up/down to change volume."
onWheel: function (delta) {
wheelAccumulator += delta
diff --git a/Modules/Bar/Widgets/WiFi.qml b/Modules/Bar/Widgets/WiFi.qml
index f4ec9dd..2362a82 100644
--- a/Modules/Bar/Widgets/WiFi.qml
+++ b/Modules/Bar/Widgets/WiFi.qml
@@ -50,6 +50,6 @@ NIconButton {
return "signal_wifi_bad"
}
}
- tooltipText: "Network / WiFi"
+ tooltipText: "Network / Wi-Fi"
onClicked: PanelService.getPanel("wifiPanel")?.toggle(screen, this)
}
diff --git a/Modules/Calendar/Calendar.qml b/Modules/Calendar/Calendar.qml
index ea5b260..891a866 100644
--- a/Modules/Calendar/Calendar.qml
+++ b/Modules/Calendar/Calendar.qml
@@ -29,7 +29,7 @@ NPanel {
NIconButton {
icon: "chevron_left"
- tooltipText: "Previous Month"
+ tooltipText: "Previous month"
onClicked: {
let newDate = new Date(grid.year, grid.month - 1, 1)
grid.year = newDate.getFullYear()
@@ -48,7 +48,7 @@ NPanel {
NIconButton {
icon: "chevron_right"
- tooltipText: "Next Month"
+ tooltipText: "Next month"
onClicked: {
let newDate = new Date(grid.year, grid.month + 1, 1)
grid.year = newDate.getFullYear()
diff --git a/Modules/Notification/NotificationHistoryPanel.qml b/Modules/Notification/NotificationHistoryPanel.qml
index 8001d39..3b10aec 100644
--- a/Modules/Notification/NotificationHistoryPanel.qml
+++ b/Modules/Notification/NotificationHistoryPanel.qml
@@ -45,7 +45,7 @@ NPanel {
NIconButton {
icon: "delete"
- tooltipText: "Clear History"
+ tooltipText: "Clear history"
sizeRatio: 0.8
onClicked: NotificationService.clearHistory()
}
@@ -158,7 +158,7 @@ NPanel {
// Trash icon button
NIconButton {
icon: "delete"
- tooltipText: "Delete Notification"
+ tooltipText: "Delete notification"
sizeRatio: 0.7
onClicked: {
diff --git a/Modules/SettingsPanel/Tabs/DisplayTab.qml b/Modules/SettingsPanel/Tabs/DisplayTab.qml
index 67905aa..b2bda25 100644
--- a/Modules/SettingsPanel/Tabs/DisplayTab.qml
+++ b/Modules/SettingsPanel/Tabs/DisplayTab.qml
@@ -212,7 +212,7 @@ ColumnLayout {
NIconButton {
icon: "refresh"
- tooltipText: "Reset Scaling"
+ tooltipText: "Reset scaling"
onClicked: ScalingService.setMonitorScale(modelData.name, 1.0)
}
}
diff --git a/Modules/SidePanel/Cards/MediaCard.qml b/Modules/SidePanel/Cards/MediaCard.qml
index eaac9a5..65f7211 100644
--- a/Modules/SidePanel/Cards/MediaCard.qml
+++ b/Modules/SidePanel/Cards/MediaCard.qml
@@ -324,7 +324,7 @@ NBox {
// Next button
NIconButton {
icon: "skip_next"
- tooltipText: "Next Media"
+ tooltipText: "Next media"
visible: MediaService.canGoNext
onClicked: MediaService.canGoNext ? MediaService.next() : {}
}
diff --git a/Modules/SidePanel/Cards/PowerProfilesCard.qml b/Modules/SidePanel/Cards/PowerProfilesCard.qml
index 2c36642..2bdd88a 100644
--- a/Modules/SidePanel/Cards/PowerProfilesCard.qml
+++ b/Modules/SidePanel/Cards/PowerProfilesCard.qml
@@ -29,7 +29,7 @@ NBox {
// Performance
NIconButton {
icon: "speed"
- tooltipText: "Set Performance Power Profile"
+ tooltipText: "Set performance power profile"
enabled: hasPP
opacity: enabled ? Style.opacityFull : Style.opacityMedium
colorBg: (enabled && powerProfiles.profile === PowerProfile.Performance) ? Color.mPrimary : Color.mSurfaceVariant
@@ -43,7 +43,7 @@ NBox {
// Balanced
NIconButton {
icon: "balance"
- tooltipText: "Set Balanced Power Profile"
+ tooltipText: "Set balanced power profile"
enabled: hasPP
opacity: enabled ? Style.opacityFull : Style.opacityMedium
colorBg: (enabled && powerProfiles.profile === PowerProfile.Balanced) ? Color.mPrimary : Color.mSurfaceVariant
@@ -57,7 +57,7 @@ NBox {
// Eco
NIconButton {
icon: "eco"
- tooltipText: "Set Eco Power Profile"
+ tooltipText: "Set eco power profile"
enabled: hasPP
opacity: enabled ? Style.opacityFull : Style.opacityMedium
colorBg: (enabled && powerProfiles.profile === PowerProfile.PowerSaver) ? Color.mPrimary : Color.mSurfaceVariant
diff --git a/Modules/SidePanel/Cards/ProfileCard.qml b/Modules/SidePanel/Cards/ProfileCard.qml
index 7374159..d58abe8 100644
--- a/Modules/SidePanel/Cards/ProfileCard.qml
+++ b/Modules/SidePanel/Cards/ProfileCard.qml
@@ -58,7 +58,7 @@ NBox {
}
NIconButton {
icon: "settings"
- tooltipText: "Open Settings"
+ tooltipText: "Open settings"
onClicked: {
settingsPanel.requestedTab = SettingsPanel.Tab.General
settingsPanel.open(screen)
@@ -68,7 +68,7 @@ NBox {
NIconButton {
id: powerButton
icon: "power_settings_new"
- tooltipText: "Power Menu"
+ tooltipText: "Power menu"
onClicked: {
powerPanel.open(screen)
sidePanel.close()
@@ -78,7 +78,7 @@ NBox {
NIconButton {
id: closeButton
icon: "close"
- tooltipText: "Close Side Panel"
+ tooltipText: "Close side panel"
onClicked: {
sidePanel.close()
}
diff --git a/Modules/SidePanel/Cards/UtilitiesCard.qml b/Modules/SidePanel/Cards/UtilitiesCard.qml
index 26f3b4e..5bb6a05 100644
--- a/Modules/SidePanel/Cards/UtilitiesCard.qml
+++ b/Modules/SidePanel/Cards/UtilitiesCard.qml
@@ -26,7 +26,7 @@ NBox {
// Screen Recorder
NIconButton {
icon: "videocam"
- tooltipText: ScreenRecorderService.isRecording ? "Stop Screen Recording" : "Start Screen Recording"
+ tooltipText: ScreenRecorderService.isRecording ? "Stop screen recording" : "Start screen recording"
colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : Color.mSurfaceVariant
colorFg: ScreenRecorderService.isRecording ? Color.mOnPrimary : Color.mPrimary
onClicked: {
@@ -37,7 +37,7 @@ NBox {
// Idle Inhibitor
NIconButton {
icon: "coffee"
- tooltipText: IdleInhibitorService.isInhibited ? "Disable Keep Awake" : "Enable Keep Awake"
+ tooltipText: IdleInhibitorService.isInhibited ? "Disable keep awake" : "Enable keep awake"
colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : Color.mSurfaceVariant
colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mPrimary
onClicked: {
@@ -48,7 +48,7 @@ NBox {
// Wallpaper
NIconButton {
icon: "image"
- tooltipText: "Open Wallpaper Selector"
+ tooltipText: "Open wallpaper selector"
onClicked: {
var settingsPanel = PanelService.getPanel("settingsPanel")
settingsPanel.requestedTab = SettingsPanel.Tab.WallpaperSelector
diff --git a/Modules/WiFiPanel/WiFiPanel.qml b/Modules/WiFiPanel/WiFiPanel.qml
index 3780b6f..4349cc4 100644
--- a/Modules/WiFiPanel/WiFiPanel.qml
+++ b/Modules/WiFiPanel/WiFiPanel.qml
@@ -51,7 +51,7 @@ NPanel {
NIconButton {
icon: "refresh"
- tooltipText: "Refresh Networks"
+ tooltipText: "Refresh networks"
sizeRatio: 0.8
enabled: Settings.data.network.wifiEnabled && !NetworkService.isLoading
onClicked: {
diff --git a/Services/ArchUpdaterService.qml b/Services/ArchUpdaterService.qml
index 02d2f06..7f5444d 100644
--- a/Services/ArchUpdaterService.qml
+++ b/Services/ArchUpdaterService.qml
@@ -141,7 +141,7 @@ Singleton {
onExited: function (exitCode) {
if (exitCode === 0 && updateInProgress) {
// Success indicators found
- console.log("ArchUpdater: Update completed successfully")
+ Logger.log("ArchUpdater", "Update completed successfully")
updateInProgress = false
updateFailed = false
updateCompleteTimer.stop()
diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml
index 5ff44fd..4ea47bd 100644
--- a/Services/BarWidgetRegistry.qml
+++ b/Services/BarWidgetRegistry.qml
@@ -23,6 +23,7 @@ Singleton {
"ScreenRecorderIndicator": screenRecorderIndicatorComponent,
"SidePanelToggle": sidePanelToggleComponent,
"SystemMonitor": systemMonitorComponent,
+ "Taskbar": taskbarComponent,
"Tray": trayComponent,
"Volume": volumeComponent,
"WiFi": wiFiComponent,
@@ -84,6 +85,9 @@ Singleton {
property Component workspaceComponent: Component {
Workspace {}
}
+ property Component taskbarComponent: Component {
+ Taskbar {}
+ }
// ------------------------------
// Helper function to get widget component by name
diff --git a/Widgets/NText.qml b/Widgets/NText.qml
index 1d54c89..00f5561 100644
--- a/Widgets/NText.qml
+++ b/Widgets/NText.qml
@@ -13,5 +13,4 @@ Text {
font.kerning: true
color: Color.mOnSurface
renderType: Text.QtRendering
- textFormat: Text.RichText
}