diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | extension.js | 29 | ||||
-rwxr-xr-x | extract.sh | 29 | ||||
-rw-r--r-- | ui.js | 79 |
5 files changed, 140 insertions, 9 deletions
@@ -1,2 +1,3 @@ /.idea /schemas/gschemas.compiled +/gnome-shell @@ -17,3 +17,14 @@ make rm -r ~/.local/share/gnome-shell/extensions/bluetooth-quick-connect@bjarosze.gmail.com cp -r gnome-bluetooth-quick-connect ~/.local/share/gnome-shell/extensions/bluetooth-quick-connect@bjarosze.gmail.com ``` + +## Troubleshooting + +### Reconnect does not work + +Not sure why, but sometimes bluetoothctl does not want to connect +device after it was disconnected. Reinstalling bluez helped on my ubuntu. +``` +$ sudo apt purge bluez gnome-bluetooth pulseaudio-module-bluetooth +$ sudo apt install bluez gnome-bluetooth pulseaudio-module-bluetooth +```
\ No newline at end of file diff --git a/extension.js b/extension.js index 403d956..33de925 100644 --- a/extension.js +++ b/extension.js @@ -16,13 +16,13 @@ const Main = imports.ui.main; const GnomeBluetooth = imports.gi.GnomeBluetooth; -const PopupMenu = imports.ui.popupMenu; const Util = imports.misc.util; const GLib = imports.gi.GLib; const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); const Convenience = Me.imports.convenience; +const UiExtension = Me.imports.ui; class BluetoothDevice { constructor(model, device) { @@ -56,7 +56,11 @@ class BluetoothDevice { } _buildMenuItem() { - this._item = new PopupMenu.PopupSwitchMenuItem(this.name, this.isConnected); + this._item = new UiExtension.PopupSwitchWithButtonMenuItem( + this.name, + this.isConnected, + this.isConnected && 'view-refresh' + ); this._item.isDeviceSwitcher = true; this._item.connect('toggled', (item, state) => { if (state) @@ -64,19 +68,26 @@ class BluetoothDevice { else this._disconnect(); }); + + this._item.connect('clicked', () => { + this._reconnect() + }); } _disconnect() { - this._call_bluetoothctl(`disconnect ${this.mac}`) + this._call_cmd(`bluetoothctl -- disconnect ${this.mac}`) } _connect() { - this._call_bluetoothctl(`connect ${this.mac}`) + this._call_cmd(`bluetoothctl -- connect ${this.mac}`) + } + + _reconnect() { + this._call_cmd(`bluetoothctl -- disconnect ${this.mac} && bluetoothctl -- connect ${this.mac}`) } - _call_bluetoothctl(command) { - let btctl_command = `echo -e "${command}\\n" | bluetoothctl`; - Util.spawn(['/usr/bin/env', 'bash', '-c', btctl_command]); + _call_cmd(command) { + Util.spawn(['/usr/bin/env', 'bash', '-c', command]); } } @@ -113,8 +124,8 @@ class BluetoothQuickConnect { test() { try { GLib.spawn_command_line_sync("bluetoothctl --version"); - } catch(error) { - Main.notifyError(`Bluetooth quick connect: error trying to execute "bluetoothctl"`); + } catch (error) { + Main.notifyError(_('Bluetooth quick connect'), _(`Error trying to execute "bluetoothctl"`)); } } diff --git a/extract.sh b/extract.sh new file mode 100755 index 0000000..a4578fe --- /dev/null +++ b/extract.sh @@ -0,0 +1,29 @@ +#!/bin/bash +if [[ $# -ne 1 ]]; then + echo "usage $0 dir" >&2 + exit 1 +fi + +dir="$1" + +if [[ -e $dir ]]; then + echo "Error: $dir already exists" >&2 + exit 1 +fi + +mkdir -p "$dir" +cd "$dir" + +GS=/usr/lib/gnome-shell/libgnome-shell.so + +for r in $(gresource list $GS); do + t="${r/#\/org\/gnome\/shell\/}" + mkdir -p $(dirname $t) + echo Extracting $t + gresource extract $GS $r >$t +done + +echo +echo "Now add the following to /etc/environment and restart gnome-shell" +echo "if you want to run with these extracted source files." +echo "GNOME_SHELL_JS=$PWD" @@ -0,0 +1,79 @@ +// Copyright 2018 Bartosz Jaroszewski +// SPDX-License-Identifier: GPL-2.0-or-later +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// 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. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + + +const {Atk, Clutter, Gio, GObject, Graphene, Shell, St} = imports.gi; +const Tweener = imports.ui.tweener; +const PopupMenu = imports.ui.popupMenu; + +var PopupSwitchWithButtonMenuItem = GObject.registerClass( + {Signals: {'clicked': {}}}, + class PopupSwitchWithButtonMenuItem extends PopupMenu.PopupSwitchMenuItem { + _init(text, active, icon, params) { + super._init(text, active, params); + + this.label.x_expand = true; + this._statusBin.x_expand = false; + + if (icon) { + this.insert_child_at_index( + this.create_button(icon), + this.get_n_children() - 1 + ); + } + } + + create_button(iconName) { + let icon = new St.Icon({ + icon_name: iconName, + style_class: 'popup-menu-icon', + }); + + let button = new St.Button({ + child: icon, + x_align: Clutter.ActorAlign.END + }); + + button.connect("enter-event", (widget) => { + Tweener.addTween( + widget.child, { + scale_x: 1.1, + scale_y: 1.1, + time: 0.05, + transition: 'linear' + } + ); + }); + + button.connect("leave-event", (widget) => { + Tweener.addTween( + widget.child, { + scale_x: 1, + scale_y: 1, + time: 0.05, + transition: 'linear' + } + ); + }); + + button.connect('clicked', () => { + this.emit('clicked'); + }); + + return button; + } + } +); |