diff --git a/bin/i3-companion b/bin/i3-companion index b20feb4..7589fae 100755 --- a/bin/i3-companion +++ b/bin/i3-companion @@ -80,6 +80,10 @@ icons = { "headset": icon(2, ""), "keyboard": icon(2, "⌨"), "laptop": icon(2, "💻"), + "layout-splith": icon(2, ""), + "layout-splitv": icon(2, ""), + "layout-stacking": icon(2, ""), + "layout-tabbed": icon(2, ""), "loudspeaker": icon(2, ""), "microphone": icon(2, ""), "mouse": icon(2, ""), @@ -235,7 +239,7 @@ def debounce(sleep, *, unless=None): return decorator -def polybar(module): +def polybar(module, silent=False): """Use returned string to update polybar module""" def decorator(fn): @@ -259,7 +263,8 @@ def polybar(module): if e.errno != errno.ENXIO: raise - logger.info(f"polybar/{module}: content updated") + log = logger.debug if silent else logger.info + log("polybar/%s: content updated", module) cache[module] = content return content @@ -587,6 +592,18 @@ async def workspace_info(i3, event): workspace_info.last_id = result[0] +@on(I3Event.WINDOW_FOCUS, CommandEvent("layout-changed"), StartEvent) +@polybar("i3layout", silent=True) +async def layout_update(i3, event): + """Display layout of the current focused container.""" + tree = await i3.get_tree() + focused = tree.find_focused() + if not focused: + return "" + layout = focused.parent.layout + return icons.get(f"layout-{layout}", icons['unknown']) + + @on(I3Event.OUTPUT, StartEvent) @static(last_setup=None) @debounce(2) @@ -930,18 +947,19 @@ async def main(options): # this mechanism as an IPC mechanism. The alternative would be # to use ticks but we would need to spawn an i3-msg process # for that. - cmd = event.binding.command - if not cmd.startswith("nop "): - return - cmd = cmd[4:].strip("\"'") - if not cmd: - return - kind = cmd.split(":")[0] - for fn, events in on.functions.items(): - for e in events: - if isinstance(e, CommandEvent) and e.name == kind: - logger.debug("received command event %s for %s", event, fn) - await fn(i3, cmd) + for cmd in event.binding.command.split(";"): + cmd = cmd.strip() + if not cmd.startswith("nop "): + continue + cmd = cmd[4:].strip(" \"'") + if not cmd: + continue + kind = cmd.split(":")[0] + for fn, events in on.functions.items(): + for e in events: + if isinstance(e, CommandEvent) and e.name == kind: + logger.debug("received command event %s for %s", event, fn) + await fn(i3, cmd) i3.on(I3Event.BINDING, binding_event) diff --git a/config b/config index b59a24d..5cc0358 100644 --- a/config +++ b/config @@ -73,8 +73,8 @@ bindsym $mod+f fullscreen toggle bindsym $mod+Shift+f fullscreen toggle global # change container layout (tabbed, toggle split) -bindsym $mod+w layout toggle splitv splith tabbed -bindsym $mod+v split toggle +bindsym $mod+w layout toggle splitv splith tabbed; nop "layout-changed" +bindsym $mod+v split toggle; nop "layout-changed" # toggle tiling / floating bindsym $mod+Shift+space floating toggle diff --git a/dotfiles/polybar.conf b/dotfiles/polybar.conf index 608044c..916f5b9 100644 --- a/dotfiles/polybar.conf +++ b/dotfiles/polybar.conf @@ -4,6 +4,7 @@ background = #c0000000 foreground = #eaeaea highlight = #4c7899 warning = #ff3121 +focused = #cc5c00 transparent = #00000000 [settings] @@ -29,7 +30,7 @@ font-0 = Iosevka Aile:style=Regular:size=10;2 font-1 = Font Awesome 6 Pro:style=Solid:size=10;2 font-2 = Font Awesome 6 Brands:style=Regular:size=10;2 -modules-left = i3 +modules-left = i3 i3layout modules-center = date [bar/alone] @@ -55,7 +56,7 @@ pin-workspaces = true label-mode-background = ${colors.highlight} label-mode-padding = 1 label-focused = %name% -label-focused-background = #cc5c00 +label-focused-background = ${colors.focused} label-focused-padding = 1 label-unfocused = %name% label-unfocused-padding = 1 @@ -66,6 +67,12 @@ label-urgent = %name% label-urgent-background = #a00000 label-urgent-padding = 1 +[module/i3layout] +type = custom/ipc +hook-0 = cat $XDG_RUNTIME_DIR/i3/i3layout.txt 2> /dev/null +format-foreground = ${colors.focused} +initial = 1 + # This needs 3.6+ [module/disk] type = internal/fs