blob: 2f9df9c4013199638f7861065c48301ad3f0819a [file] [log] [blame]
Pierre Ossmand463b572011-05-16 12:04:43 +00001/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
Peter Åstrandc359f362011-08-23 12:04:46 +000019#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
Pierre Ossman61fd4862011-05-16 12:46:51 +000023#include <stdlib.h>
24
Pierre Ossmand463b572011-05-16 12:04:43 +000025#include <list>
26
Pierre Ossmand463b572011-05-16 12:04:43 +000027#include <rdr/types.h>
28#include <rfb/encodings.h>
29
30#ifdef HAVE_GNUTLS
31#include <rfb/Security.h>
32#include <rfb/SecurityClient.h>
33#include <rfb/CSecurityTLS.h>
34#endif
35
36#include "OptionsDialog.h"
37#include "fltk_layout.h"
38#include "i18n.h"
Martin Koegler498ef462011-09-04 07:04:43 +000039#include "menukey.h"
Pierre Ossmand463b572011-05-16 12:04:43 +000040#include "parameters.h"
41
DRCb65bb932011-06-24 03:17:00 +000042#include <FL/Fl_Tabs.H>
43#include <FL/Fl_Button.H>
Pierre Ossman769963f2014-01-20 14:43:52 +010044#include <FL/Fl_Check_Button.H>
DRCb65bb932011-06-24 03:17:00 +000045#include <FL/Fl_Return_Button.H>
Pierre Ossman769963f2014-01-20 14:43:52 +010046#include <FL/Fl_Round_Button.H>
47#include <FL/Fl_Int_Input.H>
48#include <FL/Fl_Choice.H>
DRCb65bb932011-06-24 03:17:00 +000049
Pierre Ossmand463b572011-05-16 12:04:43 +000050using namespace std;
51using namespace rdr;
52using namespace rfb;
53
Pierre Ossman0c41e1d2011-05-17 09:36:04 +000054std::map<OptionsCallback*, void*> OptionsDialog::callbacks;
55
Pierre Ossmand463b572011-05-16 12:04:43 +000056OptionsDialog::OptionsDialog()
57 : Fl_Window(450, 450, _("VNC Viewer: Connection Options"))
58{
59 int x, y;
60 Fl_Button *button;
61
62 Fl_Tabs *tabs = new Fl_Tabs(OUTER_MARGIN, OUTER_MARGIN,
63 w() - OUTER_MARGIN*2,
64 h() - OUTER_MARGIN*2 - INNER_MARGIN - BUTTON_HEIGHT);
65
66 {
67 int tx, ty, tw, th;
68
69 tabs->client_area(tx, ty, tw, th, TABS_HEIGHT);
70
71 createCompressionPage(tx, ty, tw, th);
72 createSecurityPage(tx, ty, tw, th);
73 createInputPage(tx, ty, tw, th);
Pierre Ossman1c2189b2012-07-05 09:23:03 +000074 createScreenPage(tx, ty, tw, th);
Pierre Ossmand463b572011-05-16 12:04:43 +000075 createMiscPage(tx, ty, tw, th);
76 }
77
78 tabs->end();
79
80 x = w() - BUTTON_WIDTH * 2 - INNER_MARGIN - OUTER_MARGIN;
81 y = h() - BUTTON_HEIGHT - OUTER_MARGIN;
82
83 button = new Fl_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Cancel"));
84 button->callback(this->handleCancel, this);
85
86 x += BUTTON_WIDTH + INNER_MARGIN;
87
88 button = new Fl_Return_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("OK"));
89 button->callback(this->handleOK, this);
90
91 callback(this->handleCancel, this);
92
93 set_modal();
94}
95
96
97OptionsDialog::~OptionsDialog()
98{
99}
100
101
102void OptionsDialog::showDialog(void)
103{
104 static OptionsDialog *dialog = NULL;
105
106 if (!dialog)
107 dialog = new OptionsDialog();
108
109 if (dialog->shown())
110 return;
111
112 dialog->show();
113}
114
115
Pierre Ossman0c41e1d2011-05-17 09:36:04 +0000116void OptionsDialog::addCallback(OptionsCallback *cb, void *data)
117{
118 callbacks[cb] = data;
119}
120
121
122void OptionsDialog::removeCallback(OptionsCallback *cb)
123{
124 callbacks.erase(cb);
125}
126
127
Pierre Ossmand463b572011-05-16 12:04:43 +0000128void OptionsDialog::show(void)
129{
Pierre Ossman33a233b2011-09-30 12:21:58 +0000130 /* show() gets called for raise events as well */
131 if (!shown())
132 loadOptions();
Pierre Ossmand463b572011-05-16 12:04:43 +0000133
134 Fl_Window::show();
135}
136
137
138void OptionsDialog::loadOptions(void)
139{
140 /* Compression */
141 autoselectCheckbox->value(autoSelect);
142
143 int encNum = encodingNum(preferredEncoding);
144
145 switch (encNum) {
146 case encodingTight:
147 tightButton->setonly();
148 break;
149 case encodingZRLE:
150 zrleButton->setonly();
151 break;
152 case encodingHextile:
153 hextileButton->setonly();
154 break;
155 case encodingRaw:
156 rawButton->setonly();
157 break;
158 }
159
160 if (fullColour)
161 fullcolorCheckbox->setonly();
162 else {
163 switch (lowColourLevel) {
164 case 0:
Pierre Ossmancf836f22011-07-14 14:34:09 +0000165 verylowcolorCheckbox->setonly();
Pierre Ossmand463b572011-05-16 12:04:43 +0000166 break;
167 case 1:
168 lowcolorCheckbox->setonly();
169 break;
170 case 2:
Pierre Ossmancf836f22011-07-14 14:34:09 +0000171 mediumcolorCheckbox->setonly();
Pierre Ossmand463b572011-05-16 12:04:43 +0000172 break;
173 }
174 }
175
176 char digit[2] = "0";
177
178 compressionCheckbox->value(customCompressLevel);
179 jpegCheckbox->value(!noJpeg);
180 digit[0] = '0' + compressLevel;
181 compressionInput->value(digit);
182 digit[0] = '0' + qualityLevel;
183 jpegInput->value(digit);
184
185 handleAutoselect(autoselectCheckbox, this);
186 handleCompression(compressionCheckbox, this);
187 handleJpeg(jpegCheckbox, this);
188
189#ifdef HAVE_GNUTLS
190 /* Security */
191 Security security(SecurityClient::secTypes);
192
193 list<U8> secTypes;
194 list<U8>::iterator iter;
195
196 list<U32> secTypesExt;
197 list<U32>::iterator iterExt;
198
Pierre Ossmand463b572011-05-16 12:04:43 +0000199 encNoneCheckbox->value(false);
200 encTLSCheckbox->value(false);
201 encX509Checkbox->value(false);
202
203 authNoneCheckbox->value(false);
204 authVncCheckbox->value(false);
205 authPlainCheckbox->value(false);
206
207 secTypes = security.GetEnabledSecTypes();
208 for (iter = secTypes.begin(); iter != secTypes.end(); ++iter) {
209 switch (*iter) {
Pierre Ossmand463b572011-05-16 12:04:43 +0000210 case secTypeNone:
211 encNoneCheckbox->value(true);
212 authNoneCheckbox->value(true);
213 break;
214 case secTypeVncAuth:
215 encNoneCheckbox->value(true);
216 authVncCheckbox->value(true);
217 break;
218 }
219 }
220
221 secTypesExt = security.GetEnabledExtSecTypes();
222 for (iterExt = secTypesExt.begin(); iterExt != secTypesExt.end(); ++iterExt) {
223 switch (*iterExt) {
224 case secTypePlain:
225 encNoneCheckbox->value(true);
226 authPlainCheckbox->value(true);
227 break;
228 case secTypeTLSNone:
229 encTLSCheckbox->value(true);
230 authNoneCheckbox->value(true);
231 break;
232 case secTypeTLSVnc:
233 encTLSCheckbox->value(true);
234 authVncCheckbox->value(true);
235 break;
236 case secTypeTLSPlain:
237 encTLSCheckbox->value(true);
238 authPlainCheckbox->value(true);
239 break;
240 case secTypeX509None:
241 encX509Checkbox->value(true);
242 authNoneCheckbox->value(true);
243 break;
244 case secTypeX509Vnc:
245 encX509Checkbox->value(true);
246 authVncCheckbox->value(true);
247 break;
248 case secTypeX509Plain:
249 encX509Checkbox->value(true);
250 authPlainCheckbox->value(true);
251 break;
252 }
253 }
254
Pierre Ossman3d2a84b2014-09-17 16:45:35 +0200255 caInput->value(CSecurityTLS::X509CA);
256 crlInput->value(CSecurityTLS::X509CRL);
Pierre Ossmand463b572011-05-16 12:04:43 +0000257
Pierre Ossmand463b572011-05-16 12:04:43 +0000258 handleX509(encX509Checkbox, this);
259#endif
260
261 /* Input */
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000262 const char *menuKeyBuf;
263
Pierre Ossmand463b572011-05-16 12:04:43 +0000264 viewOnlyCheckbox->value(viewOnly);
265 acceptClipboardCheckbox->value(acceptClipboard);
Pierre Ossmanf862c2e2016-03-29 14:15:38 +0200266#if !defined(WIN32) && !defined(__APPLE__)
267 setPrimaryCheckbox->value(setPrimary);
268#endif
Pierre Ossmand463b572011-05-16 12:04:43 +0000269 sendClipboardCheckbox->value(sendClipboard);
Pierre Ossmanf7fef922015-12-10 21:24:08 +0100270#if !defined(WIN32) && !defined(__APPLE__)
Pierre Ossmand463b572011-05-16 12:04:43 +0000271 sendPrimaryCheckbox->value(sendPrimary);
Pierre Ossmanf7fef922015-12-10 21:24:08 +0100272#endif
Pierre Ossman407a5c32011-05-26 14:48:29 +0000273 systemKeysCheckbox->value(fullscreenSystemKeys);
Pierre Ossmand463b572011-05-16 12:04:43 +0000274
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000275 menuKeyChoice->value(0);
276
277 menuKeyBuf = menuKey;
Martin Koegler498ef462011-09-04 07:04:43 +0000278 for (int i = 0; i < getMenuKeySymbolCount(); i++)
279 if (!strcmp(getMenuKeySymbols()[i].name, menuKeyBuf))
280 menuKeyChoice->value(i + 1);
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000281
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000282 /* Screen */
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000283 int width, height;
284
285 if (sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) != 2) {
286 desktopSizeCheckbox->value(false);
287 desktopWidthInput->value("1024");
288 desktopHeightInput->value("768");
289 } else {
290 char buf[32];
291 desktopSizeCheckbox->value(true);
292 snprintf(buf, sizeof(buf), "%d", width);
293 desktopWidthInput->value(buf);
294 snprintf(buf, sizeof(buf), "%d", height);
295 desktopHeightInput->value(buf);
296 }
Pierre Ossman99197012012-07-05 11:06:18 +0000297 remoteResizeCheckbox->value(remoteResize);
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000298 fullScreenCheckbox->value(fullScreen);
Pierre Ossmanaae38912012-07-13 11:22:55 +0000299 fullScreenAllMonitorsCheckbox->value(fullScreenAllMonitors);
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000300
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000301 handleDesktopSize(desktopSizeCheckbox, this);
302
Pierre Ossmand463b572011-05-16 12:04:43 +0000303 /* Misc. */
304 sharedCheckbox->value(shared);
Pierre Ossmand463b572011-05-16 12:04:43 +0000305 dotCursorCheckbox->value(dotWhenNoCursor);
306}
307
308
309void OptionsDialog::storeOptions(void)
310{
Pierre Ossman61fd4862011-05-16 12:46:51 +0000311 /* Compression */
312 autoSelect.setParam(autoselectCheckbox->value());
313
314 if (tightButton->value())
315 preferredEncoding.setParam(encodingName(encodingTight));
316 else if (zrleButton->value())
317 preferredEncoding.setParam(encodingName(encodingZRLE));
318 else if (hextileButton->value())
319 preferredEncoding.setParam(encodingName(encodingHextile));
320 else if (rawButton->value())
321 preferredEncoding.setParam(encodingName(encodingRaw));
322
323 fullColour.setParam(fullcolorCheckbox->value());
Pierre Ossmancf836f22011-07-14 14:34:09 +0000324 if (verylowcolorCheckbox->value())
Pierre Ossman61fd4862011-05-16 12:46:51 +0000325 lowColourLevel.setParam(0);
326 else if (lowcolorCheckbox->value())
327 lowColourLevel.setParam(1);
Pierre Ossmancf836f22011-07-14 14:34:09 +0000328 else if (mediumcolorCheckbox->value())
Pierre Ossman61fd4862011-05-16 12:46:51 +0000329 lowColourLevel.setParam(2);
330
331 customCompressLevel.setParam(compressionCheckbox->value());
332 noJpeg.setParam(!jpegCheckbox->value());
333 compressLevel.setParam(atoi(compressionInput->value()));
334 qualityLevel.setParam(atoi(jpegInput->value()));
335
336#ifdef HAVE_GNUTLS
337 /* Security */
338 Security security;
339
340 /* Process security types which don't use encryption */
341 if (encNoneCheckbox->value()) {
342 if (authNoneCheckbox->value())
343 security.EnableSecType(secTypeNone);
344 if (authVncCheckbox->value())
345 security.EnableSecType(secTypeVncAuth);
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000346 if (authPlainCheckbox->value())
347 security.EnableSecType(secTypePlain);
Pierre Ossman61fd4862011-05-16 12:46:51 +0000348 }
349
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000350 /* Process security types which use TLS encryption */
351 if (encTLSCheckbox->value()) {
352 if (authNoneCheckbox->value())
353 security.EnableSecType(secTypeTLSNone);
354 if (authVncCheckbox->value())
355 security.EnableSecType(secTypeTLSVnc);
356 if (authPlainCheckbox->value())
357 security.EnableSecType(secTypeTLSPlain);
358 }
Pierre Ossman61fd4862011-05-16 12:46:51 +0000359
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000360 /* Process security types which use X509 encryption */
361 if (encX509Checkbox->value()) {
362 if (authNoneCheckbox->value())
363 security.EnableSecType(secTypeX509None);
364 if (authVncCheckbox->value())
365 security.EnableSecType(secTypeX509Vnc);
366 if (authPlainCheckbox->value())
367 security.EnableSecType(secTypeX509Plain);
Pierre Ossman61fd4862011-05-16 12:46:51 +0000368 }
369
Pierre Ossman5535fe62011-09-30 12:11:52 +0000370 SecurityClient::secTypes.setParam(security.ToString());
371
Pierre Ossman3d2a84b2014-09-17 16:45:35 +0200372 CSecurityTLS::X509CA.setParam(caInput->value());
373 CSecurityTLS::X509CRL.setParam(crlInput->value());
Pierre Ossman61fd4862011-05-16 12:46:51 +0000374#endif
375
376 /* Input */
377 viewOnly.setParam(viewOnlyCheckbox->value());
378 acceptClipboard.setParam(acceptClipboardCheckbox->value());
Pierre Ossmanf862c2e2016-03-29 14:15:38 +0200379#if !defined(WIN32) && !defined(__APPLE__)
380 setPrimary.setParam(setPrimaryCheckbox->value());
381#endif
Pierre Ossman61fd4862011-05-16 12:46:51 +0000382 sendClipboard.setParam(sendClipboardCheckbox->value());
Pierre Ossmanf7fef922015-12-10 21:24:08 +0100383#if !defined(WIN32) && !defined(__APPLE__)
Pierre Ossman61fd4862011-05-16 12:46:51 +0000384 sendPrimary.setParam(sendPrimaryCheckbox->value());
Pierre Ossmanf7fef922015-12-10 21:24:08 +0100385#endif
Pierre Ossman407a5c32011-05-26 14:48:29 +0000386 fullscreenSystemKeys.setParam(systemKeysCheckbox->value());
Pierre Ossman61fd4862011-05-16 12:46:51 +0000387
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000388 if (menuKeyChoice->value() == 0)
389 menuKey.setParam("");
390 else {
Martin Koegler498ef462011-09-04 07:04:43 +0000391 menuKey.setParam(menuKeyChoice->text());
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000392 }
393
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000394 /* Screen */
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000395 int width, height;
396
397 if (desktopSizeCheckbox->value() &&
398 (sscanf(desktopWidthInput->value(), "%d", &width) == 1) &&
399 (sscanf(desktopHeightInput->value(), "%d", &height) == 1)) {
400 char buf[64];
401 snprintf(buf, sizeof(buf), "%dx%d", width, height);
402 desktopSize.setParam(buf);
403 } else {
404 desktopSize.setParam("");
405 }
Pierre Ossman99197012012-07-05 11:06:18 +0000406 remoteResize.setParam(remoteResizeCheckbox->value());
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000407 fullScreen.setParam(fullScreenCheckbox->value());
Pierre Ossmanaae38912012-07-13 11:22:55 +0000408 fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox->value());
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000409
Pierre Ossman61fd4862011-05-16 12:46:51 +0000410 /* Misc. */
411 shared.setParam(sharedCheckbox->value());
Pierre Ossman61fd4862011-05-16 12:46:51 +0000412 dotWhenNoCursor.setParam(dotCursorCheckbox->value());
Pierre Ossman0c41e1d2011-05-17 09:36:04 +0000413
414 std::map<OptionsCallback*, void*>::const_iterator iter;
415
416 for (iter = callbacks.begin();iter != callbacks.end();++iter)
417 iter->first(iter->second);
Pierre Ossmand463b572011-05-16 12:04:43 +0000418}
419
420
421void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
422{
423 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Compression"));
424
425 int orig_tx, orig_ty;
426 int half_width, full_width;
Pierre Ossmaneb955322015-03-03 16:10:53 +0100427 int height;
Pierre Ossmand463b572011-05-16 12:04:43 +0000428
429 tx += OUTER_MARGIN;
430 ty += OUTER_MARGIN;
431
432 full_width = tw - OUTER_MARGIN * 2;
433 half_width = (full_width - INNER_MARGIN) / 2;
434
435 /* AutoSelect checkbox */
436 autoselectCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
437 CHECK_MIN_WIDTH,
438 CHECK_HEIGHT,
439 _("Auto select")));
440 autoselectCheckbox->callback(handleAutoselect, this);
441 ty += CHECK_HEIGHT + INNER_MARGIN;
442
443 /* Two columns */
444 orig_tx = tx;
445 orig_ty = ty;
446
447 /* VNC encoding box */
448 ty += GROUP_LABEL_OFFSET;
449 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
450 encodingGroup = new Fl_Group(tx, ty, half_width, height,
451 _("Preferred encoding"));
452 encodingGroup->box(FL_ENGRAVED_BOX);
453 encodingGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
454
455 {
456 tx += GROUP_MARGIN;
457 ty += GROUP_MARGIN;
458
Pierre Ossmand463b572011-05-16 12:04:43 +0000459 tightButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
460 RADIO_MIN_WIDTH,
461 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000462 "Tight"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000463 tightButton->type(FL_RADIO_BUTTON);
464 ty += RADIO_HEIGHT + TIGHT_MARGIN;
465
466 zrleButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
467 RADIO_MIN_WIDTH,
468 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000469 "ZRLE"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000470 zrleButton->type(FL_RADIO_BUTTON);
471 ty += RADIO_HEIGHT + TIGHT_MARGIN;
472
473 hextileButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
474 RADIO_MIN_WIDTH,
475 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000476 "Hextile"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000477 hextileButton->type(FL_RADIO_BUTTON);
478 ty += RADIO_HEIGHT + TIGHT_MARGIN;
479
480 rawButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
481 RADIO_MIN_WIDTH,
482 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000483 "Raw"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000484 rawButton->type(FL_RADIO_BUTTON);
485 ty += RADIO_HEIGHT + TIGHT_MARGIN;
486 }
487
488 ty += GROUP_MARGIN - TIGHT_MARGIN;
489
490 encodingGroup->end();
491
492 /* Second column */
493 tx = orig_tx + half_width + INNER_MARGIN;
494 ty = orig_ty;
495
496 /* Color box */
497 ty += GROUP_LABEL_OFFSET;
498 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
499 colorlevelGroup = new Fl_Group(tx, ty, half_width, height, _("Color level"));
500 colorlevelGroup->box(FL_ENGRAVED_BOX);
501 colorlevelGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
502
503 {
504 tx += GROUP_MARGIN;
505 ty += GROUP_MARGIN;
506
Pierre Ossmand463b572011-05-16 12:04:43 +0000507 fullcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
508 RADIO_MIN_WIDTH,
509 RADIO_HEIGHT,
510 _("Full (all available colors)")));
511 fullcolorCheckbox->type(FL_RADIO_BUTTON);
512 ty += RADIO_HEIGHT + TIGHT_MARGIN;
513
514 mediumcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
515 RADIO_MIN_WIDTH,
516 RADIO_HEIGHT,
517 _("Medium (256 colors)")));
518 mediumcolorCheckbox->type(FL_RADIO_BUTTON);
519 ty += RADIO_HEIGHT + TIGHT_MARGIN;
520
521 lowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
522 RADIO_MIN_WIDTH,
523 RADIO_HEIGHT,
524 _("Low (64 colors)")));
525 lowcolorCheckbox->type(FL_RADIO_BUTTON);
526 ty += RADIO_HEIGHT + TIGHT_MARGIN;
527
528 verylowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
529 RADIO_MIN_WIDTH,
530 RADIO_HEIGHT,
531 _("Very low (8 colors)")));
532 verylowcolorCheckbox->type(FL_RADIO_BUTTON);
533 ty += RADIO_HEIGHT + TIGHT_MARGIN;
534 }
535
536 ty += GROUP_MARGIN - TIGHT_MARGIN;
537
538 colorlevelGroup->end();
539
540 /* Back to normal */
541 tx = orig_tx;
542 ty += INNER_MARGIN;
543
544 /* Checkboxes */
545 compressionCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
546 CHECK_MIN_WIDTH,
547 CHECK_HEIGHT,
548 _("Custom compression level:")));
549 compressionCheckbox->callback(handleCompression, this);
550 ty += CHECK_HEIGHT + TIGHT_MARGIN;
551
552 compressionInput = new Fl_Int_Input(tx + INDENT, ty,
553 INPUT_HEIGHT, INPUT_HEIGHT,
DRCba7bc512011-08-17 02:30:34 +0000554 _("level (1=fast, 6=best [4-6 are rarely useful])"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000555 compressionInput->align(FL_ALIGN_RIGHT);
556 ty += INPUT_HEIGHT + INNER_MARGIN;
557
558 jpegCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
559 CHECK_MIN_WIDTH,
560 CHECK_HEIGHT,
561 _("Allow JPEG compression:")));
562 jpegCheckbox->callback(handleJpeg, this);
563 ty += CHECK_HEIGHT + TIGHT_MARGIN;
564
565 jpegInput = new Fl_Int_Input(tx + INDENT, ty,
566 INPUT_HEIGHT, INPUT_HEIGHT,
DRC41036ed2011-08-23 20:36:50 +0000567 _("quality (0=poor, 9=best)"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000568 jpegInput->align(FL_ALIGN_RIGHT);
569 ty += INPUT_HEIGHT + INNER_MARGIN;
570
571 group->end();
572}
573
574
575void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
576{
577#ifdef HAVE_GNUTLS
578 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Security"));
579
580 int orig_tx;
581 int width, height;
582
583 tx += OUTER_MARGIN;
584 ty += OUTER_MARGIN;
585
586 width = tw - OUTER_MARGIN * 2;
587
588 orig_tx = tx;
589
Pierre Ossmand463b572011-05-16 12:04:43 +0000590 /* Encryption */
591 ty += GROUP_LABEL_OFFSET;
592 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 4 + CHECK_HEIGHT * 3 + (INPUT_LABEL_OFFSET + INPUT_HEIGHT) * 2;
593 encryptionGroup = new Fl_Group(tx, ty, width, height, _("Encryption"));
594 encryptionGroup->box(FL_ENGRAVED_BOX);
595 encryptionGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
596
597 {
598 tx += GROUP_MARGIN;
599 ty += GROUP_MARGIN;
600
601 encNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
602 CHECK_MIN_WIDTH,
603 CHECK_HEIGHT,
604 _("None")));
605 ty += CHECK_HEIGHT + TIGHT_MARGIN;
606
607 encTLSCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
608 CHECK_MIN_WIDTH,
609 CHECK_HEIGHT,
610 _("TLS with anonymous certificates")));
611 ty += CHECK_HEIGHT + TIGHT_MARGIN;
612
613 encX509Checkbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
614 CHECK_MIN_WIDTH,
615 CHECK_HEIGHT,
616 _("TLS with X509 certificates")));
617 encX509Checkbox->callback(handleX509, this);
618 ty += CHECK_HEIGHT + TIGHT_MARGIN;
619
620 ty += INPUT_LABEL_OFFSET;
621 caInput = new Fl_Input(tx + INDENT, ty,
622 width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
623 _("Path to X509 CA certificate"));
624 caInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
625 ty += INPUT_HEIGHT + TIGHT_MARGIN;
626
627 ty += INPUT_LABEL_OFFSET;
628 crlInput = new Fl_Input(tx + INDENT, ty,
629 width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
630 _("Path to X509 CRL file"));
631 crlInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
632 ty += INPUT_HEIGHT + TIGHT_MARGIN;
633 }
634
635 ty += GROUP_MARGIN - TIGHT_MARGIN;
636
637 encryptionGroup->end();
638
639 /* Back to normal */
640 tx = orig_tx;
641 ty += INNER_MARGIN;
642
643 /* Authentication */
Pierre Ossmand463b572011-05-16 12:04:43 +0000644 ty += GROUP_LABEL_OFFSET;
645 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 2 + CHECK_HEIGHT * 3;
646 authenticationGroup = new Fl_Group(tx, ty, width, height, _("Authentication"));
647 authenticationGroup->box(FL_ENGRAVED_BOX);
648 authenticationGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
649
650 {
651 tx += GROUP_MARGIN;
652 ty += GROUP_MARGIN;
653
654 authNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
655 CHECK_MIN_WIDTH,
656 CHECK_HEIGHT,
657 _("None")));
658 ty += CHECK_HEIGHT + TIGHT_MARGIN;
659
660 authVncCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
661 CHECK_MIN_WIDTH,
662 CHECK_HEIGHT,
663 _("Standard VNC (insecure without encryption)")));
664 ty += CHECK_HEIGHT + TIGHT_MARGIN;
665
666 authPlainCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
667 CHECK_MIN_WIDTH,
668 CHECK_HEIGHT,
669 _("Username and password (insecure without encryption)")));
670 ty += CHECK_HEIGHT + TIGHT_MARGIN;
671 }
672
673 ty += GROUP_MARGIN - TIGHT_MARGIN;
674
675 authenticationGroup->end();
676
677 /* Back to normal */
678 tx = orig_tx;
679 ty += INNER_MARGIN;
680
681 group->end();
682#endif
683}
684
685
686void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
687{
688 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Input"));
689
690 tx += OUTER_MARGIN;
691 ty += OUTER_MARGIN;
692
693 viewOnlyCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
694 CHECK_MIN_WIDTH,
695 CHECK_HEIGHT,
696 _("View only (ignore mouse and keyboard)")));
697 ty += CHECK_HEIGHT + TIGHT_MARGIN;
698
699 acceptClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
700 CHECK_MIN_WIDTH,
701 CHECK_HEIGHT,
702 _("Accept clipboard from server")));
703 ty += CHECK_HEIGHT + TIGHT_MARGIN;
704
Pierre Ossmanf862c2e2016-03-29 14:15:38 +0200705#if !defined(WIN32) && !defined(__APPLE__)
706 setPrimaryCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty,
707 CHECK_MIN_WIDTH,
708 CHECK_HEIGHT,
709 _("Also set primary selection")));
710 ty += CHECK_HEIGHT + TIGHT_MARGIN;
711#endif
712
Pierre Ossmand463b572011-05-16 12:04:43 +0000713 sendClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
714 CHECK_MIN_WIDTH,
715 CHECK_HEIGHT,
716 _("Send clipboard to server")));
717 ty += CHECK_HEIGHT + TIGHT_MARGIN;
718
Pierre Ossmanf7fef922015-12-10 21:24:08 +0100719#if !defined(WIN32) && !defined(__APPLE__)
Pierre Ossmand463b572011-05-16 12:04:43 +0000720 sendPrimaryCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
721 CHECK_MIN_WIDTH,
722 CHECK_HEIGHT,
Pierre Ossman57cadc12016-03-29 14:18:36 +0200723 _("Send primary selection as clipboard")));
Pierre Ossmand463b572011-05-16 12:04:43 +0000724 ty += CHECK_HEIGHT + TIGHT_MARGIN;
Pierre Ossmanf7fef922015-12-10 21:24:08 +0100725#endif
Pierre Ossmand463b572011-05-16 12:04:43 +0000726
Pierre Ossman407a5c32011-05-26 14:48:29 +0000727 systemKeysCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
728 CHECK_MIN_WIDTH,
729 CHECK_HEIGHT,
730 _("Pass system keys directly to server (full screen)")));
731 ty += CHECK_HEIGHT + TIGHT_MARGIN;
732
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000733 menuKeyChoice = new Fl_Choice(LBLLEFT(tx, ty, 150, CHOICE_HEIGHT, _("Menu key")));
734
Pierre Ossman245c8022015-02-25 11:27:49 +0100735 fltk_menu_add(menuKeyChoice, _("None"), 0, NULL, (void*)0, FL_MENU_DIVIDER);
Martin Koegler498ef462011-09-04 07:04:43 +0000736 for (int i = 0; i < getMenuKeySymbolCount(); i++)
Pierre Ossman245c8022015-02-25 11:27:49 +0100737 fltk_menu_add(menuKeyChoice, getMenuKeySymbols()[i].name, 0, NULL, 0, 0);
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000738
739 ty += CHOICE_HEIGHT + TIGHT_MARGIN;
740
Pierre Ossmand463b572011-05-16 12:04:43 +0000741 group->end();
742}
743
744
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000745void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
746{
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000747 int x;
748
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000749 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Screen"));
750
751 tx += OUTER_MARGIN;
752 ty += OUTER_MARGIN;
753
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000754 desktopSizeCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
755 CHECK_MIN_WIDTH,
756 CHECK_HEIGHT,
757 _("Resize remote session on connect")));
758 desktopSizeCheckbox->callback(handleDesktopSize, this);
759 ty += CHECK_HEIGHT + TIGHT_MARGIN;
760
761 desktopWidthInput = new Fl_Int_Input(tx + INDENT, ty, 50, INPUT_HEIGHT);
762 x = desktopWidthInput->x() + desktopWidthInput->w() + \
763 gui_str_len("x") + 3 * 2;
764 desktopHeightInput = new Fl_Int_Input(x, ty, 50, INPUT_HEIGHT, "x");
765 ty += INPUT_HEIGHT + TIGHT_MARGIN;
766
Pierre Ossman99197012012-07-05 11:06:18 +0000767 remoteResizeCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
768 CHECK_MIN_WIDTH,
769 CHECK_HEIGHT,
770 _("Resize remote session to the local window")));
771 ty += CHECK_HEIGHT + TIGHT_MARGIN;
772
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000773 fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
774 CHECK_MIN_WIDTH,
775 CHECK_HEIGHT,
776 _("Full-screen mode")));
777 ty += CHECK_HEIGHT + TIGHT_MARGIN;
778
Pierre Ossmanaae38912012-07-13 11:22:55 +0000779 fullScreenAllMonitorsCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty,
780 CHECK_MIN_WIDTH,
781 CHECK_HEIGHT,
782 _("Enable full-screen mode over all monitors")));
783 ty += CHECK_HEIGHT + TIGHT_MARGIN;
784
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000785 group->end();
786}
787
788
Pierre Ossmand463b572011-05-16 12:04:43 +0000789void OptionsDialog::createMiscPage(int tx, int ty, int tw, int th)
790{
791 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Misc."));
792
793 tx += OUTER_MARGIN;
794 ty += OUTER_MARGIN;
795
796 sharedCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
797 CHECK_MIN_WIDTH,
798 CHECK_HEIGHT,
799 _("Shared (don't disconnect other viewers)")));
800 ty += CHECK_HEIGHT + TIGHT_MARGIN;
801
Pierre Ossmand463b572011-05-16 12:04:43 +0000802 dotCursorCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
803 CHECK_MIN_WIDTH,
804 CHECK_HEIGHT,
805 _("Show dot when no cursor")));
806 ty += CHECK_HEIGHT + TIGHT_MARGIN;
807
808 group->end();
809}
810
811
812void OptionsDialog::handleAutoselect(Fl_Widget *widget, void *data)
813{
814 OptionsDialog *dialog = (OptionsDialog*)data;
815
816 if (dialog->autoselectCheckbox->value()) {
817 dialog->encodingGroup->deactivate();
818 dialog->colorlevelGroup->deactivate();
819 } else {
820 dialog->encodingGroup->activate();
821 dialog->colorlevelGroup->activate();
822 }
823
824 // JPEG setting is also affected by autoselection
825 dialog->handleJpeg(dialog->jpegCheckbox, dialog);
826}
827
828
829void OptionsDialog::handleCompression(Fl_Widget *widget, void *data)
830{
831 OptionsDialog *dialog = (OptionsDialog*)data;
832
833 if (dialog->compressionCheckbox->value())
834 dialog->compressionInput->activate();
835 else
836 dialog->compressionInput->deactivate();
837}
838
839
840void OptionsDialog::handleJpeg(Fl_Widget *widget, void *data)
841{
842 OptionsDialog *dialog = (OptionsDialog*)data;
843
844 if (dialog->jpegCheckbox->value() &&
845 !dialog->autoselectCheckbox->value())
846 dialog->jpegInput->activate();
847 else
848 dialog->jpegInput->deactivate();
849}
850
851
Pierre Ossmand463b572011-05-16 12:04:43 +0000852void OptionsDialog::handleX509(Fl_Widget *widget, void *data)
853{
854 OptionsDialog *dialog = (OptionsDialog*)data;
855
856 if (dialog->encX509Checkbox->value()) {
857 dialog->caInput->activate();
858 dialog->crlInput->activate();
859 } else {
860 dialog->caInput->deactivate();
861 dialog->crlInput->deactivate();
862 }
863}
864
865
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000866void OptionsDialog::handleDesktopSize(Fl_Widget *widget, void *data)
867{
868 OptionsDialog *dialog = (OptionsDialog*)data;
869
870 if (dialog->desktopSizeCheckbox->value()) {
871 dialog->desktopWidthInput->activate();
872 dialog->desktopHeightInput->activate();
873 } else {
874 dialog->desktopWidthInput->deactivate();
875 dialog->desktopHeightInput->deactivate();
876 }
877}
878
Pierre Ossmand463b572011-05-16 12:04:43 +0000879void OptionsDialog::handleCancel(Fl_Widget *widget, void *data)
880{
881 OptionsDialog *dialog = (OptionsDialog*)data;
882
883 dialog->hide();
884}
885
886
887void OptionsDialog::handleOK(Fl_Widget *widget, void *data)
888{
889 OptionsDialog *dialog = (OptionsDialog*)data;
890
891 dialog->hide();
892
893 dialog->storeOptions();
894}