baskerville / bspwm

A tiling window manager based on binary space partitioning
BSD 2-Clause "Simplified" License
7.72k stars 415 forks source link

[?] Balance tree or how to transform spiral to grid #900

Open ivanvig opened 5 years ago

ivanvig commented 5 years ago

The scripts in matlab or python that I work with often create lots of plot windows. The problem is, I get windows that are needlessly big and others that are too small as a result of the fibonacci layout.

I would like a way to select the parent node of all this windows and change the layout to a grid where all windows have more or less the same dimension.

I suppose that balancing the tree, doing this:

  a                          a    
 / \                        / \   
1   b         --->         b   c  
   / \                    / \ / \ 
  2   c                  1  2 3  4
     / \ 
    3   4

Could create a grid, or at least something similar but don't really know how to do it.

stuin commented 5 years ago

This looks really interesting and I am going to try it.

ivanvig commented 5 years ago

The common approach to balance a binary tree is to perform a sequence of tree rotations but I couldn't find a way to do this in bspwm. Once the tree is balanced, I think using bspc node -B, which assigns to each window the same amount of screen area, should be enough to generate a grid.

So basically, if there is a way to perform a tree rotation what remains shouldn't be too hard

jstamant commented 5 years ago

@ivanvig I think your solution would be to have user-selectable layouts? I was hoping bspwm would support custom layouts, or common layouts like master+stack and grid: but it looks like it's hard-coded to only do the spiral or "longest-side" layout, which I don't find useful past 3 windows. The way I see it is if you changed your layout to a "grid" tiled-layout, all your matlab/python plot windows should automatically slot into a nice, even grid.

@baskerville Do you have any plans on implementing other layouts for tiled-mode? I understand that this can likely be scripted by the user, at the moment, which I'm about to try out. I'm just not sure how difficult it is to achieve this, and if it makes sense to make provisions for setting the layout.

+---------------+--------+
|               | stack  |
|               +--------+
|     master    |        |
|               +--------+
|               |        |
+---------------+--------+
+------------+-----------+
|    grid    |           |
|            |           |
+------------+-----------+
|            |           |
|            |           |
+------------+-----------+
mdutra commented 5 years ago

One approach to get a grid layout would be an automatic_scheme that balances the tree. It would work just like the longest_side when the focused node is in the correct level (splitting the node in half). Otherwise, it would send the focused node to a different parent to keep same level.

          a                           a                        a                         a
         / \                        /   \                    /   \                     /   \
        1   b                      c     b                  c     b                   c     b
           / \                    / \   / \                / \   / \                 / \   / \
          2   3                  1  2  4   3              1  2  d   3               1  2  d   e
          ^                            ^                       / \                       / \ / \
                                                              4   5                      6 5 3 4
                                                              ^                          ^

+-----------------------+ +-----------------------+ +-----------------------+ +-----------------------+
|           |           | |           |           | |           |     |     | |           |     |     |
|           |     2     | |     1     |     4     | |     1     |  4  |  5  | |     1     |  6  |  5  |
|           |     ^     | |           |     ^     | |           |  ^  |     | |           |  ^  |     |
|     1     |-----------| |-----------|-----------| |-----------|-----------| |-----------|-----------|
|           |           | |           |           | |           |           | |           |     |     |
|           |     3     | |     2     |     3     | |     2     |     3     | |     2     |  3  |  4  |
|           |           | |           |           | |           |           | |           |     |     |
+-----------------------+ +-----------------------+ +-----------------------+ +-----------------------+
ivanvig commented 5 years ago

One approach to get a grid layout would be an automatic_scheme that balances the tree. It would work just like the longest_side when the focused node is in the correct level (splitting the node in half). Otherwise, it would send the focused node to a different parent to keep same level.

Well that would be the ideal solution. I was looking for a way to do it with commands bspc currently has, but it doesn't seem to be that easy.

neeasade commented 5 years ago

It was my impression this sort of thing as a layout was meant to live in external_rules -- in your external_rules script/program you could query the current state of things, and balance the tree for your new node to come on the scene. You could then have different layout types by simply changing your external rules script

neeasade commented 5 years ago

if you wanted to be maximally naive/simple script, you could just alternate which dtop child you insert on with all windows -- this does the transformation for me:

#!/bin/sh

target=first
# the sort is just for consistency
for node in $(bspc query -N -n .local.window | sort); do
    bspc node $node -n "$(bspc query -N -n @$(bspc query -D -d):/${target})"
    [ "$target" = "first" ] && target="second" || target="first"
done
bspc node @/ -B

Granted, this might not be the 'right' way/balance from the bottom up with actual rotations.

edit:

So basically, if there is a way to perform a tree rotation what remains shouldn't be too hard

bspc node @parent -R 90

alechirsch commented 3 years ago

@neeasade I am interested in your solution, how do I use it? I tried adding your script as an external rule with no avail.

rjhilgefort commented 3 years ago

@alechirsch What I did was just put that script somewhere like ~/.scripts/bspwm-grid-layout and then added a hotkey to call the script from my sxhkd config file like this:

super + shift + alt + d
  ~/.scripts/bspwm-grid-layout

Hope that helps!

rjhilgefort commented 3 years ago

@neeasade Thanks for the script! I hooked it up and have been trying it out. It only sometimes works and sometimes just keeps a master-stack layout. Has that been your experience as well? Anything you can think of I could try to get it to always do a grid? Thanks!