feat: add taskbar module with configurable icon size and window management
This commit is contained in:
parent
f1c2f9bea8
commit
18bc65dff1
3 changed files with 191 additions and 0 deletions
|
|
@ -63,6 +63,10 @@ Scope {
|
||||||
Media {
|
Media {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Taskbar {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ActiveWindow {
|
ActiveWindow {
|
||||||
|
|
|
||||||
186
Bar/Modules/Taskbar.qml
Normal file
186
Bar/Modules/Taskbar.qml
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import qs.Settings
|
||||||
|
import qs.Components
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: taskbar
|
||||||
|
width: runningAppsRow.width
|
||||||
|
height: Settings.settings.taskbarIconSize
|
||||||
|
|
||||||
|
function getAppIcon(toplevel) {
|
||||||
|
if (!toplevel)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
// Try different icon resolution strategies
|
||||||
|
var icon = Quickshell.iconPath(toplevel.appId?.toLowerCase(), true);
|
||||||
|
if (!icon) {
|
||||||
|
icon = Quickshell.iconPath(toplevel.appId, true);
|
||||||
|
}
|
||||||
|
if (!icon) {
|
||||||
|
icon = Quickshell.iconPath(toplevel.title?.toLowerCase(), true);
|
||||||
|
}
|
||||||
|
if (!icon) {
|
||||||
|
icon = Quickshell.iconPath(toplevel.title, true);
|
||||||
|
}
|
||||||
|
if (!icon) {
|
||||||
|
icon = Quickshell.iconPath("application-x-executable", true);
|
||||||
|
}
|
||||||
|
console.log(icon)
|
||||||
|
|
||||||
|
return icon || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: runningAppsRow
|
||||||
|
spacing: 8
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ToplevelManager ? ToplevelManager.toplevels : null
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
|
||||||
|
id: appButton
|
||||||
|
width: Settings.settings.taskbarIconSize
|
||||||
|
height: Settings.settings.taskbarIconSize
|
||||||
|
radius: Math.max(4, Settings.settings.taskbarIconSize * 0.25)
|
||||||
|
color: isActive ? Theme.accentPrimary : (hovered ? Theme.surfaceVariant : "transparent")
|
||||||
|
border.color: isActive ? Qt.darker(Theme.accentPrimary, 1.2) : "transparent"
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
property bool isActive: ToplevelManager.activeToplevel && ToplevelManager.activeToplevel === modelData
|
||||||
|
property bool hovered: mouseArea.containsMouse
|
||||||
|
property string appId: modelData ? modelData.appId : ""
|
||||||
|
property string appTitle: modelData ? modelData.title : ""
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// App icon
|
||||||
|
IconImage {
|
||||||
|
id: appIcon
|
||||||
|
width: Math.max(12, Settings.settings.taskbarIconSize * 0.625) // 62.5% of button size (20/32 = 0.625)
|
||||||
|
height: Math.max(12, Settings.settings.taskbarIconSize * 0.625)
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: getAppIcon(modelData)
|
||||||
|
smooth: true
|
||||||
|
|
||||||
|
// Fallback to first letter if no icon
|
||||||
|
visible: source.toString() !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback text if no icon available
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: !appIcon.visible
|
||||||
|
text: appButton.appId ? appButton.appId.charAt(0).toUpperCase() : "?"
|
||||||
|
font.family: Theme.fontFamily
|
||||||
|
font.pixelSize: Math.max(10, Settings.settings.taskbarIconSize * 0.4375) // 43.75% of button size (14/32 = 0.4375)
|
||||||
|
font.bold: true
|
||||||
|
color: appButton.isActive ? Theme.onAccent : Theme.textPrimary
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
ToolTip {
|
||||||
|
id: tooltip
|
||||||
|
visible: mouseArea.containsMouse && !mouseArea.pressed
|
||||||
|
delay: 800
|
||||||
|
text: appTitle || appId
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: Theme.backgroundPrimary
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
text: tooltip.text
|
||||||
|
font.family: Theme.fontFamily
|
||||||
|
font.pixelSize: Theme.fontSizeCaption
|
||||||
|
color: Theme.textPrimary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
|
onClicked: function(mouse) {
|
||||||
|
console.log("[Taskbar] Clicked on", appButton.appId, "- Active:", appButton.isActive);
|
||||||
|
|
||||||
|
if (mouse.button === Qt.MiddleButton) {
|
||||||
|
console.log("[Taskbar] Middle-clicked on", appButton.appId);
|
||||||
|
|
||||||
|
// Example: Close the window with middle click
|
||||||
|
if (modelData && modelData.close) {
|
||||||
|
modelData.close();
|
||||||
|
} else {
|
||||||
|
console.log("[Taskbar] No close method available for:", modelData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
// Left click: Focus/activate the window
|
||||||
|
if (modelData && modelData.activate) {
|
||||||
|
modelData.activate();
|
||||||
|
} else {
|
||||||
|
console.log("[Taskbar] No activate method available for:", modelData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right-click for additional actions
|
||||||
|
onPressed: mouse => {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
console.log("[Taskbar] Right-clicked on", appButton.appId);
|
||||||
|
|
||||||
|
// Example actions you can add:
|
||||||
|
// 1. Close window
|
||||||
|
// if (modelData && modelData.close) {
|
||||||
|
// modelData.close();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 2. Minimize window
|
||||||
|
// if (modelData && modelData.minimize) {
|
||||||
|
// modelData.minimize();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 3. Show context menu (needs Menu component)
|
||||||
|
// contextMenu.popup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active indicator dot
|
||||||
|
Rectangle {
|
||||||
|
visible: isActive
|
||||||
|
width: 4
|
||||||
|
height: 4
|
||||||
|
radius: 2
|
||||||
|
color: Theme.onAccent
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.bottomMargin: -6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,6 +59,7 @@ Singleton {
|
||||||
property bool use12HourClock: false
|
property bool use12HourClock: false
|
||||||
property bool dimPanels: true
|
property bool dimPanels: true
|
||||||
property real fontSizeMultiplier: 1.0 // Font size multiplier (1.0 = normal, 1.2 = 20% larger, 0.8 = 20% smaller)
|
property real fontSizeMultiplier: 1.0 // Font size multiplier (1.0 = normal, 1.2 = 20% larger, 0.8 = 20% smaller)
|
||||||
|
property int taskbarIconSize: 24 // Taskbar icon button size in pixels (default: 32, smaller: 24, larger: 40)
|
||||||
property var pinnedExecs: [] // Added for AppLauncher pinned apps
|
property var pinnedExecs: [] // Added for AppLauncher pinned apps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue