MoveToEdge function

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 … :slight_smile:

[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 :slight_smile: :slight_smile:

GI

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 :slight_smile:. I also wrote a few extras implementing centering windows / a showdesktop mode. Bind to keystrokes as described in the comments below, and enjoy :slight_smile:

[code]# Created : Sat 07 May 2005 02:21:32 PM CDT

Modified : Thu 15 Dec 2005 05:12:38 PM CST

Author : Gautam Iyer gautam@math.uchicago.edu

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

  • I Iconify False

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 :slight_smile:

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 :slight_smile:

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]