I have been bothered by a situation where I create a window and manually
place it at one location, but the window actually appears in a different
location.  It is easy to reproduce with a very small .fvwm2rc:

    Style * ManualPlacement
    EdgeResistance 0 100

Start by placing an xterm in the lower right corner of the screen,
touching the side and bottom.  Place the mouse near the upper left
corner of the window, within the window.  Type "xterm" and press enter.
You will see the new window outline appear exactly over the border of
the first xterm; that is, it appears snapped to the edges of the screen.
Press enter to place the window.  Note that it is placed not where the
outline was, but at the pointer position.

I investigated the code in __move_loop, in move_resize.c.  (I am using
fvwm 2.5.16, but the file is identical in the 20060529 snapshot I just
checked).  The problem is that in "case ButtonRelease" (line 2445),
there is a test that says if the mouse is in the same position it
started in, don't apply the snap.  This idea is that if the mouse didn't
move, the outline never snapped, so the window shouldn't snap either.
This is an ill-conceived test for two reasons.  One, the mouse could
have moved and moved back to its original position!  It's not actually
that hard to achieve this.  Two, there are cases other than mouse
movement that causes the window outline to snap.  For example, if an
EnterNotify or LeaveNotify event is received (2301), a MotionNotify
event is faked up, and in "case MotionNotify" (2483), DoSnapAttract is
called to snap the outline.  This is in fact what happens in the test
case above.

However, it is not always the case that the initial outline is snapped.
If there were not already a window below the mouse when I ran xterm, no
EnterNotify event would have been received, and thus the outline would
have appeared unsnapped, at the pointer.  This inconsistency is cause of
further confusion to the user:  Why does the outline initially appear
snapped sometimes and not other times?

To resolve this issue, we must 1. decide whether the outline should
initially appear snapped or unsnapped; 2. ensure that the outline in
fact initially appears snapped or unsnapped consistently; 3. ensure that
the window gets placed where the outline appeared.

I took what seems to be the simplest approach (a necessity for me, given
the serpentine nature of this function), which is also the behavior I
find the most natural:  I decided that the outline should always start
out snapped.  It is only a couple of lines to snap the outline at the
top of the function, and then unconditionally snap on ButtonRelease.
The below patch Works For Me.

Andrew

PS.  Please Cc: me, as I am not subscribed.

--- move_resize.c.orig  2006-05-29 14:15:16.000000000 -0700
+++ move_resize.c       2006-05-29 14:18:37.000000000 -0700
@@ -2197,6 +2197,10 @@
        xl_orig = xl;
        yt_orig = yt;
 
+       /* Without this, the outline sometimes initially shows snapped,
+        * sometimes unsnapped.  At least this is consistent. */
+       DoSnapAttract(fw, Width, Height, &xl, &yt);
+
        /* draw initial outline */
        if (!IS_ICONIFIED(fw) &&
            ((!do_move_opaque && !Scr.gs.do_emulate_mwm) || !IS_MAPPED(fw)))
@@ -2463,15 +2467,9 @@
                                xl = xl2;
                                yt = yt2;
                        }
-                       if (xl != xl_orig || yt != yt_orig || vx != Scr.Vx ||
-                           vy != Scr.Vy)
+                       if (do_snap)
                        {
-                               /* only snap if the window actually moved! */
-                               if (do_snap)
-                               {
-                                       DoSnapAttract(
-                                               fw, Width, Height, &xl, &yt);
-                               }
+                               DoSnapAttract(fw, Width, Height, &xl, &yt);
                        }
 
                        *FinalX = xl;


Reply via email to