def reapply_rule(win_class, geometry):
    'reapply the rule to make dropdown wins floating and sticky'
    flags = ('state=floating layer=above '
             f'private=on sticky=on rectangle={geometry}')
    new_rule = f'bspc rule -a {win_class} {flags}'
    fmt_rule = f'{win_class}:*:* => {flags}'
    if fmt_rule not in cmd_output('bspc rule -l').splitlines():
        cmd_run(new_rule)
Esempio n. 2
0
def advance_is_child(pid1, pid2):
    ps_out = [
        line.split(maxsplit=3)
        for line in cmd_output(f'ps --ppid {pid1}').split('\n')[1:]
    ]
    print(ps_out)
    if any(line[-1] == 'tmux: client' for line in ps_out):
        tmux_shell_pid = cmd_output("tmux list-panes -F '#{pane_pid}'")
        print('tmux shell')
        print(tmux_shell_pid, pid2)
        return is_child(tmux_shell_pid, pid2)
    elif any(line[-1] == 'ranger' for line in ps_out):
        print(cmd_output(f'pstree -ls {pid2}').startswith('systemd---sh'))
        if cmd_output(f'pstree -ls {pid2}').startswith('systemd---sh'):
            return True
        return False
    else:
        return is_child(pid1, pid2)
Esempio n. 3
0
def tab_all():
    all_wids = cmd_output(
        "bspc query -N -d -n '.window.!floating.!hidden'").split('\n')
    all_wids = [wid for wid in all_wids
                if 'tabbed' not in get_class(wid)]
    if all_wids:
        tabbed_wid = tab_current_win(all_wids[0])
        if len(all_wids) > 1:
            for wid in all_wids[1:]:
                add_win_to_tabbed(wid, tabbed_wid)
def create_geometry_str(x, y, w, h):
    screen_dims = screen_dim(cmd_output('bspc query -M -m --names'))
    if x <= 1:
        x *= screen_dims['width']
    if y <= 1:
        y *= screen_dims['height']
    if w <= 1:
        w *= screen_dims['width']
    if h <= 1:
        h *= screen_dims['height']
    return f'{w:0.0f}x{h:0.0f}{x:+0.0f}{y:+0.0f}'
Esempio n. 5
0
def node_crawler(prefix, node, path):
    if node is None:
        return
    if node['client'] is None:
        node_crawler(prefix, node['firstChild'], path + ['1'])
        node_crawler(prefix, node['secondChild'], path + ['2'])
    else:
        client = node['client']
        temp_paths[cmd_output(f'bspc query -N -n {node["id"]}')] = {
            'className': client['className'],
            'instanceName': client['instanceName'],
            'path': prefix + '/'.join(path)
        }
Esempio n. 6
0
def swallow():
    '''
    monitore node_add and node_remove events and store swallowed
    windows in a dictionary
    '''
    swallowed = {}
    for event in execute('bspc subscribe node_add node_remove'):
        try:
            logging.debug(f'Processing Event: {event}')
            event = event.split()
            if not event:
                continue
            if event[0] == 'node_add':
                rotate_flag = False
                new_wid = event[-1]
                last_wid = cmd_output(
                    "bspc query -N -d -n 'last.window.!floating.!fullscreen'")
                if not swallow_cond(new_wid, last_wid):
                    continue
                new_pid = get_pid(new_wid)
                last_pid = get_pid(last_wid)
                if not all([new_pid, last_pid]):
                    continue
                if advance_is_child(last_pid, new_pid):
                    capture_layout()
                    last_path = temp_paths[last_wid]['path']
                    print(last_path)
                    new_path = last_path + '/1'
                    print(new_path)
                    cmd_run(f'bspc node {last_wid} --flag hidden=on')
                    cmd_run(f"bspc node {new_wid} --to-node {new_path}")
                    swallowed[new_wid] = last_wid
            if event[0] == 'node_remove':
                removed_wid = event[-1]
                if removed_wid in swallowed.keys():
                    swallowed_id = swallowed[removed_wid]
                    del swallowed[removed_wid]
                    cmd_run(f'bspc node {swallowed_id} --flag hidden=off')
                    cmd_run(f"bspc node {last_wid} --to-node {last_path}")
                    print(last_path.split(':')[-1])
                    if not len(last_path.split(':')[-1]) <= 5:
                        if last_path[-3] == '2':
                            cmd_run(f'bspc node {last_path[:-4]} --rotate 270')
                        else:
                            cmd_run(f'bspc node {last_path[:-4]} --rotate 90')
                    cmd_run(f'bspc node --focus {swallowed_id}')
        except Exception as e:
            print(e)
            print(traceback.format_exc())
            logging.debug('Error occured in mainloop:'
                          f'\n{e}\n{traceback.format_exc()}')
Esempio n. 7
0
def advance_is_child_depr(pid1, pid2):
    # TODO finish this
    # is this a terminal?
    ps_out = [
        line.split(maxsplit=3)
        for line in cmd_output(f'ps --ppid {pid1}').split('\n')[1:]
    ]
    print(ps_out)
    ttys = {line[1]: (line[0], line[-1]) for line in ps_out if line[1] != '?'}
    print(ttys)
    if ttys:
        if any('tmux: client' in x[1] for x in ttys.values()):
            last_tmux_pid = cmd_output("tmux ")
            tmux_server_pid = cmd_output("pgrep 'tmux: server'")
            print(tmux_server_pid)
            ps_out = [
                line.split(maxsplit=3) for line in cmd_output(
                    f'ps --ppid {tmux_server_pid}').split('\n')[1:]
            ]
            tmux_ttys = {
                line[1]: (line[0], line[-1])
                for line in ps_out if line[1] != '?'
            }
            print(ps_out)
            print(tmux_ttys)
            for tty in ttys:
                tty_pid = tmux_ttys.get(tty, '')
                print(tty_pid)
                if tty_pid:
                    if is_child(tty_pid[0], pid2):
                        return True
        else:
            for tty_pid, _ in ttys.values():
                if is_child(tty_pid, pid2):
                    return True
    return False
def repair_geometry(wid, gmt):
    current = win_geometry(wid)
    screen_dims = screen_dim(cmd_output('bspc query -M -m --names'))
    re_obj = re.match(r'(\d+)x(\d+)([+-]\d+)([+-]\d+)', gmt)
    w, h, x, y = (float(re_obj.group(i)) for i in range(1, 5))
    x = x + screen_dims['width'] if x < 0 else x
    y = y + screen_dims['height'] if y < 0 else y
    if w != current['width']:
        w_chg = w - current['width']
        cmd_run(f'bspc node {wid} --resize right {w_chg} 0')
    if h != current['height']:
        h_chg = current['height'] - h
        cmd_run(f'bspc node {wid} --resize top 0 {h_chg}')
    if x != current['x_pos']:
        x_chg = x - current['x_pos']
        cmd_run(f'bspc node {wid} --move {x_chg} 0')
    if y != current['y_pos']:
        y_chg = y - current['y_pos']
        cmd_run(f'bspc node {wid} --move 0 {y_chg}')
Esempio n. 9
0
def swallow():
    '''
    monitore node_add and node_remove events and store swallowed
    windows in a dictionary
    '''
    swallowed = {}
    for event in execute('bspc subscribe node_add node_remove'):
        try:
            logging.debug(f'Processing Event: {event}')
            event = event.split()
            if not event:
                continue
            if event[0] == 'node_add':
                new_wid = event[-1]
                last_wid = cmd_output(
                    "bspc query -N -d -n 'last.window.!floating.!fullscreen'")
                print(new_wid, last_wid)
                print(swallow_cond(new_wid, last_wid))
                if not swallow_cond(new_wid, last_wid):
                    continue
                new_pid = get_pid(new_wid)
                last_pid = get_pid(last_wid)
                print(new_pid, last_pid)
                print(advance_is_child(last_pid, new_pid))
                if not all([new_pid, last_pid]):
                    continue
                if advance_is_child(last_pid, new_pid):
                    cmd_run(f'bspc node {last_wid} --flag private=on')
                    cmd_run(f'bspc node --swap {last_wid} --follow')
                    cmd_run(f'bspc node {last_wid} --flag hidden=on')
                    cmd_run(f'bspc node {new_wid} --flag private=on')
                    swallowed[new_wid] = last_wid
            if event[0] == 'node_remove':
                removed_wid = event[-1]
                if removed_wid in swallowed.keys():
                    swallowed_id = swallowed[removed_wid]
                    cmd_run(f'bspc node {swallowed_id} --flag hidden=off')
                    cmd_run(f'bspc node --focus {swallowed_id}')
        except Exception as e:
            print(e)
            print(traceback.format_exc())
            logging.debug('Error occured in mainloop:'
                          f'\n{e}\n{traceback.format_exc()}')
Esempio n. 10
0
#!/usr/bin/env python

import time
from wmutils.processes import cmd_run, cmd_output
from wmutils.utils import is_desk_empty, bspwm_events

events = bspwm_events('node_remove')
for event in events:
    if is_desk_empty(cmd_output("bspc query -D -d --names")):
        try:
            time.sleep(4)
            if is_desk_empty(cmd_output("bspc query -D -d --names")):
                cmd_run('bspc desktop --focus last.occupied')
        except Exception:
            pass
Esempio n. 11
0
#! /usr/bin/env python3

import os
import sys
import subprocess
from wmutils.processes import cmd_run, cmd_output

swap_flag = False
if len(sys.argv) == 2:
    swap_flag = sys.argv[1] == 'swap'

rofi_theme = os.getenv('ROFI_THEME')
hidden_windows = cmd_output(
    "bspc query -N -d -n '.hidden.local.window.!sticky'")

if len(hidden_windows.split('\n')) == 0:
    sys.exit()
elif len(hidden_windows.split('\n')) == 1:
    selected_window = hidden_windows
else:
    try:
        wins_titles = '\n'.join([
            f'{i}|' + cmd_output('xtitle ' + win_id)
            for i, win_id in enumerate(hidden_windows.split('\n'))
        ])
        selected_window = cmd_output(
            f'echo "{wins_titles}" | rofi -dmenu -dpi 0 -theme {rofi_theme}')
        selected_window = hidden_windows.split('\n')[int(
            selected_window.split('|')[0])]
    except subprocess.CalledProcessError:
        sys.exit()
Esempio n. 12
0
        return False
    if last_wid == '':
        return False
    win_class = get_class(last_wid)
    curwin_class = get_class(event[-1])
    if 'tabbed' in win_class and 'tabbed' not in curwin_class:
        # weird but children windows ids in a `tabbed`
        # skip a `0` in window ids so it is 0x... instead of 0x0...
        # therefore the replace sentence
        was_tabbed_child = any(wid.lower() in children_ids
                               for wid in (event[-1],
                                           event[-1].replace('0x0', '0x')))
        if not was_tabbed_child:
            return True
    else:
        return False


if __name__ == '__main__':
    children_ids = []
    for event in execute('bspc subscribe node_add node_focus'):
        event = event.split()
        if event[0] == 'node_add':
            last_wid = cmd_output('bspc query -N -d -n last.local.window')
            if auto_tab_cond(event, last_wid):
                add_win_to_tabbed(event[-1], last_wid)
        if event[0] == 'node_focus':
            node_id = event[-1]
            if 'tabbed' in get_class(node_id):
                children_ids = get_tabbed_children(node_id)
Esempio n. 13
0
#! /usr/bin/env python3

import os
import sys
import inspect

cmd_folder = os.path.realpath(
    os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0]))
sys.path.append(os.path.join(cmd_folder, 'wmutils'))

from wmutils.utils import win_geometry, screen_dim
from wmutils.processes import cmd_run, cmd_output

if __name__ == '__main__':
    wid = cmd_output("bspc query -N -d -n 'any.floating.window.!hidden'").strip()
    if wid == '':
        sys.exit()

    win_gt = win_geometry(wid)

    current_monitor = cmd_output('bspc query -M --names -m focused').strip()

    scr_dim = screen_dim(current_monitor)

    at_rightedge = win_gt['x_pos'] + win_gt['width'] == scr_dim['width']
    at_leftedge = win_gt['x_pos'] == 0
    at_bottom = win_gt['y_pos'] + win_gt['height'] == scr_dim['height']

    if (at_bottom and at_rightedge) or (at_bottom and at_leftedge):
        if at_rightedge:
            cmd_run(
Esempio n. 14
0
def rm_win_from_tabbed(wid):
    root_wid = cmd_output('xwininfo -root').split('\n')[0].split()[3]
    cmd_run(f'xdotool windowreparent {wid} {root_wid}')
Esempio n. 15
0
def get_tabbed_children(tabbed_id):
    out = cmd_output(f'xwininfo -id {tabbed_id} -children')
    split_wrd = 'child:' if 'child:' in out else 'children:'
    children = [win.strip().split()[0].lower() for win in
                out.split(split_wrd)[1].split('\n') if win]
    return children
Esempio n. 16
0

def tab_all():
    all_wids = cmd_output(
        "bspc query -N -d -n '.window.!floating.!hidden'").split('\n')
    all_wids = [wid for wid in all_wids
                if 'tabbed' not in get_class(wid)]
    if all_wids:
        tabbed_wid = tab_current_win(all_wids[0])
        if len(all_wids) > 1:
            for wid in all_wids[1:]:
                add_win_to_tabbed(wid, tabbed_wid)


if __name__ == '__main__':
    cur_wid = cmd_output(
        "bspc query -N -d -n 'focused.window.!hidden.!floating'")
    if cur_wid:
        if sys.argv[1] == 'create':
            if 'tabbed' not in get_class(cur_wid):
                tab_current_win(cur_wid)
        elif sys.argv[1] == 'join':
            if 'tabbed' in get_class(sys.argv[2]):
                add_win_to_tabbed(cur_wid, sys.argv[2])
        elif sys.argv[1] == 'remove':
            rm_win_from_tabbed(get_tabbed_children(cur_wid)[0])
        elif sys.argv[1] == 'children':
            print(get_tabbed_children(cur_wid))
        elif sys.argv[1] == 'all':
            tab_all()
Esempio n. 17
0
def hideall():
    for win in cmd_output(
            "bspc query -N -d -n '.!hidden.window.!focused'").split('\n'):
        cmd_run(f'bspc node {win} -g hidden=on')
Esempio n. 18
0
#!/usr/bin/env python
# Python version of the following code
# https://github.com/phenax/dotfiles/blob/master/.config/bspwm/scripts/resize.sh

import sys
from wmutils.utils import is_floating
from wmutils.processes import cmd_run, cmd_output

dir_ = sys.argv[1]
delta = 40 if len(sys.argv) < 3 else sys.argv[2]

x = f'+{delta}' if dir_ == 'right' else f'-{delta}' if dir_ == 'left' else '0'
y = f'+{delta}' if dir_ == 'down' else f'-{delta}' if dir_ == 'up' else '0'

pair_dict = {
    'right': 'left',
    'left': 'right',
    'top': 'bottom',
    'bottom': 'top'
}
DIR_ = 'right' if dir_ in ('left', 'right') else 'top'

FALLDIR = pair_dict[DIR_]

cmd_run(f'bspc node --resize {DIR_} {x} {y}')
if not is_floating(cmd_output('bspc query -N -n')):
    cmd_run(f'bspc node --resize {FALLDIR} {x} {y}')
def win_exists(win_class):
    'Return True (and window id) if window with a matching class is open'
    for wid in cmd_output('bspc query -N -n .window').split('\n'):
        if win_class in get_class(wid):
            return wid
    return False
Esempio n. 20
0
cmd_folder = os.path.realpath(
    os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0]))
sys.path.append(os.path.join(cmd_folder, 'wmutils'))

from wmutils.utils import get_class
from wmutils.processes import cmd_output, cmd_run


def confirm_close_tabbed(cur_wid):
    rofi_cmd = ('echo -e "yes\nno" | rofi -selected-row 1 -width 20% -dmenu'
                f' -dpi 0 -theme {os.getenv("ROFI_THEME")} -lines 2 -p "Do you'
                ' want to close all tabbed windows?"')
    if 'tabbed' in get_class(cur_wid):
        if len(get_tabbed_children(cur_wid)) == 1:
            cmd_run(f'bspc node --{sys.argv[1]}')
        else:
            P = cmd_run(rofi_cmd, stdout=subprocess.PIPE)
            P.wait()
            answr = P.stdout.read().strip()
            if answr == 'yes':
                cmd_run(f'bspc node --{sys.argv[1]}')
    else:
        cmd_run(f'bspc node --{sys.argv[1]}')


if __name__ == '__main__':
    cur_wid = cmd_output('bspc query -N -n')
    if cur_wid and sys.argv[1] in ['kill', 'close']:
        confirm_close_tabbed(cur_wid)