status/bluetooth: Show immediate feedback on toggle

Since commit 6a23e8ee0f, we use the adapter state (that includes
transitional state) to indicate progress when a state change takes
a long time.

However on many systems, the delay happens on the rfkill side,
before a change request even reaches the adapter.

Address this by temporarily overriding the adapter-state with the
expected transitional state, until an actual adapter state change
occurs.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5773

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2815>
This commit is contained in:
Florian Müllner 2022-08-23 00:06:42 +02:00 committed by Marge Bot
parent 8c57eab5e6
commit 56103edc0e

View File

@ -24,6 +24,8 @@ const rfkillManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(RfkillManagerInterfa
Gio._promisify(GnomeBluetooth.Client.prototype, 'connect_service');
const STATE_CHANGE_FAILED_TIMEOUT_MS = 30 * 1000;
const BtClient = GObject.registerClass({
Properties: {
'available': GObject.ParamSpec.boolean('available', '', '',
@ -48,8 +50,10 @@ const BtClient = GObject.registerClass({
this._client.connect('notify::default-adapter-powered', () => {
this.notify('active');
});
this._client.connect('notify::default-adapter-state',
() => this.notify('adapter-state'));
this._client.connect('notify::default-adapter-state', () => {
delete this._predictedState;
this.notify('adapter-state');
});
this._client.connect('notify::default-adapter', () => {
const newAdapter = this._client.default_adapter ?? null;
@ -108,11 +112,30 @@ const BtClient = GObject.registerClass({
}
get adapter_state() {
if (this._predictedState !== undefined)
return this._predictedState;
return this._client.default_adapter_state;
}
toggleActive() {
this._proxy.BluetoothAirplaneMode = this.active;
const {active} = this;
// on many systems, there's a significant delay until the rfkill
// state results in an adapter state change; work around that by
// overriding the current state with the expected transition
this._predictedState = active
? AdapterState.TURNING_OFF
: AdapterState.TURNING_ON;
this.notify('adapter-state');
// toggling the state *really* should result in an adapter-state
// change eventually (even on error), but just to be sure to not
// be stuck with the overriden state, force a notify signal after
// a timeout
setTimeout(() => this._client.notify('default-adapter-state'),
STATE_CHANGE_FAILED_TIMEOUT_MS);
this._proxy.BluetoothAirplaneMode = active;
if (!this._client.default_adapter_powered)
this._client.default_adapter_powered = true;
}