Hi All,
I was wondering if anyone knows how to implement a “MoveToEdge” function? I’d like to have a keyboard shortcut (CTRL-J, let’s say) so that when I press Control J in Window context it moves the current window so that the bottom edge of the current window coincides with the top edge of the nearest window below?
I’ve been using OpenBox for a while … and really miss this feature.
Thanks in advance,
GI
PS: I just switched to fvwm. I like it a lot so far. I’ve spent a day and a half writing my config file though …
[color=red]Edited by theBlackDragon:
–> Moved from Basic questions[/color]
You mean like the following functions?
DestroyFunc PackWindowUp
AddToFunc PackWindowUp
+ I SetEnv low_w 0
+ I WindowId $3 Raise
+ I All (CurrentPage !Iconic AcceptsFocus \
!Shaded) PipeRead "test `expr $[w.y] + $[w.height]` -gt $[low_w] \
-a `expr $[w.y] + $[w.height]` -lt $0 \
-a \\( \\( $[w.x] -gt $1 -a $[w.x] -lt `expr $1 + $2` \\) \
-o \\( $1 -gt $[w.x] -a $1 -lt `expr $[w.x] + $[w.width]` \\) \
-o \\( $1 -le $[w.x] -a `expr $1 + $2` -ge `expr $[w.x] + $[w.width]` \\) \
-o \\( $[w.x] -lt $1 -a `expr $[w.x] + $[w.width]` -gt `expr $1 + $2` \\) \
\\) \
&& echo SetEnv low_w `expr $[w.y] + $[w.height]` \
|| echo Nop"
+ I WindowId $3 AnimatedMove keep $[low_w]p
#+ I WindowId $3 RefreshWindow
AddToFunc PackWrapperUp I NoWindow PackWindowUp $[w.y] $[w.x] $[w.width] $[w.id]
#####
# Name: PackWindowDown
# Bound: Alt+Shift+Down When a window is active.
# Purpose: See PackWindowUp.
#
#################
DestroyFunc PackWindowDown
AddToFunc PackWindowDown
+ I SetEnv high_w $[vp.height]
+ I WindowId $3 Raise
+ I All (CurrentPage !Iconic AcceptsFocus \
!Shaded) PipeRead "test $[w.y] -lt $[high_w] \
-a $[w.y] -gt `expr $0 + $4` \
-a \\( \\( $[w.x] -gt $1 -a $[w.x] -lt `expr $1 + $2` \\) \
-o \\( $1 -gt $[w.x] -a $1 -lt `expr $[w.x] + $[w.width]` \\) \
-o \\( $1 -le $[w.x] -a `expr $1 + $2` -ge `expr $[w.x] + $[w.width]` \\) \
-o \\( $[w.x] -lt $1 -a `expr $[w.x] + $[w.width]` -gt `expr $1 + $2` \\) \
\\) \
&& echo SetEnv high_w $[w.y] \
|| echo Nop"
+ I PipeRead "echo WindowId $3 AnimatedMove keep `expr $[high_w] - $4`p"
#+ I WindowId $3 RefreshWindow
AddToFunc PackWrapperDown I NoWindow PackWindowDown $[w.y] $[w.x] $[w.width] $[w.id] $[w.height]
#####
# Name: PackWindowLeft
# Bound: Alt+Shift+Left When a window is active
# Purpose: See PackWindowUp.
#
# The Logic works likes this:
# 1. Set Destination to the Left Edge
# 2. For every window, Run these tests:
# + Is the Window's Right edge further _Right_ than furthest edge seen yet?
# And: + Is it's Right edge Further _Left_ than Target Windows Left edge? (ie,
#in the way)
# Yes:
# + Does the window start inside Target Window, and end below?
# Or + Does it start above, and end inside?
# Or + Is it the same vertical position/height/size, or start inside and
#end inside?
# Or + Does it start above, and end below?
# Yes:
# This is the new Destination.
# No:
# Nop
# No:
# Nop
# 3. Move to Destination.
#
#################
DestroyFunc PackWindowLeft
AddToFunc PackWindowLeft
+ I SetEnv left_w 0
+ I WindowId $3 Raise
+ I All (CurrentPage !Iconic AcceptsFocus \
!Shaded) PipeRead "test `expr $[w.x] + $[w.width]` -gt $[left_w] \
-a `expr $[w.x] + $[w.width]` -lt $1 \
-a \\( \\( $[w.y] -gt $0 -a $[w.y] -lt `expr $0 + $4` \\) \
-o \\( $[w.y] -lt $0 -a `expr $[w.y] + $[w.height]` -gt $0 \\) \
-o \\( $[w.y] -ge $0 -a `expr $[w.y] + $[w.height]` -le `expr $0 + $4` \\) \
-o \\( $[w.y] -lt $0 -a `expr $[w.y] + $[w.height]` -gt `expr $0 + $4` \\) \
\\) \
&& echo SetEnv left_w `expr $[w.x] + $[w.width]` \
|| echo Nop"
+ I WindowId $3 AnimatedMove $[left_w]p keep
#+ I WindowId $3 RefreshWindow
AddToFunc PackWrapperLeft I NoWindow PackWindowLeft $[w.y] $[w.x] $[w.width] $[w.id] $[w.height]
DestroyFunc PackWindowRight
AddToFunc PackWindowRight
+ I SetEnv right_w $[vp.width]
+ I WindowId $3 Raise
+ I All (CurrentPage !Iconic AcceptsFocus \
!Shaded) PipeRead "test $[w.x] -lt $[right_w] \
-a $[w.x] -gt `expr $1 + $2` \
-a \\( \\( $[w.y] -gt $0 -a $[w.y] -lt `expr $0 + $4` \\) \
-o \\( $[w.y] -lt $0 -a `expr $[w.y] + $[w.height]` -gt $0 \\) \
-o \\( $[w.y] -ge $0 -a `expr $[w.y] + $[w.height]` -le `expr $0 + $4` \\) \
-o \\( $[w.y] -lt $0 -a `expr $[w.y] + $[w.height]` -gt `expr $0 + $4` \\) \
\\) \
&& echo SetEnv right_w $[w.x] \
|| echo Nop"
+ I PipeRead "echo WindowId $3 AnimatedMove `expr $[right_w] - $2`p keep"
#+ I WindowId $3 RefreshWindow
AddToFunc PackWrapperRight I NoWindow PackWindowRight $[w.y] $[w.x] $[w.width] $[w.id] $[w.height]
You can then bind each function for left, right, up and down as appropriate. I use the following (CTRL+windowskey+arrowkey):
Key Up WTSF C3 PackWrapperUp
Key Down WTSF C3 PackWrapperDown
Key Left WTSF C3 PackWrapperLeft
Key Right WTSF C3 PackWrapperRight
– Thomas Adam
Ooh. Super thanks. Just what I was looking for
GI
gi1242
16 December 2005 00:14
4
After about a year I realized that the above functions are pretty slow on my computer. Mainly because they exec some three or four shells, and on my outdated machine I get a busy cursor for half a second or so. It’s not too nice when I perform these operations repeatedly.
I reimplemented these functions using FvwmPerl. They now run super quick. Code below . I also wrote a few extras implementing centering windows / a showdesktop mode. Bind to keystrokes as described in the comments below, and enjoy
[code]# Created : Sat 07 May 2005 02:21:32 PM CDT
Modified : Thu 15 Dec 2005 05:12:38 PM CST
Description : Implement a few usefull window operations using FvwmPerl.
Functions:
ToggleShowDesktop
Show / Hide desktop by hiding/restoring all windows
PackLeft, PackRight, PackUp, PackDown
Move window till it hits the nearest edge in the appropriate direction.
CenterWindow
Center the window.
Either read this file from a running fvwm, or Read it after defining
StartFunction from your .fvwm/config.
We use FvwmPerl aliased as perlwops for these functions. As long as you don’t
mess with the global array @a , you can use this module for whatever you feel
like.
BUGS
Fvwm doesn’t seem to negate “Layer n” correctly. As a workaround we
manually hide all windows in layers 3 – 6.
Show/Hide desktop functions
We use the global array @a , to store the window id’s of hidden windows The
reason we have to resort to FvwmPerl is while restoring the desktop, we need
to restore windows in the reverse order we hid them in. I’ve no idea how to
do this using just an fvwm script.
Use this as the bottom layer (windows to leave untouched).
SetEnv BottomLayer 2
DestroyFunc ToggleShowDesktop
AddToFunc ToggleShowDesktop
I SendToModule perlwops eval cmd( scalar( @a ) ? “RestoreDesktop” : “ShowDesktop” )
Hidden windows are pushed onto a window stack (@a ).
DestroyFunc HideWindow
AddToFunc HideWindow
I SendToModule perlwops eval push( @a , “$[w.id]”);
I WindowStyle NoIcon, NoIconTitle
I Iconify True
DestroyFunc RestoreWindow
AddToFunc RestoreWindow
Leave everything on Layer 2 and below untouched
DestroyFunc ShowDesktop
AddToFunc ShowDesktop
I SendToModule FvwmAnimate push pause
I SendToModule perlwops eval @a = ()
I All (!Iconic, !Shaded, Layer 6) HideWindow
I All (!Iconic, !Shaded, Layer 5) HideWindow
I All (!Iconic, !Shaded, Layer 4) HideWindow
I All (!Iconic, !Shaded, Layer 3) HideWindow
2005-12-14: Some bug in fvwm-2.5.12 causes All( !Layer 2) to return no
windows. As a workaround call this function in window context to hide all
windows on that Layer.
+ I All (!Iconic, !Layer $[BottomLayer]) HideWindow
I SendToModule FvwmAnimate pop
DestroyFunc RestoreDesktop
AddToFunc RestoreDesktop
I SendToModule FvwmAnimate push pause
I SendToModule perlwops eval cmd( “WindowId “.pop(@a ).” RestoreWindow”) while(@a );
I SendToModule FvwmAnimate pop
Openbox style MoveToEdge functions.
GetCoords: Get the window coordinates in @b . Each array element is a hash
refference with keys x, y, width and height. This function MUST be called in
NoWindow context.
2005-12-15 BUG: Fvwm really doesn’t like Layer selection. In window context
All (Layer) doesnt’ give the desired result. Short story – We can’t only
grab the coordinates of windows on the current window’s layer. Workaround:
Grab coordinates from every damn window that accepts focus
DestroyFunc GetCoords
AddToFunc GetCoords
I SendToModule FvwmPerl eval @b=();
I All (CurrentPage, !Iconic, !Shaded, AcceptsFocus) SendToModule perlwops eval
push( @b , {x=>$[w.x], y=>$[w.y], width=>$[w.width], height=>$[w.height]});
Variables like $new get kindly substituted by fvwm to [window name]ew. If
this was in the docs I’d have saved 30 mins debugging this crap
Start with NEWX=0. Loop over all windows, and set NEWX to the window right
edge if the window is “blocking” this one. Move to NEWX. If the window starts
with it’s left edge to the left of the screen, then do nothing.
Replace Move below with AnimatedMove if you like.
DestroyFunc PackLeft
AddToFunc PackLeft
I NoWindow GetCoords
I SendToModule perlwops eval
my ($NEWX, $WIN) = (0, undef);
foreach $WIN (@b ) {
$NEWX = $WIN->{x}+$WIN->{width}
if( $NEWX < $WIN->{x}+$WIN->{width}
&& $WIN->{x}+$WIN->{width} < $[w.x]
&& (
($WIN->{y} >= $[w.y] && $WIN->{y} <= $[w.y] + $[w.height])
|| ($WIN->{y}+$WIN->{height} >= $[w.y]
&& $WIN->{y}+$WIN->{height} <= $[w.y]+$[w.height])
)
)
;
};
cmd( “WindowId $[w.id] Move +${NEWX}p w0”) if( $NEWX < $[w.x]);
Same as before, exept start with the right edge of the screen
DestroyFunc PackRight
AddToFunc PackRight
I NoWindow GetCoords
I SendToModule perlwops eval
my $DWIDTH = $[desk.width] / $[desk.pagesx];
my ($NEWX, $WIN) = ($DWIDTH, undef);
foreach $WIN (@b ) {
$NEWX = $WIN->{x}
if( $NEWX > $WIN->{x} && $WIN->{x} > $[w.x] + $[w.width]
&& (
($WIN->{y} >= $[w.y] && $WIN->{y} <= $[w.y] + $[w.height])
|| ($WIN->{y}+$WIN->{height} >= $[w.y]
&& $WIN->{y}+$WIN->{height} <= $[w.y]+$[w.height])
)
)
;
};
cmd( “WindowId $[w.id] Move +” . ($NEWX-$[w.width]) . “p w0”)
if( $NEWX-$[w.width] > $[w.x] );
DestroyFunc PackUp
AddToFunc PackUp
I NoWindow GetCoords
I SendToModule perlwops eval
my ($NEWY, $WIN) = (0, undef);
foreach $WIN (@b ) {
$NEWY = $WIN->{y}+$WIN->{height}
if( $NEWY < $WIN->{y}+$WIN->{height}
&& $WIN->{y}+$WIN->{height} < $[w.y]
&& (
($WIN->{x} >= $[w.x] && $WIN->{x} <= $[w.x] + $[w.width])
|| ($WIN->{x}+$WIN->{width} >= $[w.x]
&& $WIN->{x}+$WIN->{width} <= $[w.x]+$[w.width])
)
)
;
};
cmd( “WindowId $[w.id] Move w0 +${NEWY}p”) if( $NEWY < $[w.y]);
DestroyFunc PackDown
AddToFunc PackDown
I NoWindow GetCoords
I SendToModule perlwops eval
my $DHEIGHT = $[desk.height] / $[desk.pagesy];
my ($NEWY, $WIN) = ($DHEIGHT, undef);
foreach $WIN (@b ) {
$NEWY = $WIN->{y}
if( $NEWY > $WIN->{y} && $WIN->{y} > $[w.y] + $[w.height]
&& (
($WIN->{x} >= $[w.x] && $WIN->{x} <= $[w.x] + $[w.width])
|| ($WIN->{x}+$WIN->{width} >= $[w.x]
&& $WIN->{x}+$WIN->{width} <= $[w.x]+$[w.width])
)
)
;
};
cmd( “WindowId $[w.id] Move w0 +” . (${NEWY}-$[w.height]) . “p”)
if( $NEWY-$[w.height] > $[w.y]);
DestroyFunc CenterWindow
AddToFunc CenterWindow
+ I WindowStyle CenterPlacement
+ I PlaceAgain
+ I UpdateStyles
+ I WindowStyle MinOverlapPlacement
Perl implementation
DestroyFunc CenterWindow
AddToFunc CenterWindow
I SendToModule perlwops preprocess -c WindowId $[w.id] Move
+%{ ($[desk.width] / $[desk.pagesx] - $[w.width])/2 }%p
+%{ ($[desk.height] / $[desk.pagesy] - $[w.height])/2 }%p
Test (Start) AddToFunc StartFunction I Module FvwmPerl perlwops
Test (!Start) KillModule FvwmPerl perlwops
Test (!Start) Module FvwmPerl perlwops[/code]