Fix dotfiles structure
This commit is contained in:
110
.config/polybar/menu.py
Executable file
110
.config/polybar/menu.py
Executable file
@@ -0,0 +1,110 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gio # noqa
|
||||
from gi.repository import GLib # noqa
|
||||
|
||||
DMENU_CMD = ['rofi', '-dmenu', '-i', '-no-sort']
|
||||
|
||||
|
||||
class Bus:
|
||||
def __init__(self, conn, name, path):
|
||||
self.conn = conn
|
||||
self.name = name
|
||||
self.path = path
|
||||
|
||||
def call_sync(self, interface, method, params, params_type, return_type):
|
||||
return self.conn.call_sync(
|
||||
self.name,
|
||||
self.path,
|
||||
interface,
|
||||
method,
|
||||
GLib.Variant(params_type, params),
|
||||
GLib.VariantType(return_type),
|
||||
Gio.DBusCallFlags.NONE,
|
||||
-1,
|
||||
None,
|
||||
)
|
||||
|
||||
def get_menu_layout(self, *args):
|
||||
return self.call_sync(
|
||||
'com.canonical.dbusmenu',
|
||||
'GetLayout',
|
||||
args,
|
||||
'(iias)',
|
||||
'(u(ia{sv}av))',
|
||||
)
|
||||
|
||||
def menu_event(self, *args):
|
||||
self.call_sync('com.canonical.dbusmenu', 'Event', args, '(isvu)', '()')
|
||||
|
||||
|
||||
def dmenu(_input):
|
||||
p = subprocess.Popen(
|
||||
DMENU_CMD,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
encoding='utf-8',
|
||||
)
|
||||
out, _ = p.communicate(_input)
|
||||
return out
|
||||
|
||||
|
||||
def format_toggle_value(props):
|
||||
toggle_type = props.get('toggle-type', '')
|
||||
toggle_value = props.get('toggle-state', -1)
|
||||
|
||||
if toggle_value == 0:
|
||||
s = ' '
|
||||
elif toggle_value == 1:
|
||||
s = 'X'
|
||||
else:
|
||||
s = '~'
|
||||
|
||||
if toggle_type == 'checkmark':
|
||||
return f'[{s}] '
|
||||
elif toggle_type == 'radio':
|
||||
return f'({s}) '
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
||||
def format_menu_item(item, level=1):
|
||||
id, props, children = item
|
||||
|
||||
if not props.get('visible', True):
|
||||
return ''
|
||||
if props.get('type', 'standard') == 'separator':
|
||||
label = '---'
|
||||
else:
|
||||
label = format_toggle_value(props) + props.get('label', '')
|
||||
if not props.get('enabled', True):
|
||||
label = f'({label})'
|
||||
|
||||
indentation = ' ' * level
|
||||
ret = f'{id}{indentation}{label}\n'
|
||||
for child in children:
|
||||
ret += format_menu_item(child, level + 1)
|
||||
return ret
|
||||
|
||||
|
||||
def show_menu(conn, name, path):
|
||||
bus = Bus(conn, name, path)
|
||||
item = bus.get_menu_layout(0, -1, [])[1]
|
||||
|
||||
menu = format_menu_item(item)
|
||||
selected = dmenu(menu)
|
||||
|
||||
if selected:
|
||||
id = int(selected.split()[0])
|
||||
bus.menu_event(id, 'clicked', GLib.Variant('s', ''), time.time())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
conn = Gio.bus_get_sync(Gio.BusType.SESSION)
|
||||
show_menu(conn, sys.argv[1], sys.argv[2])
|
||||
Reference in New Issue
Block a user