From 9c00c48d9e2f0cb0c7cc56a4cac8f629012f40b0 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Mon, 14 Sep 2026 13:57:07 +0200 Subject: feat(desktop): pair bluetooth devices Quickshell has no BlueZ agent and no generic D-Bus module, so a pairing that needs a passkey confirmed cannot be done from QML. bluetoothctl registers its own agent, so pairing is the one shell-out; adapter state, scanning, connecting and forgetting all stay native. The timeout is the ceiling: a device bluetoothctl cannot auto-confirm fails visibly rather than hanging the page. --- desktop/modules/bluetooth/Pairing.qml | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 desktop/modules/bluetooth/Pairing.qml (limited to 'desktop/modules/bluetooth/Pairing.qml') diff --git a/desktop/modules/bluetooth/Pairing.qml b/desktop/modules/bluetooth/Pairing.qml new file mode 100644 index 0000000..83fc9c2 --- /dev/null +++ b/desktop/modules/bluetooth/Pairing.qml @@ -0,0 +1,50 @@ +// Copyright (C) 2026 Danilo M. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +import Quickshell.Io +import QtQuick + +// The one action that is not native. Quickshell ships no BlueZ agent and no +// generic D-Bus module, so a device that needs a passkey or PIN confirmed +// cannot be paired from QML. bluetoothctl registers its own agent and handles +// the prompt, so pairing goes through it and everything else stays native. +// +// ponytail: one-shot bluetoothctl with a timeout, keyed on the exit code. If +// a device needs input bluetoothctl cannot auto-confirm, pairing times out +// and the error surfaces; upgrade to driving interactive bluetoothctl only +// when a real device needs it. +QtObject { + id: root + + property string address: "" + property string error: "" + readonly property bool busy: proc.running + + signal finished(string address, bool ok) + + function pair(address) { + root.address = address; + root.error = ""; + proc.command = ["bluetoothctl", "--timeout", "20", "pair", address]; + proc.running = false; + proc.running = true; + } + + property Process proc: Process { + stdout: StdioCollector { id: out } + stderr: StdioCollector { id: err } + onExited: code => { + const ok = code === 0; + if (!ok) root.error = (err.text.trim() || out.text.trim() || ("bluetoothctl exited " + code)); + root.finished(root.address, ok); + } + } +} -- cgit v1.2.3