From 466ce70f96f8bdde32260f6951c5cbb62cfc02a7 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Sun, 31 Aug 2025 21:57:00 +0200 Subject: ... --- .../shell/quickshell/ActiveWindowDisplay.qml | 3 +- accounts/gkleen@sif/shell/quickshell/Bar.qml | 10 +- accounts/gkleen@sif/shell/quickshell/Clock.qml | 241 ++++++++++++--------- .../gkleen@sif/shell/quickshell/KeyboardLayout.qml | 43 +++- .../gkleen@sif/shell/quickshell/SystemTray.qml | 21 +- accounts/gkleen@sif/shell/quickshell/shell.qml | 12 +- 6 files changed, 204 insertions(+), 126 deletions(-) diff --git a/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml index d7e8e7c5..57ade488 100644 --- a/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml +++ b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml @@ -7,10 +7,11 @@ Item { id: activeWindowDisplay required property int maxWidth + required property var screen property var activeWindow: { let currWindowId = Array.from(NiriService.workspaces).find(ws => { - return ws.output === bar.screen.name && ws.is_active; + return ws.output === screen.name && ws.is_active; })?.active_window_id; return currWindowId ? Array.from(NiriService.windows).find(win => win.id == currWindowId) : null; diff --git a/accounts/gkleen@sif/shell/quickshell/Bar.qml b/accounts/gkleen@sif/shell/quickshell/Bar.qml index accad2a9..aab1607f 100644 --- a/accounts/gkleen@sif/shell/quickshell/Bar.qml +++ b/accounts/gkleen@sif/shell/quickshell/Bar.qml @@ -5,7 +5,9 @@ import QtQuick PanelWindow { id: bar - property var modelData + required property var screen + + property var calendarMouseArea: clock.calendarMouseArea anchors { top: true @@ -17,7 +19,6 @@ PanelWindow { right: 26 + 8 } - screen: modelData implicitHeight: 21 color: "transparent" @@ -50,6 +51,7 @@ PanelWindow { spacing: 5 ActiveWindowDisplay { + screen: bar.screen maxWidth: bar.width - 2*Math.max(left.width, right.width) - 2*8 } } @@ -78,6 +80,8 @@ PanelWindow { width: 4 } - Clock {} + Clock { + id: clock + } } } \ No newline at end of file diff --git a/accounts/gkleen@sif/shell/quickshell/Clock.qml b/accounts/gkleen@sif/shell/quickshell/Clock.qml index 68efb558..58600adb 100644 --- a/accounts/gkleen@sif/shell/quickshell/Clock.qml +++ b/accounts/gkleen@sif/shell/quickshell/Clock.qml @@ -21,12 +21,14 @@ Item { property real angleRem: 0 property real sensitivity: 1 / 120 - onWheel: event => { + function scrollYear(event) { angleRem += event.angleDelta.y; const d = Math.round(angleRem * sensitivity); yearCalendar.year += d; angleRem -= d / sensitivity; } + + onWheel: event => scrollYear(event) } Text { @@ -48,11 +50,23 @@ Item { } PopupWindow { + id: tooltip + + property bool nextVisible: clockMouseArea.containsMouse || tooltipMouseArea.containsMouse + anchor { item: clockMouseArea - edges: Edges.Bottom + edges: Edges.Bottom | Edges.Left + } + visible: false + + onNextVisibleChanged: hangTimer.restart() + + Timer { + id: hangTimer + interval: 100 + onTriggered: tooltip.visible = tooltip.nextVisible } - visible: clockMouseArea.containsMouse implicitWidth: clockTooltipContent.width implicitHeight: clockTooltipContent.height @@ -64,159 +78,170 @@ Item { clockMouseArea.angleRem = 0; } - WrapperItem { - id: clockTooltipContent - - margin: 8 - leftMargin: 0 + WrapperMouseArea { + id: tooltipMouseArea - ColumnLayout { - Text { - id: yearLabel + hoverEnabled: true + enabled: true - horizontalAlignment: Text.AlignHCenter + onWheel: event => clockMouseArea.scrollYear(event) - font.pointSize: 14 - font.family: "Fira Sans" - font.features: { "tnum": 1 } - color: "white" + anchors.fill: parent - text: yearCalendar.year + WrapperItem { + id: clockTooltipContent - Layout.fillWidth: true - Layout.bottomMargin: 8 - } + margin: 8 + leftMargin: 0 - GridLayout { - property int year: { const d = new Date(); return d.getFullYear(); } + ColumnLayout { + Text { + id: yearLabel - id: yearCalendar + horizontalAlignment: Text.AlignHCenter - columns: 3 - columnSpacing: 16 - rowSpacing: 16 + font.pointSize: 14 + font.family: "Fira Sans" + font.features: { "tnum": 1 } + color: "white" - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: false + text: yearCalendar.year - Repeater { - model: 12 - - GridLayout { - columns: 2 + Layout.fillWidth: true + Layout.bottomMargin: 8 + } - required property int index - property int month: index + GridLayout { + property int year: { const d = new Date(); return d.getFullYear(); } - id: monthCalendar + id: yearCalendar - Layout.alignment: Qt.AlignTop | Qt.AlignRight - Layout.fillWidth: false + columns: 3 + columnSpacing: 16 + rowSpacing: 16 - Text { - Layout.column: 1 - Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: false - horizontalAlignment: Text.AlignHCenter + Repeater { + model: 12 - font.pointSize: 10 - font.family: "Fira Sans" + GridLayout { + columns: 2 - text: { - const date = Date.fromLocaleDateString(Qt.locale(), `${yearCalendar.year}-${monthCalendar.month + 1}-01`, "yyyy-M-dd"); - return date.toLocaleString(Qt.locale("en_DK"), "MMMM") - } + required property int index + property int month: index - color: "#ffead3" - } + id: monthCalendar - DayOfWeekRow { - locale: grid.locale + Layout.alignment: Qt.AlignTop | Qt.AlignRight + Layout.fillWidth: false - Layout.row: 1 - Layout.column: 1 - Layout.fillWidth: true + Text { + Layout.column: 1 + Layout.fillWidth: true - delegate: Text { - required property string shortName + horizontalAlignment: Text.AlignHCenter font.pointSize: 10 - font.family: "Fira Mono" + font.family: "Fira Sans" - text: shortName - color: "#ffcc66" + text: { + const date = Date.fromLocaleDateString(Qt.locale(), `${yearCalendar.year}-${monthCalendar.month + 1}-01`, "yyyy-M-dd"); + return date.toLocaleString(Qt.locale("en_DK"), "MMMM") + } - horizontalAlignment: Text.AlignRight - verticalAlignment: Text.AlignVCenter + color: "#ffead3" } - } - WeekNumberColumn { - month: grid.month - year: grid.year - locale: grid.locale + DayOfWeekRow { + locale: grid.locale - Layout.fillHeight: true + Layout.row: 1 + Layout.column: 1 + Layout.fillWidth: true - delegate: Text { - required property int weekNumber + delegate: Text { + required property string shortName - opacity: { - const simple = new Date(weekNumber == 1 && monthCalendar.month == 12 ? yearCalendar.year + 1 : yearCalendar.year, 0, 1 + (weekNumber - 1) * 7); - const dayOfWeek = simple.getDay(); - const isoWeekStart = simple; + font.pointSize: 10 + font.family: "Fira Mono" - isoWeekStart.setDate(simple.getDate() - dayOfWeek + 1); - if (dayOfWeek > 4) { - isoWeekStart.setDate(isoWeekStart.getDate() + 7); - } + text: shortName + color: "#ffcc66" - for (let i = 0; i < 7; i++) { - const dayInWeek = new Date(isoWeekStart); - dayInWeek.setDate(dayInWeek.getDate() + i); - if (dayInWeek.getMonth() == monthCalendar.month) - return 1; - } - - return 0; + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter } + } - font.pointSize: 10 - font.family: "Fira Sans" - font.features: { "tnum": 1 } - - text: weekNumber - color: "#99ffdd" + WeekNumberColumn { + month: grid.month + year: grid.year + locale: grid.locale - horizontalAlignment: Text.AlignRight - verticalAlignment: Text.AlignVCenter - } - } + Layout.fillHeight: true - MonthGrid { - id: grid + delegate: Text { + required property int weekNumber - year: yearCalendar.year - month: monthCalendar.month - locale: Qt.locale("en_DK") + opacity: { + const simple = new Date(weekNumber == 1 && monthCalendar.month == 12 ? yearCalendar.year + 1 : yearCalendar.year, 0, 1 + (weekNumber - 1) * 7); + const dayOfWeek = simple.getDay(); + const isoWeekStart = simple; - Layout.fillWidth: true - Layout.fillHeight: true + isoWeekStart.setDate(simple.getDate() - dayOfWeek + 1); + if (dayOfWeek > 4) { + isoWeekStart.setDate(isoWeekStart.getDate() + 7); + } - delegate: Text { - required property var model + for (let i = 0; i < 7; i++) { + const dayInWeek = new Date(isoWeekStart); + dayInWeek.setDate(dayInWeek.getDate() + i); + if (dayInWeek.getMonth() == monthCalendar.month) + return 1; + } - opacity: model.month === monthCalendar.month ? 1 : 0 + return 0; + } font.pointSize: 10 font.family: "Fira Sans" font.features: { "tnum": 1 } - text: model.day - color: model.today ? "#ff6699" : "white" + text: weekNumber + color: "#99ffdd" horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter + } + } + + MonthGrid { + id: grid + + year: yearCalendar.year + month: monthCalendar.month + locale: Qt.locale("en_DK") + + Layout.fillWidth: true + Layout.fillHeight: true + + delegate: Text { + required property var model + + opacity: model.month === monthCalendar.month ? 1 : 0 + + font.pointSize: 10 + font.family: "Fira Sans" + font.features: { "tnum": 1 } + + text: model.day + color: model.today ? "#ff6699" : "white" + + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml index 710ea10c..b9f91580 100644 --- a/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml +++ b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml @@ -1,6 +1,7 @@ import Quickshell import QtQuick import qs.Services +import Quickshell.Widgets Rectangle { id: kbdWidget @@ -27,6 +28,9 @@ Rectangle { onClicked: { NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": "Next" } } }, _ => {}) } + onWheel: event => { + NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": event.angleDelta > 0 ? "Next" : "Prev" } } }, _ => {}) + } } Text { @@ -50,28 +54,47 @@ Rectangle { } PopupWindow { + id: tooltip + + property bool nextVisible: kbdMouseArea.containsMouse || tooltipMouseArea.containsMouse + anchor { item: kbdMouseArea - edges: Edges.Bottom + edges: Edges.Bottom | Edges.Left + } + visible: false + + onNextVisibleChanged: hangTimer.restart() + + Timer { + id: hangTimer + interval: 100 + onTriggered: tooltip.visible = tooltip.nextVisible } - visible: kbdMouseArea.containsMouse implicitWidth: kbdTooltipText.contentWidth + 16 implicitHeight: kbdTooltipText.contentHeight + 16 color: "black" - Text { - id: kbdTooltipText + WrapperMouseArea { + id: tooltipMouseArea + + hoverEnabled: true + enabled: true anchors.centerIn: parent - font.pointSize: 10 - font.family: "Fira Sans" - color: "white" + Text { + id: kbdTooltipText + + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" - text: { - const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx]; - return currentLayout || ""; + text: { + const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx]; + return currentLayout || ""; + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml index afed4bf0..ba678138 100644 --- a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml +++ b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml @@ -91,18 +91,35 @@ Item { } PopupWindow { + id: tooltip + + property bool nextVisible: (trayItem.tooltipTitle || trayItem.tooltipDescription) && (trayItemArea.containsMouse || tooltipMouseArea.containsMouse) && !menuAnchor.visible + anchor { item: trayItemArea edges: Edges.Bottom } - visible: (trayItem.tooltipTitle || trayItem.tooltipDescription) && trayItemArea.containsMouse && !menuAnchor.visible + + visible: false + onNextVisibleChanged: hangTimer.restart() + + Timer { + id: hangTimer + interval: 100 + onTriggered: tooltip.visible = tooltip.nextVisible + } color: "black" implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16 implicitHeight: tooltipTitle.contentHeight + tooltipDescription.contentHeight + 16 - WrapperItem { + WrapperMouseArea { + id: tooltipMouseArea + + hoverEnabled: true + enabled: true + margin: 8 Column { diff --git a/accounts/gkleen@sif/shell/quickshell/shell.qml b/accounts/gkleen@sif/shell/quickshell/shell.qml index 2abd1fef..4934cd4d 100644 --- a/accounts/gkleen@sif/shell/quickshell/shell.qml +++ b/accounts/gkleen@sif/shell/quickshell/shell.qml @@ -8,8 +8,16 @@ ShellRoot { Variants { model: Quickshell.screens - delegate: Bar { - modelData: item + delegate: Scope { + id: screenScope + + required property var modelData + + Bar { + id: bar + + screen: screenScope.modelData + } } } } -- cgit v1.2.3