Idea: "elastic" move

2021-11-21 Thread Dominik Vogt
Duing the the discussion about annoying page flipping during
interactive move Thomas said that he switched it off because it
was annoying and that the pages then felt like disconnected
desktops.

This is precisely true and matches my own opinion.  Fvwm should be
better than that.  The big, paged virtual desktop should not feel
like disjoint desktops but like a big sketch block with plenty of
space.

=> Make crossing the page boundaries easier and intuitive without
   being annoying.

Situation:  At the moment, interactive move with the mouse feels
awkward.  Pushing windows past the page edge often fails because
the pointer hits the edge and cannot move further.  It's annoying
and uncomfortable.  The "pointer hits page border" this is a real
show stopper.

--

This is the idea (working title "elastic paging"):

1. When an interactive move starts:

- Replace the pointer with an invisible one.
- Warp the pointer to the middle of the screen.  There it can
  always be moved in all directions.
- If the pointer gets too close to the page edges, warp it back
  to the middle of the screen.
- At the end of the move, warp it back to the original
  position relative to the window.
   (- Maybe a fake cursor can be drawn at the original position so
  that the user does not get confused.)

   Note: Its then possible to move a window any distance without
   releasing the pointer.

   Note 2: As a side effect, windows can also be pushed over the
   desktop borders (maybe enforce that at least a couple of pixels
   remain visible).

2. Remove timed paging during interactive move completely
   (EdgeMoveDelay style)

3. Instead, when you push the original pointer position off page
   the viewport automatically starts scrolling to keep that
   position (the fake pointer) visible.

   Think of the current viewport position being connected with the
   original one with a rubber band:  If you change you mind and
   move the window back towards its original position, the viewport
   also moves back, relaxing the rubber band.

   (When windows on other pages become visible, snapattraction
   automatically allows to snap to them.)

4. When the move ends, the window is placed and the viewport snaps
   back to a full page.  It may be a bit tricky to choose the
   proper page automatically.  It's easy if the window has
   completely moved to another page, but what if it's stuck between
   two or even four pages?

5. Visual feedback (optional)

- If the viewport jumps use some kind of smooth animation.
  This may be especially important if the viewport snaps to a
  full page when the move ends.

- See how the fake pointer can be implemented.

- Add a new "activity" colour to window decorations.  This
  colour may be used while a long running action affects a
  window (interactive move/resize etc.).

- The "activity" colour could also be used when a window
  border hits the page edge during an interactive move.  Say,
  if the window is already at the edge and you keep "pushing",
  that border uses the "activity" colour to indicate that
  something is happening.

6. Future

- Also do something about interactive resize.
- If elastic paging works nicely, it should become the default
  behaviour.  To disable it, you have to turn it off
  explicitly - an empty config still has it on.


Ciao

Dominik ^_^  ^_^

--

Dominik Vogt



Re: Idea: "elastic" move

2021-11-21 Thread Thomas Adam
On Sun, Nov 21, 2021 at 03:29:29PM +0100, Dominik Vogt wrote:
> Situation:  At the moment, interactive move with the mouse feels
> awkward.  Pushing windows past the page edge often fails because
> the pointer hits the edge and cannot move further.  It's annoying
> and uncomfortable.  The "pointer hits page border" this is a real
> show stopper.

Yeah, that all makes sense.

> 1. When an interactive move starts:
> 
> - Replace the pointer with an invisible one.
> - Warp the pointer to the middle of the screen.  There it can
>   always be moved in all directions.
> - If the pointer gets too close to the page edges, warp it back
>   to the middle of the screen.
> - At the end of the move, warp it back to the original
>   position relative to the window.
>(- Maybe a fake cursor can be drawn at the original position so
>   that the user does not get confused.)

So... if I understand this correctly, you would have something like this:

   +--+ 

   |S | 

   |  | 

   |  | 

   |  | 

   |  | 

   |  | 

   |  | 

   |  | 

   |  | 

   |P | 

   |  | 

   |  | 

   |  | 

   |  ++  | 

   |  ||  | 

   |  ||  | 

   |  ||  | 

   |  |   W|  | 

   |  ||  | 

   |  ||  | 

   |  ++  | 

   |  | 

   +--+ 
 


If I'm moving window W interactively, pointer (P) is moved to the middle of
the screen, if I move it right, the window follows that -- but at the distance
of the window's top border and where the pointer is, presumably?

What if I want to have window W moved to the top-right of the screen (S)?
Wouldn't my pointer end up being at the top of the screen before the window
could reach it, and hence the pointer would be warped back to the middle of
screen S?

> 2. Remove timed paging during interactive move completely
>(EdgeMoveDelay style)

Yes please.

> 3. Instead, when you push the original pointer position off page
>the viewport automatically starts scrolling to keep that
>position (the fake pointer) visible.
> 
>Think of the current viewport position being connected with the
>original one with a rubber band:  If you change you mind and
>move the window back towards its original position, the viewport
>also moves back, relaxing the rubber band.

I think I can visualise this in my mind -- and I think it makes sense as
moving a window is a conscious choice in that a user's going to know where it
started, and so treating its moving like an elastic band could work.

> 4. When the move ends, the window is placed and the viewport snaps
>back to a full page.  It may be a bit tricky to choose the
>proper page automatically.  It's easy if the window has
>completely moved to another page, but what if it's stuck between
>two or even four pages?

This concept between pages and viewing many different parts of the overall
virtual desktop has always meant situations like this happen even now.  I
don't have a good answer to this.

We also need to think about:

* How FvwmPager is going to react to this -- I think it will handle the
  scrolling nature just fine, but there's still a chance it might get
  confused.
* Edge-sensitivity to 'DesktopConfiguration per-monitor' and screen boundaries
  wher

Re: Idea: "elastic" move

2021-11-21 Thread Dominik Vogt
On Sun, Nov 21, 2021 at 10:11:57PM +, Thomas Adam wrote:
> > - Replace the pointer with an invisible one.
> > - Warp the pointer to the middle of the screen.  There it can
> >   always be moved in all directions.
> > - If the pointer gets too close to the page edges, warp it back
> >   to the middle of the screen.
> > - At the end of the move, warp it back to the original
> >   position relative to the window.
> >(- Maybe a fake cursor can be drawn at the original position so
> >   that the user does not get confused.)
>
> So... if I understand this correctly, you would have something like this:
>
>+--+
>|S |
>|  |
>|..|
>|::|
>|::|
>|::|
>|::|
>|::|
>|::|
>|::|
>|:   P:|
>|::|
>|::|
>|  +-:--X---+ :|
>|  | :  | :|
>|  | :  | :|
>|  | :  | :|
>|  | : W| :|
>|  | :  | :|
>|  | ::|
>|  ++  |
>|  |
>+--+

Yes.  In addition "X" if the spon on the winode title where the
pointer was when it started to move the window, i.e. the position
of the fake pointer during the move.

> If I'm moving window W interactively, pointer (P) is moved to the middle of
> the screen, if I move it right, the window follows that -- but at the distance
> of the window's top border and where the pointer is, presumably?

Yes.  The window (and the "X") make the same moves as the pointer.
The offset between pointer and window stays the same.

> What if I want to have window W moved to the top-right of the screen (S)?
> Wouldn't my pointer end up being at the top of the screen before the window
> could reach it, and hence the pointer would be warped back to the middle of
> screen S?

Yes, when the pointer comes too close to any border (leaves the
dotted area on the sketch), it's warped back by the __move_loop to
the original "P" in the sketch.  Thus it can continue moving in
all directions.  Of course, the window does not follow the warp.
The (P)ointer to (W)indow offset is internally adjusted to a new
value.

Your other comments make sense.  There are no answers at the
moment.  First we need to play with it and see how it feels.

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt



Re: Idea: "elastic" move

2021-11-21 Thread Thomas Adam
On Mon, Nov 22, 2021 at 12:24:09AM +0100, Dominik Vogt wrote:
> Yes, when the pointer comes too close to any border (leaves the
> dotted area on the sketch), it's warped back by the __move_loop to
> the original "P" in the sketch.  Thus it can continue moving in
> all directions.  Of course, the window does not follow the warp.
> The (P)ointer to (W)indow offset is internally adjusted to a new
> value.

Ah, yes of course.  This makes sense now.  Thanks.  I guess there could be
more movement with the mouse than before, but we'll have to see what it's
like.

Incidentally, isn't this sort of concept what FvwmProxy was trying to do?  I
seem to recall you could simultaneously move multiple windows...

Kindly,
Thomas



Re: Idea: "elastic" move

2021-11-21 Thread Dominik Vogt
On Sun, Nov 21, 2021 at 03:29:29PM +0100, Dominik Vogt wrote:
> - If the viewport jumps use some kind of smooth animation.
>   This may be especially important if the viewport snaps to a
>   full page when the move ends.

Tried this with the attached patch.  It's not smooth and it
doesn't look good.  Windows that move into view are only half
drawn because the screen is grabbed, and the pager flickers.

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt
From 9963bda7bf0fda6f6a3f4750b7e7e5911a04066a Mon Sep 17 00:00:00 2001
From: Dominik Vogt 
Date: Mon, 22 Nov 2021 01:37:04 +0100
Subject: [PATCH] !!! MoveViewport animation

---
 fvwm/virtual.c | 357 +++--
 1 file changed, 198 insertions(+), 159 deletions(-)

diff --git a/fvwm/virtual.c b/fvwm/virtual.c
index 94ad4418..e965322b 100644
--- a/fvwm/virtual.c
+++ b/fvwm/virtual.c
@@ -1393,14 +1393,182 @@ Bool is_pan_frame(Window w)
  *  Moves the viewport within the virtual desktop
  *
  */
-void MoveViewport(struct monitor *m, int newx, int newy, Bool grab)
+static void move_viewport_delta(
+	struct monitor *m, position delta, position page_tl, position page_br,
+	int do_broadcast)
 {
-	struct monitor *m_loop;
+	struct monitor	*mloop;
 	FvwmWindow *t, *t1;
-	int deltax,deltay;
-	int PageTop, PageLeft;
-	int PageBottom, PageRight;
 	int txl, txr, tyt, tyb;
+
+	if (do_broadcast)
+	{
+		TAILQ_FOREACH(mloop, &monitor_q, entry)
+		{
+			BroadcastPacket(
+M_NEW_PAGE, 8,
+(long)mloop->virtual_scr.Vx,
+(long)mloop->virtual_scr.Vy,
+(long)mloop->virtual_scr.CurrentDesk,
+(long) monitor_get_all_widths(),
+(long) monitor_get_all_heights(),
+(long)((mloop->virtual_scr.VxMax /
+	monitor_get_all_widths()) + 1),
+(long)((mloop->virtual_scr.VyMax /
+	monitor_get_all_heights()) + 1),
+(long)mloop->si->rr_output);
+		}
+	}
+	/*
+	 * RBW - 11/13/1998  - new:  chase the chain
+	 * bidirectionally, all at once! The idea is to move the
+	 * windows that are moving out of the viewport from the bottom
+	 * of the stacking order up, to minimize the expose-redraw
+	 * overhead. Windows that will be moving into view will be
+	 * moved top down, for the same reason. Use the new
+	 * stacking-order chain, rather than the old last-focused
+	 * chain.
+	 *
+	 * domivogt (29-Nov-1999): It's faster to first map windows
+	 * top to bottom and then unmap windows bottom up.
+	 */
+	/* TA: 2020-01-21:  This change of skipping monitors will
+	 * break using 'Scroll' and __drag_viewport().  We need to
+	 * ensure we handle this case properly.
+	 */
+	t = get_next_window_in_stack_ring(&Scr.FvwmRoot);
+	while (t != &Scr.FvwmRoot)
+	{
+		if (NOT_GLOBALLY_ACTIVE(t->m, m)) {
+			/*  Bump to next win...  */
+			t = get_next_window_in_stack_ring(t);
+			continue;
+		}
+		/*
+		 * If the window is moving into the viewport...
+		 */
+		txl = t->g.frame.x;
+		tyt = t->g.frame.y;
+		txr = t->g.frame.x + t->g.frame.width - 1;
+		tyb = t->g.frame.y + t->g.frame.height - 1;
+		if (is_window_sticky_across_pages(t) &&
+		!IS_VIEWPORT_MOVED(t))
+		{
+			/* the absolute position has changed */
+			t->g.normal.x -= delta.x;
+			t->g.normal.y -= delta.y;
+			t->g.max.x -= delta.x;
+			t->g.max.y -= delta.y;
+			/*  Block double move.  */
+			SET_VIEWPORT_MOVED(t, 1);
+		}
+		if ((txr >= page_tl.x && txl <= page_br.x
+		 && tyb >= page_tl.y && tyt <= page_br.y)
+		&& !IS_VIEWPORT_MOVED(t)
+		&& !IS_WINDOW_BEING_MOVED_OPAQUE(t))
+		{
+			/*  Block double move.  */
+			SET_VIEWPORT_MOVED(t, 1);
+			/* If the window is iconified, and sticky Icons is set,
+			 * then the window should essentially be sticky */
+			if (!is_window_sticky_across_pages(t))
+			{
+if (IS_ICONIFIED(t))
+{
+	modify_icon_position(
+		t, delta.x, delta.y);
+	move_icon_to_position(t);
+	if (do_broadcast)
+	{
+		broadcast_icon_geometry(
+			t, False);
+	}
+}
+frame_setup_window(
+	t, t->g.frame.x + delta.x,
+	t->g.frame.y + delta.y,
+	t->g.frame.width,
+	t->g.frame.height, False);
+			}
+		}
+		/*  Bump to next win...  */
+		t = get_next_window_in_stack_ring(t);
+	}
+	t1 = get_prev_window_in_stack_ring(&Scr.FvwmRoot);
+	while (t1 != &Scr.FvwmRoot)
+	{
+		if (NOT_GLOBALLY_ACTIVE(t1->m, m)) {
+			/*  Bump to next win...  */
+			t1 = get_prev_window_in_stack_ring(t1);
+			continue;
+		}
+		/*
+		 *If the window is not moving into the viewport...
+		 */
+		SET_VIEWPORT_MOVED(t, 1);
+		txl = t1->g.frame.x;
+		tyt = t1->g.frame.y;
+		txr = t1->g.frame.x + t1->g.frame.width - 1;
+		tyb = t1->g.frame.y + t1->g.frame.height - 1;
+		if (! (txr >= page_tl.x && txl <= page_br.x
+		   && tyb >= page_tl.y && tyt <= page_br.y)
+		&& !IS_VIEWPORT_MOVED(t1)
+		&& !IS_WINDOW_BEING_MOVED_OPAQUE(t1))
+		{
+			/* If the window is iconified, and sticky Icons is set,
+			 * then the window should essentially be sticky */
+			if (!is_window_sticky_across_pages(t1))
+			{
+if (IS_ICONIFIED(

[RFC] Re: Idea: "elastic" move

2021-11-29 Thread Dominik Vogt
On Sun, Nov 21, 2021 at 03:29:29PM +0100, Dominik Vogt wrote:
> 1. When an interactive move starts:
>
>...
> - Warp the pointer to the middle of the screen.  There it can
>   always be moved in all directions.
> - If the pointer gets too close to the page edges, warp it back
>   to the middle of the screen.
>...

To get an idea how this feels, please try the branch
dv/elastic-paging-prototype.  (It also contains a stack of
unrelated pending changes that can beignored).

What's implemented:

  + Keeps the pointer away from the screen edges.  The window can
be moved any distance (but is not visible off screen yet).
  + The old paging code is removed.

Not implemented:

  - Switching off the cursor.
  - Fake cursor.
  - Warping the cursor back.
  - Actual paging.

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt



Re: [RFC] Re: Idea: "elastic" move

2021-11-29 Thread Dominik Vogt
On Mon, Nov 29, 2021 at 11:04:04PM +0100, Dominik Vogt wrote:
> On Sun, Nov 21, 2021 at 03:29:29PM +0100, Dominik Vogt wrote:
> > 1. When an interactive move starts:
> >
> >...
> > - Warp the pointer to the middle of the screen.  There it can
> >   always be moved in all directions.
> > - If the pointer gets too close to the page edges, warp it back
> >   to the middle of the screen.
> >...
>
> To get an idea how this feels, please try the branch
> dv/elastic-paging-prototype.  (It also contains a stack of
> unrelated pending changes that can beignored).
>
> What's implemented:
>
>   + Keeps the pointer away from the screen edges.  The window can
> be moved any distance (but is not visible off screen yet).
>   + The old paging code is removed.
>
> Not implemented:
>

>   - Switching off the cursor.

Now implemented.

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt