#+title: window tags #+title_extra: Thoughts after 5 years #+pubdate: <2025-08-14> #+filetags: #+rss_title: I used to be a multi-screen maximalist. Everyone knows the more monitors you have the more powerful you are, right? I ran a triple-head setup turned in [[https://notes.neeasade.net/rice.html#2016-01-28][various ways]], and it came with it's own challenges for my wm management and window wants. One day I saw someone talking about their single monitor workflow and they said it helped them focus. After some reflection I came to the conclusion they were right - even if I'm referencing docs, having windows side by side rather than splatted helps me hone in on what matters. I would have to be a little more intentional with /what/ is on the single screen in front of me instead of just splatting things into whatever space is available. And so (initially as an experiment) I went from 3 mid monitors to one really nice monitor. Many edge cases left my dotfiles. I didn't have to worry about lemonbar's [[https://github.com/LemonBoy/bar/issues/163][-g flag]] behaving oddly anymore. When the border of the monitor is the edge of the total display, you don't have to worry about pseudo-borders for things like window movement scripts. All in all it was a great success! The result was a calmer, more focused desktop experience. Around 2020 I saw a talk about the [[https://hikari.acmelabs.space/][hikari]] wayland compositor and it mentioned taking great inspo from [[https://man.openbsd.org/cwm][cwm]], a window group wm in the openbsd world. I did some further digging and thought that window groups might be a fine thing to have, and it might stack further into the single-monitor feels described above - after all, you go from N virtual desktops to just 1, with tags for summoning or dismissing things at will. Thus the latter half of 2020 saw a lot of tag/group experiments for me, jamming the concept into bspwm with a script, currently called [[https://github.com/neeasade/dotfiles/blob/master/bin/bin/btags][=btags=]]. =bspc= can hide windows by toggling a hidden flag on them - After ~6 months of messing with the concept, things largely stabilized, though I did come back to tweak the flow once or twice in the 5 years since. So.. What worked? What didn't? ----- ** Overview: - I have 4 tags - Tags have their own associated border color - Toggling a tag just means flipping the hidden flag with bspc - I still tile my windows, am not interested in a floating experience ** Ideas that worked *** The hole, and dismissal The 4th tag is my "hole" tag. It's where I banish windows I don't want to see, but still keep them open - things like a torrent client, spare emacs window, or steam. After a few years, I realized I needed a "dismiss" notion in all this. Something to say "idc where this window goes, but not here". Adding it made my experience much smoother pretty much right away. *** Standard roles for tags My tags uses are pretty much always: | tag | use | name | |-----+------------------------------+------| | 1 | emacs/code | code | | 2 | qutebrowser | net | | 3 | misc: chat, osrs, a document | misc | | 4 | the hole | hole | This means that I can always hit =Alt+1= to see/cycle through emacs windows, or 2 for browsing. This predictability is extremely nice, I can always go to either without thinking much about it. Summon chat for a second to type something and then dismiss it? donezo. *** Subscription Subscribing to bspwm events allows me to automatically assign tags to windows based on their =WM_CLASS=, or inherit the value from the currently focused tag. This means I don't have to assign window tags often, things go where they should (ready to be summoned without thought) Showing how I get the info to make those decisions: #+begin_src sh bspc subscribe node_add | while read -r event m d i wid; do current_class=$(xprop WM_CLASS -id $wid) current_name=$(xprop WM_NAME -id $wid) last_class=$(xprop WM_CLASS -id $(bspc query -N last -n)) # ... done #+end_src *** Window border colors from tag Using distinct colors, I can tell assigned tags at a glance (drawn with [[https://github.com/neeasade/opt][chwbn]]): {{{image(btags.png)}}} #+begin_center From the top left clockwise: net, code, code, hole #+end_center #+begin_src sh # tag, visible, border color, wids $ btags state-plain code true e9a4d1 0x01ACB110 0x01AD21ED net true 7bcc7b 0x01E00013 chat false 98bde1 hole true b9b9b9 0x01AE254F none true 000000 0x0340003B #+end_src *** Fishing I have a script called =find_class= that finds and shows a =WM_CLASS=, unhiding it if it is hidden - it does _not_ touch the tag toggle state, which allows me to view a window in a hidden tag. Thus, I can summon steam from the hole without conjuring all the other windows I've thrown in there, and it returns on the next action that triggers a tag render. ** Ideas that didn't pan out *** Multiple tags per window I thought it would be neat to allow multiple tags/groups per window, but in practice this got messy super fast. Much easier to manage a single tag allowed per window, and then do tag juggling higher level commands. *** Status lines I gave =btags= an option to match the output format of =bspc subscribe= initially, thinking it would be nice to plug and play into existing status bar helpers, but ultimately ended up implementing a more plain status reporter and using it in my panel #+begin_src sh $ btags state : WMDP-0:Fa:Ob:Fc:ohole:fd:LT:TT:G #+end_src #+begin_src text $ btags state-plain a true e9a4d1 b true 7bcc7b 0x01A25F85 0x01E00013 0x01E00013 0x01A219FF c true 98bde1 hole false b9b9b9 0x0340003B 0x01A042CE none true 000000 #+end_src *** Resize-averse applications In bspwm, showing/hiding a tiled node means re-inserting it into the tree, which can result in many resize events in nearby windows. Some programs (terminals, emacs, most websites) take this in stride, but occasionally you run into programs that don't. The runelite runescape client was causing my entire wm to freeze when being resized so often for the show/hide action. ** What might a return to virtual desktops look like for me? I'm writing this post because occasionally I feel like I should scrape this whole notion and return to a more traditional setup. Let's think about it: - I'd miss the "summon browser" key via tag focus - would probably make it a search-for-browser instead? - The "hole" concept can still exist in an nth desktop, along with a dismissal notion - cycling between current window class could be a thing - I could get rid of btags and tag state most likely, simplify border handling (would only have to worry about one focused window, no multi-color drawing) - Would be a feeling of "going to" windows rather than summoning/dismissing them in one space - benefit: could leave some workspace in-progress with an idea alone for awhile and pick it right back up - Is it possible to have summon/dismiss notions with keybinds for desktop flicking and not have it be keybind hell? right now these things are conflated because it's done via tags, so I don't have to think about it, which is /very/ nice. - Flicking through window class is more limited than a tagging notion because you get to tag windows in an adhoc fashion. Is there some world where I mix tags and desktops? I would want a way to show details of the current tab group next to the desktop status - perhaps in the panel. - One thing that would be missing/have to implement if I wanted it: per desktop layouts