blob: 62b5d9c5a0b972b39230164ce619021d3d87d9df [file] [log] [blame] [edit]
/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <list>
#include <rdr/types.h>
#include <rfb/encodings.h>
#ifdef HAVE_GNUTLS
#include <rfb/Security.h>
#include <rfb/SecurityClient.h>
#include <rfb/CSecurityTLS.h>
#endif
#include "OptionsDialog.h"
#include "fltk_layout.h"
#include "i18n.h"
#include "menukey.h"
#include "parameters.h"
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Round_Button.H>
#include <FL/Fl_Int_Input.H>
#include <FL/Fl_Choice.H>
using namespace std;
using namespace rdr;
using namespace rfb;
std::map<OptionsCallback*, void*> OptionsDialog::callbacks;
OptionsDialog::OptionsDialog()
: Fl_Window(450, 450, _("VNC Viewer: Connection Options"))
{
int x, y;
Fl_Button *button;
Fl_Tabs *tabs = new Fl_Tabs(OUTER_MARGIN, OUTER_MARGIN,
w() - OUTER_MARGIN*2,
h() - OUTER_MARGIN*2 - INNER_MARGIN - BUTTON_HEIGHT);
{
int tx, ty, tw, th;
tabs->client_area(tx, ty, tw, th, TABS_HEIGHT);
createCompressionPage(tx, ty, tw, th);
createSecurityPage(tx, ty, tw, th);
createInputPage(tx, ty, tw, th);
createScreenPage(tx, ty, tw, th);
createMiscPage(tx, ty, tw, th);
}
tabs->end();
x = w() - BUTTON_WIDTH * 2 - INNER_MARGIN - OUTER_MARGIN;
y = h() - BUTTON_HEIGHT - OUTER_MARGIN;
button = new Fl_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Cancel"));
button->callback(this->handleCancel, this);
x += BUTTON_WIDTH + INNER_MARGIN;
button = new Fl_Return_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("OK"));
button->callback(this->handleOK, this);
callback(this->handleCancel, this);
set_modal();
}
OptionsDialog::~OptionsDialog()
{
}
void OptionsDialog::showDialog(void)
{
static OptionsDialog *dialog = NULL;
if (!dialog)
dialog = new OptionsDialog();
if (dialog->shown())
return;
dialog->show();
}
void OptionsDialog::addCallback(OptionsCallback *cb, void *data)
{
callbacks[cb] = data;
}
void OptionsDialog::removeCallback(OptionsCallback *cb)
{
callbacks.erase(cb);
}
void OptionsDialog::show(void)
{
/* show() gets called for raise events as well */
if (!shown())
loadOptions();
Fl_Window::show();
}
void OptionsDialog::loadOptions(void)
{
/* Compression */
autoselectCheckbox->value(autoSelect);
int encNum = encodingNum(preferredEncoding);
switch (encNum) {
case encodingTight:
tightButton->setonly();
break;
case encodingZRLE:
zrleButton->setonly();
break;
case encodingHextile:
hextileButton->setonly();
break;
case encodingRaw:
rawButton->setonly();
break;
}
if (fullColour)
fullcolorCheckbox->setonly();
else {
switch (lowColourLevel) {
case 0:
verylowcolorCheckbox->setonly();
break;
case 1:
lowcolorCheckbox->setonly();
break;
case 2:
mediumcolorCheckbox->setonly();
break;
}
}
char digit[2] = "0";
compressionCheckbox->value(customCompressLevel);
jpegCheckbox->value(!noJpeg);
digit[0] = '0' + compressLevel;
compressionInput->value(digit);
digit[0] = '0' + qualityLevel;
jpegInput->value(digit);
handleAutoselect(autoselectCheckbox, this);
handleCompression(compressionCheckbox, this);
handleJpeg(jpegCheckbox, this);
#ifdef HAVE_GNUTLS
/* Security */
Security security(SecurityClient::secTypes);
list<U8> secTypes;
list<U8>::iterator iter;
list<U32> secTypesExt;
list<U32>::iterator iterExt;
encNoneCheckbox->value(false);
encTLSCheckbox->value(false);
encX509Checkbox->value(false);
authNoneCheckbox->value(false);
authVncCheckbox->value(false);
authPlainCheckbox->value(false);
secTypes = security.GetEnabledSecTypes();
for (iter = secTypes.begin(); iter != secTypes.end(); ++iter) {
switch (*iter) {
case secTypeNone:
encNoneCheckbox->value(true);
authNoneCheckbox->value(true);
break;
case secTypeVncAuth:
encNoneCheckbox->value(true);
authVncCheckbox->value(true);
break;
}
}
secTypesExt = security.GetEnabledExtSecTypes();
for (iterExt = secTypesExt.begin(); iterExt != secTypesExt.end(); ++iterExt) {
switch (*iterExt) {
case secTypePlain:
encNoneCheckbox->value(true);
authPlainCheckbox->value(true);
break;
case secTypeTLSNone:
encTLSCheckbox->value(true);
authNoneCheckbox->value(true);
break;
case secTypeTLSVnc:
encTLSCheckbox->value(true);
authVncCheckbox->value(true);
break;
case secTypeTLSPlain:
encTLSCheckbox->value(true);
authPlainCheckbox->value(true);
break;
case secTypeX509None:
encX509Checkbox->value(true);
authNoneCheckbox->value(true);
break;
case secTypeX509Vnc:
encX509Checkbox->value(true);
authVncCheckbox->value(true);
break;
case secTypeX509Plain:
encX509Checkbox->value(true);
authPlainCheckbox->value(true);
break;
}
}
caInput->value(CSecurityTLS::X509CA);
crlInput->value(CSecurityTLS::X509CRL);
handleX509(encX509Checkbox, this);
#endif
/* Input */
const char *menuKeyBuf;
viewOnlyCheckbox->value(viewOnly);
acceptClipboardCheckbox->value(acceptClipboard);
#if !defined(WIN32) && !defined(__APPLE__)
setPrimaryCheckbox->value(setPrimary);
#endif
sendClipboardCheckbox->value(sendClipboard);
#if !defined(WIN32) && !defined(__APPLE__)
sendPrimaryCheckbox->value(sendPrimary);
#endif
systemKeysCheckbox->value(fullscreenSystemKeys);
menuKeyChoice->value(0);
menuKeyBuf = menuKey;
for (int i = 0; i < getMenuKeySymbolCount(); i++)
if (!strcmp(getMenuKeySymbols()[i].name, menuKeyBuf))
menuKeyChoice->value(i + 1);
/* Screen */
int width, height;
if (sscanf((const char*)desktopSize, "%dx%d", &width, &height) != 2) {
desktopSizeCheckbox->value(false);
desktopWidthInput->value("1024");
desktopHeightInput->value("768");
} else {
char buf[32];
desktopSizeCheckbox->value(true);
snprintf(buf, sizeof(buf), "%d", width);
desktopWidthInput->value(buf);
snprintf(buf, sizeof(buf), "%d", height);
desktopHeightInput->value(buf);
}
remoteResizeCheckbox->value(remoteResize);
fullScreenCheckbox->value(fullScreen);
fullScreenAllMonitorsCheckbox->value(fullScreenAllMonitors);
handleDesktopSize(desktopSizeCheckbox, this);
/* Misc. */
sharedCheckbox->value(shared);
dotCursorCheckbox->value(dotWhenNoCursor);
}
void OptionsDialog::storeOptions(void)
{
/* Compression */
autoSelect.setParam(autoselectCheckbox->value());
if (tightButton->value())
preferredEncoding.setParam(encodingName(encodingTight));
else if (zrleButton->value())
preferredEncoding.setParam(encodingName(encodingZRLE));
else if (hextileButton->value())
preferredEncoding.setParam(encodingName(encodingHextile));
else if (rawButton->value())
preferredEncoding.setParam(encodingName(encodingRaw));
fullColour.setParam(fullcolorCheckbox->value());
if (verylowcolorCheckbox->value())
lowColourLevel.setParam(0);
else if (lowcolorCheckbox->value())
lowColourLevel.setParam(1);
else if (mediumcolorCheckbox->value())
lowColourLevel.setParam(2);
customCompressLevel.setParam(compressionCheckbox->value());
noJpeg.setParam(!jpegCheckbox->value());
compressLevel.setParam(atoi(compressionInput->value()));
qualityLevel.setParam(atoi(jpegInput->value()));
#ifdef HAVE_GNUTLS
/* Security */
Security security;
/* Process security types which don't use encryption */
if (encNoneCheckbox->value()) {
if (authNoneCheckbox->value())
security.EnableSecType(secTypeNone);
if (authVncCheckbox->value())
security.EnableSecType(secTypeVncAuth);
if (authPlainCheckbox->value())
security.EnableSecType(secTypePlain);
}
/* Process security types which use TLS encryption */
if (encTLSCheckbox->value()) {
if (authNoneCheckbox->value())
security.EnableSecType(secTypeTLSNone);
if (authVncCheckbox->value())
security.EnableSecType(secTypeTLSVnc);
if (authPlainCheckbox->value())
security.EnableSecType(secTypeTLSPlain);
}
/* Process security types which use X509 encryption */
if (encX509Checkbox->value()) {
if (authNoneCheckbox->value())
security.EnableSecType(secTypeX509None);
if (authVncCheckbox->value())
security.EnableSecType(secTypeX509Vnc);
if (authPlainCheckbox->value())
security.EnableSecType(secTypeX509Plain);
}
SecurityClient::secTypes.setParam(security.ToString());
CSecurityTLS::X509CA.setParam(caInput->value());
CSecurityTLS::X509CRL.setParam(crlInput->value());
#endif
/* Input */
viewOnly.setParam(viewOnlyCheckbox->value());
acceptClipboard.setParam(acceptClipboardCheckbox->value());
#if !defined(WIN32) && !defined(__APPLE__)
setPrimary.setParam(setPrimaryCheckbox->value());
#endif
sendClipboard.setParam(sendClipboardCheckbox->value());
#if !defined(WIN32) && !defined(__APPLE__)
sendPrimary.setParam(sendPrimaryCheckbox->value());
#endif
fullscreenSystemKeys.setParam(systemKeysCheckbox->value());
if (menuKeyChoice->value() == 0)
menuKey.setParam("");
else {
menuKey.setParam(menuKeyChoice->text());
}
/* Screen */
int width, height;
if (desktopSizeCheckbox->value() &&
(sscanf(desktopWidthInput->value(), "%d", &width) == 1) &&
(sscanf(desktopHeightInput->value(), "%d", &height) == 1)) {
char buf[64];
snprintf(buf, sizeof(buf), "%dx%d", width, height);
desktopSize.setParam(buf);
} else {
desktopSize.setParam("");
}
remoteResize.setParam(remoteResizeCheckbox->value());
fullScreen.setParam(fullScreenCheckbox->value());
fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox->value());
/* Misc. */
shared.setParam(sharedCheckbox->value());
dotWhenNoCursor.setParam(dotCursorCheckbox->value());
std::map<OptionsCallback*, void*>::const_iterator iter;
for (iter = callbacks.begin();iter != callbacks.end();++iter)
iter->first(iter->second);
}
void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
{
Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Compression"));
int orig_tx, orig_ty;
int half_width, full_width;
int height;
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
full_width = tw - OUTER_MARGIN * 2;
half_width = (full_width - INNER_MARGIN) / 2;
/* AutoSelect checkbox */
autoselectCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Auto select")));
autoselectCheckbox->callback(handleAutoselect, this);
ty += CHECK_HEIGHT + INNER_MARGIN;
/* Two columns */
orig_tx = tx;
orig_ty = ty;
/* VNC encoding box */
ty += GROUP_LABEL_OFFSET;
height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
encodingGroup = new Fl_Group(tx, ty, half_width, height,
_("Preferred encoding"));
encodingGroup->box(FL_ENGRAVED_BOX);
encodingGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
tx += GROUP_MARGIN;
ty += GROUP_MARGIN;
tightButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
"Tight"));
tightButton->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
zrleButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
"ZRLE"));
zrleButton->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
hextileButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
"Hextile"));
hextileButton->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
rawButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
"Raw"));
rawButton->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
}
ty += GROUP_MARGIN - TIGHT_MARGIN;
encodingGroup->end();
/* Second column */
tx = orig_tx + half_width + INNER_MARGIN;
ty = orig_ty;
/* Color box */
ty += GROUP_LABEL_OFFSET;
height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
colorlevelGroup = new Fl_Group(tx, ty, half_width, height, _("Color level"));
colorlevelGroup->box(FL_ENGRAVED_BOX);
colorlevelGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
tx += GROUP_MARGIN;
ty += GROUP_MARGIN;
fullcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
_("Full (all available colors)")));
fullcolorCheckbox->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
mediumcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
_("Medium (256 colors)")));
mediumcolorCheckbox->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
lowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
_("Low (64 colors)")));
lowcolorCheckbox->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
verylowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
_("Very low (8 colors)")));
verylowcolorCheckbox->type(FL_RADIO_BUTTON);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
}
ty += GROUP_MARGIN - TIGHT_MARGIN;
colorlevelGroup->end();
/* Back to normal */
tx = orig_tx;
ty += INNER_MARGIN;
/* Checkboxes */
compressionCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Custom compression level:")));
compressionCheckbox->callback(handleCompression, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
compressionInput = new Fl_Int_Input(tx + INDENT, ty,
INPUT_HEIGHT, INPUT_HEIGHT,
_("level (1=fast, 6=best [4-6 are rarely useful])"));
compressionInput->align(FL_ALIGN_RIGHT);
ty += INPUT_HEIGHT + INNER_MARGIN;
jpegCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Allow JPEG compression:")));
jpegCheckbox->callback(handleJpeg, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
jpegInput = new Fl_Int_Input(tx + INDENT, ty,
INPUT_HEIGHT, INPUT_HEIGHT,
_("quality (0=poor, 9=best)"));
jpegInput->align(FL_ALIGN_RIGHT);
ty += INPUT_HEIGHT + INNER_MARGIN;
group->end();
}
void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
{
#ifdef HAVE_GNUTLS
Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Security"));
int orig_tx;
int width, height;
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
width = tw - OUTER_MARGIN * 2;
orig_tx = tx;
/* Encryption */
ty += GROUP_LABEL_OFFSET;
height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 4 + CHECK_HEIGHT * 3 + (INPUT_LABEL_OFFSET + INPUT_HEIGHT) * 2;
encryptionGroup = new Fl_Group(tx, ty, width, height, _("Encryption"));
encryptionGroup->box(FL_ENGRAVED_BOX);
encryptionGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
tx += GROUP_MARGIN;
ty += GROUP_MARGIN;
encNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("None")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
encTLSCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("TLS with anonymous certificates")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
encX509Checkbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("TLS with X509 certificates")));
encX509Checkbox->callback(handleX509, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
ty += INPUT_LABEL_OFFSET;
caInput = new Fl_Input(tx + INDENT, ty,
width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
_("Path to X509 CA certificate"));
caInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
ty += INPUT_HEIGHT + TIGHT_MARGIN;
ty += INPUT_LABEL_OFFSET;
crlInput = new Fl_Input(tx + INDENT, ty,
width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
_("Path to X509 CRL file"));
crlInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
ty += INPUT_HEIGHT + TIGHT_MARGIN;
}
ty += GROUP_MARGIN - TIGHT_MARGIN;
encryptionGroup->end();
/* Back to normal */
tx = orig_tx;
ty += INNER_MARGIN;
/* Authentication */
ty += GROUP_LABEL_OFFSET;
height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 2 + CHECK_HEIGHT * 3;
authenticationGroup = new Fl_Group(tx, ty, width, height, _("Authentication"));
authenticationGroup->box(FL_ENGRAVED_BOX);
authenticationGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
tx += GROUP_MARGIN;
ty += GROUP_MARGIN;
authNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("None")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
authVncCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Standard VNC (insecure without encryption)")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
authPlainCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Username and password (insecure without encryption)")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
}
ty += GROUP_MARGIN - TIGHT_MARGIN;
authenticationGroup->end();
/* Back to normal */
tx = orig_tx;
ty += INNER_MARGIN;
group->end();
#endif
}
void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
{
Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Input"));
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
viewOnlyCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("View only (ignore mouse and keyboard)")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
acceptClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Accept clipboard from server")));
acceptClipboardCheckbox->callback(handleClipboard, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
#if !defined(WIN32) && !defined(__APPLE__)
setPrimaryCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Also set primary selection")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
#endif
sendClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Send clipboard to server")));
sendClipboardCheckbox->callback(handleClipboard, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
#if !defined(WIN32) && !defined(__APPLE__)
sendPrimaryCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Send primary selection as clipboard")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
#endif
systemKeysCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Pass system keys directly to server (full screen)")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
menuKeyChoice = new Fl_Choice(LBLLEFT(tx, ty, 150, CHOICE_HEIGHT, _("Menu key")));
fltk_menu_add(menuKeyChoice, _("None"), 0, NULL, (void*)0, FL_MENU_DIVIDER);
for (int i = 0; i < getMenuKeySymbolCount(); i++)
fltk_menu_add(menuKeyChoice, getMenuKeySymbols()[i].name, 0, NULL, 0, 0);
ty += CHOICE_HEIGHT + TIGHT_MARGIN;
group->end();
}
void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
{
int x;
Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Screen"));
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
desktopSizeCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Resize remote session on connect")));
desktopSizeCheckbox->callback(handleDesktopSize, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
desktopWidthInput = new Fl_Int_Input(tx + INDENT, ty, 50, INPUT_HEIGHT);
x = desktopWidthInput->x() + desktopWidthInput->w() + \
gui_str_len("x") + 3 * 2;
desktopHeightInput = new Fl_Int_Input(x, ty, 50, INPUT_HEIGHT, "x");
ty += INPUT_HEIGHT + TIGHT_MARGIN;
remoteResizeCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Resize remote session to the local window")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Full-screen mode")));
ty += CHECK_HEIGHT + TIGHT_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;
group->end();
}
void OptionsDialog::createMiscPage(int tx, int ty, int tw, int th)
{
Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Misc."));
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
sharedCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Shared (don't disconnect other viewers)")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
dotCursorCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Show dot when no cursor")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
group->end();
}
void OptionsDialog::handleAutoselect(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;
if (dialog->autoselectCheckbox->value()) {
dialog->encodingGroup->deactivate();
dialog->colorlevelGroup->deactivate();
} else {
dialog->encodingGroup->activate();
dialog->colorlevelGroup->activate();
}
// JPEG setting is also affected by autoselection
dialog->handleJpeg(dialog->jpegCheckbox, dialog);
}
void OptionsDialog::handleCompression(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;
if (dialog->compressionCheckbox->value())
dialog->compressionInput->activate();
else
dialog->compressionInput->deactivate();
}
void OptionsDialog::handleJpeg(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;
if (dialog->jpegCheckbox->value() &&
!dialog->autoselectCheckbox->value())
dialog->jpegInput->activate();
else
dialog->jpegInput->deactivate();
}
void OptionsDialog::handleX509(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;
if (dialog->encX509Checkbox->value()) {
dialog->caInput->activate();
dialog->crlInput->activate();
} else {
dialog->caInput->deactivate();
dialog->crlInput->deactivate();
}
}
void OptionsDialog::handleDesktopSize(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;
if (dialog->desktopSizeCheckbox->value()) {
dialog->desktopWidthInput->activate();
dialog->desktopHeightInput->activate();
} else {
dialog->desktopWidthInput->deactivate();
dialog->desktopHeightInput->deactivate();
}
}
void OptionsDialog::handleClipboard(Fl_Widget *widget, void *data)
{
#if !defined(WIN32) && !defined(__APPLE__)
OptionsDialog *dialog = (OptionsDialog*)data;
if (dialog->acceptClipboardCheckbox->value())
dialog->setPrimaryCheckbox->activate();
else
dialog->setPrimaryCheckbox->deactivate();
if (dialog->sendClipboardCheckbox->value())
dialog->sendPrimaryCheckbox->activate();
else
dialog->sendPrimaryCheckbox->deactivate();
#endif
}
void OptionsDialog::handleCancel(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;
dialog->hide();
}
void OptionsDialog::handleOK(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;
dialog->hide();
dialog->storeOptions();
}