diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml index 9983cdb3b..174b7851f 100644 --- a/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml @@ -65,8 +65,8 @@ Scope { } onClosed: { - barLoader.active = false; GlobalStates.sidebarLeftOpen = false; + barLoader.active = false; } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/nightLight/NightLightControl.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/nightLight/NightLightControl.qml index 45ba6bba2..71630295c 100644 --- a/dots/.config/quickshell/ii/modules/waffle/actionCenter/nightLight/NightLightControl.qml +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/nightLight/NightLightControl.qml @@ -84,7 +84,7 @@ Item { } ToggleItem { - name: Translation.tr("Enable") + name: Translation.tr("Enable now") description: Translation.tr("More comfortable viewing at night") iconName: WIcons.nightLightIcon checked: Hyprsunset.active diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml index da5e464d2..4a1bcaa07 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml @@ -31,7 +31,13 @@ BarButton { id: internetHoverArea iconItem: FluentIcon { anchors.verticalCenter: parent.verticalCenter - icon: WIcons.internetIcon + icon: "wifi-1" + color: Looks.colors.inactiveIcon + + FluentIcon { + anchors.fill: parent + icon: WIcons.internetIcon + } } } @@ -39,7 +45,13 @@ BarButton { id: volumeHoverArea iconItem: FluentIcon { anchors.verticalCenter: parent.verticalCenter - icon: WIcons.volumeIcon + icon: "speaker" + color: Looks.colors.inactiveIcon + + FluentIcon { + anchors.fill: parent + icon: WIcons.volumeIcon + } } onScrollDown: Audio.decrementVolume(); onScrollUp: Audio.incrementVolume(); diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index a20839d12..ce636e741 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -17,7 +17,7 @@ Singleton { property string iconsPath: `${Directories.assetsPath}/icons/fluent` property bool dark: Appearance.m3colors.darkmode - property real backgroundTransparency: 0.11 + property real backgroundTransparency: 0.18 property real panelBackgroundTransparency: 0.12 property real panelLayerTransparency: root.dark ? 0.9 : 0.7 property real contentTransparency: root.dark ? 0.9 : 0.5 @@ -83,7 +83,7 @@ Singleton { } colors: QtObject { id: colors - property color shadow: ColorUtils.transparentize("#000000", 0.62) + property color shadow: ColorUtils.transparentize('#161616', 0.62) property color ambientShadow: ColorUtils.transparentize("#000000", 0.75) property color bgPanelFooterBase: ColorUtils.transparentize(root.dark ? root.darkColors.bgPanelFooter : root.lightColors.bgPanelFooter, root.panelBackgroundTransparency) property color bgPanelFooter: ColorUtils.transparentize(root.dark ? root.darkColors.bgPanelFooter : root.lightColors.bgPanelFooter, root.panelLayerTransparency) diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml index ca8fa16a6..3035a6511 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml @@ -10,11 +10,13 @@ import qs.modules.waffle.looks Item { id: root - signal closed + signal closed() property alias border: borderRect - default required property Item contentItem + property alias borderColor: borderRect.border.color + required property Item contentItem property real visualMargin: 12 + property int closeAnimDuration: 150 function close() { closeAnim.start(); @@ -70,7 +72,7 @@ Item { target: borderRect property: "sourceEdgeMargin" to: -(implicitHeight + root.visualMargin) - duration: 150 + duration: root.closeAnimDuration easing.type: Easing.BezierSpline easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WProgressBar.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WProgressBar.qml new file mode 100644 index 000000000..490358c61 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WProgressBar.qml @@ -0,0 +1,49 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell.Widgets +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.waffle.looks + +ProgressBar { + id: root + + Behavior on value { + SmoothedAnimation { + velocity: Looks.transition.velocity + } + } + + implicitHeight: 4 + background: null + + contentItem: Item { + id: background + + Rectangle { + id: trackTrough + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + radius: root.implicitHeight / 2 + color: Looks.colors.controlBg + implicitHeight: root.implicitHeight + } + + Rectangle { + id: trackHighlight + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + radius: root.implicitHeight / 2 + color: Looks.colors.accent + implicitHeight: root.implicitHeight + width: background.width * root.value + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/BrightnessOSD.qml b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/BrightnessOSD.qml new file mode 100644 index 000000000..0f901ec34 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/BrightnessOSD.qml @@ -0,0 +1,21 @@ +import QtQuick +import Quickshell +import Quickshell.Hyprland +import qs.services +import qs.modules.waffle.looks + +OSDValue { + id: root + property var focusedScreen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) + property var brightnessMonitor: Brightness.getMonitorForScreen(focusedScreen) + iconName: "weather-sunny" + value: brightnessMonitor?.brightness ?? 0 + showNumber: false + + Connections { + target: Brightness + function onBrightnessChanged() { + root.timer.restart(); + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/OSDValue.qml b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/OSDValue.qml new file mode 100644 index 000000000..8d48a6f92 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/OSDValue.qml @@ -0,0 +1,65 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +WBarAttachedPanelContent { + id: root + required property string iconName + property real value + property bool showNumber: true + borderColor: Looks.colors.ambientShadow + + property Timer timer: Timer { + id: autoCloseTimer + running: true + interval: Config.options.osd.timeout + repeat: false + onTriggered: { + root.close() + } + } + + contentItem: Rectangle { + anchors.centerIn: parent + color: Looks.colors.bg1Base + radius: Looks.radius.medium + implicitWidth: root.showNumber ? 192 : 170 + implicitHeight: 46 + + RowLayout { + id: contentRow + anchors.fill: parent + anchors.margins: 12 + + spacing: 12 + + FluentIcon { + Layout.alignment: Qt.AlignVCenter + icon: root.iconName + implicitSize: 18 + } + + WProgressBar { + id: progressBar + value: root.value + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + Layout.rightMargin: root.showNumber ? 0 : 3 + } + + WTextWithFixedWidth { + visible: root.showNumber + text: Math.round(root.value * 100) + // longestText: "100" + implicitWidth: 16 + horizontalAlignment: Text.AlignHCenter + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/VolumeOSD.qml b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/VolumeOSD.qml new file mode 100644 index 000000000..2be8e4fcb --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/VolumeOSD.qml @@ -0,0 +1,22 @@ +import QtQuick +import qs.services +import qs.modules.waffle.looks + +OSDValue { + id: root + iconName: WIcons.volumeIcon + value: Audio.sink?.audio.volume ?? 0 + + Connections { + // Listen to volume changes + target: Audio.sink?.audio ?? null + function onVolumeChanged() { + if (Audio.ready) + root.timer.restart(); + } + function onMutedChanged() { + if (Audio.ready) + root.timer.restart(); + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/WaffleOSD.qml b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/WaffleOSD.qml new file mode 100644 index 000000000..538fa264e --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/onScreenDisplay/WaffleOSD.qml @@ -0,0 +1,154 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Hyprland +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.waffle.looks + +Scope { + id: root + + property var focusedScreen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) + property string currentIndicator: "volume" + property var indicators: [ + { + id: "volume", + sourceUrl: "VolumeOSD.qml", + globalStateValue: "osdVolumeOpen" + }, + { + id: "brightness", + sourceUrl: "BrightnessOSD.qml", + globalStateValue: "osdBrightnessOpen" + }, + ] + + function triggerBrightnessOsd() { + root.currentIndicator = "brightness"; + GlobalStates.osdBrightnessOpen = true; + } + + function triggerVolumeOSD() { + root.currentIndicator = "volume"; + GlobalStates.osdVolumeOpen = true; + } + + // Listen to brightness changes + Connections { + target: Brightness + function onBrightnessChanged() { + root.triggerBrightnessOsd(); + } + } + + // Listen to volume changes + Connections { + target: Audio.sink?.audio ?? null + function onVolumeChanged() { + if (Audio.ready) + root.triggerVolumeOSD(); + } + function onMutedChanged() { + if (Audio.ready) + root.triggerVolumeOSD(); + } + } + + // Open when global state changes + Connections { + target: GlobalStates + + function onOsdBrightnessOpenChanged() { + if (GlobalStates.osdBrightnessOpen) + panelLoader.active = true; + } + function onOsdVolumeOpenChanged() { + if (GlobalStates.osdVolumeOpen) + panelLoader.active = true; + } + } + + // The actual thing + Loader { + id: panelLoader + active: GlobalStates.osdBrightnessOpen || GlobalStates.osdVolumeOpen + sourceComponent: PanelWindow { + id: panelWindow + + Connections { + target: root + function onFocusedScreenChanged() { + osdRoot.screen = root.focusedScreen; + } + } + + color: "transparent" + exclusiveZone: 0 + WlrLayershell.namespace: "quickshell:wOnScreenDisplay" + WlrLayershell.layer: WlrLayer.Overlay + anchors { + top: !Config.options.waffles.bar.bottom + bottom: Config.options.waffles.bar.bottom + } + mask: Region { + item: osdIndicatorLoader + } + + implicitWidth: osdIndicatorLoader.implicitWidth + osdIndicatorLoader.item.visualMargin * 2 + implicitHeight: osdIndicatorLoader.implicitHeight + osdIndicatorLoader.item.visualMargin * 2 + + Loader { + id: osdIndicatorLoader + anchors.fill: parent + anchors.margins: item.visualMargin + source: root.indicators.find(i => i.id === root.currentIndicator)?.sourceUrl + + Connections { + target: osdIndicatorLoader.item + function onClosed() { + panelLoader.active = false; + GlobalStates[root.indicators.find(i => i.id === root.currentIndicator)?.globalStateValue] = false; + } + } + + Behavior on source { + id: switchBehavior + + SequentialAnimation { + id: switchAnim + // Animate close of current indicator + ScriptAction { + script: { + osdIndicatorLoader.item.close() + } + } + // Wait for close anim + PauseAnimation { + duration: osdIndicatorLoader.item.closeAnimDuration + } + PropertyAction {} // The source change happens here + } + } + } + } + } + + IpcHandler { + target: "osd" + + function trigger() { + root.trigger(); + } + } + + GlobalShortcut { + name: "osdTrigger" + description: "Triggers OSD display" + + onPressed: root.trigger() + } +} diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml index 756c0a155..b8193812f 100644 --- a/dots/.config/quickshell/ii/shell.qml +++ b/dots/.config/quickshell/ii/shell.qml @@ -31,6 +31,7 @@ import qs.modules.ii.wallpaperSelector import qs.modules.waffle.actionCenter import qs.modules.waffle.background import qs.modules.waffle.bar +import qs.modules.waffle.onScreenDisplay import QtQuick import QtQuick.Window @@ -78,6 +79,7 @@ ShellRoot { PanelLoader { identifier: "wActionCenter"; component: WaffleActionCenter {} } PanelLoader { identifier: "wBar"; component: WaffleBar {} } PanelLoader { identifier: "wBackground"; component: WaffleBackground {} } + PanelLoader { identifier: "wOnScreenDisplay"; component: WaffleOSD {} } ReloadPopup {} component PanelLoader: LazyLoader { @@ -90,7 +92,7 @@ ShellRoot { property list families: ["ii", "waffle"] property var panelFamilies: ({ "ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"], - "waffle": ["wBar", "wBackground", "wActionCenter", "iiCheatsheet", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiSessionScreen", "iiSidebarRight", "iiWallpaperSelector"], + "waffle": ["wActionCenter", "wBar", "wBackground", "wOnScreenDisplay", "iiCheatsheet", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiSessionScreen", "iiSidebarRight", "iiWallpaperSelector"], }) function cyclePanelFamily() { const currentIndex = families.indexOf(Config.options.panelFamily)