This commit is contained in:
end-4
2025-04-21 17:51:28 +02:00
parent 9678751156
commit 0faf9287ba
13 changed files with 392 additions and 28 deletions
+70 -14
View File
@@ -12,6 +12,7 @@ Scope {
readonly property int barHeight: Appearance.sizes.barHeight
readonly property int barCenterSideModuleWidth: Appearance.sizes.barCenterSideModuleWidth
readonly property int osdHideMouseMoveThreshold: 20
Process {
id: openSidebarRight
@@ -21,6 +22,10 @@ Scope {
id: openSidebarLeft
command: ["qs", "ipc", "call", "sidebarLeft", "open"]
}
Process {
id: hideOsd
command: ["qs", "ipc", "call", "osd", "hide"]
}
Variants {
model: Quickshell.screens
@@ -60,18 +65,6 @@ Scope {
ActiveWindow {
bar: barRoot
}
// Scroll to change brightness
WheelHandler {
onWheel: (event) => {
if (event.angleDelta.y < 0)
Brightness.value = -1;
else if (event.angleDelta.y > 0)
Brightness.value = 1;
}
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
}
}
// Middle section
@@ -179,9 +172,57 @@ Scope {
}
MouseArea {
// Interactions
MouseArea { // Left side: scroll to change brightness
id: barLeftSideMouseArea
property bool hovered: false
property real lastScrollX: 0
property real lastScrollY: 0
property bool trackingScroll: false
anchors.fill: leftSection
acceptedButtons: Qt.LeftButton
hoverEnabled: true
propagateComposedEvents: true
onEntered: (event) => {
barLeftSideMouseArea.hovered = true
}
onExited: (event) => {
barLeftSideMouseArea.hovered = false
barLeftSideMouseArea.trackingScroll = false
}
// Scroll to change brightness
WheelHandler {
onWheel: (event) => {
if (event.angleDelta.y < 0)
Brightness.increment = -1;
else if (event.angleDelta.y > 0)
Brightness.increment = 1;
// Store the mouse position and start tracking
barLeftSideMouseArea.lastScrollX = event.x;
barLeftSideMouseArea.lastScrollY = event.y;
barLeftSideMouseArea.trackingScroll = true;
}
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
}
onPositionChanged: (mouse) => {
if (barLeftSideMouseArea.trackingScroll) {
const dx = mouse.x - barLeftSideMouseArea.lastScrollX;
const dy = mouse.y - barLeftSideMouseArea.lastScrollY;
if (Math.sqrt(dx*dx + dy*dy) > osdHideMouseMoveThreshold) {
hideOsd.running = true;
barLeftSideMouseArea.trackingScroll = false;
}
}
}
}
MouseArea { // Right side: scroll to change volume
id: barRightSideMouseArea
property bool hovered: false
property real lastScrollX: 0
property real lastScrollY: 0
property bool trackingScroll: false
anchors.fill: rightSection
acceptedButtons: Qt.LeftButton
hoverEnabled: true
@@ -191,6 +232,7 @@ Scope {
}
onExited: (event) => {
barRightSideMouseArea.hovered = false
barRightSideMouseArea.trackingScroll = false
}
onPressed: (event) => {
if (event.button === Qt.LeftButton) {
@@ -200,15 +242,29 @@ Scope {
// Scroll to change volume
WheelHandler {
onWheel: (event) => {
const currentVolume = Audio.sink?.audio.volume;
const currentVolume = Audio.value;
const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2;
if (event.angleDelta.y < 0)
Audio.sink.audio.volume -= step;
else if (event.angleDelta.y > 0)
Audio.sink.audio.volume += step;
// Store the mouse position and start tracking
barRightSideMouseArea.lastScrollX = event.x;
barRightSideMouseArea.lastScrollY = event.y;
barRightSideMouseArea.trackingScroll = true;
}
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
}
onPositionChanged: (mouse) => {
if (barRightSideMouseArea.trackingScroll) {
const dx = mouse.x - barRightSideMouseArea.lastScrollX;
const dy = mouse.y - barRightSideMouseArea.lastScrollY;
if (Math.sqrt(dx*dx + dy*dy) > osdHideMouseMoveThreshold) {
hideOsd.running = true;
barRightSideMouseArea.trackingScroll = false;
}
}
}
}
}
@@ -134,6 +134,7 @@ Singleton {
property color colTooltip: m3colors.m3inverseSurface
property color colOnTooltip: m3colors.m3inverseOnSurface
property color colScrim: transparentize(m3colors.m3scrim, 0.5)
property color colShadow: transparentize(m3colors.m3shadow, 0.75)
}
rounding: QtObject {
@@ -26,12 +26,16 @@ Singleton {
}
}
property QtObject osd: QtObject {
property int timeout: 1000
}
property QtObject resources: QtObject {
property int updateInterval: 3000
}
property QtObject hacks: QtObject {
property int arbitraryRaceConditionDelay: 10
property int arbitraryRaceConditionDelay: 10 // milliseconds
}
}
@@ -1,6 +1,6 @@
// From https://github.com/rafzby/circular-progressbar
// License: LGPL-3.0 - A copy can be found in `licenses` folder of repo
// Modified
// Modified so it looks like in Material 3: https://m3.material.io/components/progress-indicators/specs
import QtQuick 2.9
Item {
@@ -0,0 +1,57 @@
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Qt5Compat.GraphicalEffects
ProgressBar {
id: root
property real valueBarWidth: 120
property real valueBarHeight: 4
property real valueBarGap: 4
Behavior on value {
NumberAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
}
}
background: Rectangle {
anchors.fill: parent
color: "transparent"
radius: Appearance.rounding.full
implicitHeight: valueBarHeight
implicitWidth: valueBarWidth
}
contentItem: Item {
implicitWidth: parent.width
implicitHeight: parent.height
Rectangle { // Left progress fill
width: root.visualPosition * parent.width
height: parent.height
radius: Appearance.rounding.full
color: Appearance.m3colors.m3primary
}
Rectangle { // Right remaining part fill
anchors.right: parent.right
width: (1 - root.visualPosition) * parent.width - valueBarGap
height: parent.height
radius: Appearance.rounding.full
color: Appearance.m3colors.m3secondaryContainer
}
Rectangle { // Stop point
anchors.right: parent.right
width: valueBarGap
height: valueBarGap
radius: Appearance.rounding.full
color: Appearance.m3colors.m3primary
}
}
}
@@ -0,0 +1,118 @@
import "root:/services/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
Scope {
id: root
property bool showOsdValues: false
function triggerOsd() {
showOsdValues = true
osdTimeout.restart()
}
Timer {
id: osdTimeout
interval: ConfigOptions.osd.timeout
repeat: false
running: false
onTriggered: {
showOsdValues = false
}
}
Connections {
target: Brightness
function onValueChanged() {
if (!Brightness.ready) return
root.triggerOsd()
}
}
Connections {
target: Audio.sink.audio
function onVolumeChanged() {
if (!Audio.ready) return
root.triggerOsd()
}
}
Variants {
model: Quickshell.screens
PanelWindow {
property var modelData
screen: modelData
exclusionMode: ExclusionMode.Normal
WlrLayershell.namespace: "quickshell:onScreenDisplay"
WlrLayershell.layer: WlrLayer.Overlay
color: "transparent"
anchors {
top: true
left: true
right: true
}
mask: Region {
item: columnLayout
}
width: columnLayout.implicitWidth
height: columnLayout.implicitHeight
visible: showOsdValues
ColumnLayout {
id: columnLayout
anchors.horizontalCenter: parent.horizontalCenter
Item {
height: 1 // Prevent Wayland protocol error
}
Item {
implicitHeight: true ? osdValues.implicitHeight : 0
implicitWidth: osdValues.implicitWidth
clip: true
Behavior on implicitHeight {
NumberAnimation {
duration: Appearance.animation.menuDecel.duration
easing.type: Appearance.animation.menuDecel.type
}
}
OsdValues {
id: osdValues
anchors.bottom: parent.bottom
// height: showOsdValues ? implicitHeight : 0
// implicitHeight: 0
}
}
}
}
}
IpcHandler {
target: "osd"
function trigger() {
root.triggerOsd()
}
function hide() {
showOsdValues = false
}
function toggle() {
showOsdValues = !showOsdValues
}
}
}
@@ -0,0 +1,86 @@
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Qt5Compat.GraphicalEffects
Item {
id: root
required property real value
required property string icon
required property string name
property real valueIndicatorVerticalPadding: 5
property real valueIndicatorLeftPadding: 10
property real valueIndicatorRightPadding: 20 // An icon is circle ish, a column isn't, hence the extra padding
Layout.margins: Appearance.sizes.elevationMargin
implicitWidth: valueIndicator.implicitWidth
implicitHeight: valueIndicator.implicitHeight
WrapperRectangle {
id: valueIndicator
radius: Appearance.rounding.full
color: Appearance.colors.colLayer0
implicitWidth: valueRow.implicitWidth
RowLayout { // Icon on the left, stuff on the right
id: valueRow
spacing: 5
Layout.margins: 10
MaterialSymbol { // Icon
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: valueIndicatorLeftPadding
Layout.topMargin: valueIndicatorVerticalPadding
Layout.bottomMargin: valueIndicatorVerticalPadding
text: root.icon
font.pixelSize: 30
}
ColumnLayout { // Stuff
Layout.alignment: Qt.AlignVCenter
Layout.rightMargin: valueIndicatorRightPadding
spacing: 5
RowLayout { // Name fill left, value on the right end
Layout.leftMargin: valueBarHeight / 2 // Align text with progressbar radius curve's left end
Layout.rightMargin: valueBarHeight / 2 // Align text with progressbar radius curve's left end
StyledText {
color: Appearance.colors.colOnLayer0
font.pixelSize: Appearance.font.pixelSize.small
Layout.fillWidth: true
text: root.name
}
StyledText {
color: Appearance.colors.colOnLayer0
font.pixelSize: Appearance.font.pixelSize.small
Layout.fillWidth: false
text: Math.round(root.value * 100)
}
}
StyledProgressBar {
id: valueProgressBar
value: root.value
}
}
}
}
DropShadow {
id: valueShadow
anchors.fill: valueIndicator
source: valueIndicator
radius: Appearance.sizes.elevationMargin
samples: radius * 2 + 1
color: Appearance.colors.colShadow
verticalOffset: 2
horizontalOffset: 0
}
}
@@ -0,0 +1,24 @@
import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Qt5Compat.GraphicalEffects
RowLayout {
spacing: -5
OsdValueIndicator {
value: Brightness.value
icon: "light_mode"
name: "Brightness"
}
OsdValueIndicator {
value: Audio.sink.audio.volume
icon: "volume_up"
name: "Volume"
}
}
@@ -14,7 +14,6 @@ Scope {
model: Quickshell.screens
PanelWindow {
id: barRoot
visible: (ConfigOptions.appearance.fakeScreenRounding === 1 || (ConfigOptions.appearance.fakeScreenRounding === 2 && !activeWindow?.fullscreen))
property var modelData
@@ -162,7 +162,7 @@ Scope {
verticalOffset: 2
radius: Appearance.sizes.elevationMargin
samples: Appearance.sizes.elevationMargin * 2 + 1 // Ideally should be 2 * radius + 1, see qt docs
color: Appearance.transparentize(Appearance.m3colors.m3shadow, 0.55)
color: Appearance.colors.colShadow
source: sidebarRightBackground
}
+1
View File
@@ -7,6 +7,7 @@ pragma ComponentBehavior: Bound
Singleton {
id: root
property bool ready: Pipewire.defaultAudioSink.ready
property var sink: Pipewire.defaultAudioSink
property var source: Pipewire.defaultAudioSource
+26 -10
View File
@@ -6,22 +6,22 @@ pragma ComponentBehavior: Bound
Singleton {
id: root
property string brightness
property int value: 0
property bool ready: false
property real value
property int increment: 0
function refresh() {
getBrightness.running = true;
}
onValueChanged: () => {
if (value > 0) {
onIncrementChanged: () => {
if (increment > 0) {
increaseBrightness.running = true;
root.value = 0;
} else if (value < 0) {
root.increment = 0;
} else if (increment < 0) {
decreaseBrightness.running = true;
root.value = 0;
root.increment = 0;
}
getBrightness.running = true;
}
Process {
@@ -30,12 +30,15 @@ Singleton {
command: ["sh", "-c", "brightnessctl -m i | cut -d, -f4"]
running: true
onExited: {
running = false;
if (!ready) ready = true
}
stdout: SplitParser {
onRead: (data) => {
root.brightness = data;
root.value = parseFloat(data.replace("%", "")) / 100;
if (root.value < 0.01) {
preventPitchBlack.running = true;
}
}
}
@@ -48,6 +51,7 @@ Singleton {
running: false
onExited: {
running = false;
getBrightness.running = true;
}
}
@@ -58,6 +62,18 @@ Singleton {
running: false
onExited: {
running = false;
getBrightness.running = true;
}
}
Process {
id: preventPitchBlack
command: ["brightnessctl", "set", "1%+"]
running: false
onExited: {
running = false;
getBrightness.running = true;
}
}
+2
View File
@@ -1,6 +1,7 @@
//@ pragma UseQApplication
import "./modules/bar/"
import "./modules/onScreenDisplay/"
import "./modules/screenCorners/"
import "./modules/sidebarRight/"
import QtQuick
@@ -14,5 +15,6 @@ ShellRoot {
SidebarRight {}
ScreenCorners {}
ReloadPopup {}
OnScreenDisplay {}
}