Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java Viewer: Per-host options + the ability to save connection info files #135

Closed
dcommander opened this issue Aug 9, 2018 · 4 comments
Closed

Comments

@dcommander
Copy link
Member

dcommander commented Aug 9, 2018

Since the Windows TurboVNC Viewer will be retired in the next major release, this is a catch-all issue for any GUI features from the Windows TurboVNC Viewer that still need to be ported into the Java TurboVNC Viewer, including:

  1. The ability to save connection profiles
  2. Saving and managing settings per-connection instead of globally
  3. The view-only, zoom, and clipboard transfer hotkeys from Viewer: additional toolbar functionality (toggle view-only mode & clipboard transfer, zoom in/out/reset, display toolbar in full-screen mode) #45
@dcommander
Copy link
Member Author

The view-only and zoom hotkeys have been implemented in the latest 3.0 evolving build. The clipboard transfer hotkey isn’t a good fit for the Java viewer, since it has independent settings for disabling inbound and outbound clipboard transfer. (The clipboard transfer hotkey was implemented primarily as an easy workaround for the flaky daemon-based clipboard transfer mechanism that has long since been replaced.)

dcommander added a commit that referenced this issue Nov 3, 2021
(when non-automatic desktop scaling is enabled)

Note that, unfortunately, there is no straightforward way to use '+' as
an accelerator in Swing, since that character is usually not located on
the primary keyboard layer.  Because the key codes in Swing are only
valid for a U.S. keyboard layout, there is not enough information in the
KeyEvent to determine, with any degree of reliability, whether
Ctrl-Alt-Shift + or Ctrl-Alt-Shift - has been pressed.  Thus, the new
implementation of this feature uses the 8 and 9 keys for, respectively,
zooming out and in instead of the - and + keys.  This provides a similar
feel to the old implementation when using U.S. keyboards, since the
8 and 9 keys are also adjacent to the 0 key.

Refer to #135
@dcommander dcommander changed the title Make the Java/Un*x/Mac TurboVNC Viewer behave more like the Windows native viewer Java Viewer: Per-connection options + the ability to save connection profiles Dec 21, 2021
@dcommander dcommander changed the title Java Viewer: Per-connection options + the ability to save connection profiles Java Viewer: Per-host options + the ability to save connection info files Dec 21, 2021
dcommander added a commit that referenced this issue Aug 14, 2022
This partially resolves feature regressions introduced when the Windows
TurboVNC Viewer was retired.

Partially implements #135
@relcodedev
Copy link

Is there a possibility of providing the UI selection to options file mapping.
I am trying to figure out the change to "Lossless Tight + Zlib (WAN)" translates to in the options file. It is not obvious from docs.

@dcommander
Copy link
Member Author

@relcodedev Yeah, it's a bit nonintuitive, because the format of .vnc connection info files comes from TightVNC 1.3.x, and I had to map TurboVNC features onto that format. I'm about to replace all of that mess with a new .turbovnc connection info file format that just uses the TurboVNC Viewer command-line parameters.

In the meantime, you can achieve what you want with

quality=-1
compresslevel=6

For other mappings, refer to:

public static void load(String filename) {
if (filename == null)
return;
/* Read parameters from file */
Properties props = new Properties();
try {
props.load(new FileInputStream(filename));
} catch (Exception e) {
throw new WarningException("Cannot open connection info file:\n" +
e.getMessage());
}
int scaleNum = -1, scaleDenom = -1, fitWindow = -1;
int resizeMode = -1, desktopWidth = -1, desktopHeight = -1;
String desktopSizeStr = null;
for (Enumeration<?> i = props.propertyNames(); i.hasMoreElements();) {
String name = (String)i.nextElement();
if (name.startsWith("[")) {
// skip the section delimiters
continue;
} else if (name.equalsIgnoreCase("host")) {
set("Server", props.getProperty(name));
} else if (name.equalsIgnoreCase("port")) {
set("Port", props.getProperty(name));
} else if (name.equalsIgnoreCase("password")) {
set("EncPassword", props.getProperty(name));
} else if (name.equalsIgnoreCase("user")) {
set("User", props.getProperty(name));
} else if (name.equalsIgnoreCase("preferred_encoding")) {
int encoding = -1;
try {
encoding = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (encoding >= 0 && encoding <= RFB.ENCODING_LAST)
set("Encoding", RFB.encodingName(encoding));
} else if (name.equalsIgnoreCase("restricted")) {
set("Restricted", props.getProperty(name));
} else if (name.equalsIgnoreCase("viewonly")) {
set("ViewOnly", props.getProperty(name));
} else if (name.equalsIgnoreCase("reversescroll")) {
set("ReverseScroll", props.getProperty(name));
} else if (name.equalsIgnoreCase("fullscreen")) {
set("FullScreen", props.getProperty(name));
} else if (name.equalsIgnoreCase("fsaltenter")) {
set("FSAltEnter", props.getProperty(name));
} else if (name.equalsIgnoreCase("grabkeyboard")) {
int grabKeyboardValue = -1;
try {
grabKeyboardValue = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
switch (grabKeyboardValue) {
case Options.GRAB_FS:
set("GrabKeyboard", "FS"); break;
case Options.GRAB_ALWAYS:
set("GrabKeyboard", "Always"); break;
case Options.GRAB_MANUAL:
set("GrabKeyboard", "Manual"); break;
}
} else if (name.equalsIgnoreCase("span")) {
int spanValue = -1;
try {
spanValue = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (spanValue == 0) set("Span", "Primary");
else if (spanValue == 1) set("Span", "All");
else if (spanValue == 2) set("Span", "Auto");
} else if (name.equalsIgnoreCase("8bit")) {
int _8bit = -1;
try {
_8bit = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (_8bit >= 1)
set("Colors", "256");
else if (_8bit == 0)
set("Colors", "-1");
} else if (name.equalsIgnoreCase("shared")) {
set("Shared", props.getProperty(name));
} else if (name.equalsIgnoreCase("disableclipboard")) {
int disableclipboard = -1;
try {
disableclipboard = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (disableclipboard >= 1) {
set("RecvClipboard", "0");
set("SendClipboard", "0");
} else if (disableclipboard == 0) {
set("RecvClipboard", "1");
set("SendClipboard", "1");
}
} else if (name.equalsIgnoreCase("fitwindow")) {
try {
fitWindow = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
} else if (name.equalsIgnoreCase("scale_num")) {
int temp = -1;
try {
temp = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (temp >= 1) scaleNum = temp;
} else if (name.equalsIgnoreCase("scale_den")) {
int temp = -1;
try {
temp = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (temp >= 1) scaleDenom = temp;
} else if (name.equalsIgnoreCase("resizemode")) {
int temp = -1;
try {
temp = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (temp >= 0) resizeMode = temp;
} else if (name.equalsIgnoreCase("desktopwidth")) {
int temp = -1;
try {
temp = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (temp >= 1) desktopWidth = temp;
} else if (name.equalsIgnoreCase("desktopheight")) {
int temp = -1;
try {
temp = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (temp >= 1) desktopHeight = temp;
} else if (name.equalsIgnoreCase("desktopsize")) {
desktopSizeStr = props.getProperty(name);
} else if (name.equalsIgnoreCase("cursorshape")) {
set("CursorShape", props.getProperty(name));
} else if (name.equalsIgnoreCase("noremotecursor")) {
set("LocalCursor", props.getProperty(name));
} else if (name.equalsIgnoreCase("compresslevel")) {
set("CompressLevel", props.getProperty(name));
} else if (name.equalsIgnoreCase("subsampling")) {
int subsamplingValue = -1;
try {
subsamplingValue = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
switch (subsamplingValue) {
case Options.SUBSAMP_NONE: set("Subsampling", "1X"); break;
case Options.SUBSAMP_4X: set("Subsampling", "4X"); break;
case Options.SUBSAMP_2X: set("Subsampling", "2X"); break;
case Options.SUBSAMP_GRAY: set("Subsampling", "Gray"); break;
}
} else if (name.equalsIgnoreCase("quality")) {
int qualityValue = -2;
try {
qualityValue = Integer.parseInt(props.getProperty(name));
} catch (NumberFormatException e) {}
if (qualityValue == -1) set("JPEG", "0");
else if (qualityValue >= 1 && qualityValue <= 100) {
set("Quality", props.getProperty(name));
}
} else if (name.equalsIgnoreCase("continuousupdates")) {
set("CU", props.getProperty(name));
} else if (name.equalsIgnoreCase("nounixlogin")) {
set("NoUnixLogin", props.getProperty(name));
}
}

@dcommander
Copy link
Member Author

Per-host options were implemented in the TurboVNC 3.1 evolving code base back in August. Later today, I plan to push a commit that implements a new .turbovnc connection info file format that accepts the same parameters and values that the TurboVNC Viewer accepts. However, upon further reflection, the ability to save connection info files doesn't make a lot of sense with the TurboVNC Session Manager and the advanced authentication features that the TurboVNC Viewer supports. If a TurboVNC session was started using the session manager, then (unless SessMgrAuto is explicitly disabled) the TurboVNC Viewer will only be able to connect to the session using SSH and will only be able to authenticate with the session using a one-time password. There is no way to enable OTP authentication using a connection info file, and since SSH tunneling uses an ephemeral client-side port, creating a connection info file that properly emulated an SSH-tunneled connection would be tricky at best. These days, connection info files are primarily meant to be generated on the fly by TurboVNC web portals and downloaded to the client via a web browser. Once the viewer has connected to the TurboVNC session, the initial parameter state will have usually changed, so saving the parameters to a connection info file wouldn't usually allow the connection to be reproduced. The only case in which that would work is the case in which the viewer was used only to connect to a static TurboVNC session using a static VNC password, and that is a "supported but de-emphasized" use case in TurboVNC these days. Other use cases might be supportable with some difficulty, but it would require maintaining a separate copy of the parameters prior to the connection and synchronizing that copy whenever the primary parameters change (such as when using the Options dialog.) A big reason why TightVNC needed a "save connection info file" feature was the fact that its connection info file format was somewhat inscrutable, but the new .turbovnc connection info file format addresses that concern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants