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 } } } } }