The user might not always want to use all monitors when in fullscreen
mode, but instead only a few. This commit adds support for configuring
selected monitors from command line, in the config file and graphically
in the options menu.
Because it might be hard to guarantee the consistency of monitor
identifiers coming from third-parties (for example FLTK), it has been
decided to use our own numerical identifier. This identifier is based on
the monitor's positions. The mapping between this identifier and the
indices used by FLTK is done by MonitorIndicesParameter.
Before this commit, `FullScreen` and `FullScreenAllMonitors` could be
used to configure whether to use the current monitor in fullscreen,
or all monitors in fullscreen.
This commit deprecates `FullScreenAllMonitors` in favour of
`FullScreenMode` (which can either be `current` or `all`). This allows
for additional modes to be added, without the risk of having invalid
states (for example two activate two different fullscreen modes at the
same time).
A new concept has been added; read-only parameters. They are parameters
that will be read, but never written back. This allows for migration
paths to be constructed, where a parameter can be taken to consideration
but then for example be discarded, logged or changed into something else.
This has been used for `FullScreenAllMonitors` to provide a migration
path. On startup of vncviewer, if `FullScreenAllMonitors` is enabled,
`FullScreenMode=all` will be automatically enabled instead. The next
time the configuration file is written to disk, `FullScreenAllMonitors`
will then be removed.
Previously, it was assumed that all monitors (and especially the primary
monitor, index 0) was inside the window when we calculate the position
of the overlay.
That might not always be the case, for example when using fullscreen
mode over a narrower set of monitors. This commit does so the overlay is
positioned correctly based on the actual window size, instead of what we
expect it to be.
cocoa_capture_displays it captures all displays enclosed by the
window_rect. If a set of displays were captured, but the configuration of
what monitors to use changed, a second call would only add to the set
of captured displays. Therefore, if the user enabled
FullScreenAllMonitors (all displays captured) and then disabled it (only
one display captured) they would get into a state were monitors not used
for the VNC session still were captured (which on macOS for example,
results in displays being unusable for other things).
This has now been fixed, resulting in monitors outside the window_rect
not being unnecessarily captured.
It was only possible to capture either the current, or all displays
previously. This could become an issue if you want to show a vnc session
over only a selected set of displays, because then we only want to
capture those displays.
The solution in the commit was chosen because it handles all cases - by
looking at what monitors are enclosed by the viewport the implementation
is independent on any configuration, but instead captures the monitors
actually being used.
made full-screen edge scrolling smoother and faster
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.
Support the VMware Cursor Position extension on vncviewer
This change makes it possible for re-synchronizing the remote cursor on
the vncviewer when in fullscreen mode. This is done by locally moving
the cursor position to what the server thinks it should be.
Now SDL games should work!
Switch from using Core events to using X Input events for pointer
devices in order to differentiate between mouse events and touch events.
Because FLTK doesn't understand X Input 2, we intercept these events and
translate them to core events where possible.
We now filter incoming data, which means we can start assuming the
clipboard data is always null terminated. This allows us to clean
up a lot of the internal handling.
Avoid direct access to the screen dimensions and layout so that we
can make sure it stays sane. This also makes sure the layout is
properly updated when we only get the screen dimensions from the
server.
Grabbing (and ungrabbing) the keyboard generates fake focus events
with modern versions of Xorg. This causes an infinite loop since we
update the grab status on focus events.
Work around this by ignoring these fake events.
The VNC servers aren't great at getting full frames with each update,
so avoid calling it "frames per second" in the statistics as that
can be misleading.
Copy paste errors/brain fart:
- Pixels do not need a factor 8 for any conversion
- Multiplying bytes by 8 gives bits, so lower case 'b', and bits
use SI prefixes, not IEC
Similar to 841e9f32d5 but for the
pointer. Fixes a problem where the desktop environment is unresponsive
(to the mouse) after fullscreen exit; Fixes #579.
We don't need the grab any more if the pointer cannot click on our
window. This makes it possible to shift focus to another application
when we aren't covering all monitors.
Have a window that is sized to the remote screen. Now shrink the window
vertically, making it shorter than the remote screen in one axis. The
vertical scrollbar appears. However, the horizontal scrollbar does not
appear, despite the rightmost ~24 pixels (Fl::scrollbar_size()) being
hidden by the vertical scroll bar.
Fix that.
For clarity, move the fullscreen checks into a separate `if` statement,
rather than keeping the size and fullscreen checks together.
I think the comment does a decent job of explaining and justifying the
check's logic, but if you require further convincing, perhaps this
alternate explanation will help:
The check for the X-axis is
if ((w() - (h() < viewport->h() ? Fl::scrollbar_size() : 0) < viewport->w())
To be a bit more verbose and repetitive, we can split that ternary in to
two separate checks, and add some comments:
if (
(w() - < viewport->w()) // X needs a scrollbar
||
( (w() - Fl::scrollbar_size() < viewport->w()) && (h() < viewport->h()) )
//( X doesn't need a scrollbar unless Y does ) && ( Y does need one ) )
)
Within the "Y does need one" check, we don't need to worry about the
case where `h() - Fl::scrollbar_size() < viewport-h()` is true,
because if both axes are saying "I don't need a scrollbar unless
you do", then neither needs one.
Adds an optional graph to the viewer to display current frame rate,
pixel rate and network bandwidth. Makes it easier to debug and test
performance related issues.
Some platforms draw directly to the screen, which means that updates
will flicker if we draw multiple layers. Prevent this by first
composing the update on a hidden surface.
Delegate decoder object management to a separate class
Done in preparation for multi-core decoding. Keeps the complexity
out of the other classes. This also moves ownership of the
framebuffer in to CConnection. It's the CConnection object that is
aware of the threads and how to synchronise with them. Therefore
the ownership of the framebuffer must also be there to make sure
it isn't deleted whilst threads are working.
This workaround is no longer effective with the new system handler
method of handling keyboard events. The bug has also been fixed
in upstream FLTK, further making it pointless.