Browse Source

Add fullscreen mode parameter

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.
tags/v1.11.90
Hugo Lundin 2 years ago
parent
commit
c084e58692

+ 4
- 3
vncviewer/DesktopWindow.cxx View File

return ret; return ret;
} }



void DesktopWindow::fullscreen_on() void DesktopWindow::fullscreen_on()
{ {
if (not fullScreenAllMonitors)
bool all_monitors = !strcasecmp(fullScreenMode, "all");

if (not all_monitors)
fullscreen_screens(-1, -1, -1, -1); fullscreen_screens(-1, -1, -1, -1);
else { else {
int top, bottom, left, right; int top, bottom, left, right;
self->ungrabKeyboard(); self->ungrabKeyboard();


// Call fullscreen_on even if active since it handles // Call fullscreen_on even if active since it handles
// fullScreenAllMonitors
// fullScreenMode
if (fullScreen) if (fullScreen)
self->fullscreen_on(); self->fullscreen_on();
else if (!fullScreen && self->fullscreen_active()) else if (!fullScreen && self->fullscreen_active())

+ 40
- 9
vncviewer/OptionsDialog.cxx View File

} }
remoteResizeCheckbox->value(remoteResize); remoteResizeCheckbox->value(remoteResize);
fullScreenCheckbox->value(fullScreen); fullScreenCheckbox->value(fullScreen);
fullScreenAllMonitorsCheckbox->value(fullScreenAllMonitors);

if (!strcasecmp(fullScreenMode, "all")) {
allMonitorsButton->setonly();
} else {
currentMonitorButton->setonly();
}


handleDesktopSize(desktopSizeCheckbox, this); handleDesktopSize(desktopSizeCheckbox, this);


} }
remoteResize.setParam(remoteResizeCheckbox->value()); remoteResize.setParam(remoteResizeCheckbox->value());
fullScreen.setParam(fullScreenCheckbox->value()); fullScreen.setParam(fullScreenCheckbox->value());
fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox->value());

if (allMonitorsButton->value()) {
fullScreenMode.setParam("All");
} else {
fullScreenMode.setParam("Current");
}


/* Misc. */ /* Misc. */
shared.setParam(sharedCheckbox->value()); shared.setParam(sharedCheckbox->value());
void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th) void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
{ {
int x; int x;
int width, height;


Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Screen")); Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Screen"));


fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty, fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH, CHECK_MIN_WIDTH,
CHECK_HEIGHT, CHECK_HEIGHT,
_("Full-screen mode")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
_("Enable full-screen")));
ty += CHECK_HEIGHT + INNER_MARGIN;


fullScreenAllMonitorsCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Enable full-screen mode over all monitors")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
width = tw - OUTER_MARGIN * 2;
height = th - ty + OUTER_MARGIN * 3;
Fl_Group *fullScreenModeGroup = new Fl_Group(tx,
ty,
width,
height);

{
tx += INDENT;

currentMonitorButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
_("Use current monitor")));
currentMonitorButton->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;

allMonitorsButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
_("Use all monitors")));
allMonitorsButton->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
}


fullScreenModeGroup->end();
group->end(); group->end();
} }



+ 3
- 1
vncviewer/OptionsDialog.h View File

Fl_Int_Input *desktopHeightInput; Fl_Int_Input *desktopHeightInput;
Fl_Check_Button *remoteResizeCheckbox; Fl_Check_Button *remoteResizeCheckbox;
Fl_Check_Button *fullScreenCheckbox; Fl_Check_Button *fullScreenCheckbox;
Fl_Check_Button *fullScreenAllMonitorsCheckbox;

Fl_Round_Button *currentMonitorButton;
Fl_Round_Button *allMonitorsButton;


/* Misc. */ /* Misc. */
Fl_Check_Button *sharedCheckbox; Fl_Check_Button *sharedCheckbox;

+ 113
- 53
vncviewer/parameters.cxx View File

8); 8);


BoolParameter maximize("Maximize", "Maximize viewer window", false); BoolParameter maximize("Maximize", "Maximize viewer window", false);
BoolParameter fullScreen("FullScreen", "Full screen mode", false);
BoolParameter fullScreen("FullScreen", "Enable full screen", false);
StringParameter fullScreenMode("FullScreenMode", "Specify which monitors to use when in full screen. "
"Should be either Current or All",
"Current");
BoolParameter fullScreenAllMonitors("FullScreenAllMonitors", BoolParameter fullScreenAllMonitors("FullScreenAllMonitors",
"Enable full screen over all monitors",
true);
"[DEPRECATED] Enable full screen over all monitors",
false);
StringParameter desktopSize("DesktopSize", StringParameter desktopSize("DesktopSize",
"Reconfigure desktop size on the server on " "Reconfigure desktop size on the server on "
"connect (if possible)", ""); "connect (if possible)", "");
&noJpeg, &noJpeg,
&qualityLevel, &qualityLevel,
&fullScreen, &fullScreen,
&fullScreenAllMonitors,
&fullScreenMode,
&desktopSize, &desktopSize,
&remoteResize, &remoteResize,
&viewOnly, &viewOnly,
&fullscreenSystemKeys &fullscreenSystemKeys
}; };


static VoidParameter* readOnlyParameterArray[] = {
&fullScreenAllMonitors
};

// Encoding Table // Encoding Table
static struct { static struct {
const char first; const char first;
return true; return true;
} }


static bool removeValue(const char* _name, HKEY* hKey) {
const DWORD buffersize = 256;
wchar_t name[buffersize];

unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
if (size >= buffersize) {
vlog.error(_("The name of the parameter %s was too large to remove from the registry"), _name);
return false;
}

LONG res = RegDeleteValueW(*hKey, name);
if (res != ERROR_SUCCESS) {
if (res == ERROR_FILE_NOT_FOUND) {
// The value does not exist, no need to remove it.
return true;
} else {
vlog.error(_("Failed to remove parameter %s from the registry: %ld"),
_name, res);
return false;
}
}

return true;
}


void saveHistoryToRegKey(const vector<string>& serverHistory) { void saveHistoryToRegKey(const vector<string>& serverHistory) {
HKEY hKey; HKEY hKey;
} }
} }


// Remove read-only parameters to replicate the behaviour of Linux/macOS when they
// store a config to disk. If the parameter hasn't been migrated at this point it
// will be lost.
for (size_t i = 0; i < sizeof(readOnlyParameterArray)/sizeof(VoidParameter*); i++)
removeValue(readOnlyParameterArray[i]->getName(), &hKey);

res = RegCloseKey(hKey); res = RegCloseKey(hKey);
if (res != ERROR_SUCCESS) { if (res != ERROR_SUCCESS) {
vlog.error(_("Failed to close registry key: %ld"), res); vlog.error(_("Failed to close registry key: %ld"), res);
} }
} }


static void findAndSetViewerParametersFromReg(VoidParameter* parameters[], size_t parameters_len, HKEY* hKey) {

const size_t buffersize = 256;
int intValue = 0;
char stringValue[buffersize];

for (size_t i = 0; i < parameters_len/sizeof(VoidParameter*); i++) {
if (dynamic_cast<StringParameter*>(parameters[i]) != NULL) {
if (getKeyString(parameters[i]->getName(), stringValue, buffersize, hKey))
parameters[i]->setParam(stringValue);
} else if (dynamic_cast<IntParameter*>(parameters[i]) != NULL) {
if (getKeyInt(parameters[i]->getName(), &intValue, hKey))
((IntParameter*)parameters[i])->setParam(intValue);
} else if (dynamic_cast<BoolParameter*>(parameters[i]) != NULL) {
if (getKeyInt(parameters[i]->getName(), &intValue, hKey))
((BoolParameter*)parameters[i])->setParam(intValue);
} else {
vlog.error(_("Unknown parameter type for parameter %s"),
parameters[i]->getName());
}
}
}

static char* loadFromReg() { static char* loadFromReg() {


HKEY hKey; HKEY hKey;
if (getKeyString("ServerName", servernameBuffer, buffersize, &hKey)) if (getKeyString("ServerName", servernameBuffer, buffersize, &hKey))
snprintf(servername, buffersize, "%s", servernameBuffer); snprintf(servername, buffersize, "%s", servernameBuffer);
int intValue = 0;
char stringValue[buffersize];
for (size_t i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
if (getKeyString(parameterArray[i]->getName(), stringValue, buffersize, &hKey))
parameterArray[i]->setParam(stringValue);
} else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
if (getKeyInt(parameterArray[i]->getName(), &intValue, &hKey))
((IntParameter*)parameterArray[i])->setParam(intValue);
} else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
if (getKeyInt(parameterArray[i]->getName(), &intValue, &hKey))
((BoolParameter*)parameterArray[i])->setParam(intValue);
} else {
vlog.error(_("Unknown parameter type for parameter %s"),
parameterArray[i]->getName());
}
}
findAndSetViewerParametersFromReg(parameterArray, sizeof(parameterArray), &hKey);
findAndSetViewerParametersFromReg(readOnlyParameterArray, sizeof(readOnlyParameterArray), &hKey);


res = RegCloseKey(hKey); res = RegCloseKey(hKey);
if (res != ERROR_SUCCESS){ if (res != ERROR_SUCCESS){
fclose(f); fclose(f);
} }


static bool findAndSetViewerParameterFromValue(
VoidParameter* parameters[], size_t parameters_len,
char* value, char* line, int lineNr, char* filepath)
{
const size_t buffersize = 256;
char decodingBuffer[buffersize];

// Find and set the correct parameter
for (size_t i = 0; i < parameters_len/sizeof(VoidParameter*); i++) {

if (dynamic_cast<StringParameter*>(parameters[i]) != NULL) {
if (strcasecmp(line, ((StringParameter*)parameters[i])->getName()) == 0) {

if(!decodeValue(value, decodingBuffer, sizeof(decodingBuffer))) {
vlog.error(_("Failed to read line %d in file %s: %s"),
lineNr, filepath, _("Invalid format or too large value"));
continue;
}
((StringParameter*)parameters[i])->setParam(decodingBuffer);
return false;
}

} else if (dynamic_cast<IntParameter*>(parameters[i]) != NULL) {
if (strcasecmp(line, ((IntParameter*)parameters[i])->getName()) == 0) {
((IntParameter*)parameters[i])->setParam(atoi(value));
return false;
}

} else if (dynamic_cast<BoolParameter*>(parameters[i]) != NULL) {
if (strcasecmp(line, ((BoolParameter*)parameters[i])->getName()) == 0) {
((BoolParameter*)parameters[i])->setParam(atoi(value));
return false;
}

} else {
vlog.error(_("Unknown parameter type for parameter %s"),
parameters[i]->getName());
}
}

return true;
}


char* loadViewerParameters(const char *filename) { char* loadViewerParameters(const char *filename) {


invalidParameterName = false; invalidParameterName = false;


} else { } else {
invalidParameterName = findAndSetViewerParameterFromValue(parameterArray, sizeof(parameterArray),
value, line, lineNr, filepath);


// Find and set the correct parameter
for (size_t i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {

if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
if (strcasecmp(line, ((StringParameter*)parameterArray[i])->getName()) == 0) {

if(!decodeValue(value, decodingBuffer, sizeof(decodingBuffer))) {
vlog.error(_("Failed to read line %d in file %s: %s"),
lineNr, filepath, _("Invalid format or too large value"));
continue;
}
((StringParameter*)parameterArray[i])->setParam(decodingBuffer);
invalidParameterName = false;
}

} else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
if (strcasecmp(line, ((IntParameter*)parameterArray[i])->getName()) == 0) {
((IntParameter*)parameterArray[i])->setParam(atoi(value));
invalidParameterName = false;
}

} else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
if (strcasecmp(line, ((BoolParameter*)parameterArray[i])->getName()) == 0) {
((BoolParameter*)parameterArray[i])->setParam(atoi(value));
invalidParameterName = false;
}

} else {
vlog.error(_("Unknown parameter type for parameter %s"),
parameterArray[i]->getName());
}
if (invalidParameterName) {
invalidParameterName = findAndSetViewerParameterFromValue(readOnlyParameterArray, sizeof(readOnlyParameterArray),
value, line, lineNr, filepath);
} }
} }



+ 2
- 1
vncviewer/parameters.h View File



extern rfb::BoolParameter maximize; extern rfb::BoolParameter maximize;
extern rfb::BoolParameter fullScreen; extern rfb::BoolParameter fullScreen;
extern rfb::BoolParameter fullScreenAllMonitors;
extern rfb::StringParameter fullScreenMode;
extern rfb::BoolParameter fullScreenAllMonitors; // deprecated
extern rfb::StringParameter desktopSize; extern rfb::StringParameter desktopSize;
extern rfb::StringParameter geometry; extern rfb::StringParameter geometry;
extern rfb::BoolParameter remoteResize; extern rfb::BoolParameter remoteResize;

+ 12
- 0
vncviewer/vncviewer.cxx View File

} }
} }


static void
migrateDeprecatedOptions()
{
if (fullScreenAllMonitors) {
vlog.info(_("FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead."));

fullScreenMode.setParam("all");
}
}

#ifndef WIN32 #ifndef WIN32
static int static int
interpretViaParam(char *remoteHost, int *remotePort, int localPort) interpretViaParam(char *remoteHost, int *remotePort, int localPort)
// Check if the server name in reality is a configuration file // Check if the server name in reality is a configuration file
potentiallyLoadConfigurationFile(vncServerName); potentiallyLoadConfigurationFile(vncServerName);


migrateDeprecatedOptions();

mkvnchomedir(); mkvnchomedir();


CSecurity::upg = &dlg; CSecurity::upg = &dlg;

+ 8
- 2
vncviewer/vncviewer.man View File

Start in full-screen mode. Start in full-screen mode.
. .
.TP .TP
.B \-FullScreenAllMonitors
.B \-FullScreenAllMonitors (DEPRECATED)
Use all local monitors and not just the current one when switching to Use all local monitors and not just the current one when switching to
full-screen mode.
full-screen mode. Replaced by \fB-FullScreenMode=all\fP
.
.TP
.B \-FullScreenMode \fImode\fP
Specify which monitors to use when in full screen. It should be either "Current" or "All".
The default is "Current".
.
. .
.TP .TP
.B \-FullscreenSystemKeys .B \-FullscreenSystemKeys

Loading…
Cancel
Save