Xfce Forum

Sub domains
 

You are not logged in.

#1 2012-02-24 22:00:28

caibbor
Member
Registered: 2012-02-08
Posts: 11

New Script: Tile, Cascade, Expose' Windows, etc

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

#2 2012-02-25 16:32:32

wkr
Member
Registered: 2011-01-01
Posts: 88

Re: New Script: Tile, Cascade, Expose' Windows, etc

It works perfectly. Many thanks.

Offline

#3 2012-02-25 18:05:07

xfcelav
Member
From: /var/www/xfcelav
Registered: 2008-04-10
Posts: 94
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#4 2012-02-25 20:29:06

caibbor
Member
Registered: 2012-02-08
Posts: 11

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#5 2012-02-26 05:31:51

caibbor
Member
Registered: 2012-02-08
Posts: 11

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#6 2012-02-27 12:42:55

xfcelav
Member
From: /var/www/xfcelav
Registered: 2008-04-10
Posts: 94
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#7 2012-02-27 14:56:55

wkr
Member
Registered: 2011-01-01
Posts: 88

Re: New Script: Tile, Cascade, Expose' Windows, etc

Perhaps, have you forgot to add 'tile' (or select and so) after /usr/share/bin/winfun.sh ?

Offline

#8 2012-02-27 16:20:49

xfcelav
Member
From: /var/www/xfcelav
Registered: 2008-04-10
Posts: 94
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

Nop. I add tile and not work!!


url: blog.desdelinux.net
twt: @elavdeveloper

Offline

#9 2012-02-29 18:07:46

caibbor
Member
Registered: 2012-02-08
Posts: 11

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#10 2012-02-29 19:49:51

xfcelav
Member
From: /var/www/xfcelav
Registered: 2008-04-10
Posts: 94
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#11 2012-02-29 21:38:40

caibbor
Member
Registered: 2012-02-08
Posts: 11

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#12 2012-03-01 15:03:54

caibbor
Member
Registered: 2012-02-08
Posts: 11

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#13 2012-03-01 18:46:12

xfcelav
Member
From: /var/www/xfcelav
Registered: 2008-04-10
Posts: 94
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#14 2012-03-07 18:29:20

caibbor
Member
Registered: 2012-02-08
Posts: 11

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#15 2012-03-07 18:39:17

xfcelav
Member
From: /var/www/xfcelav
Registered: 2008-04-10
Posts: 94
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

Old

xdotool version 2.20100701.2961

url: blog.desdelinux.net
twt: @elavdeveloper

Offline

#16 2012-05-07 12:55:50

rudametw
Member
Registered: 2012-05-07
Posts: 4

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#17 2012-05-24 13:11:17

dyfet
Member
From: Cape May
Registered: 2011-05-28
Posts: 13
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

#18 2012-05-25 00:17:14

LuX
Member
Registered: 2012-05-24
Posts: 1

Re: New Script: Tile, Cascade, Expose' Windows, etc

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! cool
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! lol) 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

#19 2013-03-30 16:32:28

Digger
Member
Registered: 2012-01-18
Posts: 23
Website

Re: New Script: Tile, Cascade, Expose' Windows, etc

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

Board footer

Powered by FluxBB