baskerville / bspwm

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

drag to float posslible #1128

Closed kristoferus75 closed 4 years ago

kristoferus75 commented 4 years ago

Hi !

Is drag to float possible in bspwm ?

press & hold the super key und hold the left mouse button and move -> to make window floating from a tiled window !

I have used this on spectrwm !

Meta+LeftClick+Drag: move window (and float it if tiled)

How can i achieve this ?

Thanks !

kind regrads

kristoferus75

emanuele6 commented 4 years ago

This issue can be closed now.

I gave @kristoferus75 a solution in a reddit post some days ago:

In the sxhkd configuration file:

ctrl + button1
    BUTTON=1 /path/to/script

/path/to/script:

#!/bin/env bash

: "${BUTTON:=1}"

node="$(bspc query -N -n pointed)"

die() {
    jobs -p | xargs -r -n1 -I{} kill {}
    exit
}

trap 'die' USR1

{ bspc subscribe node_focus | while read -r _ _ _ wid; do
    (( wid != node )) && break; done; kill -USR1 "$$" ;} &
{ while xinput list \
      | sed -nE 's,.*id=([0-9]+).*slave\s+pointer.*,\1,p' \
      | xargs -r -n1 -I{} xinput query-state {} 2> /dev/null \
      | grep -qF "button[${BUTTON}]=down"; do sleep .3; done; kill -USR1 "$$" ;} &

if bspc node "$node.tiled" -f; then
    node_tiled_rect=($(bspc query -T -n "$node" | jq -r '.client.tiledRectangle[]'))
    bspc node "$node" -t floating
    xdo move   -x "${node_tiled_rect[0]}" -y "${node_tiled_rect[1]}" "$node"
    xdo resize -w "${node_tiled_rect[2]}" -h "${node_tiled_rect[3]}" "$node"
elif bspc node "$node.floating" -f; then
    :
else
    die
fi

eval "$(xdotool getmouselocation --shell)"
x="$X" y="$Y"
while :; do
    eval "$(xdotool getmouselocation --shell)"
    (( X != x || Y != y )) && {
        bspc node "$node" -v "$((X - x))" "$((Y - y))"
        x="$X" y="$Y"
    }
done

wait

Video demonstration of this script working: https://youtu.be/2AAjX5odQWs.

jallbrit commented 4 years ago

@kristoferus75 , please either close the issue or respond to @emanuele6 if this issue still exists.

emanuele6 commented 4 years ago

Hey, @kristoferus75.

I decided that I also wanted to use this script, but the 300ms delay (.3) was really annoying and made it unusable for me.

I took a bit of time to rewrite this script to avoid using xinput and remove the delay completely:

bspdragtofloat:

#!/bin/env bash

: "${BSPWM_DIR:="${XDG_CONFIG_HOME:-$HOME/.config}/bspwm"}"

status_file="$BSPWM_DIR/tmp/drag_to_float"

[[ "$1" = stop ]] && {
    [[ -e "$status_file" ]] \
        && rm -r -- "$status_file"
    exit
}

[[ -e "$status_file" ]] \
    && exit

< <(bspc query -T -n pointed.window | jq -r '"\(.id) \(.client.state)"') read -r node node_state

[[ -z "$node" ]] \
    && exit

case "$node_state" in
    floating)
        ;;
    tiled|pseudo_tiled)
        node_tiled_rect=($(bspc query -T -n "$node" | jq -r '.client.tiledRectangle[]'))
        bspc node "$node" -t floating
        xdo move   -x "${node_tiled_rect[0]}" -y "${node_tiled_rect[1]}" "$node"
        xdo resize -w "${node_tiled_rect[2]}" -h "${node_tiled_rect[3]}" "$node" ;;
    *) # fullscreen
        exit ;;
esac

eval "$(xdotool getmouselocation --shell)"
x="$X" y="$Y"
touch -- "$status_file"
while [[ -e "$status_file" ]]; do
    eval "$(xdotool getmouselocation --shell)"
    (( X != x || Y != y )) && {
        bspc node "$node" -v "$((X - x))" "$((Y - y))"
        x="$X" y="$Y"
    }
    sleep .01
done

[[ -e "$status_file" ]] \
    && rm -r -- "$status_file"

In sxhkdrc:

# "Drag to floating" tiled windows or move floating windows.
ctrl + button3
    bspdragtofloat
ctrl + @button3
    bspdragtofloat stop
@button3
    bspdragtofloat stop
~button3
    :

~button3 : is required! If you don't put it in sxhkdrc, right-clicking won't work. It's probably due to a bug in sxhkd: using ~@button3 (which would be used instead of @button3 here) doesn't work as it should. (note: you don't need ~button3 : if you already have something bound to ~button3, you just need to have something bound to it.)

If you already have something bound to @button3, combine the two keybinds: i.e. this:

@button3
    whatever_command_you_already_had

..becomes this:

@button3
    bspdragtofloat stop; \
    whatever_command_you_already_had

NOTES

You need to create a tmp directory in ~/.config/bspwm if you don't have it already to make this work:

mkdir -p ~/.config/bspwm/tmp

This tmp directory is a directory I use to keep metadata about my bspwm-related scripts. I suggest you empty this directory every time bspwm is launched. i.e. add something like this in bspwmrc:

[[ "$1" -eq 0 ]] \
    && find "$BSPWM_DIR/tmp" -type f -exec rm -- {} ';'

If you don't want to bother with ~/.config/bspwm/tmp (there is no benefit), just use /tmp:

replace..

: "${BSPWM_DIR:="${XDG_CONFIG_HOME:-$HOME/.config}/bspwm"}"

status_file="$BSPWM_DIR/tmp/drag_to_float"

..with..

status_file='/tmp/drag_to_float'

ADDITIONAL_NOTE: I also changed the behaviour of the script to not focus windows before moving them: the focused window stays the same.

kristoferus75 commented 4 years ago

Thanks emanuele6 Cool -> it works perfectly :-)