You are not logged in.
I created this bash scripts to make up for some features I wished XFCE had. these scripts should theoretically work with several window/desktop managers. the only requirements for these is wmctrl, xwininfo and xdotool.
update: I've merged the two scripts and they should run a tad faster.
I'm still looking for a way to re-maximize windows after the "window select" function.
I'm also still looking for a way to determine what windows are non-resizable by the user so that the script doesn't resize them, either (currently, it does)
usage
./winfuncs.sh select # arrange windows in a tiled manner, click on one to have it brought forward, all windows return to previous positions/sizes (suggested xbindkeys combo: Mod4 + Tab)
./winfuncs.sh tile # tile all windows on screen (suggested xbindkeys combo: Mod4 + t)
./winfuncs.sh tiletwo # after running this, click two windows. they will tile side-by-side. (suggested xbindkeys combo: Mod4 + c:23) (c:23 is the '2' key)
./winfuncs.sh cascade
./winfuncs.sh showdesktop
winfuncs.sh:
#!/bin/bash
#todo:
# cancel for tile functions
# determine what windows are maximized and re-max after the "window select" function
# determine what windows are non-resizable by the user so that the script doesn't resize them
# cascade also shaded windows
# which workspace we're on
function get_workspace {
if [[ "$DTOP" == "" ]] ; then
DTOP=`xdotool get_desktop`
fi
}
function is_desktop {
xwininfo -id "$*" | grep '"Desktop"'
return "$?"
}
function get_visible_window_ids {
if (( ${#WDOWS[@]} == 0 )) ; then
WDOWS=(`xdotool search --desktop $DTOP --onlyvisible "" 2>/dev/null`)
fi
}
function get_desktop_dim {
#desktop dimensions
if (( ${#DIM[@]} == 0 )) ; then
DIM=(`wmctrl -d | egrep "^0" | sed 's/.*DG: \([0-9]*x[0-9]*\).*/\1/g' | sed 's/x/ /g'`)
fi
}
function win_showdesktop {
get_workspace
get_visible_window_ids
command="search --desktop $DTOP \"\""
if (( ${#WDOWS[@]} > 0 )) ; then
command="$command windowminimize %@"
else
command="$command windowraise %@"
fi
echo "$command" | xdotool -
}
function win_tile_two {
get_desktop_dim
wid1=`xdotool selectwindow 2>/dev/null`
is_desktop "$wid1" && return
wid2=`xdotool selectwindow 2>/dev/null`
is_desktop "$wid2" && return
half_w=`expr ${DIM[0]} / 2`
commands="windowsize $wid1 $half_w ${DIM[1]}"
commands="$commands windowsize $wid2 $half_w ${DIM[1]}"
commands="$commands windowmove $wid1 0 0"
commands="$commands windowmove $wid2 $half_w 0"
commands="$commands windowraise $wid1"
commands="$commands windowraise $wid2"
wmctrl -i -r $wid1 -b remove,maximized_vert,maximized_horz
wmctrl -i -r $wid2 -b remove,maximized_vert,maximized_horz
echo "$commands" | xdotool -
}
function win_tile {
get_workspace
get_visible_window_ids
(( ${#WDOWS[@]} < 1 )) && return;
get_desktop_dim
# determine how many rows and columns we need
cols=`echo "sqrt(${#WDOWS[@]})" | bc`
rows=$cols
wins=`expr $rows \* $cols`
if (( "$wins" < "${#WDOWS[@]}" )) ; then
cols=`expr $cols + 1`
wins=`expr $rows \* $cols`
if (( "$wins" < "${#WDOWS[@]}" )) ; then
rows=`expr $rows + 1`
wins=`expr $rows \* $cols`
fi
fi
(( $cols < 1 )) && cols=1;
(( $rows < 1 )) && rows=1;
win_w=`expr ${DIM[0]} / $cols`
win_h=`expr ${DIM[1]} / $rows`
# do tiling
x=0; y=0; commands=""
for window in ${WDOWS[@]} ; do
wmctrl -i -r $window -b remove,maximized_vert,maximized_horz
commands="$commands windowsize $window $win_w $win_h"
commands="$commands windowmove $window `expr $x \* $win_w` `expr $y \* $win_h`"
x=`expr $x + 1`
if (( $x > `expr $cols - 1` )) ; then
x=0
y=`expr $y + 1`
fi
done
echo "$commands" | xdotool -
}
function win_cascade {
get_workspace
get_visible_window_ids
(( ${#WDOWS[@]} < 1 )) && return;
x=0; y=0; commands=""
for window in ${WDOWS[@]} ; do
wmctrl -i -r $window -b remove,maximized_vert,maximized_horz
commands="$commands windowsize $window 640 480"
commands="$commands windowmove $window $x $y"
x=`expr $x + 22`
y=`expr $y + 22`
done
echo "$commands" | xdotool -
}
function win_select {
get_workspace
get_visible_window_ids
(( ${#WDOWS[@]} < 1 )) && return;
# store window positions and widths
i=0
for window in ${WDOWS[@]} ; do
GEO=`xdotool getwindowgeometry $window | grep Geometry | sed 's/.* \([0-9].*\)/\1/g'`;
height[$i]=`echo $GEO | sed 's/\(.*\)x.*/\1/g'`
width[$i]=`echo $GEO | sed 's/.*x\(.*\)/\1/g'`
# ( xwininfo gives position not ignoring titlebars and borders, unlike xdotool )
POS=(`xwininfo -stats -id $window | grep 'geometry ' | sed 's/.*[-+]\([0-9]*[-+][0-9*]\)/\1/g' | sed 's/[+-]/ /g'`)
posx[$i]=${POS[0]}
posy[$i]=${POS[1]}
i=`expr $i + 1`
done
# tile windows
win_tile
# select a window
wid=`xdotool selectwindow 2>/dev/null`
is_desktop "$wid" && return
# restore window positions and widths
i=0; commands=""
for (( i=0; $i<${#WDOWS[@]}; i++ )) ; do
commands="$commands windowsize ${WDOWS[i]} ${height[$i]} ${width[$i]}"
commands="$commands windowmove ${WDOWS[i]} ${posx[$i]} ${posy[$i]}"
done
commands="$commands windowraise $wid"
echo "$commands" | xdotool -
}
for command in ${@} ; do
if [[ "$command" == "tile" ]] ; then
win_tile
elif [[ "$command" == "select" ]] ; then
win_select
elif [[ "$command" == "tiletwo" ]] ; then
win_tile_two
elif [[ "$command" == "cascade" ]] ; then
win_cascade
elif [[ "$command" == "showdesktop" ]] ; then
win_showdesktop
fi
done
Last edited by caibbor (2012-03-01 15:08:35)
Offline
It works perfectly. Many thanks.
Offline
Does it work with Xfwm4? I copied the script in /usr/local/bin, I gave execute permissions, and put it to begin with Xfce, but nothing happens.
url: blog.desdelinux.net
twt: @elavdeveloper
Offline
xfcelav, you'll need to set up a key combo. the easiest way in XFCE4 (xfwm4) is to open up the "control center" thingy, go into keyboard settings, and create a new Application Shortcut that calls the script with whatever function you want it to do. for example, `/usr/local/bin/winfuncs.sh tile` to tile windows. should work if
Also, there is a bug I've noticed with the 'select' (window expose) feature. although the windows are moved back to their original places, sometimes they'll be put 44 pixels lower than they ought to. only some windows. xfce-terminals with no borders or titlebar aren't affected by this for some reason.
Last edited by caibbor (2012-02-25 20:47:12)
Offline
update top post.
ADDED: Cascade windows feature. (22 pixels is assumed titlebar height. will make it determine real height later)
ADDED: Show Desktop. (minimizes all on current workspace. if they already are, it unminimizes instead)
FIXED: doesn't count minimized windows when tiling
FIXED: moves windows back to their proper positions after 'select' feature
FIXED: lots of other lil things
new dependency: xwininfo
Last edited by caibbor (2012-02-26 06:33:07)
Offline
Excuse my ignorance. Maybe I'm doing something wrong. I went to menu » preferences » keyboard » application shortcuts and create a new application with the path /usr/share/bin/winfun.sh and I assigned keys Super L + e. Does not work either. Did I do something wrong?
Last edited by xfcelav (2012-02-27 12:43:52)
url: blog.desdelinux.net
twt: @elavdeveloper
Offline
Perhaps, have you forgot to add 'tile' (or select and so) after /usr/share/bin/winfun.sh ?
Offline
Nop. I add tile and not work!!
url: blog.desdelinux.net
twt: @elavdeveloper
Offline
edit: I noticed you typed the path as winfun.sh. the name I gave it is winfuncs.sh. try that.
open a terminal and run this:
/usr/share/bin/winfuncs.sh tile
if it doesn't work, these are the likely problems:
* the script is not at that path, or
* the script is not executable, or
* you do not have xdotool, xwininfo, or wmctrl installed
Last edited by caibbor (2012-02-29 18:10:11)
Offline
I have installed xdotool and wmctrl, but xwininfo is not in the repositories of Debian Testing. The script I have it in /usr/local/bin as /usr/share/bin does not exist.
BTW: When I run the script in terminal, it show me this:
/usr/local/bin/winfuncs.sh tile
expr: división por cero
expr: división por cero
Last edited by xfcelav (2012-02-29 20:02:52)
url: blog.desdelinux.net
twt: @elavdeveloper
Offline
well xwininfo is required for the select option, anyhow. other functions might not work at all. do a package search to find out which one has it.
your division by zero error probably happens when you try to tile windows when there are none (which I'll fix soon)
Last edited by caibbor (2012-02-29 21:41:19)
Offline
div by zero fixed, though now that I think about it, you'd have to have a terminal open to see the error message, and that would mean at least one window is open. so heh. fixed anyway.
Offline
div by zero it's ok, but:
/usr/local/bin/winfuncs.sh showdesktop
search: unrecognized option '--desktop'
Invalid usage
Usage: xdotool search [options] regexp_pattern
--class check regexp_pattern agains the window class
--classname check regexp_pattern agains the window classname
--maxdepth N set search depth to N. Default is infinite.
-1 also means infinite.
--onlyvisible matches only windows currently visible
--pid PID only show windows belonging to specific process
Not supported by all X11 applications
--screen N only search a specific screen. Default is all screens
--name check regexp_pattern agains the window name
--title DEPRECATED. Same as --name.
--all Require all conditions match a window. Default is --any
--any Windows matching any condition will be reported
-h, --help show this help output
If none of --name, --classname, or --class are specified, the
defaults are: --name --classname --class
man xdotool
DESKTOP AND WINDOW COMMANDS
These commands follow the EWMH standard. See the section "EXTENDED WINDOW MANAGER HINTS" for more information.
windowactivate [options] [window=%1]
Activate the window. This command is different from windowfocus: if the window is on another desktop, we will
switch to that desktop. It also uses a different method for bringing the window up. I recommend trying this
command before using windowfocus, as it will work on more window managers.
If no window is given, %1 is the default. See "WINDOW STACK" and "COMMAND CHAINING" for more details.
--sync
After sending the window activation, wait until the window is actually activated. This is useful for
scripts that depend on actions being completed before moving on.
getactivewindow
Output the current active window. This command is often more reliable than getwindowfocus. The result is saved
to the window stack. See "WINDOW STACK" for more details.
set_num_desktops number
Changes the number of desktops or workspaces.
get_num_desktops
Output the current number of desktops.
set_desktop desktop_number
Change the current view to the specified desktop.
get_desktop
Output the current desktop in view.
set_desktop_for_window [window=%1] desktop_number
Move a window to a different desktop. If no window is given, %1 is the default. See "WINDOW STACK" and "COMMAND
CHAINING" for more details.
get_desktop_for_window [window=%1]
Output the desktop currently containing the given window. Move a window to a different desktop. If no window is
given, %1 is the default. See WINDOW STACK and "COMMAND CHAINING" for more details.
url: blog.desdelinux.net
twt: @elavdeveloper
Offline
my guess is you have an old or crippled version of xdotool.
brandon@brandon-700GR ~ $ xdotool search --fakeoption
search: unrecognized option '--fakeoption'
Invalid usage
Usage: xdotool search [options] regexp_pattern
--class check regexp_pattern agains the window class
--classname check regexp_pattern agains the window classname
--maxdepth N set search depth to N. Default is infinite.
-1 also means infinite.
--onlyvisible matches only windows currently visible
--pid PID only show windows belonging to specific process
Not supported by all X11 applications
--screen N only search a specific screen. Default is all screens
--desktop N only search a specific desktop number
--limit N break search after N results
--name check regexp_pattern agains the window name
--title DEPRECATED. Same as --name.
--all Require all conditions match a window. Default is --any
--any Windows matching any condition will be reported
--sync Wait until a search result is found.
-h, --help show this help output
If none of --name, --classname, or --class are specified, the
defaults are: --name --classname --class
brandon@brandon-700GR ~ $ man xdotool | grep -A44 'search \['
search [options] pattern
Search for windows with titles, names, or classes with a regular expression pattern.
The output is line-delimited list of X window identifiers. If you are using "COMMAND
CHAINING", the search command will only write window ids to stdout if it is the last
(or only) command in the chain; otherwise, it is silent.
The result is saved to the window stack for future chained commands. See "WINDOW
STACK" and "COMMAND CHAINING" for details.
The default options are "--name --class --classname" (unless you specify one one or
more of --name --class or --classname).
The options available are:
--class
Match against the window class.
--classname
Match against the window classname.
--maxdepth N
Set recursion/child search depth. Default is -1, meaning infinite. 0 means no
depth, only root windows will be searched. If you only want toplevel windows, set
maxdepth of 1 (or 2, depending on how your window manager does decorations).
--name
Match against the window name. This is the same string that is displayed in the
window titlebar.
--onlyvisible
Show only visible windows in the results. This means ones with map state
IsViewable.
--pid PID
Match windows that belong to a specific process id. This may not work for some X
applications that do not set this metadata on its windows.
--screen N
Select windows only on a specific screen. Default is to search all screens. Only
meaningful if you have multiple displays and are not using Xinerama.
--desktop N
Only match windows on a certain desktop. 'N' is a number. The default is to
search all desktops.
brandon@brandon-700GR ~ $ xdotool search --desktop 0 xfce4-terminal
Defaulting to search window name, class, and classname
67108868
brandon@brandon-700GR ~ $ xdotool --version
xdotool version 2.20110530.1
brandon@brandon-700GR ~ $ dpkg -l xdotool
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Description
+++-==================-==================-====================================================
ii xdotool 1:2.20110530.1-3ub simulate X11 keyboard/mouse input
brandon@brandon-700GR ~ $
Last edited by caibbor (2012-03-07 18:30:49)
Offline
Old
xdotool version 2.20100701.2961
url: blog.desdelinux.net
twt: @elavdeveloper
Offline
Hi,
Thanks, I found your script very useful.
I'm mostly interested in the showdesktop function but I'm having a couple of issues with it.
1) It's pretty slow -- much slower than the native 'Show Desktop'. Is this do to wmctrl/xdotool/xwininfo/bash? Anything we can do to speed it up?
2) When un-minimizing (lots of) windows it changes the order in which un-focused windows are above one another somewhat randomly. It does properly keep focus on the last focused window though.
3) It un-minimizes all windows. I'd prefer it only un-minimize the windows that it minimized on the previous call.
As a side-note, for anyone on Debian, I had to install xdotool from unstable (the version in testing is too old).
apt-get install -t unstable xdotool
Offline
Very cool! This touches upon the only "fancy" feature I have wanted in xfwin4 itself, a.select/tile/expose, as it is very useful when you have a lot of windows open and just need to find and organize better. Well, I would also love to have rule matching placement like openbox does, too, but devilspie already does that one.
"Information in the computer age is the last genuine free market left on earth except those free markets where indigenous people are still surviving" - Russell Means
Offline
Hello!
I have been looking for similar functions for a while, thank you very much for this great script. I'm using it with openbox and it's cooool!
I have a few remarks anyway:
1) There is one more needed package that you don't mention, namely bc.
2) At line 84, where you call bc, you assume that bc's variable 'scale' is set to 0 (an integral result is required). The man page of bc says that this is the default, but not in my distribution (Archlinux). Thus your script didn't work for me until I understood this. I suggest to replace this line by the following, which will work in every case:
cols=`echo "scale=0 ; sqrt(${#WDOWS[@]})" | bc`
3) I have tiled 6 windows and noticed that the title bar of the bottom windows overlap the top windows. Perhaps this is specific to openbox, but it would be nice (more than nice, it would be fantastic! ) if your script would work with every EWMH compliant window manager, or at least those provided by the most popular desktop managers (gnome, kde, xfce, lxde), don't you think?
4) The grid used when tiling windows does not respect the area in the bottom of my screen occupied by lxpanel : the bottom of the bottom windows is hiden by lxpanel. For seek of generality it would be nice that your script got the ability to guess which areas of the screen must not be covered by the windows, but I can imagine that this can be difficult to determine (a fortiori if you aim at a uniform treatment for every EWMH compliant WM). So what would you think about introducing at the begining of the script four global variables, containing the distance to the four edges of the screen of a rectangular area where the windows must be placed when tiling?
5) Do you plan to develop other functions? I would be glad to have in openbox the same combinations of move/resize functions of the focused window as those provided by the 'grid' plugin of compiz. A video demonstration of these functions is available here (the grid plugin is inspired by winsplit, which unfortunately is a script for windows):
http://www.winsplit-revolution.com/scre … deos-demos
Thanks again!
Last edited by LuX (2012-05-25 09:42:20)
Offline
Caib,
Thanks for posting this handy script!
I'm using it on my Debian Squeeze system.
A word to the wise, however: If you are running Debian Squeeze, your default shell is probably dash. You listed the first line in your script as "#!/bin/bash".
If you are running Squeeze, do not try (as I did) running this script under "#!/bin/sh", as the system will most likely default to the dash shell....which will not run your script correctly.
Bottom line: I recommend all Debian Squeeze users to run your script under bash proper (with a top line of "#!/bin/bash").
Thanks for the great work!
Xfce 4.6.2; Debian Squeeze
Offline
Hello Caibbor,
Complete newbie here, registered about 10 secs ago after about 4 years lurking, getting tips & solutions from reading previous answers ... but today ... I come here simply to give praise !!
This thread might be long-lost and maybe you won't get my comment but anyway I had to say this script is WONDERFUL.
Out the box it had some tasty effects with my triple-monitor set-up so I had to tweak it ... but ... I've now got a totally sexy nest of commands;
>> tile all windows to leftmost screen
>> tile_all_left and maximise one to the middle screen
>> tile_all_left and maximise two to share the middle screen
>> tile_all_left and maximise two to the middle and right screens ... all in all it gives me a similar looking layout to a proper tiling WM (I've installed i3wm and xmonad but just can't make the time-investment to get used to them)
So like I said the script is just WICKED. Thanks ever so much!
I don't know how to get the attention of the xfce developers but to my mind your functionality should be integrated into the core DE!!
And a fringe benefit is that I've learned a lot about stylish coding from reading through your script ... I especially like the way you build up the commands to pass to xdotool and I like the "for command in ${@} ... " block at the bottom, for me as a reader it's an elegant denouement to reach at the end of file. Just about to go see if you've posted any other code !
cheers & best of luck
xxA
Offline
I modifed script a bit, added few more tiling options and option to have gaps. I'll leave it here in case someone finds it useful
winfuncs.sh
Offline
I modifed script a bit, added few more tiling options and option to have gaps. I'll leave it here in case someone finds it useful
winfuncs.sh
Thanks for posting. This script has really taken off with a life of its own.
Please remember to mark your thread [SOLVED] to make it easier for others to find
--- How To Ask For Help | FAQ | Developer Wiki | Community | Contribute ---
Offline
Hi,
Just in case anyone is interested... I added to my winfuncs.sh two more functions.
I was using Openbox for a while, and I really loved the possibilities it brings to resize windows to 55%, 75% or 95% and stuff like that. It's very easy to write those functionalities in Openbox and I really miss those features now on XFCE. So I added a maximize with gaps function, and a resize to 55% function (and 75% too, you can also create your own ones, as it's simply a percentage applied to the same function) so you can turn very fast a big window, into a small-mid one without having to resize dragging on 1px window borders.
Those functions are not tile-related as the original script was but I think it fits the script as it is designed for floating window managers.
Last edited by Reaccion Raul (2021-11-08 20:04:31)
Offline
Thanks for your nice 'on-demand-tiling' - script.
If you like, take a look at xpytile https://github.com/jaywilkas/xpytile/
This pseudo tiling manager is more an approach for automatic tiling and resizing side-by-side windows simultaneously.
Offline
I'd really like to try this script. I can't quite figure out how to do it. I have read that you are supposed to assign a keybinding in the keyboard settings, and the top post has suggested bindings but I am not sure how to put that together. I'm not sure if I have a mod4 key? I wish I had more modifiers.
How do you set up the keybinding so it will do different things in one script?
I tried looking in the file but it is over my head to work it out.
If I get enough information to make sense of it, I will try to create some more accessible descriptions.
Thanks for any insight.
Offline
[ Generated in 0.021 seconds, 7 queries executed - Memory usage: 712.63 KiB (Peak: 761.48 KiB) ]