diff --git a/config/dot/hypr/DESKTOP-PARITY.md b/config/dot/hypr/DESKTOP-PARITY.md index f80250d..17d1a9c 100644 --- a/config/dot/hypr/DESKTOP-PARITY.md +++ b/config/dot/hypr/DESKTOP-PARITY.md @@ -77,7 +77,7 @@ than presenting inert Hyprland controls. | Caffeine | Replaced by a real logind inhibitor in quick settings | | Blur My Shell / Openbar / User Theme | Replaced by the Prism shell and compositor blur | | Bluetooth Quick Connect | Replaced by the full Bluetooth picker | -| Wi-Fi QR | Deliberately omitted; it is not useful enough to justify another credential-reading surface | +| Wi-Fi QR | Replaced by an on-demand QR-code sharing flow in Control Center's Wi-Fi panel; the code is generated only while shown and written to tmpfs, never persisted | | GSConnect | Replaced by capability-aware KDE Connect phone continuity in Control Center; the paired iPhone exposes file, clipboard, and Ring actions when reachable | | Home Assistant | Replaced by secure favourites in Control Center; explicit private environment values take precedence over the existing GNOME extension and Secret Service setup | | Custom Hot Corners Extended | No action was configured, so there is no behavior to port | diff --git a/config/dot/quickshell/modules/bar/CalendarPopup.qml b/config/dot/quickshell/modules/bar/CalendarPopup.qml deleted file mode 100644 index c041a55..0000000 --- a/config/dot/quickshell/modules/bar/CalendarPopup.qml +++ /dev/null @@ -1,222 +0,0 @@ -// The calendar that drops out of the clock — GNOME's date menu, minus the -// notification list (that lives in its own panel). Month grid, today marked -// with the accent, arrows to page through months, current weather at the foot. - -import Quickshell -import QtQuick -import qs.config -import qs.services -import qs.widgets - -Popover { - id: root - - // Popover's container is a plain Item, which does not derive an implicit - // size from its children, so the window has to be sized from the body. - implicitWidth: body.implicitWidth + contentPadding * 2 - implicitHeight: body.implicitHeight + contentPadding * 2 - - readonly property int cellSize: 34 - readonly property int cellHeight: 30 - - // Hours precision is enough: the only thing that has to change on its own - // is which cell counts as "today", and that only moves at midnight. - SystemClock { - id: clock - precision: SystemClock.Hours - } - - readonly property int todayYear: clock.date.getFullYear() - readonly property int todayMonth: clock.date.getMonth() - readonly property int todayDay: clock.date.getDate() - - // The month currently on screen. Reset to today every time the popover - // opens, so it never comes back showing wherever you paged off to. - property int viewYear: root.todayYear - property int viewMonth: root.todayMonth - - onVisibleChanged: if (visible) - root.showToday() - - function showToday(): void { - root.viewYear = root.todayYear; - root.viewMonth = root.todayMonth; - } - - function stepMonth(delta: int): void { - const d = new Date(root.viewYear, root.viewMonth + delta, 1); - root.viewYear = d.getFullYear(); - root.viewMonth = d.getMonth(); - } - - // Six weeks of cells, so the grid height never changes as you page through - // months. Days from the neighbouring months fill the edges, dimmed. - readonly property var cells: { - const first = new Date(root.viewYear, root.viewMonth, 1); - const offset = first.getDay(); // 0 = Sunday, matching the header row - const inThisMonth = new Date(root.viewYear, root.viewMonth + 1, 0).getDate(); - const inPrevMonth = new Date(root.viewYear, root.viewMonth, 0).getDate(); - - const out = []; - for (let i = 0; i < 42; i++) { - const n = i - offset + 1; - if (n < 1) - out.push({ - day: inPrevMonth + n, - current: false - }); - else if (n > inThisMonth) - out.push({ - day: n - inThisMonth, - current: false - }); - else - out.push({ - day: n, - current: true - }); - } - return out; - } - - Column { - id: body - spacing: Theme.itemSpacing - - // ── Month header ──────────────────────────────────────────────────── - Item { - width: root.cellSize * 7 - height: 28 - - CalendarArrow { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - glyph: "\u{F0141}" // md-chevron_left - onActivated: root.stepMonth(-1) - } - - Text { - anchors.centerIn: parent - text: Qt.formatDateTime(new Date(root.viewYear, root.viewMonth, 1), "MMMM yyyy") - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeLarge - font.weight: Font.DemiBold - color: Theme.fg - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: root.showToday() - } - } - - CalendarArrow { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - glyph: "\u{F0142}" // md-chevron_right - onActivated: root.stepMonth(1) - } - } - - // ── Weekday header ────────────────────────────────────────────────── - Row { - Repeater { - model: ["S", "M", "T", "W", "T", "F", "S"] - - delegate: Text { - required property string modelData - - width: root.cellSize - height: 20 - text: modelData - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeSmall - color: Theme.fgMuted - } - } - } - - // ── Day grid ──────────────────────────────────────────────────────── - Grid { - columns: 7 - - Repeater { - model: root.cells - - delegate: Item { - id: cell - - required property var modelData - - readonly property bool isToday: cell.modelData.current && cell.modelData.day === root.todayDay && root.viewMonth === root.todayMonth && root.viewYear === root.todayYear - - width: root.cellSize - height: root.cellHeight - - Rectangle { - anchors.centerIn: parent - width: root.cellHeight - 2 - height: root.cellHeight - 2 - radius: width / 2 - border.width: 0 - visible: cell.isToday - color: Theme.accent - } - - Text { - anchors.centerIn: parent - text: cell.modelData.day - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSize - font.weight: cell.isToday ? Font.DemiBold : Font.Normal - - color: { - if (cell.isToday) - return Theme.bgDark; - return cell.modelData.current ? Theme.fg : Theme.fgMuted; - } - } - } - } - } - - // ── Weather ───────────────────────────────────────────────────────── - Rectangle { - width: root.cellSize * 7 - height: 1 - color: Theme.alpha(Theme.fg, 0.1) - visible: Weather.available - } - - Row { - spacing: Theme.itemSpacing - visible: Weather.available - - Text { - anchors.verticalCenter: parent.verticalCenter - text: Weather.icon - font.family: Theme.fontMono - font.pixelSize: Theme.fontSizeTitle - color: Theme.accentAlt - } - - Column { - Text { - text: Math.round(Weather.temperature) + Weather.unitSuffix - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSize - color: Theme.fg - } - - Text { - text: Weather.description - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeSmall - color: Theme.fgDim - } - } - } - } -} diff --git a/config/dot/quickshell/modules/capture/RecordingIndicator.qml b/config/dot/quickshell/modules/capture/RecordingIndicator.qml deleted file mode 100644 index 093bb5c..0000000 --- a/config/dot/quickshell/modules/capture/RecordingIndicator.qml +++ /dev/null @@ -1,109 +0,0 @@ -// The "you are being recorded" pill. -// -// GNOME puts a red dot and a timer in the top bar while a screencast runs and -// clicking it stops the recording. The bar is another module's window, so this -// is its own tiny layer surface parked just below it. - -import Quickshell -import Quickshell.Wayland -import QtQuick -import qs.config -import qs.services - -PanelWindow { - id: win - - visible: Capture.recording - color: "transparent" - - // Top only: with neither left nor right anchored, layer-shell centres the - // surface horizontally. - anchors.top: true - margins.top: Theme.barGap * 2 + Theme.barHeight + Theme.barGap - - implicitWidth: pill.implicitWidth - implicitHeight: pill.implicitHeight - exclusiveZone: 0 - - WlrLayershell.namespace: "qs-popover-recording" - WlrLayershell.layer: WlrLayer.Overlay - WlrLayershell.keyboardFocus: WlrKeyboardFocus.None - - function elapsed(): string { - const t = Capture.recordingSeconds; - const s = ("0" + (t % 60)).slice(-2); - const m = Math.floor(t / 60) % 60; - const h = Math.floor(t / 3600); - return h > 0 ? h + ":" + ("0" + m).slice(-2) + ":" + s : m + ":" + s; - } - - Rectangle { - id: pill - implicitWidth: row.implicitWidth + 12 - implicitHeight: 34 - radius: Theme.pillRadius - border.width: 0 - color: Theme.redDeep - - Row { - id: row - anchors.centerIn: parent - spacing: 8 - - // Static dot, not a blinking one: nothing in this shell repaints - // while idle. - Rectangle { - anchors.verticalCenter: parent.verticalCenter - width: 10 - height: 10 - radius: 5 - border.width: 0 - color: Theme.fg - } - - Text { - anchors.verticalCenter: parent.verticalCenter - text: win.elapsed() - color: Theme.fg - // Tabular figures: the timer must not shuffle as it counts. - font.family: Theme.fontFamily - font.features: Theme.tabularFigures - font.pixelSize: Theme.fontSize - font.weight: Font.Medium - } - - Rectangle { - id: stop - anchors.verticalCenter: parent.verticalCenter - width: 26 - height: 26 - radius: width / 2 - border.width: 0 - color: stopMouse.containsMouse ? Theme.alpha(Theme.fg, 0.28) : Theme.alpha(Theme.fg, 0.14) - - Behavior on color { - ColorAnimation { - duration: Theme.durFast - } - } - - Text { - anchors.centerIn: parent - text: "󰓛" - color: Theme.fg - font.family: Theme.fontMono - font.pixelSize: Theme.fontSize - } - - MouseArea { - id: stopMouse - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - // SIGINT, so wf-recorder finalises the container. - onClicked: Capture.stopRecording() - } - } - } - } -} diff --git a/config/dot/quickshell/modules/notifications/NotificationCenter.qml b/config/dot/quickshell/modules/notifications/NotificationCenter.qml deleted file mode 100644 index 64c0ace..0000000 --- a/config/dot/quickshell/modules/notifications/NotificationCenter.qml +++ /dev/null @@ -1,219 +0,0 @@ -// GNOME's message tray: everything that has arrived, grouped by app. -// -// Drops from the top centre because that is where GNOME's tray lives and the -// muscle memory is the whole point. Layer-shell centres a surface on whichever -// axis it is not anchored to, so anchoring only `top` does it. - -import QtQuick -import Quickshell -import Quickshell.Wayland -import Quickshell.Hyprland -import Quickshell.Widgets -import qs.config -import qs.services -import qs.modules.quicksettings -import qs.widgets - -PanelWindow { - id: root - - visible: ShellState.notificationsOpen - color: "transparent" - - anchors.top: true - margins.top: Theme.barHeight + Theme.barGap * 2 - exclusiveZone: 0 - - implicitWidth: 440 - implicitHeight: surface.implicitHeight - - WlrLayershell.namespace: "qs-popover-notifications" - WlrLayershell.layer: WlrLayer.Overlay - WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand - - onVisibleChanged: { - if (root.visible) - Notifs.markAllRead(); - } - - HyprlandFocusGrab { - windows: [root] - active: root.visible - onCleared: ShellState.close() - } - - Rectangle { - id: surface - anchors.fill: parent - implicitHeight: content.implicitHeight + Theme.popoverPadding * 2 - radius: Theme.popoverRadius - color: Theme.alpha(Theme.bgPopover, Theme.popoverAlpha) - border.width: 1 - border.color: Theme.alpha(Theme.fg, 0.08) - - // The prism edge — see widgets/PrismEdge.qml. Sits just inside the 1px - // border so the two don't fight for the same row of pixels. - PrismEdge { - anchors.top: parent.top - anchors.topMargin: 1 - anchors.left: parent.left - anchors.right: parent.right - inset: parent.radius - } - - Item { - anchors.fill: parent - focus: true - Keys.onEscapePressed: ShellState.close() - - Column { - id: content - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: Theme.popoverPadding - spacing: Theme.itemSpacing - - // ── Header ────────────────────────────────────────────────── - Item { - width: parent.width - height: 32 - - Text { - anchors.left: parent.left - anchors.leftMargin: 4 - anchors.verticalCenter: parent.verticalCenter - text: "Notifications" - color: Theme.fg - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeLarge - font.weight: Font.DemiBold - } - - Row { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - spacing: 4 - - IconButton { - size: 30 - iconSize: 16 - icon: "notifications-disabled-symbolic" - tint: Notifs.doNotDisturb ? Theme.accent : Theme.fgDim - onClicked: Notifs.doNotDisturb = !Notifs.doNotDisturb - } - - Rectangle { - width: clearLabel.implicitWidth + 20 - height: 28 - radius: Theme.pillRadius - border.width: 0 - visible: Notifs.hasNotifications - color: clearMouse.containsMouse ? Theme.alpha(Theme.fg, 0.16) : Theme.alpha(Theme.fg, 0.08) - - Behavior on color { - ColorAnimation { - duration: Theme.durFast - } - } - - Text { - id: clearLabel - anchors.centerIn: parent - text: "Clear all" - color: Theme.fg - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeSmall - font.weight: Font.Medium - } - - MouseArea { - id: clearMouse - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: Notifs.dismissAll() - } - } - } - } - - // ── Empty state ───────────────────────────────────────────── - Item { - width: parent.width - height: 120 - visible: !Notifs.hasNotifications - - Text { - anchors.centerIn: parent - text: Notifs.doNotDisturb ? "Do Not Disturb is on" : "No notifications" - color: Theme.fgMuted - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSize - } - } - - // ── Grouped history ───────────────────────────────────────── - ScrollColumn { - width: parent.width - maxHeight: 620 - spacing: Theme.itemSpacing - visible: Notifs.hasNotifications - - Repeater { - model: Notifs.groups - - Column { - id: group - - required property var modelData - - width: parent.width - spacing: 4 - - Item { - width: parent.width - height: 26 - - Text { - anchors.left: parent.left - anchors.leftMargin: 4 - anchors.verticalCenter: parent.verticalCenter - text: group.modelData.app - color: Theme.fgDim - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeSmall - font.weight: Font.DemiBold - } - - IconButton { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - size: 24 - iconSize: 13 - tint: Theme.fgDim - icon: "edit-clear-all-symbolic" - iconFallback: "window-close-symbolic" - onClicked: Notifs.dismissApp(group.modelData.app) - } - } - - Repeater { - model: group.modelData.items - - NotificationCard { - required property var modelData - - width: group.width - compact: true - notification: modelData - onDismissed: Notifs.dismiss(modelData) - } - } - } - } - } - } - } - } -} diff --git a/config/dot/quickshell/modules/settings/HealthPage.qml b/config/dot/quickshell/modules/settings/HealthPage.qml index 92a03f1..957bd04 100644 --- a/config/dot/quickshell/modules/settings/HealthPage.qml +++ b/config/dot/quickshell/modules/settings/HealthPage.qml @@ -441,7 +441,7 @@ SettingsPage { ActionRow { objectName: "health-fedora-handoff:color" label: "Colour profiles" - detail: "ICC profiles for displays, printers, and scanners" + detail: "Assigning an ICC profile here has no visible effect in this session: the colord daemon that loads it onto a display isn't running under Hyprland" action: "Open colour" onTriggered: SystemSettings.openGnomePanel("color") } diff --git a/config/dot/quickshell/services/Displays.qml b/config/dot/quickshell/services/Displays.qml index 1a862da..067c55c 100644 --- a/config/dot/quickshell/services/Displays.qml +++ b/config/dot/quickshell/services/Displays.qml @@ -95,7 +95,6 @@ Singleton { root.revertWithMessage("The display rejected that change and Panama restored the previous setting."); return; } - verifyTimer.attempts = 0; verifyTimer.ticks = 0; verifyTimer.restart(); } @@ -107,7 +106,6 @@ Singleton { // Exit status is advisory only. Hyprland's Lua bridge can report // success without applying a value, so exact readback decides. root.revertVerificationActive = true; - revertVerifyTimer.attempts = 0; revertVerifyTimer.ticks = 0; revertVerifyTimer.restart(); } @@ -542,7 +540,6 @@ Singleton { Timer { id: verifyTimer - property int attempts: 0 property int ticks: 0 interval: 120 repeat: true @@ -552,14 +549,12 @@ Singleton { root.verificationTimedOut(); return; } - if (root.refresh()) - attempts++; + root.refresh(); } } Timer { id: revertVerifyTimer - property int attempts: 0 property int ticks: 0 interval: 120 repeat: true @@ -569,8 +564,7 @@ Singleton { root.revertVerificationTimedOut(); return; } - if (root.refresh()) - attempts++; + root.refresh(); } }