]> source.dussan.org Git - tigervnc.git/commitdiff
made full-screen edge scrolling smoother and faster 1242/head
authorSelene ToyKeeper <git@toykeeper.net>
Fri, 30 Apr 2021 14:34:17 +0000 (08:34 -0600)
committerSelene ToyKeeper <git@toykeeper.net>
Fri, 30 Apr 2021 14:34:17 +0000 (08:34 -0600)
The old method used a very slow frame rate with small steps,
which made it obnoxious during use.  The new method has a few
improvements:

- Calculates "edge" region width automatically, as a ratio of
  the viewport size.  Default is 1/16th.

- Uses a different edge width for x and y, which works better
  on very wide or very tall screens.

- Increased default frame rate from 10 fps to 60 fps.

- Replaced hardcoded frame rate with a #define.

- Reduced maximum movement per frame slightly, because the
  frame rate is so much faster.  The overall result is still much
  faster, but also easier to do small adjustments with.

- Fixed off-by-one error in scroll rate calculation formula.  Left/up
  scrolls were faster than down/right, but this is fixed.

This makes it more comfortable to use TigerVNC on a small screen
to work on a larger screen for hours at a time.

vncviewer/DesktopWindow.cxx

index 5401b191fa6840c1a6bb86cdfb9735bfc5ce6220..dddd74d7151a57511c3c448160a4d629690e21ef 100644 (file)
 #include <Carbon/Carbon.h>
 #endif
 
-#define EDGE_SCROLL_SIZE 32
-#define EDGE_SCROLL_SPEED 20
+// width of each "edge" region where scrolling happens,
+// as a ratio compared to the viewport size
+// default: 1/16th of the viewport size
+#define EDGE_SCROLL_SIZE 16
+// edge width is calculated at runtime; these values are just examples
+static int edge_scroll_size_x = 128;
+static int edge_scroll_size_y = 96;
+// maximum pixels to scroll per frame
+#define EDGE_SCROLL_SPEED 16
+// how long to wait between viewport scroll position changes
+// default: roughly 60 fps for smooth motion
+#define EDGE_SCROLL_SECONDS_PER_FRAME 0.016666
 
 using namespace rfb;
 
@@ -768,12 +778,16 @@ int DesktopWindow::handle(int event)
       }
     }
     if (fullscreen_active()) {
-      if (((viewport->x() < 0) && (Fl::event_x() < EDGE_SCROLL_SIZE)) ||
-          ((viewport->x() + viewport->w() > w()) && (Fl::event_x() > w() - EDGE_SCROLL_SIZE)) ||
-          ((viewport->y() < 0) && (Fl::event_y() < EDGE_SCROLL_SIZE)) ||
-          ((viewport->y() + viewport->h() > h()) && (Fl::event_y() > h() - EDGE_SCROLL_SIZE))) {
+      // calculate width of "edge" regions
+      edge_scroll_size_x = viewport->w() / EDGE_SCROLL_SIZE;
+      edge_scroll_size_y = viewport->h() / EDGE_SCROLL_SIZE;
+      // if cursor is near the edge of the viewport, scroll
+      if (((viewport->x() < 0) && (Fl::event_x() < edge_scroll_size_x)) ||
+          ((viewport->x() + viewport->w() >= w()) && (Fl::event_x() >= w() - edge_scroll_size_x)) ||
+          ((viewport->y() < 0) && (Fl::event_y() < edge_scroll_size_y)) ||
+          ((viewport->y() + viewport->h() >= h()) && (Fl::event_y() >= h() - edge_scroll_size_y))) {
         if (!Fl::has_timeout(handleEdgeScroll, this))
-          Fl::add_timeout(0.1, handleEdgeScroll, this);
+          Fl::add_timeout(EDGE_SCROLL_SECONDS_PER_FRAME, handleEdgeScroll, this);
       }
     }
     // Continue processing so that the viewport also gets mouse events
@@ -1408,27 +1422,27 @@ void DesktopWindow::handleEdgeScroll(void *data)
   if (my > self->h())
     my = self->h();
 
-  if ((self->viewport->x() < 0) && (mx < EDGE_SCROLL_SIZE))
+  if ((self->viewport->x() < 0) && (mx < edge_scroll_size_x))
     dx = EDGE_SCROLL_SPEED -
-         EDGE_SCROLL_SPEED * mx / EDGE_SCROLL_SIZE;
-  if ((self->viewport->x() + self->viewport->w() > self->w()) &&
-      (mx > self->w() - EDGE_SCROLL_SIZE))
-    dx = EDGE_SCROLL_SPEED * (self->w() - mx) / EDGE_SCROLL_SIZE -
-         EDGE_SCROLL_SPEED;
-  if ((self->viewport->y() < 0) && (my < EDGE_SCROLL_SIZE))
+         EDGE_SCROLL_SPEED * mx / edge_scroll_size_x;
+  if ((self->viewport->x() + self->viewport->w() >= self->w()) &&
+      (mx >= self->w() - edge_scroll_size_x))
+    dx = EDGE_SCROLL_SPEED * (self->w() - mx) / edge_scroll_size_x -
+         EDGE_SCROLL_SPEED - 1;
+  if ((self->viewport->y() < 0) && (my < edge_scroll_size_y))
     dy = EDGE_SCROLL_SPEED -
-         EDGE_SCROLL_SPEED * my / EDGE_SCROLL_SIZE;
-  if ((self->viewport->y() + self->viewport->h() > self->h()) &&
-      (my > self->h() - EDGE_SCROLL_SIZE))
-    dy = EDGE_SCROLL_SPEED * (self->h() - my) / EDGE_SCROLL_SIZE -
-         EDGE_SCROLL_SPEED;
+         EDGE_SCROLL_SPEED * my / edge_scroll_size_y;
+  if ((self->viewport->y() + self->viewport->h() >= self->h()) &&
+      (my >= self->h() - edge_scroll_size_y))
+    dy = EDGE_SCROLL_SPEED * (self->h() - my) / edge_scroll_size_y -
+         EDGE_SCROLL_SPEED - 1;
 
   if ((dx == 0) && (dy == 0))
     return;
 
   self->scrollTo(self->hscroll->value() - dx, self->vscroll->value() - dy);
 
-  Fl::repeat_timeout(0.1, handleEdgeScroll, data);
+  Fl::repeat_timeout(EDGE_SCROLL_SECONDS_PER_FRAME, handleEdgeScroll, data);
 }
 
 void DesktopWindow::handleStatsTimeout(void *data)