Efficient Resizing (what's wrong!?)

Ok, so I don’t like how you can only resize with respect to one particular edge/corner of the window. I want a resize function that detects which edge you are closest to and resizes in that direction. That is what the following functions accomplish. Unfortunately, this method is quite a bit laggy. I also use ResizeOpaque on almost all my windows, and with this MyResize function the window that you are resizing does not refresh very well during the resize.

Any ideas on how I can make this more efficient?

[code]DestroyFunc MyResize
AddToFunc MyResize
#+ I resize direction SE

  • I PipeRead
    ‘if [ $[pointer.wx] -lt $(($[w.width]/3)) ]; then
    echo ResizeLeft;
    elif [ $[pointer.wx] -lt $((2*$[w.width]/3)) ]; then
    echo ResizeMiddle;
    else echo ResizeRight; fi’
  • I Resize $[direction]

– helper functions

DestroyFunc ResizeLeft
AddToFunc ResizeLeft

  • I PipeRead
    ‘if [ $[pointer.wy] -lt $(($[w.height]/3)) ]; then
    echo CursorStyle RESIZE top_left_corner;
    echo SetEnv direction ‘“direction NW”’;
    elif [ $[pointer.wy] -lt $((2*$[w.height]/3)) ]; then
    echo CursorStyle RESIZE left_side;
    echo SetEnv direction ‘“direction W”’;
    else echo CursorStyle RESIZE bottom_left_corner;
    echo SetEnv direction ‘“direction SW”’; fi’

DestroyFunc ResizeMiddle
AddToFunc ResizeMiddle

  • I PipeRead
    ‘if [ $[pointer.wy] -lt $(($[w.height]/3)) ]; then
    echo CursorStyle RESIZE top_side;
    echo SetEnv direction ‘“direction N”’;
    elif [ $[pointer.wy] -lt $((2*$[w.height]/3)) ]; then
    echo CursorStyle RESIZE cross;
    echo SetEnv direction;
    else echo CursorStyle RESIZE bottom_side;
    echo SetEnv direction ‘“direction S”’; fi’

DestroyFunc ResizeRight
AddToFunc ResizeRight

  • I PipeRead
    ‘if [ $[pointer.wy] -lt $(($[w.height]/3)) ]; then
    echo CursorStyle RESIZE top_right_corner;
    echo SetEnv direction ‘“direction NE”’;
    elif [ $[pointer.wy] -lt $((2*$[w.height]/3)) ]; then
    echo CursorStyle RESIZE right_side;
    echo SetEnv direction ‘“direction E”’;
    else echo CursorStyle RESIZE bottom_right_corner;
    echo SetEnv direction ‘“direction SE”’; fi’[/code]

Hmm, that’s ugly (no offense – not your fault). But it’s about as good as you’re going to get. I’m not quite sure though why you’re using the functions – one can resize a window anywhere, as long as you have a decent HandleWidth so that you can see where the edges are… :slight_smile:

– Thomas Adam

Yeah, but I don’t want to manually move to the edge of the window to resize, that’s annoying. Almost every window manager out there allows for a Alt + Mouse behavior that allows you to resize a window from anywhere in that window. It automatically determines which edge you are closer to and (without warping the pointer) resizes relative to that edge. I think it’s pretty sad that fvwm does not have a similar feature, and this was my attempt to add that feature.

Edit: Seriously, name one window manager out there that is more popular than FVWM and does NOT have this feature!

So, there is a very good reason for doing this.

  • Phil

I’ve just been trying to do the same thing. Frankly large borders look crap and small borders are too fricken hard to grab :wink:
I didn’t try your script verbatim, so I haven’t experienced the exact lag issue you are having. I did have a POS laggy resizing function at one point, I think it was when I had a Resize command coming directly from PipeRead instead of doing a SetEnv… or maybe it was when I was invoking said PipeRead on Immediate, Hold and Move.
I dunno, having been through a couple of lame incarnations where resizing started on button click (as opposed to button press), or the window snapped back to its original position unless I confirmed the resize by pressing Mouse1 I’m not sure which variable affects what anymore.
But, I ended up with some functions which seem to do the job - resizing starts on the mouse press, and stops when you release the button. Not laggy - or at least I couldn’t notice any difference between using the function and using just ‘Resize direction se’. Yes, I remembered to restart fvwm after changing the config :P. I’m using ResizeOpaque. Here it is:

[code]# Bind the function to alt + right button
Mouse 3 W 1 FuncResize

DestroyFunc FuncResize
AddToFunc FuncResize

  • I FuncResizeDir
  • M Resize direction $[direction]

Sets the direction

DestroyFunc FuncResizeDir
AddToFunc FuncResizeDir

  • I PipeRead
    ‘if [ $[pointer.wx] -lt $(($[w.width]/2)) ]; then
    if [ $[pointer.wy] -lt $(($[w.height]/2)) ]; then
    echo SetEnv direction nw;
    echo SetEnv direction sw;
    if [ $[pointer.wy] -lt $(($[w.height]/2)) ]; then
    echo SetEnv direction ne;
    echo SetEnv direction se;

So, compared to your function, mine just does the four corners (I don’t really care for pure horizontal/vertical resizing), and doesn’t change the cursor (which doesn’t really bother me… yet). I don’t know if either of those complexities are causing the lagginess, but other than that I can see two differences:[list][]You’re calling the resize Immediately, I’m calling on Movement[/:m]
[]You have two PipeReads, I have one[/:m][/list:u]

Blablabla, I’ve probably talked enough crap - thanks for posting the sample, it would have taken me far longer to create the PipeRead script from scratch (/me is a fvwm newbie). I hope you can get it working nicely on your end aswell :slight_smile:

I moved the computations into a C programs (seems unnecessary, but it works), and now it runs efficiently.

The fvwm code looks like this now:

[code]DestroyFunc MyResize
AddToFunc MyResize

  • I PipeRead echo $[pointer.wx] $[pointer.wy] $[w.width] $[w.height] | $[BIN]/myresize[/code]

And the C program is like this:

[code]// ------------------------------------------------------
// myresize.cxx
// takes in pointer.wx, pointer.wy, w.width, and w.height
// from fvwm, then prints out a command to resize
// to nearest corner/edge of window
// -------------------------------------------------------

// arguments are passed in through stdin in this order:
// pointer.wx, pointer.wy, w.width, w.height

#include <stdio.h>
#include <stdlib.h>

//#define DEBUG

// pointer.wx, pointer.wy, w.width, w.height:
int pwx, pwy, width, height;

enum vertical { TOP, MIDDLE, BOTTOM };
enum horizontal { LEFT, CENTER, RIGHT };

// calculate distance between pwx, pwy and x,y
// where x and y are per_x% and per_y% across the width and height of the window
// don’t bother square rooting, since we’re just comparing them
int distance(int per_x, int per_y) {

int x = per_x * width / 100;
int y = per_y * height / 100;

int dx = x - pwx;
int dy = y - pwy;

return dxdx + dydy;

int main() {

// read variables in from standard in
scanf("%i %i %i %i", &pwx, &pwy, &width, &height);

#ifdef DEBUG
printf(“echo %i %i %i %i\n”, pwx, pwy, width, height);;

// calculate distance to each edge and corner from pointer
// northeast, north, northwest, west, east, etc…

int d_NW = distance(0,0);
int d_W = distance(0,50);
int d_SW = distance(0,100);

int d_N = distance(50,0);
int d_S = distance(50,100);

int d_NE = distance(100,0);
int d_E = distance(100,50);
int d_SE = distance(100,100);

char* direction;
char* cursor_style;

int min_distance = d_NW;
direction = “NW”;
cursor_style = “top_left_corner”;

if (d_NE < min_distance) {
min_distance = d_NE;
direction = “NE”;
cursor_style = “top_right_corner”;

if (d_SW < min_distance) {
min_distance = d_SW;
direction = “SW”;
cursor_style = “bottom_left_corner”;

if (d_SE < min_distance) {
min_distance = d_SE;
direction = “SE”;
cursor_style = “bottom_right_corner”;

if (d_W < min_distance/2) {
min_distance = d_W;
direction = “W”;
cursor_style = “left_side”;

if (d_E < min_distance/2) {
min_distance = d_E;
direction = “E”;
cursor_style = “right_side”;

if (d_S < min_distance/2) {
min_distance = d_S;
direction = “S”;
cursor_style = “bottom_side”;

if (d_N < min_distance/2) {
min_distance = d_N;
direction = “N”;
cursor_style = “top_side”;

printf(“CursorStyle RESIZE %s\n”, cursor_style);
printf(“Resize direction %s\n”, direction);
printf(“CursorStyle RESIZE\n”);

Then compile it:

g++ -c myresize.cxx -O3 g++ -o myresize myresize.o -O3