Files
dms-gamebar/GameBarBarWidget.qml

201 lines
6.5 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Modules.Plugins
import qs.Services
import qs.Widgets
import "./components"
PluginComponent {
id: root
property var popoutService: null
readonly property var daemon: (typeof PluginService !== "undefined" && PluginService.pluginInstances) ? PluginService.pluginInstances["gameBar"] : null
// "focused" follows whichever monitor has focus, "own" sticks to the screen
// this particular bar instance lives on.
readonly property string targetMode: String(pluginData.barBrightnessTarget || "focused")
property var resolvedScreen: null
readonly property string screenName: {
const screen = root.resolvedScreen || root.parentScreen;
return (screen && screen.name) ? screen.name : "";
}
readonly property string deviceId: root.daemon ? root.daemon.brightnessDeviceForScreen(root.screenName) : ""
readonly property var device: DisplayService.devices ? (DisplayService.devices.find(d => d.id === root.deviceId) || null) : null
readonly property bool usable: DisplayService.brightnessAvailable && root.deviceId !== ""
readonly property int brightness: {
DisplayService.brightnessVersion;
return root.deviceId !== "" ? DisplayService.getDeviceBrightness(root.deviceId) : 0;
}
readonly property string brightnessIcon: {
if (!root.usable)
return "brightness_low";
if (root.brightness <= 33)
return "brightness_low";
if (root.brightness <= 66)
return "brightness_medium";
return "brightness_high";
}
function updateScreen() {
if (root.targetMode === "own") {
root.resolvedScreen = root.parentScreen;
return;
}
root.resolvedScreen = CompositorService.getFocusedScreen() || root.parentScreen;
}
// The Control Center pill click follows the shell's own convention for
// non-boolean widgets (see DisplayProfilesWidget): step through presets.
readonly property var brightnessPresets: [10, 25, 50, 75, 100]
function cyclePreset() {
if (!root.usable)
return;
const current = root.brightness;
for (let i = 0; i < root.brightnessPresets.length; i++) {
if (root.brightnessPresets[i] > current + 1) {
DisplayService.setBrightness(root.brightnessPresets[i], root.deviceId, false);
return;
}
}
DisplayService.setBrightness(root.brightnessPresets[0], root.deviceId, false);
}
function adjust(delta) {
if (!root.usable)
return;
const next = Math.max(1, Math.min(100, root.brightness + delta));
DisplayService.setBrightness(next, root.deviceId, false);
}
pluginId: "gameBar"
pluginService: PluginService
popoutWidth: 320
popoutHeight: 150
Component.onCompleted: {
root.updateScreen();
if (root.daemon)
root.daemon.ensureBrightnessMap();
}
onTargetModeChanged: root.updateScreen()
// Focus usually moves with the active toplevel; the timer covers moves to an
// empty workspace on another monitor, which raise no toplevel change.
Connections {
target: ToplevelManager
function onActiveToplevelChanged() {
root.updateScreen();
}
}
Timer {
running: root.targetMode === "focused"
interval: 2000
repeat: true
onTriggered: root.updateScreen()
}
horizontalBarPill: Component {
Item {
implicitWidth: pillRow.implicitWidth + Theme.spacingS * 2
height: parent.widgetThickness
Row {
id: pillRow
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
anchors.verticalCenter: parent.verticalCenter
name: root.brightnessIcon
size: root.iconSize
color: root.usable ? Theme.surfaceText : Theme.surfaceVariantText
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
text: root.usable ? root.brightness + "%" : "--"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
}
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: event => root.adjust(event.angleDelta.y > 0 ? 5 : -5)
}
}
}
verticalBarPill: Component {
Item {
width: parent.widgetThickness
implicitHeight: verticalColumn.implicitHeight + Theme.spacingS * 2
Column {
id: verticalColumn
anchors.centerIn: parent
spacing: 0
DankIcon {
anchors.horizontalCenter: parent.horizontalCenter
name: root.brightnessIcon
size: root.iconSize
color: root.usable ? Theme.surfaceText : Theme.surfaceVariantText
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: root.usable ? root.brightness : "--"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
}
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: event => root.adjust(event.angleDelta.y > 0 ? 5 : -5)
}
}
}
popoutContent: Component {
PopoutComponent {
headerText: "Brightness"
detailsText: root.screenName !== "" ? root.screenName + (root.deviceId !== "" ? " · " + root.deviceId : "") : "No display detected"
showCloseButton: true
Column {
width: parent.width
spacing: Theme.spacingS
BrightnessControl {
width: parent.width
daemon: root.daemon
screenName: root.screenName
}
StyledText {
width: parent.width
text: root.targetMode === "own" ? "Controls this monitor" : "Follows the focused monitor"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
}
}
}