Преглед изворни кода

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 година
родитељ
комит
c084e58692

+ 4
- 3
vncviewer/DesktopWindow.cxx Прегледај датотеку

@@ -880,10 +880,11 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
return ret;
}


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

if (not all_monitors)
fullscreen_screens(-1, -1, -1, -1);
else {
int top, bottom, left, right;
@@ -1377,7 +1378,7 @@ void DesktopWindow::handleOptions(void *data)
self->ungrabKeyboard();

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

+ 40
- 9
vncviewer/OptionsDialog.cxx Прегледај датотеку

@@ -297,7 +297,12 @@ void OptionsDialog::loadOptions(void)
}
remoteResizeCheckbox->value(remoteResize);
fullScreenCheckbox->value(fullScreen);
fullScreenAllMonitorsCheckbox->value(fullScreenAllMonitors);

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

handleDesktopSize(desktopSizeCheckbox, this);

@@ -407,7 +412,12 @@ void OptionsDialog::storeOptions(void)
}
remoteResize.setParam(remoteResizeCheckbox->value());
fullScreen.setParam(fullScreenCheckbox->value());
fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox->value());

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

/* Misc. */
shared.setParam(sharedCheckbox->value());
@@ -755,6 +765,7 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
{
int x;
int width, height;

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

@@ -783,15 +794,35 @@ void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
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();
}


+ 3
- 1
vncviewer/OptionsDialog.h Прегледај датотеку

@@ -125,7 +125,9 @@ protected:
Fl_Int_Input *desktopHeightInput;
Fl_Check_Button *remoteResizeCheckbox;
Fl_Check_Button *fullScreenCheckbox;
Fl_Check_Button *fullScreenAllMonitorsCheckbox;

Fl_Round_Button *currentMonitorButton;
Fl_Round_Button *allMonitorsButton;

/* Misc. */
Fl_Check_Button *sharedCheckbox;

+ 113
- 53
vncviewer/parameters.cxx Прегледај датотеку

@@ -101,10 +101,13 @@ IntParameter qualityLevel("QualityLevel",
8);

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",
"Enable full screen over all monitors",
true);
"[DEPRECATED] Enable full screen over all monitors",
false);
StringParameter desktopSize("DesktopSize",
"Reconfigure desktop size on the server on "
"connect (if possible)", "");
@@ -175,7 +178,7 @@ static VoidParameter* parameterArray[] = {
&noJpeg,
&qualityLevel,
&fullScreen,
&fullScreenAllMonitors,
&fullScreenMode,
&desktopSize,
&remoteResize,
&viewOnly,
@@ -190,6 +193,10 @@ static VoidParameter* parameterArray[] = {
&fullscreenSystemKeys
};

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

// Encoding Table
static struct {
const char first;
@@ -399,6 +406,30 @@ static bool getKeyInt(const char* _name, int* dest, HKEY* hKey) {
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) {
HKEY hKey;
@@ -456,6 +487,12 @@ static void saveToReg(const char* servername) {
}
}

// 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);
if (res != ERROR_SUCCESS) {
vlog.error(_("Failed to close registry key: %ld"), res);
@@ -500,6 +537,29 @@ void loadHistoryFromRegKey(vector<string>& serverHistory) {
}
}

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() {

HKEY hKey;
@@ -523,24 +583,8 @@ static char* loadFromReg() {
if (getKeyString("ServerName", servernameBuffer, buffersize, &hKey))
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);
if (res != ERROR_SUCCESS){
@@ -607,6 +651,48 @@ void saveViewerParameters(const char *filename, const char *servername) {
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) {

@@ -705,38 +791,12 @@ char* loadViewerParameters(const char *filename) {
invalidParameterName = false;

} 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 Прегледај датотеку

@@ -49,7 +49,8 @@ extern rfb::IntParameter qualityLevel;

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

+ 12
- 0
vncviewer/vncviewer.cxx Прегледај датотеку

@@ -435,6 +435,16 @@ potentiallyLoadConfigurationFile(char *vncServerName)
}
}

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

fullScreenMode.setParam("all");
}
}

#ifndef WIN32
static int
interpretViaParam(char *remoteHost, int *remotePort, int localPort)
@@ -613,6 +623,8 @@ int main(int argc, char** argv)
// Check if the server name in reality is a configuration file
potentiallyLoadConfigurationFile(vncServerName);

migrateDeprecatedOptions();

mkvnchomedir();

CSecurity::upg = &dlg;

+ 8
- 2
vncviewer/vncviewer.man Прегледај датотеку

@@ -205,9 +205,15 @@ Maximize viewer window.
Start in full-screen mode.
.
.TP
.B \-FullScreenAllMonitors
.B \-FullScreenAllMonitors (DEPRECATED)
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
.B \-FullscreenSystemKeys

Loading…
Откажи
Сачувај