def i3clients(): """Populate a dictionary with window strings for rofi. Structure of the dictionary: key: Formatted string containing workspace name and window name. value: ID of the window to be able to focus it. Return: The generated dictionary. """ clients = {} tree = i3.get_tree() # Iterate over all workspaces for ws in i3.get_workspaces(): wsname = ws["name"] wsshow = re.sub(r'[0-9]+(:)', "", wsname) workspace = i3.filter(tree, name=wsname)[0] # We do not want to go to the focused window windows = [ win for win in i3.filter(workspace, nodes=[]) if not win["focused"] ] # Build the formatted string to pass to rofi and add it to the # dictionary for window in windows: wsname = re.sub("<.*?>", "", wsshow) win_str = "%-6s %-50s" % (wsname, window["name"]) clients[win_str] = window["id"] return clients
def main(): tree = i3.get_tree() result = {} win_map = {} focused_window = None for output in tree['nodes']: if output['name'].startswith('__'): continue result.update(handle_output(output['nodes'])) text_list = [] for workspace in result: for win in result[workspace]: text_list.append(u"{kind} [{workspace}] -> {name} #{wid}".format(wid=win['id'], workspace=workspace, kind=win['class'], name=win['name'])) win_map[win['id']] = win if win['focused']: focused_window = win old_output = get_active_output_name(focused_window) answer = dmenu(sorted(text_list), dmenu_cmd('select window: ', )) if answer: wid = answer.split('#')[-1] i3.focus(id=wid) if old_output != get_active_output_name(win_map[int(wid)]): os.system("i3-msg 'move workspace to output left'")
def i3clients(): """Populate a dictionary with window strings for rofi. Structure of the dictionary: key: Formatted string containing workspace name and window name. value: ID of the window to be able to focus it. Return: The generated dictionary. """ clients = {} tree = i3.get_tree() # Iterate over all workspaces for ws in i3.get_workspaces(): wsname = ws["name"] wsshow = re.sub(r'[0-9]+(:)', "", wsname) workspace = i3.filter(tree, name=wsname)[0] # We do not want to go to the focused window windows = [win for win in i3.filter(workspace, nodes=[]) if not win["focused"]] # Build the formatted string to pass to rofi and add it to the # dictionary for window in windows: wsname = re.sub("<.*?>", "", wsshow) win_str = "%-6s %-50s" % (wsname, window["name"]) clients[win_str] = window["id"] return clients
def find_matching(pred, tree=None): tree = tree or i3.get_tree() queue = [tree] for w in queue: queue.extend(w["nodes"]) if pred(w): yield w
def get_windows(formatting_function=None): """ Get all windows. The formatting_function is passed through and governs how items are displayed """ windows = parse_for_windows(i3.get_tree()) return create_lookup_table(windows, formatting_function)
def get_workspace_tree(): """Return the partial i3 tree for the current workspace.""" for workspace in filter_nodes(lambda x: x['type'] == 'workspace', i3.get_tree()): if contains_focus(workspace): return workspace else: raise IndexError('no workspace contains a focused container')
def i3clients(): """ Returns a dictionary with convoluted strings with window information as keys, and the i3 window id as values. Each window text is of format "[workspace] mark window title (instance number)." """ clients = {} lengths = {'workspace': 0, 'mark': 0} tree = i3.get_tree() for ws in i3.get_workspaces(): wsname = ws['name'] if len(wsname) > lengths['workspace']: lengths['workspace'] = len(wsname) workspace = i3.filter(tree, name=wsname) if not workspace: continue workspace = workspace[0] windows = i3.filter(workspace, nodes=[]) instances = {} # Adds windows and their ids to the clients dictionary for window in windows: windowdict = { 'con_id': window['id'], \ 'ws': wsname, \ 'name': window['name']} try: windowdict['mark'] = window['mark'] if len(window['mark']) > lengths['mark']: lengths['mark'] = len(window['mark']) except KeyError: windowdict['mark'] = "" if window['name'] in instances: instances[window['name']] += 1 else: instances[window['name']] = 1 windowdict['instance'] = instances[window['name']] # win_str = '[%s] %s' % (workspace['name'], window['name']) clients[window['id']] = windowdict # Now build the strings to pass to dmenu: newdict = {} clientlist = [] for con_id in clients.keys(): clientlist.append(con_id) for con_id in clientlist: wslen = lengths['workspace'] mlen = lengths['mark'] win_str = '[{k:<{v}}] {l:<{w}} {m} ({n})'.format(\ k=clients[con_id]['ws'], v=wslen, \ l=clients[con_id]['mark'], w=mlen, \ m=clients[con_id]['name'], \ n=clients[con_id]['instance']) clients[win_str] = clients[con_id] del clients[con_id] return clients
def i3clients(): """ Returns a dictionary with convoluted strings with window information as keys, and the i3 window id as values. Each window text is of format "[workspace] mark window title (instance number)." """ clients = {} lengths = {'workspace': 0, 'mark': 0} tree = i3.get_tree() for ws in i3.get_workspaces(): wsname = ws['name'] if len(wsname) > lengths['workspace']: lengths['workspace'] = len(wsname) workspace = i3.filter(tree, name=wsname) if not workspace: continue workspace = workspace[0] windows = i3.filter(workspace, nodes=[]) instances = {} # Adds windows and their ids to the clients dictionary for window in windows: windowdict = { 'con_id': window['id'], \ 'ws': wsname, \ 'name': window['name']} try: windowdict['mark'] = window['mark'] if len(window['mark']) > lengths['mark']: lengths['mark'] = len(window['mark']) except KeyError: windowdict['mark'] = "" if window['name'] in instances: instances[window['name']] += 1 else: instances[window['name']] = 1 windowdict['instance'] = instances[window['name']] # win_str = '[%s] %s' % (workspace['name'], window['name']) clients[window['id']] = windowdict # Now build the strings to pass to dmenu: newdict = {} clientlist = [] for con_id in clients.keys(): clientlist.append(con_id) for con_id in clientlist: wslen = lengths['workspace'] mlen = lengths['mark'] win_str = u'[{k:<{v}}] {l:<{w}} {m} ({n})'.format(\ k=clients[con_id]['ws'], v=wslen, \ l=clients[con_id]['mark'], w=mlen, \ m=clients[con_id]['name'], \ n=clients[con_id]['instance']) clients[win_str] = clients[con_id] del clients[con_id] return clients
def window_title(self): window = find_focused(i3.get_tree()) transformed = False if window and 'name' in window and window['name'] != self.title: self.title = (len(window['name']) > self.max_width and u"...{}".format(window['name'][-(self.max_width - 3):]) or window['name']) transformed = True return { 'cached_until': self.py3.time_in(self.cache_timeout), 'full_text': self.py3.safe_format(self.format, {'title': self.title}), 'transformed': transformed }
def currentTitle(self, json, i3status_config): response = {'full_text': '', 'name': 'current-title', 'cached_until': time.time() + CACHED_TIME} try: window = find_focused(i3.get_tree()) if window and "name" in window: response["full_text"] = len(window["name"]) > MAX_WIDTH and "..." + window["name"][-MAX_WIDTH:] or window["name"] # There is such encode in py3status, if it fails plugin will shutdown response['full_text'].encode('utf-8') except: pass return (0, response)
def main(): tree = i3.get_tree() result = [] for output in tree['nodes']: if output['name'].startswith('__'): continue result.extend(handle_output(output['nodes'])) print(result) text_list = [] for workspace in result: text_list.append('%s -> #%s' % (workspace['name'], workspace['num'])) answer = dmenu(sorted(text_list), dmenu_cmd('select window: ', )) if answer: num = answer.split('#')[-1] i3.workspace(num)
def window_title(self, i3s_output_list, i3s_config): window = find_focused(i3.get_tree()) transformed = False if window and 'name' in window and window['name'] != self.text: self.text = (len(window['name']) > self.max_width and "..." + window['name'][-(self.max_width - 3):] or window['name']) transformed = True response = { 'cached_until': time() + self.cache_timeout, 'full_text': self.text, 'transformed': transformed } return response
def window_title(self, i3_status_output_json, i3status_config): window = find_focused(i3.get_tree()) transformed = False if window and 'name' in window and window['name'] != self.text: self.text = len(window['name']) > MAX_WIDTH and "..." + window['name'][-(MAX_WIDTH-3):] or window['name'] transformed = True response = { 'cached_until': time() + CACHE_TIMEOUT, 'full_text': self.text, 'name': 'window-title', 'transformed': transformed } return (POSITION, response)
def window_title(self): window = find_focused(i3.get_tree()) transformed = False if window and 'name' in window and window['name'] != self.text: self.text = (len(window['name']) > self.max_width and "..." + window['name'][-(self.max_width - 3):] or window['name']) transformed = True response = { 'cached_until': self.py3.time_in(self.cache_timeout), 'full_text': self.text, 'transformed': transformed } return response
def main(): tree = i3.get_tree() result = {} for output in tree['nodes']: if output['name'].startswith('__'): continue result[output['name']] = handle_output(output['nodes']) text_list = [] for key in result: tmp_text = '%s: ' % key tmp_text += ','.join([i['name'] for i in result[key]]) for i in result[key]: if i['focused']: focused = i['name'] text_list.append(tmp_text) text = '%s\n\nfocused: %s ' % ('\n\n'.join(text_list), focused) os.system('notify-send "workspace info" "%s"' % text)
def __init__(self): tree = i3.get_tree() output_order = sys.argv[1:] output_map = {x['name']: self.get_workspaces(x) for x in tree['nodes']} self.outputs = [output_map[o] for o in output_order] ws_nums = [] for output in self.outputs: for workspace in output: ws_nums.append(workspace['num']) for window in workspace['windows']: window['label'] = self.get_win_label(window) self.set_ws_attrs(workspace) self.available = [num for num in range(1, 9) if num not in ws_nums]
def scratchpad_counter(self, i3status_output_json, i3status_config): count = len(find_scratch(i3.get_tree()).get("floating_nodes", [])) if self.count != count: transformed = True self.count = count else: transformed = False response = { "cached_until": time() + CACHE_TIMEOUT, "full_text": "" if HIDE_WHEN_NONE and count == 0 else STRFORMAT.format(count), "name": "scratchpad-counter", "transformed": transformed, } return (POSITION, response)
def find_parent(window_id): """ Find the parent of a given window id """ root_window = i3.get_tree() result = [None] def finder(n, p=None): if result[0] is not None: return for node in n: if node['id'] == window_id: result[0] = p return if len(node['nodes']): finder(node['nodes'], node) finder(root_window['nodes']) return result[0]
def scratchpad_counter(self): count = len(find_scratch(i3.get_tree()).get("floating_nodes", [])) if self.count != count: transformed = True self.count = count else: transformed = False response = { 'cached_until': time() + self.cache_timeout, 'transformed': transformed } if self.hide_when_none and count == 0: response['full_text'] = '' else: response['full_text'] = self.format.format(count) return response
def scratchpad_counter(self): count = len(find_scratch(i3.get_tree()).get("floating_nodes", [])) if self.count != count: transformed = True self.count = count else: transformed = False response = { 'cached_until': self.py3.time_in(self.cache_timeout), 'transformed': transformed } if self.hide_when_none and count == 0: response['full_text'] = '' else: response['full_text'] = self.format.format(count) return response
def assign_focus_node(self, all_key=False) -> None: tree = i3.get_tree() wkspc = [ node for node in tree["nodes"] if node["name"] == self.current_display["output"] ] assert len(wkspc) > 0, "window could not be found" for w in wkspc: self.find_focused_window(w) if not all_key: return wkspc = [ k["nodes"] for k in wkspc[0]["nodes"] if k["name"] == "content" ][0] fcsd = [i for i in self.all_outputs if i["focused"]][0]["name"] def grep_nest(obj, key, key2, key3) -> list: arr = [] # TODO: change keys to kwargs def fetch(obj, arr, key) -> list: if isinstance(obj, dict): for k, v in obj.items(): if isinstance(v, (dict, list)): fetch(v, arr, key) elif k == key: arr.append((obj[key2], v, obj[key3])) elif isinstance(obj, list): for item in obj: fetch(item, arr, key) return arr results = fetch(obj, arr, key) return results data = [k for k in wkspc if k["name"] == fcsd][0] names = grep_nest(data, "id", key2="name", key3="floating") self.current_windows = [i for i in names if i[0] and i[0] != fcsd] self.current_floating_windows = [i for i in self.current_windows]
def window_title(self, i3s_output_list, i3s_config): window = find_focused(i3.get_tree()) transformed = False if window and 'name' in window and window['name'] != self.text: name = ( len(window['name']) > self.max_width and "…" + window['name'][-(self.max_width-1):] or window['name'] ) cls = window['window_properties']['class'] transformed = True self.text = output(name, cls) response = { 'cached_until': time() + i3s_config.get('cache_timeout',0), 'full_text': self.text, 'transformed': transformed, 'color': i3s_config['color_good'] } return response
def float_with_storage(workspaces): focused_window = my_filter(i3.get_tree()['nodes'])[0] window_class = focused_window['window_properties']['class'] if window_class != None and len(window_class) > 1: window_class += "\n" found = False lines = [] with open(floating_windows,'r+') as f: lines = f.readlines() print(repr(lines)) print(repr(window_class)) try: lines.remove(window_class) except ValueError: # couldn't remove since it wasn't there lines.append(window_class) print(repr(lines)) with open(floating_windows,'w') as f: f.writelines(lines) i3.command('floating', 'toggle') return
def float_with_storage(workspaces): focused_window = my_filter(i3.get_tree()['nodes'])[0] window_class = focused_window['window_properties']['class'] if window_class != None and len(window_class) > 1: window_class += "\n" found = False lines = [] with open(floating_windows, 'r+') as f: lines = f.readlines() print(repr(lines)) print(repr(window_class)) try: lines.remove(window_class) except ValueError: # couldn't remove since it wasn't there lines.append(window_class) print(repr(lines)) with open(floating_windows, 'w') as f: f.writelines(lines) i3.command('floating', 'toggle') return
def scratchpad_counter(self, i3status_output_json, i3status_config): count = len(find_scratch(i3.get_tree()).get("floating_nodes", [])) if self.count != count: transformed = True self.count = count else: transformed = False response = { 'cached_until': time() + CACHE_TIMEOUT, 'full_text': '' if HIDE_WHEN_NONE and count == 0 else STRFORMAT.format(count), 'name': 'scratchpad-counter', 'transformed': transformed } return (POSITION, response)
def __init__(self, outputs): tree = i3.get_tree() output_order = outputs output_map = { x['name']: self.get_workspaces(x) for x in tree['nodes'] } self.outputs = [ output_map[o] for o in output_order ] ws_nums = [] for output in self.outputs: for workspace in output: ws_nums.append(workspace['num']) for window in workspace['windows']: window['label'] = self.get_win_label(window) self.set_ws_attrs(workspace) self.available = [ num for num in range(1,9) if num not in ws_nums ]
def __init__(self, tree=None): if not tree: tree = i3.get_tree() self.raw_tree = tree self.root = i3Node(self.raw_tree)
def _create_tree(self): #clean the tree-box from all children for child in self.tree_grid.get_children(): self.tree_grid.remove(child) #get the current tree layout tree = i3.get_tree() # the top level of the trees are the displays num_displays = len(tree["nodes"]) - 1 # ignore the __i3 thingy display_counter = 0 for display in tree["nodes"]: if "__i3" in display[ "name"]: # ignores the __i3 thingy. i think it contains the i3bar continue # every display gets his own label on the top disp_label = Gtk.Label(label=display["name"]) disp_label.override_background_color(0, Gdk.RGBA(0.8, 0, 0, 1)) disp_label.override_color(0, Gdk.RGBA(1, 1, 1, 1)) display_grid = Gtk.Grid( ) #every display gets its own grid, so we can present them tidely display_grid.override_background_color(0, Gdk.RGBA(0, 0, 0, 1)) spacer = Gtk.Label(label="Hah") spacer.override_background_color(0, Gdk.RGBA( 0, 0, 0, 1)) # needed because grids dont support spacing spacer.override_color(0, Gdk.RGBA(0, 0, 0, 1)) row = 0 if display_counter > num_displays / 2 - 1: row = 1 line = display_counter % (num_displays / 2) self.tree_grid.attach(disp_label, line, row * 3, 1, 1) self.tree_grid.attach(display_grid, line, row * 3 + 1, 1, 1) self.tree_grid.attach(spacer, line, row * 3 + 2, 1, 1) for cont in display["nodes"]: if "content" == cont[ "name"]: #each display has content and top/bottom docker. we only want the content ws_counter = 0 num_ws = len(cont["nodes"]) for workspace in cont["nodes"]: if len(workspace["nodes"]) == 0: continue # every workspace gets his own label on the top label = Gtk.Label() label.set_label(workspace["name"]) label.override_color(0, Gdk.RGBA(1, 1, 1, 1)) label.override_background_color( 0, Gdk.RGBA(0, 0.1, 0.6, 0.6)) grid = Gtk.Grid() next_level_box = Gtk.Box( spacing=0, ) # here is the place where the containers/windows get added grid.attach(label, 0, 0, 1, 1) grid.attach(next_level_box, 0, 1, 1, 1) spacerh = Gtk.Label( label="Hah" ) # needed because grids dont support spacing spacerv = Gtk.Label( label="Hah" ) # needed because grids dont support spacing spacerh.override_background_color( 0, Gdk.RGBA(0, 0, 0, 1)) spacerv.override_background_color( 0, Gdk.RGBA(0, 0, 0, 1)) spacerh.override_color(0, Gdk.RGBA(0, 0, 0, 1)) spacerv.override_color(0, Gdk.RGBA(0, 0, 0, 1)) # partion the workspaces into three rows (and in my case maximum 3 lines) row = 0 if ws_counter > num_ws / 3 - 1: row = 1 if ws_counter > (num_ws * 2) / 3 - 1: row = 2 line = ws_counter % (num_ws / 3) display_grid.attach(grid, line * 2, row * 2, 1, 1) display_grid.attach(spacerh, line * 2, row * 2 + 1, 1, 1) display_grid.attach(spacerv, line * 2 + 1, row * 2, 1, 1) self._rec_tree_func(workspace, next_level_box, 0) ws_counter += 1 display_counter += 1
#!/usr/bin/env python from pprint import pprint import i3 pprint(i3.filter(nodes=[], focused=True, tree=i3.get_tree())) #pprint(i3.get_tree()) exit() outputs = i3.get_outputs() # set current workspace to output 0 i3.workspace(outputs[0]['current_workspace']) # ..and move it to the other output. # outputs wrap, so the right of the right is left ;) i3.move__workspace__to__output__right("workspace") # rinse and repeat i3.workspace(outputs[1]['current_workspace']) i3.move__workspace__to__output__right()
def get_children(workspace): tree = i3.get_tree() workspace_info = i3.filter(tree, name=workspace["name"]) nodes = i3.filter(workspace_info, nodes=[]) return _format_nodes(nodes)
#!/usr/bin/env python import i3 import re import sys from time import sleep import json #resize <grow|shrink> <direction> [<px> px [or <ppt> ppt]] barHeight = 18 tree = str(i3.get_tree()); def positionWindow(): i3.scratchpad("show", instance="metask") workspace = [ws for ws in i3.get_workspaces() if ws['focused']][0] screen_w =str(workspace['rect']['width']) screen_h =str(workspace['rect']['height']) targetheight = str(workspace['rect']['height']/3) current = i3.filter(nodes=[], focused=True) i3.command("move","absolute","position","0",str(barHeight)) i3.command("resize","shrink","width",screen_w); i3.command("resize","shrink","height",screen_h); i3.command("resize","grow","width",screen_w); i3.command("resize","grow","height",targetheight); #look for an entity that has the unique name of a scratchpad m = re.search("metask", tree)
def get_windows(): """Get all windows.""" windows = parse_for_windows(i3.get_tree(), []) return create_lookup_table(windows)
def i3clients(): """ Returns a dictionary with convoluted strings with window information as keys, and the i3 window id as values. Each window text is of format "[workspace] mark window title (instance number)." """ clients = {} lengths = {'name': 0, 'workspace': 0, 'mark': 0} tree = i3.get_tree() for ws in i3.get_workspaces(): wsre = re.compile(r'([0-9]+):? ?([a-zA-Z0-9 -]+)?') wsreres = wsre.match(ws['name']) wsnum = wsreres.group(1) wsname = wsreres.group(2) if not wsname: wsname = wsnum if len(wsname) > lengths['workspace']: lengths['workspace'] = len(wsname) wsname = ws['name'] workspace = i3.filter(tree, name=wsname) if not workspace: continue workspace = workspace[0] windows = i3.filter(workspace, nodes=[]) instances = {} # Adds windows and their ids to the clients dictionary for window in windows: windowdict = { 'con_id': window['id'], \ 'ws': wsname, \ 'name': window['name']} try: windowdict['mark'] = window['mark'] if len(window['mark']) > lengths['mark']: lengths['mark'] = len(window['mark']) except KeyError: windowdict['mark'] = "" if window['name'] in instances: instances[window['name']] += 1 else: instances[window['name']] = 1 if len(window['name']) > lengths['name']: lengths['name'] = len(window['name']) windowdict['instance'] = instances[window['name']] # win_str = '[%s] %s' % (workspace['name'], window['name']) clients[window['id']] = windowdict # Now build the strings to pass to dmenu: newdict = {} clientlist = [] for con_id in clients.keys(): clientlist.append(con_id) for con_id in clientlist: wslen = lengths['workspace'] mlen = lengths['mark'] nlen = lengths['name'] wsre = re.compile(r'([0-9]+):? ?([a-zA-Z0-9 -]+)?') wsreres = wsre.match(clients[con_id]['ws']) wsnum = wsreres.group(1) wsname = wsreres.group(2) if not wsname: wsname = wsnum client=clients[con_id] print(client) win_str = u'{wsn}: {m:<{nl}}[{k:<{v}}] {l:<{w}} ({n})'\ .format(m=client['name'], nl=nlen + 1, \ k=wsname, wsn=wsnum, v=wslen, \ l=client['mark'], w=mlen + 1, \ n=str(client['instance'])) clients[win_str] = clients[con_id] del clients[con_id] return clients
def on_window_focus(i3, e): focused = i3.get_tree().find_focused() print(focused.name)