import QtQuick import Quickshell.Bluetooth import Quickshell.Services.Pipewire import "../.." Item { id: root width: parent ? parent.width : 1280 height: parent ? parent.height : 820 focus: true /* ------------------------------ PIXEL CONSTANTS (DO NOT TOUCH) ------------------------------ */ property int menuLeft: 64 property int menuTop: 140 property int lineHeight: 38 + 40 + 1 property int nameFontSize: 32 property int stateFontSize: 28 property int stateColumnX: 824 property int soulOffsetX: -36 - 32 property int soulOffsetY: -26 /* ------------------------------ */ property ShellStateManager manager: null property int activeSelection: 0 property bool inBluetoothMenu: false property bool isSelected: false function clamp(v, lo, hi) { return Math.max(lo, Math.min(hi, v)); } function menuLength() { if (root.inBluetoothMenu && bluetoothRepeater) return bluetoothRepeater.count; if (!menuModel) return 0; if (typeof menuModel.count === "function") return menuModel.count(); if (menuModel.count !== undefined) return menuModel.count; if (menuModel.length !== undefined) return menuModel.length; return 0; } function menuAt(index) { if (!menuModel) return null; if (menuModel.get) return menuModel.get(index); if (menuModel.length !== undefined) return menuModel[index]; return null; } function wrapIndex(i) { const length = menuLength(); if (length === 0) return 0; return (i + length) % length; } function currentAction() { if (root.inBluetoothMenu) return null; return menuLength() > 0 ? menuAt(activeSelection) : null; } function clampSelection() { const length = menuLength(); if (length === 0) { activeSelection = 0; return; } activeSelection = clamp(activeSelection, 0, length - 1); } function bluetoothDisplayName(device) { if (!device) return ""; if (device.name && device.name.length > 0) return device.name; return device.deviceName || ""; } function bluetoothDisplayState(device) { if (!device) return ""; // dont change symbols return device.connected ? "✓" : ""; } function bluetoothDeviceAt(index) { const item = bluetoothRepeater.itemAt(index); if (!item) return null; return item.device || null; } PwObjectTracker { objects: [Pipewire.defaultAudioSink] } property int bluetoothActionIndex: 1 property var actions: [ { name: "Master Volume", arr: function (dir) { const sink = Pipewire.defaultAudioSink; if (!sink || !sink.audio) return; const step = 0.05; sink.audio.muted = false; sink.audio.volume = clamp(sink.audio.volume + dir * step, 0, 1); }, getState: function () { const sink = Pipewire.defaultAudioSink; if (!sink || !sink.audio) return "—"; return Math.round(sink.audio.volume * 100) + "%"; } }, { name: "Bluetooth", ent: function () { root.inBluetoothMenu = true; root.isSelected = false; root.activeSelection = 0; root.clampSelection(); }, getState: function () { return ""; } } ] property var menuModel: root.inBluetoothMenu ? Bluetooth.devices : actions Connections { target: Bluetooth.devices ignoreUnknownSignals: true function onCountChanged() { if (root.inBluetoothMenu) root.clampSelection(); } function onModelReset() { if (root.inBluetoothMenu) root.clampSelection(); } function onRowsInserted() { if (root.inBluetoothMenu) root.clampSelection(); } function onRowsRemoved() { if (root.inBluetoothMenu) root.clampSelection(); } } Text { text: root.inBluetoothMenu ? "BLUETOOTH" : "CONFIG" font.family: "8bitoperator JVE" font.pixelSize: 71 renderType: Text.NativeRendering font.hintingPreference: Font.PreferNoHinting smooth: false antialiasing: false anchors.horizontalCenter: parent.horizontalCenter color: "#ffffff" y: 32 } Repeater { id: bluetoothRepeater model: root.menuModel delegate: Item { width: root.width height: lineHeight x: 0 y: menuTop + index * lineHeight property var device: root.inBluetoothMenu ? modelData : null Image { source: "./soul.png" width: 36 height: 36 x: 182 y: 8 + 14 visible: root.activeSelection == index } Text { x: 239 y: 0 text: root.inBluetoothMenu ? root.bluetoothDisplayName(modelData) : modelData.name font.family: "8bitoperator JVE" font.pixelSize: 71 font.letterSpacing: 1 renderType: Text.NativeRendering font.hintingPreference: Font.PreferNoHinting smooth: false antialiasing: false color: (root.activeSelection == index && root.isSelected == true) ? "#fefe00" : "#ffffff" } // Option state Text { x: menuLeft + stateColumnX y: 4 text: root.inBluetoothMenu ? root.bluetoothDisplayState(modelData) : (modelData.getState ? modelData.getState() : "") font.family: "8bitoperator JVE" font.pixelSize: 71 font.letterSpacing: 1 renderType: Text.NativeRendering font.hintingPreference: Font.PreferNoHinting smooth: false antialiasing: false color: (root.activeSelection == index && root.isSelected == true) ? "#fefe00" : "#ffffff" } } } /* ------------------------------ INPUT HANDLING ------------------------------ */ function handleKey(key) { switch (key) { case Qt.Key_Up: if (root.inBluetoothMenu || root.isSelected === false) activeSelection = wrapIndex(activeSelection - 1); return true; case Qt.Key_Down: if (root.inBluetoothMenu || root.isSelected === false) activeSelection = wrapIndex(activeSelection + 1); return true; case Qt.Key_Left: { const a = currentAction(); if (a && a.arr && root.isSelected === true) a.arr(-1); return true; } case Qt.Key_Right: { const a = currentAction(); if (a && a.arr && root.isSelected === true) a.arr(1); return true; } case Qt.Key_Z: case Qt.Key_Return: case Qt.Key_Enter: { if (root.inBluetoothMenu) { const device = bluetoothDeviceAt(activeSelection); console.log(root.inBluetoothMenu, activeSelection, device); if (device) { if (!device.connected) { device.connect(); } else { device.disconnect(); } // device.connected = !device.connected; } } else { const a = currentAction(); if (a && a.ent) { a.ent(); } else { root.isSelected = !root.isSelected; } } return true; } case Qt.Key_X: case Qt.Key_Shift: case Qt.Key_Escape: if (root.inBluetoothMenu) { root.inBluetoothMenu = false; root.isSelected = false; root.activeSelection = root.bluetoothActionIndex; root.clampSelection(); } else if (root.isSelected === true) { root.isSelected = false; } else { if (manager && manager.closeQuickSettings) { manager.closeQuickSettings(); } } return true; } return false; } Component.onCompleted: { root.activeSelection = 0; root.isSelected = false; root.inBluetoothMenu = false; ShellInputManager.registerHandler("quickSettings", handleKey); } Component.onDestruction: { ShellInputManager.unregisterHandler("quickSettings"); } }