def workspace(pl, segment_info, workspace=None, strip=False): '''Return the specified workspace name :param str workspace: Specifies which workspace to show. If unspecified, may be set by the ``list_workspaces`` lister if used, otherwise falls back to currently focused workspace. :param bool strip: Specifies whether workspace numbers (in the ``1: name`` format) should be stripped from workspace names before being displayed. Defaults to false. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' if workspace: try: w = next((w for w in get_i3_connection().get_workspaces() if w['name'] == workspace)) except StopIteration: return None elif segment_info.get('workspace'): w = segment_info['workspace'] else: try: w = next((w for w in get_i3_connection().get_workspaces() if w['focused'])) except StopIteration: return None return [{ 'contents': format_name(w['name'], strip=strip), 'highlight_groups': workspace_groups(w) }]
def get_icon(w, separator, icons, show_multiple_icons): if 'dummy' in w: return "" icons_tmp = WS_ICONS icons_tmp.update(icons) icons = icons_tmp ws_containers = { w_con.name: w_con for w_con in get_i3_connection().get_tree().workspaces() } wins = [ win for win in ws_containers[w['name']].leaves() if win.parent.scratchpad_state == 'none' ] if len(wins) == 0: return "" result = "" cnt = 0 for key in icons: if not icons[key] or len(icons[key]) < 1: continue if any(key in win.window_class for win in wins if win.window_class): result += separator + icons[key] cnt += 1 if not show_multiple_icons and cnt > 1: if 'multiple' in icons: return separator + icons['multiple'] else: return "" return result
def workspace_lister(pl, segment_info, only_show=None, output=None): '''List all workspaces in segment_info format Sets the segment info values of ``workspace`` and ``output`` to the name of the i3 workspace and the ``xrandr`` output respectively and the keys ``"visible"``, ``"urgent"`` and ``"focused"`` to a boolean indicating these states. :param list only_show: Specifies which workspaces to list. Valid entries are ``"visible"``, ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces are listed. :param str output: May be set to the name of an X output. If specified, only workspaces on that output are listed. Overrides automatic output detection by the lemonbar renderer and bindings. Set to ``false`` to force all workspaces to be shown. ''' if output == None: output = output or segment_info.get('output') return ((updated( segment_info, output=w.output, workspace=w, ), { 'draw_inner_divider': None }) for w in get_i3_connection().get_workspaces() if (((not only_show or any(getattr(w, typ) for typ in only_show)) and ( not output or w.output == output))))
def workspaces(pl, segment_info, only_show=None, output=None, strip=0): '''Return list of used workspaces :param list only_show: Specifies which workspaces to show. Valid entries are ``"visible"``, ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces are shown. :param str output: May be set to the name of an X output. If specified, only workspaces on that output are shown. Overrides automatic output detection by the lemonbar renderer and bindings. :param int strip: Specifies how many characters from the front of each workspace name should be stripped (e.g. to remove workspace numbers). Defaults to zero. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' output = output or segment_info.get('output') return [{ 'contents': w['name'][strip:], 'highlight_groups': workspace_groups(w) } for w in get_i3_connection().get_workspaces() if ((not only_show or any( w[typ] for typ in only_show)) and (not output or w['output'] == output))]
def workspaces(pl, segment_info, only_show=None, output=None, strip=0): '''Return list of used workspaces :param list only_show: Specifies which workspaces to show. Valid entries are ``"visible"``, ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces are shown. :param str output: May be set to the name of an X output. If specified, only workspaces on that output are shown. Overrides automatic output detection by the lemonbar renderer and bindings. :param int strip: Specifies how many characters from the front of each workspace name should be stripped (e.g. to remove workspace numbers). Defaults to zero. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' output = output or segment_info.get('output') return [ { 'contents': w['name'][strip:], 'highlight_groups': workspace_groups(w) } for w in get_i3_connection().get_workspaces() if ((not only_show or any(w[typ] for typ in only_show)) and (not output or w['output'] == output)) ]
def workspace(pl, segment_info, workspace=None, strip=False): '''Return the specified workspace name :param str workspace: Specifies which workspace to show. If unspecified, may be set by the ``list_workspaces`` lister if used, otherwise falls back to currently focused workspace. :param bool strip: Specifies whether workspace numbers (in the ``1: name`` format) should be stripped from workspace names before being displayed. Defaults to false. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' if workspace: try: w = next(( w for w in get_i3_connection().get_workspaces() if w['name'] == workspace )) except StopIteration: return None elif segment_info.get('workspace'): w = segment_info['workspace'] else: try: w = next(( w for w in get_i3_connection().get_workspaces() if w['focused'] )) except StopIteration: return None return [{ 'contents': format_name(w['name'], strip=strip), 'highlight_groups': workspace_groups(w) }]
def scratchpad(pl, icons=SCRATCHPAD_ICONS): '''Returns the windows currently on the scratchpad :param dict icons: Specifies the strings to show for the different scratchpad window states. Must contain the keys ``fresh`` and ``changed``. Highlight groups used: ``scratchpad`` or ``scratchpad:visible``, ``scratchpad`` or ``scratchpad:focused``, ``scratchpad`` or ``scratchpad:urgent``. ''' return [{ 'contents': icons.get(w.scratchpad_state, icons['changed']), 'highlight_groups': scratchpad_groups(w) } for w in get_i3_connection().get_tree().descendents() if w.scratchpad_state != 'none']
def scratchpad(pl, icons=SCRATCHPAD_ICONS): '''Returns the windows currently on the scratchpad :param dict icons: Specifies the strings to show for the different scratchpad window states. Must contain the keys ``fresh`` and ``changed``. Highlight groups used: ``scratchpad`` or ``scratchpad:visible``, ``scratchpad`` or ``scratchpad:focused``, ``scratchpad`` or ``scratchpad:urgent``. ''' return [ { 'contents': icons.get(w.scratchpad_state, icons['changed']), 'highlight_groups': scratchpad_groups(w) } for w in get_i3_connection().get_tree().descendents() if w.scratchpad_state != 'none' ]
def active_window(pl, cutoff=100): '''Returns the title of the currently active window. :param int cutoff: Maximum title length. If the title is longer, the window_class is used instead. Highlight groups used: ``active_window_title``. ''' focused = get_i3_connection().get_tree().find_focused() cont = focused.name if len(cont) > cutoff: cont = focused.window_class return [{ 'contents': cont, 'highlight_groups': ['active_window_title'] }] if focused.name != focused.workspace().name else []
def workspace_lister(pl, segment_info, only_show=None, output=None): '''List all workspaces in segment_info format Sets the segment info values of ``workspace`` and ``output`` to the name of the i3 workspace and the ``xrandr`` output respectively and the keys ``"visible"``, ``"urgent"`` and ``"focused"`` to a boolean indicating these states. :param list only_show: Specifies which workspaces to list. Valid entries are ``"visible"``, ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces are listed. :param str output: May be set to the name of an X output. If specified, only workspaces on that output are listed. Overrides automatic output detection by the lemonbar renderer and bindings. Set to ``false`` to force all workspaces to be shown. ''' if output == None: output = output or segment_info.get('output') return ( ( updated( segment_info, output=w['output'], workspace={ 'name': w['name'], 'visible': w['visible'], 'urgent': w['urgent'], 'focused': w['focused'], }, ), { 'draw_inner_divider': None } ) for w in get_i3_connection().get_workspaces() if (((not only_show or any(w[typ] for typ in only_show)) and (not output or w['output'] == output))) )
def workspaces(pl, segment_info, only_show=None, output=None, strip=0, separator=" ", icons=WS_ICONS, show_icons=True, show_multiple_icons=True, show_dummy_workspace=False, show_output=False, priority_workspaces=[]): '''Return list of used workspaces :param list only_show: Specifies which workspaces to show. Valid entries are ``"visible"``, ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces are shown. :param str output: May be set to the name of an X output. If specified, only workspaces on that output are shown. Overrides automatic output detection by the lemonbar renderer and bindings. Use "__all__" to show workspaces on all outputs. :param int strip: Specifies how many characters from the front of each workspace name should be stripped (e.g. to remove workspace numbers). Defaults to zero. :param string separator: Specifies a string to be inserted between the workspace name and program icons and between program icons. :param dict icons: A dictionary mapping a substring of window classes to strings to be used as an icon for that window class. The following window classes have icons by default: ``Xfce4-terminal``, ``Chromium``, ``Steam``, ``jetbrains``, ``Gimp``, ``Pavucontrol``, ``Lmms``, ``Thunderbird``, ``Thunar``, ``Skype``, ``TelegramDesktop``, ``feh``, ``Firefox``, ``Evince``, ``Okular``, ``libreoffice-calc``, ``libreoffice-writer``. You can override the default icons by defining an icon for that window class yourself, and disable single icons by setting their icon to "" or None. Further, there is a ``multiple`` icon for workspaces containing more than one window (which is used if ``show_multiple_icons`` is ``False``) :param boolean show_icons: Determines whether to show icons. Defaults to True. :param boolean show_multiple_icons: If this is set to False, instead of displying multiple icons per workspace, the icon "multiple" will be used. :param boolean show_dummy_workspace: If this is set to True, this segment will alway display an additional, non-existing workspace. This workspace will be handled as if it was a non-urgent and non-focused regular workspace, i.e., click events will work as with normal workspaces. :param boolean show_output: Show the name of the output if more than one output is connected and output is not set to ``__all__``. :param string list priority_workspaces: A list of workspace names to be sorted before any other workspaces in the given order. Highlight groups used: ``workspace`` or ``workspace:visible``, ``workspace`` or ``workspace:focused``, ``workspace`` or ``workspace:urgent`` or ``output``. Click values supplied: ``workspace_name`` (string) for workspaces and ``output_name`` (string) for outputs. ''' output_count = 1 if not output == "__all__": output = output or segment_info.get('output') if show_output: output_count = len( [o for o in get_i3_connection().get_outputs() if o['active']]) else: output = None if output: output = [output] else: output = [ o['name'] for o in get_i3_connection().get_outputs() if o['active'] ] def sort_ws(ws): import re def natural_key(ws): str = ws['name'] return [ int(s) if s.isdigit() else s for s in re.split(r'(\d+)', str) ] ws = sorted(ws, key=natural_key) + (get_next_ws(ws, output) if show_dummy_workspace else []) result = [] for n in priority_workspaces: result += [w for w in ws if w['name'] == n] return result + [w for w in ws if not w['name'] in priority_workspaces] if len(output) <= 1: res = [] if output_count > 1: res += [{ 'contents': output[0], 'highlight_groups': ['output'], 'click_values': { 'output_name': output[0] } }] res += [{ 'contents': w['name'][min(len(w['name']), strip):] + (get_icon(w, separator, icons, show_multiple_icons) if show_icons else ""), 'highlight_groups': workspace_groups(w), 'click_values': { 'workspace_name': w['name'] } } for w in sort_ws(get_i3_connection().get_workspaces()) if (not only_show or any( w[typ] for typ in only_show)) and w['output'] == output[0]] return res else: res = [] for n in output: res += [{ 'contents': n, 'highlight_groups': ['output'], 'click_values': { 'output_name': n } }] res += [{ 'contents': w['name'][min(len(w['name']), strip):] + (get_icon(w, separator, icons, show_multiple_icons) if show_icons else ""), 'highlight_groups': workspace_groups(w), 'click_values': { 'workspace_name': w['name'] } } for w in sort_ws(get_i3_connection().get_workspaces()) if (not only_show or any( w[typ] for typ in only_show)) and w['output'] == n] return res
if __name__ == '__main__': name = 'wm' if len(sys.argv) > 1: name = sys.argv[1] powerline = I3Powerline(name, renderer_module='i3bar') powerline.update_renderer() interval = 0.5 print('{"version": 1}') print('[') print('[]') lock = Lock() def render(event=None, data=None, sub=None): global lock with lock: print(',[' + powerline.render()[:-1] + ']') sys.stdout.flush() i3 = get_i3_connection() i3_subscribe(i3, 'workspace', render) while True: start_time = monotonic() render() time.sleep(max(interval - (monotonic() - start_time), 0.1))
def workspaces(pl, segment_info, only_show=None, output=None, strip=0, format='{name}', icons=WS_ICONS, sort_workspaces=False, show_output=False, priority_workspaces=[], hide_empty_workspaces=False): '''Return list of used workspaces :param list only_show: Specifies which workspaces to show. Valid entries are ``"visible"``, ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces are shown. :param str output: May be set to the name of an X output. If specified, only workspaces on that output are shown. Overrides automatic output detection by the lemonbar renderer and bindings. Use "__all__" to show workspaces on all outputs. :param int strip: Specifies how many characters from the front of each workspace name should be stripped (e.g. to remove workspace numbers). Defaults to zero. :param str format: Specifies the format used to display workspaces; defaults to ``{name}``. Valid fields are: ``name`` (workspace name), ``number`` (workspace number if present), `stipped_name`` (workspace name stripped of leading number), ``icon`` (if available, icon for application running in the workspace, uses the ``multiple`` icon instead of multiple different icons), ``multi_icon`` (similar to ``icon``, but does not use ``multiple``, instead joins all icons with a single space) :param dict icons: A dictionary mapping a substring of window classes to strings to be used as an icon for that window class. Further, there is a ``multiple`` icon for workspaces containing more than one window. :param bool sort_workspaces: Sort the workspaces displayed by their name according to the natural ordering. :param bool show_output: Shows the name of the output if more than one output is connected. :param list priority_workspaces: A list of workspace names to be sorted before any other workspaces in the given order. :param bool hide_empty_workspaces: Hides all workspaces without any open window. Also hides non-focussed workspaces containing only an open scratchpad. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace:visible``, ``workspace`` or ``w_focused``, ``workspace:focused``, ``workspace`` or ``w_urgent``, ``workspace:urgent``, ``workspace`` or ``output``. ''' conn = get_i3_connection() if not output == "__all__": output = output or segment_info.get('output') else: output = None if output: output = [output] else: output = [o.name for o in conn.get_outputs() if o.active] def sort_ws(ws): if sort_workspaces: def natural_key(ws): str = ws.name return [ int(s) if s.isdigit() else s for s in re.split(r'(\d+)', str) ] ws = sorted(ws, key=natural_key) result = [] for n in priority_workspaces: result += [w for w in ws if w.name == n] return result + [w for w in ws if not w.name in priority_workspaces] ws_containers = { w_con.name: w_con for w_con in conn.get_tree().workspaces() } if len(output) <= 1: res = [] if show_output: res += [{'contents': output[0], 'highlight_groups': ['output']}] res += [{ 'contents': format.format(name = w.name[min(len(w.name), strip):], stripped_name = format_name(w.name, strip=True), number = w.num, icon = get_icon(w, '', icons, False, ws_containers), multi_icon = get_icon(w, ' ', icons, True, ws_containers)), 'highlight_groups': workspace_groups(w) } for w in sort_ws(conn.get_workspaces()) \ if (not only_show or any(getattr(w, tp) for tp in only_show)) \ if w.output == output[0] \ if not (hide_empty_workspaces and is_empty_workspace(w, ws_containers))] return res else: res = [] for n in output: if show_output: res += [{'contents': n, 'highlight_groups': ['output']}] res += [{ 'contents': format.format(name = w.name[min(len(w.name), strip):], stripped_name = format_name(w.name, strip=True), number = w.num, icon = get_icon(w, '', icons, False, ws_containers), multi_icon = get_icon(w, ' ', icons, True, ws_containers)), 'highlight_groups': workspace_groups(w) } for w in sort_ws(conn.get_workspaces()) \ if (not only_show or any(getattr(w, tp) for tp in only_show)) \ if w.output == n \ if not (hide_empty_workspaces and is_empty_workspace(w, ws_containers))] return res
def workspace(pl, segment_info, workspace=None, strip=False, format=None, icons=WS_ICONS): '''Return the specified workspace name :param str workspace: Specifies which workspace to show. If unspecified, may be set by the ``list_workspaces`` lister if used, otherwise falls back to currently focused workspace. :param bool strip: Specifies whether workspace numbers (in the ``1: name`` format) should be stripped from workspace names before being displayed. Defaults to false. Deprecated: Use {name} or {stripped_name} of format instead. :param str format: Specifies the format used to display workspaces; defaults to ``{name}``. Valid fields are: ``name`` (workspace name), ``number`` (workspace number if present), `stipped_name`` (workspace name stripped of leading number), ``icon`` (if available, icon for application running in the workspace, uses the ``multiple`` icon instead of multiple different icons), ``multi_icon`` (similar to ``icon``, but does not use ``multiple``, instead joins all icons with a single space) :param dict icons: A dictionary mapping a substring of window classes to strings to be used as an icon for that window class. Further, there is a ``multiple`` icon for workspaces containing more than one window. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace:visible``, ``workspace`` or ``w_focused``, ``workspace:focused``, ``workspace`` or ``w_urgent``, ``workspace:urgent``, ``workspace``. ''' if format == None: format = '{stripped_name}' if strip else '{name}' conn = get_i3_connection() ws_containers = { w_con.name: w_con for w_con in conn.get_tree().workspaces() } if workspace: try: w = next((w for w in conn.get_workspaces() if w.name == workspace)) except StopIteration: return None elif segment_info.get('workspace'): w = segment_info['workspace'] else: try: w = next((w for w in conn.get_workspaces() if w.focused)) except StopIteration: return None return [{ 'contents': format.format(name=w.name, stripped_name=format_name(w.name, strip=True), number=w.num, icon=get_icon(w, '', icons, False, ws_containers), multi_icon=get_icon(w, ' ', icons, True, ws_containers)), 'highlight_groups': workspace_groups(w) }]
def active_window(pl, segment_info, cutoff=100, global_menu=False, item_length=20, \ max_width=80, auto_expand=False, show_empty=False, **kwargs): ''' Returns the title of the currently active window. To enhance the global menu support, add the following to your ``.bashrc``: .. code-block:: shell if [ -n "$GTK_MODULES" ]; then GTK_MODULES="${GTK_MODULES}:appmenu-gtk-module" else GTK_MODULES="appmenu-gtk-module" fi if [ -z "$UBUNTU_MENUPROXY" ]; then UBUNTU_MENUPROXY=1 fi export GTK_MODULES export UBUNTU_MENUPROXY :param int cutoff: Maximum title length. If the title is longer, the window_class is used instead. :param boolean global_menu: Activate global menu support (experimental) :param int item_length: Maximum length of a menu item. :param int max_width: Maximum total length of the content. :param bool auto_expand: Add spaces to center the segment. :param bool show_empty: Show the sehment if no window is focused. Highlight groups used: ``active_window_title:single`` or ``active_window_title:stacked_unfocused`` or ``active_window_title:stacked`` or ``active_window_title``. ''' global active_window_state global last_active_window global last_active_window_name global last_oneshot global menu_items global current_layer global start global path conn = get_i3_connection() if len(path) > 0: max_width = max_width - len('Main Menu') if len(path) > 1: max_width = max_width - len('Up a Level') channel_name = 'i3wm.active_window' channel_value = None if global_menu and 'payloads' in segment_info and channel_name in segment_info[ 'payloads']: channel_value = segment_info['payloads'][channel_name] focused = conn.get_tree().find_focused() ws = focused.workspace() o_name = [w.output for w in conn.get_workspaces() \ if w.name == ws.name][0] output = segment_info.get('output') if last_active_window != focused.window and last_active_window: # Please, don't kill me for this line if global_menu and last_active_window and 'payloads' in segment_info \ and 'i3wm.workspaces' in segment_info['payloads']: segment_info['payloads']['i3wm.workspaces'] = None last_active_window = None last_active_window_name = None active_window_state = 0 start = 0 menu_items = None current_layer = None path = [] if o_name != output: if not show_empty: return None # Get visible workspace ws = [w for w in conn.get_workspaces() if w.output == output \ and w.visible] if not len(ws): return None ws = [w for w in focused.workspaces() if w.name == ws[0].name] if not len(ws): return None highlight = compute_highlight(ws[0], None) return [{ 'contents': '', 'width': 'auto', 'highlight_groups': highlight, 'click_values': { 'segment': '' }, 'payload_name': 'DROP' }] if focused.name == focused.workspace().name: if not show_empty: return None return [{ 'contents': '', 'width': 'auto', 'highlight_groups': compute_highlight(ws, None), 'click_values': { 'segment': '' }, 'payload_name': 'DROP' }] cont = [focused.name] if cutoff and len(cont) > cutoff: cont = [focused.window_class] main_cont = cont[0] if channel_value and not isinstance(channel_value, str) and len(channel_value) == 2 \ and channel_value[0].startswith('menu_click') and channel_value[1] > last_oneshot: last_oneshot = channel_value[1] click_area = channel_value[0].split(':')[1] if active_window_state == 0: last_active_window = focused.window last_active_window_name = focused.name menu_items = compute_menu(focused.window) current_layer = split_layer(menu_items, max_width, item_length) path = [] active_window_state = 1 elif click_area == 'Main Menu': start = 0 current_layer = split_layer(menu_items, max_width, item_length) path = [] elif click_area == 'Up a Level': start = 0 path = path[:-1] current_layer = menu_items cnt = 0 for i in path: current_layer = current_layer[i] cnt += 1 if cnt > 1: current_layer.update({'Up a Level': ''}) current_layer.update({'Main Menu': ''}) current_layer = split_layer(current_layer, max_width, item_length) elif click_area == '$<': start = max(0, start - 1) elif click_area == '$>': start = min(len(current_layer) - 1, start + 1) elif click_area != '': if isinstance(current_layer[start][click_area], dict): current_layer = current_layer[start][click_area] if len(path) > 0: current_layer.update({'Up a Level': ''}) current_layer.update({'Main Menu': ''}) current_layer = split_layer(current_layer, max_width, item_length) start = 0 path += [click_area] else: if isinstance(current_layer[start][click_area], tuple): gtk_click(current_layer[start][click_area][0], current_layer[start][click_area][1]) else: current_layer[start][click_area]() current_layer = split_layer(menu_items, max_width, item_length) path = [] start = 0 if channel_value and not isinstance(channel_value, str) and len(channel_value) == 2 \ and channel_value[0] == 'menu_off' and channel_value[1] > last_oneshot: last_oneshot = channel_value[1] active_window_state = 0 if channel_value and not isinstance(channel_value, str) and len(channel_value) == 2 \ and channel_value[0] == 'menu_on' and channel_value[1] > last_oneshot: last_oneshot = channel_value[1] active_window_state = 1 if last_active_window != focused.window: last_active_window = focused.window last_active_window_name = focused.name menu_items = compute_menu(focused.window) current_layer = split_layer(menu_items, max_width, item_length) path = [] start = 0 if current_layer and active_window_state: cont = list(current_layer[start].keys()) highlight = compute_highlight(ws, focused) res = [] show_prev = start > 0 and active_window_state > 0 show_next = current_layer and active_window_state > 0 \ and start < len(current_layer) - 1 def shorten(string, length): if len(string) < length - 1: return string return string[:length - 1] + '…' if global_menu and (auto_expand or show_prev): res += [{ 'contents': '<' if show_prev else '', 'highlight_groups': highlight, 'payload_name': channel_name if show_prev else 'DROP', 'draw_soft_divider': False, 'draw_inner_divider': True if show_prev else False, 'width': 'auto' if auto_expand else None, 'align': 'r', 'click_values': { 'segment': '$<' } }] total_len = 0 for i in range(0, len(cont)): total_len += min(len(cont[i]), item_length) if cont[i] != main_cont \ else min(len(cont[i]), max_width) def truncate(pl, wd, seg): nl = max(5 * len(cont), int(total_len) - wd) if int(total_len) <= nl: return seg['contents'] shr = (int(total_len) - nl) // len(cont) return shorten(seg['contents'], len(seg['contents']) - shr) for i in range(0, len(cont)): draw_div = i != 0 or show_prev or not auto_expand res += [{ 'contents': (shorten(cont[i],item_length) if cont[i] != main_cont \ else shorten(cont[i], max_width)), 'highlight_groups': highlight, 'payload_name': channel_name, 'draw_inner_divider': draw_div, 'draw_soft_divider': True , 'click_values': { 'segment': cont[i] if cont[i] != main_cont else '' }, 'truncate': truncate }] if global_menu and (auto_expand or show_next): res += [{ 'contents': '>' if show_next else '', 'highlight_groups': highlight, 'payload_name': channel_name if show_next else 'DROP', 'width': 'auto' if auto_expand else None, 'click_values': { 'segment': '$>' }, 'draw_inner_divider': bool(show_next), }] return res
if __name__ == '__main__': name = 'wm' if len(sys.argv) > 1: name = sys.argv[1] powerline = I3Powerline(name, renderer_module='i3bar') powerline.update_renderer() interval = 0.5 print ('{"version": 1}') print ('[') print ('[]') lock = Lock() def render(event=None, data=None, sub=None): global lock with lock: print (',[' + powerline.render()[:-1] + ']') sys.stdout.flush() i3 = get_i3_connection() i3_subscribe(i3, 'workspace', render) while True: start_time = monotonic() render() time.sleep(max(interval - (monotonic() - start_time), 0.1))