import subprocess, os, getpass from enum import Enum import i3_lemonbar_config as config kill_on_unfocus = [] # Loggers, initialized in main function logger = None health_logger = None screen = None parsing_queue = None class bar_mode(Enum): power, normal, control = range(-1,2) # Don't cycle through power def cycle(self): try: return bar_mode(self.value + 1) except ValueError: return bar_mode(0) mode = bar_mode.normal floatterm_args = lambda prog : ['terminator', '-r', 'FLOAT_TERM', '-p' , 'dark', '-e', 'echo kill_unfocus $$ > {}; exec {}'.format( config.fifo_file_executor, prog)] def date_comm(args): subprocess.Popen(['yad', '--no-buttons', '--calendar', '--sticky' , '--on-top' , '--class' , '"YADWIN"', '--posx=1650', '--posy=24' , '--close-on-unfocus']) def pavu_comm(args): global kill_on_unfocus p = subprocess.Popen(['pavucontrol', '--class=FLOAT_PAVU']) kill_on_unfocus.append(p.pid) def htop_comm(args): subprocess.Popen(floatterm_args('htop')) def nmtui_comm(args): subprocess.Popen(floatterm_args('nmtui')) def lang_comm(args): subprocess.Popen(['sh', '/home/kuba/.i3/scripts/lang.sh', 'next']) def dpms_comm(args): subprocess.Popen(['sh', '/home/kuba/.i3/scripts/dpmsctl.sh']) def adj_br(args): subprocess.Popen(['/home/kuba/.i3/scripts/adjbr.sh', '-b', config.fifo_file_executor]) def i3msg_comm(args): subprocess.Popen(args.split()) def add_tokill(args): global kill_on_unfocus kill_on_unfocus.append(int(args.split()[1])) def set_mode(args): global mode new_mode = args.split()[1] if new_mode == "cycle": mode = mode.cycle() for m in bar_mode: if new_mode == m.name: mode = m break def bluetooth(args): btcargs = args.split()[1:] btcargs = [a.replace('pxc550', '00:16:94:22:29:0E') for a in btcargs] inp = ' '.join(btcargs) screen.send_cmd('bluetoothctl ' + inp) show_secs = False def toggle_secs(args): global show_secs show_secs = not show_secs # Keymaps def_keymap = 'pl' keymaps = {'Firefox': 'se'} cur_class = '' def set_lang(args): global keymaps lang = args.split()[1] keymaps[cur_class] = lang commands_dict = {'toggle_secs': toggle_secs ,'date': date_comm ,'pavu': pavu_comm ,'load': htop_comm ,'wlan': nmtui_comm ,'dpms': dpms_comm ,'i3-msg': i3msg_comm ,'switch_lang': lang_comm ,'kill_unfocus': add_tokill ,'mode': set_mode ,'adj_br': adj_br ,'setlang': set_lang ,'bluetooth': bluetooth } # Callbacks for workspaces def add_callbacks(i3ws): i3ws.change_callbacks.append(set_bg) i3ws.focus_callbacks.append(set_keymap) i3ws.focus_callbacks.append(kill_floating_windows) def img_path(num): dir = '/home/kuba/Obrazy/Wallpapers/' return dir + { 1: '1_main', 2: '2_web', 3: '3_music', 4: '4_work', 5: '5_terms', 6: '6_stats', 7: '7', 8: '8', 9: '9', }.get(int(num), 'default') def set_bg(i3ws): cmd_args = ['sh', '/home/kuba/scripts/set_bg.sh'] for output in i3ws.outputs: if output.active: bg = img_path(output.current_workspace.partition(' ')[0]) cmd_args.append(bg) subprocess.call(cmd_args) def kill_floating_windows(i3ws): global kill_on_unfocus, logger role = i3ws.focused_window.window_role wclass = i3ws.focused_window.window_class if role != 'FLOAT_TERM' and wclass != 'FLOAT_PAVU' and wclass != 'YADWINBR': # Is there a window that the bar has opened? for pid in kill_on_unfocus: try: os.kill(pid, signal.SIGTERM) except ProcessLookupError: logger.debug('Tried killing process {} but it doesn\'t exist'.format(pid)) kill_on_unfocus = [] def set_keymap(i3ws): global cur_class, keymaps, logger wclass = i3ws.focused_window.window_class cur_class = wclass if wclass in keymaps: new_km = keymaps[wclass] logger.debug('Setting {} as keymap for {}'.format(new_km, wclass)) else: new_km = def_keymap logger.debug('Setting default keymap {} for {}'.format(def_keymap, wclass)) subprocess.call(['/home/kuba/.i3/scripts/lang.sh', 'qset', new_km]) def create_new_fifo(fifo_file): """ Create new fifo file, removing old one if it exists """ try: os.remove(fifo_file) logger.debug('''Removed old fifo file''') except OSError: logger.debug('''No old fifo file, good''') try: os.mkfifo(fifo_file) except OSError: logger.error('''Failed, couldn't create fifo file''') os.remove(config.pid_file) # Clean up own PID file sys.exit(0) class LemonbarScreen: # Start, stop and send commands to screen instance # Start detached, in UTF-8 mode. Log to fifo start_flags = ['-d', '-m', '-U', '-L', '-Logfile', config.fifo_screen_log] def __init__(self): self.identifier = 'lemonbar_{}_{}'.format(getpass.getuser(), os.getpid()) create_new_fifo(config.fifo_screen_log) self.send(self.start_flags) # Start screen self.send_cmd('stty -echo') # Do not echo what is written to screen terminal self.send_colon('logfile flush 0.1') # Log quickly def destroy(self): self.send_colon('kill') def send(self, args): # Send something to our screen instance subprocess.call(['screen', '-S', self.identifier] + args) def send_cmd(self, cmd): # Send terminal input to our screen instance self.send(['-X', 'stuff', cmd + '\n']) def send_colon(self, cmd): # Send colon command to our screen instance self.send(['-X', 'colon', cmd + '\n'])