diff --git a/bumblebee/modules/bluetooth.py b/bumblebee/modules/bluetooth.py index 323df9d..8e54b56 100644 --- a/bumblebee/modules/bluetooth.py +++ b/bumblebee/modules/bluetooth.py @@ -14,6 +14,8 @@ import bumblebee.input import bumblebee.output import bumblebee.engine import bumblebee.util +import bumblebee.popup +import logging class Module(bumblebee.engine.Module): @@ -34,7 +36,7 @@ class Module(bumblebee.engine.Module): cmd=self.manager) engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE, - cmd=self.toggle) + cmd=self.popup) def status(self, widget): """Get status.""" @@ -69,14 +71,31 @@ class Module(bumblebee.engine.Module): """Launch manager.""" bumblebee.util.execute(self.manager) - def toggle(self, widget): + def popup(self, widget): + """Show a popup menu.""" + menu = bumblebee.popup.PopupMenu() + if self._status == "On": + menu.add_menuitem('Disable Bluetooth') + elif self._status == "Off": + menu.add_menuitem('Enable Bluetooth') + else: + return + + # show menu and get return code + ret = menu.show(widget) + if ret == 0: + logging.debug('bt: toggling bluetooth') + # first (and only) item selected. + self._toggle() + + def _toggle(self): """Toggle bluetooth state.""" if self._status == "On": state = "false" else: state = "true" - cmd = "dbus-send --system --dest=org.blueman.Mechanism"\ + cmd = "dbus-send --system --print-reply --dest=org.blueman.Mechanism"\ " / org.blueman.Mechanism.SetRfkillState"\ " boolean:{}".format(state) diff --git a/bumblebee/popup.py b/bumblebee/popup.py new file mode 100644 index 0000000..5a288c4 --- /dev/null +++ b/bumblebee/popup.py @@ -0,0 +1,77 @@ +"""Pop-up menus.""" + +try: + import Tkinter as tk +except ImportError: + # python 3 + import tkinter as tk + +import logging + +class PopupMenu: + """The popup-menu.""" + + def __init__(self): + """Initialize.""" + # menu widget + self.root = tk.Tk() + self.root.withdraw() + self.menu = tk.Menu(self.root) + + # internal state + self._item_count = 0 + self._clicked_item = None + self._active = False + + # bind event of popup getting closed by clicking outside of its area + self.menu.bind('', + lambda event: self.root.after_idle( + self._dismiss_callback)) + + def add_menuitem(self, menuitem, callback=None): + """Add menu items.""" + item_count = self._item_count + + def click_callback(): + # call internal callback with item index + self._item_callback(item_count) + + # default to internal callback + if callback is None: + callback = click_callback + self.menu.add_command(label=menuitem, + command=click_callback) + + # track item index + self._item_count += 1 + + def _item_callback(self, which_item): + """Menu item click callback.""" + logging.debug('popup: item callback: {}'.format(which_item)) + self._clicked_item = which_item + self.root.destroy() + self._active = False + + def _dismiss_callback(self): + """Menu dismissed.""" + logging.debug('popup: menu dismissed') + if self._active is True: + self._clicked_item = None + self.root.destroy() + + def show(self, event): + """Show popup.""" + self._clicked_item = None + self.menu.tk_popup(event['x'], event['y']-50) + self._active = True + self.root.mainloop() + return self._clicked_item + + +def create_and_show_menu(event, *menuitems): + """Create a menu object and show.""" + menu_obj = PopupMenu() + for menuitem in menuitems: + menu_obj.add_menuitem(*menuitem) + + return menu_obj.show(event)