Subject: moving windows with the keyboard across pages

From: Dan Espen <[email-masked]>
Date: Tue, 02 Jan 2001 14:17:05 -0500

I have:

Key F7		A	M	Move
EdgeResistance 500 1
EdgeScroll 100 100

When I move a  window using the keyboard to  the point where the mouse
cursor would cross  the screen edge, the  window starts to bounce back
and forth.  If I'm  lucky   and leave the  window   alone, for a   few
seconds, it will sometimes cross the page.

If I set the EdgeResistance to "0 0"  the window moves smoothly across
the screen edge.

I  don't think EdgeResistance   should have any  effect  on a keyboard
controlled move.

-- 
Dan Espen
444 Hoes Lane  Room RRC 1C-214             E-mail: [email-masked]
Piscataway, NJ 08854                       Phone: (732) 699-5570
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 3 Jan 2001 19:46:57 +0100

> If I set the EdgeResistance to "0 0"  the window moves smoothly across

The fvwmlib_keyboard_shortcuts() function generated a MotionNotify
when you hit the screen edge, although the pointer was not moved
at all.  Suppressing these superflous events prevents this window
bouncing effect.  Furthermore, if you moved the pointer to the
edge (keyboard), then back one step (bigger than the pan frame
thickness) then back to the border again, paging was disabled
completely, which may explain that old outstanding bug report with
netscape windows refusing to move over the edge.  This was because
the code checked if the pointer was in the pan frame before paging
but left the LeaveNotify for the pan frame in the queue.  This was
read in the next pass through HandlePaging() and messed up the
static state of this function.

> I  don't think EdgeResistance   should have any  effect  on a keyboard

But is must have an effect.  At least it must honour if paging
is possible at all.  Anyway, removing the delay for keyboard
driven motion is too complex to do this right now.

Bye

Dominik ^_^  ^_^

--
Dominik Vogt, [email-masked]
Reply-To: [email-masked]
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Dan Espen <[email-masked]>
Date: Wed, 03 Jan 2001 16:11:56 -0500

> static state of this function.

Despite the comment  in  the code, I  didn't think  there was anything
important in Keyboard_shortcuts() and hadn't looked there yet.

Its better but not good yet.

I  don't see any bouncing,  but there are  times when  the window just
won't cross the screen edge.   It seems to   have something to do with
windows covering the  panframes.  Or maybe its  crossing  the edge and
coming back again.  It seems more common moving up than down.

> driven motion is too complex to do this right now.

I see your point, if there is going to be a page flip, I guess it
should resist.

---

From: Dominik Vogt <[email-masked]>
Date: Thu, 4 Jan 2001 23:26:22 +0100

> coming back again.  It seems more common moving up than down.

Can you pin that down?  Just by playing with the keyboard
shortcuts I found one of these problems, but fixed it in my last
commit.  I grepped through the code for XRaiseWindow() and
XRestackWindows() calls but could not find any place where a
window might be raised over the pan frames where the pan frames
are not raised to the top soon after.

Bye

Dominik ^_^  ^_^

---

From: Dan Espen <[email-masked]>
Date: Thu, 04 Jan 2001 19:19:56 -0500

> are not raised to the top soon after.

If you mean your most recent commit, I didn't see any of the relevant
files change.

I tried, but couldn't find a consistent action that caused the problem.
I'm at home now, until Monday.

I just  tried  to reproduce  this  at home  with  my Exceed setup  and
current CVS.    I still had problems moving   windows over  the screen
edges...

Oh, maybe I've got it.

When I move a window with the keyboard, the pointer  can move ahead of
the window.  If I hold down the arrow  key, the pointer will move more
than the window.  When I release the key, the window catches up.

It looks like the window gets hung up when I  use the keyboard to move
the mouse pointer  into the screen edge.  After  I do  that, no matter
how many times I hit the arrow key the paging  won't take place.  If I
move backward and then  toward the screen edge  again, the paging will
take place.  If  I  use the  arrow  keys  to move  90 degrees  to  the
original direction, it will also page.

To reproduce this it might help to use a big window so that the repeat
rate on your keys will out pace the window redraws.

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 5 Jan 2001 19:36:42 +0100

> If you mean your most recent commit, I didn't see any of the relevant

I think you're mixing up my mails.  The debug fprintfs in
events.c, icons.c and add_window.c are related to the xemacs live
icon problem.

> original direction, it will also page.

Try as I might, I can't reproduce this.  I slowed down my machine
until X dumped core, but I can still cross page boundaries
(although sometimes I see the moved window flipping between the
positions on the old page and the new page a few times).  To debug
this you should put an fprintf before each 'return' in the
HandlePaging() function.  Then look at the output when paging is
disabled.  It should be easy from there to identify the reason why
paging does not take place.

Bye

Dominik ^_^  ^_^

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 5 Jan 2001 19:36:42 +0100

Bye

Dominik ^_^  ^_^

---

From: Dan Espen <[email-masked]>
Date: Fri, 05 Jan 2001 16:20:48 -0500

> paging does not take place.

Can you get the mouse pointer to move faster than the window itself?

I did what you suggested.

Most normal moving is associated with the fprintf I added around
line 447 where it gets the pointer location.

When it won't move anymore, it executes the first return
statement around line 379.

The logic around line 464 never gets executed.
This is the code with the comment, "the pointer is moving too fast".
That looks suspicious, since the pointer is not moving, except that
fvwm moves it in response to keyboard events.

Its strange that fvwm moves the pointer before it moves the window.
I guess the idea is to move the pointer, and from then on make the
rest of the logic only worry about the pointer.  If thats the case,
it doesn't seem to be able to get into the "too fast" logic
from the keyboard.

I did make it go into the "too fast" logic using the mouse.

---

From: Dominik Vogt <[email-masked]>
Date: Sat, 6 Jan 2001 14:18:49 +0100

> Can you get the mouse pointer to move faster than the window itself?

It's very difficult on a local X server, but I could by mapping
55 rxvts with a pixmap background.

> statement around line 379.

Hm, line 379 belongs to the second return, but I think you are
talking about this code:

  /* Only continue to count the time, but do not start counting from
   * scratch. */
  if (!is_timestamp_valid && do_continue_previous)
  {
    /* Free some CPU */
    usleep(10000);
    return False;
  }

The is_timestamp_valid flag is basically set when the pointer
enters a pan frame and reset when the pointer leaves the pan
frames.  The do_continue_previous parameter tells HandlePaging to
continue counting time as long as the pointer is over the pan
frames.  Obviously this only makey sense if the pointer is already
there.
In moveLoop(), HandlePaging() is called twice.  Once while waiting
for events with do_continue_previous set.  This takes care of
paging while the pointer does not move.  When a motion is
started, the is_timestamp_valid is not set, so the HandlePaging()
calls will do nothing at first.  The second call is down in the
MotionNotify code and has the do_continue_previous flag unset.  So
this code can start paging by setting the is_timestamp_valid flag
(i.e. paging can only take place after at least one MotionNotify
event).
Now, I think somehow is_timestamp_valid is unset when the pointer
hits the screen edge.  Because of my change in
fvwmlib_keyboard_shortcuts() no MotionNotify event will be
generated anymore if the pointer does not move.  Hence
HandlePaging() will always be called with do_continue_previous set
and is_timestamp_valid unset, so it will always bag out at the
first return.
I think the fix is to generate even +/- 0 motion events.  Although
that appears to negate the benefit of my last changes in
fvwmlib_keyboard_shortcuts(), there is a difference: in the past,
when the pointer was at (1, y) and you hit shift-left, the pointer
would travel 100 pixels to the left.  The generated event
contained the new position (-99, y) which is nonsense.  With my
latest patch it will have (0, y), even if it started at (0, y).

Before you test that patch, can you please try out and see where
the is_timestamp_valid flag is unset right before you get stuck on
the page, Dan?  I suspect there is another hidden bug.  There are
four places where the flag could be reset:

(I)
  if (Scr.ScrollResistance >= 10000 || (HorWarpSize == 0 && VertWarpSize==0))
  {
    is_timestamp_valid = False;
    ...
    return False;
  }

It can't be here because this condition is only true if paging is
completely disabled.

(II)
  if (Scr.VxMax == 0 && Scr.VyMax == 0)
  {
    is_timestamp_valid = False;
    ...
    return False;
  }

But in this case you would have a 1x1 desktop and paging would
never take place.

(III)

    if (XPending(dpy) > 0 &&
       (XCheckWindowEvent(
     dpy, Scr.PanFrameTop.win, LeaveWindowMask, &Event) ||
    XCheckWindowEvent(
      dpy, Scr.PanFrameBottom.win, LeaveWindowMask, &Event) ||
    XCheckWindowEvent(
      dpy, Scr.PanFrameLeft.win, LeaveWindowMask, &Event) ||
    XCheckWindowEvent(
      dpy, Scr.PanFrameRight.win, LeaveWindowMask, &Event)))
    {
      ...
      is_timestamp_valid = False;
      ...
      return False;
    }

This contition should only be true if the pointer leaves the pan
frames.

(IV)
    if (x >= edge_thickness && x < Scr.MyDisplayWidth-edge_thickness &&
        y >= edge_thickness && y < Scr.MyDisplayHeight-edge_thickness)
    {
      is_timestamp_valid = False;
      ...
      return False;
    }

Same as III.

The fifth possibility is that paging is triggered on a desktop edge.  
I don't understand how any of these conditions can kick off.

> fvwm moves it in response to keyboard events.

This code prevents paging while you move the pointer along a
screen edge.  For example, if you grab a window title near the
page top and move it horizontally, you will often touch the page
top for a moment during the motion.  This code prevents that
paging takes place in this situation if the pointer still moves
fast enough (6 pixels or more per event).  Otherwise you may flip
pages a few times with a low edge resistance.  This would only
delay paging, but not disable it (it does not reset said flag).
Basically, this code is meant to trigger when you move *along* the
edge, not when you *hit* the edge (although this will still happen
once if you hit it too fast).

> it doesn't seem to be able to get into the "too fast" logic

The keyboard shortcut code tries to emulate real pointer motion.
If you move the pointer with the mouse, the window will also lag
behind the pointer since you can't move the window before you know
where the pointer travels.  This is exactly what keyboard
shortcuts do: move the pointer, then overwrite the KeyPress event
with a proper MotionNotify event.

> I did make it go into the "too fast" logic using the mouse.

This code will be executed most of the time if you use the shift
key during motion (100 pixels per keystroke), but it does not
really matter.  The default motion step size is the width_inc or
height_inc of the window or 5, whichever is greater.  So, you will
often move 5 pixels per keystroke which is just one pixel smaller
than the distance needed to trigger this code.  Even if you move
windows with ..._inc > 5, it will only be called if the last step
of the motion when hitting the edge was really 6 pixels or more.

Bye

Dominik ^_^  ^_^

---

From: Dominik Vogt <[email-masked]>
Date: Sat, 6 Jan 2001 14:18:49 +0100

(I)

(II)

(III)

    if (XPending(dpy) > 0 &&
       (XCheckWindowEvent(

(IV)

Same as III.

Bye

Dominik ^_^  ^_^

---

From: Dan Espen <[email-masked]>
Date: Mon, 08 Jan 2001 09:53:19 -0500

> four places where the flag could be reset:

Sorry, I only read this closely after I did a CVS update, I can
update back to a few days ago, but I think I have what you want.

Looking back thru my debug output, I only saw 2 different returns being
activated, the first one:

  if (!is_timestamp_valid && do_continue_previous)
  {
    /* Free some CPU */
    usleep(10000);
    fprintf(stderr,"timestamp %d, valid %d, continue %d\n",
            countit++, (int)!is_timestamp_valid, (int)do_continue_previous);
    return False;
  }

and this one:

    /* check actual pointer location since PanFrames can get buried under
       a window being moved or resized - mab */
    if (x >= edge_thickness && x < Scr.MyDisplayWidth-edge_thickness &&
        y >= edge_thickness && y < Scr.MyDisplayHeight-edge_thickness)
    {
      is_timestamp_valid = False;
      add_time = 0;
      discard_window_events(Scr.PanFrameTop.win, LeaveWindowMask);
      discard_window_events(Scr.PanFrameBottom.win, LeaveWindowMask);
      discard_window_events(Scr.PanFrameLeft.win, LeaveWindowMask);
      discard_window_events(Scr.PanFrameRight.win, LeaveWindowMask);
    fprintf(stderr,"thickness\n");
      return False;
    }

When actual moves were taking place, it would print "thickness"
after that, it just keeps printing "timestamp...".

---

From: Dominik Vogt <[email-masked]>
Date: Sat, 6 Jan 2001 14:18:49 +0100

(I)

(II)

(III)

    if (XPending(dpy) > 0 &&
       (XCheckWindowEvent(

(IV)

Same as III.

Bye

Dominik ^_^  ^_^

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 12 Jan 2001 22:02:21 +0100

> after that, it just keeps printing "timestamp...".

Hm, I don't think this is what I'm looking for.  The "thickness"
line should only be printed while the pointer is still outside the
pan frame and not in the instant the pointer enters the pan
frames.

Bye

Dominik ^_^  ^_^