waffles: osd

This commit is contained in:
end-4
2025-11-23 11:39:11 +01:00
parent 6e986fa8b0
commit 3087e5da92
11 changed files with 337 additions and 10 deletions
@@ -65,8 +65,8 @@ Scope {
}
onClosed: {
barLoader.active = false;
GlobalStates.sidebarLeftOpen = false;
barLoader.active = false;
}
}
}
@@ -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
@@ -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();
@@ -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)
@@ -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
}
@@ -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
}
}
}
@@ -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();
}
}
}
@@ -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
}
}
}
}
@@ -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();
}
}
}
@@ -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()
}
}
+3 -1
View File
@@ -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<string> 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)