baskerville / bspwm

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

Strange behaviour with bspc node -s #753

Closed dramm33 closed 6 years ago

dramm33 commented 6 years ago

I have been using bspwm on a desktop for a while now and all has been working fine. However recently I started using a multi head setup on my laptop. I found some configs for multi head in this website http://notes.neeasade.net/bspwm-multihead/

Since some of the arguments are for older versions of bspwm, I adapted it.

The desired behaviour is to move the current node keeping it focused, even if I'm moving it no another monitor (which could be empty or not).

The config I'm using:

super + shift + {h,j,k,l}
    bspc config pointer_follows_focus true; \
    cur_win=$(bspc query -N -n); \
    cur_mon=$(bspc query -M -m); \
    dir={west,south,north,east}; \
    if ! bspc node -f $dir; then \
        bspc node -m $dir; \
        bspc monitor -f $dir; \
    else \
        new_mon=$(bspc query -M -m); \
        if [ $new_mon -eq $cur_mon ]; then \
                bspc node -s $cur_win; \
        else \
                bspc node $cur_win -m $new_mon; \
        fi; \
        bspc node -f $cur_win; \
    fi; \
    bspc config pointer_follows_focus false

What is happening is that when moving a node within the same monitor, only moving to the right (super + shift + l ) works. Yeah, it makes no sense... The explain in another way, if I have two nodes in a single monitor:

Also, if I presel to either north or south and then try super + shift + {j,k} the nodes go back to the standard vertical split.

neeasade commented 6 years ago

Hi there,

FWIW I exported my keybinding into scripts and have the following mapping in my sxhkd

super + {_,shift,alt,ctrl} + {h,j,k,l}
    {focus,move,resize,presel}.sh {west,south,north,east}

the scripts can be found here: https://github.com/neeasade/dotfiles/tree/master/wm/.wm/scripts/interact

msteen commented 6 years ago

I am using the following script, which I believe matches your intended behavior:

# Give priority to swapping to locations that have been preselected.
super + shift + {Left,Down,Up,Right}
  d={west,south,north,east}; \
  bspc node --to-node "${d}.!automatic" || \
  bspc node $d --to-node 'focused.!automatic' || \
  bspc node --swap $d || \
  bspc node --to-monitor $d
dramm33 commented 6 years ago

@neeasade I'm glad to know that you have updated config, I will look into them and probably copy a bit 😛 @msteen Thanks for the script, it does almost all that I wanted, the only difference is that when moving to another monitor, yours swaps the nodes and I want to "add" a node, if that makes sense. Anyway I'm going to use it until I find/write exactly what I want.

Since I still couldn't find an explanation to why the script I posted only works when moving east, I going to leave the issue open just in case someone else wants to try to replicate it and see if its a bug or not.

msteen commented 6 years ago

With your "add" behavior, do you mean you never want to swap nodes between monitors, but move them over to the other monitor when nodes cross monitors? If so, you can simply add the local modifier to the node selection when calling swap:

# Give priority to swapping to locations that have been preselected.
super + shift + {Left,Down,Up,Right}
  d={west,south,north,east}; \
  bspc node --to-node "${d}.!automatic" || \
  bspc node $d --to-node 'focused.!automatic' || \
  bspc node --swap "${d}.local" || \
  bspc node --to-monitor $d
msteen commented 6 years ago

I just checked your code, it is safe to close this issue, no bug, just a mistake in the script. If you checked your logs you should have seen the following error: /bin/sh: line 0: [: 0x00A00012: integer expression expected. So if you just change the check from [ $new_mon -eq $cur_mon ] to [ "$new_mon" == "$cur_mon" ] the error goes away and the script seems to work again, going left and right.

Oh, and the reason why it does seems to work going to the right is because the aforementioned error causes the if-check to always fail, so the else-branch will always be taken, which calls bspc node -m short for --to-monitor and moves the focused node to the current window, which reinserts the node in the monitor, causing it to effectively swap to the default position a node will be added to in a monitor, depending on your configuration.

dramm33 commented 6 years ago

Thanks @msteen For future reference [ "$new_mon" = "$cur_mon" ] did the trick. To me it's the best solution since I can choose when to also move the cursor.

About the logs, I couldn't find anything about it in the docs.

Anyway problem solved and mystery revealed.

Thank you all for the help.

msteen commented 6 years ago

Right, I should have used [ "$new_mon" = "$cur_mon" ], = and == are synonyms, but only = is POSIX compliant.

According to the manual it should be possible to change the shell that is called for the commands:

The commands are executed via SHELL -c COMMAND (hence you can use environment variables). SHELL will be the content of the first defined environment variable in the following list: SXHKD_SHELL, SHELL.

If you set one of those environment variables to e.g. bash or zsh, you could also have used these conditions, like you probably normally would: (( $new_mon == $cur_mon )), [[ $new_mon -eq $cur_mon ]], or [[ "$new_mon" == "$cur_mon" ]].

With regards to the log, I did not mean any log specific to either bspwm or sxhkd, I just meant whatever system log you are using. I am using NixOS which uses systemd, so I just used journalctl -e to check the latest entries.

I do not see how your initial script is better because you "can choose when to also move the cursor". I have updated mine to do the same as well:

# Give priority to swapping to locations that have been preselected.
super + shift + {Left,Down,Up,Right}
  pff_save=$(bspc config pointer_follows_focus); \
  bspc config pointer_follows_focus true; \
  d={west,south,north,east}; \
  bspc node --to-node "${d}.!automatic" || \
  bspc node $d --to-node 'focused.!automatic' || \
  bspc node --swap "${d}.local" || \
  bspc node --to-monitor $d; \
  bspc config pointer_follows_focus $pff_save

But by all means use whatever script you prefer. I would recommend creating your own little collection of scripts like @neeasade has done, incorporating ideas of others as you stumble upon them, and optimizing them for your needs. Good luck!