blob: d3ed33346a2dec0eb241e00827013001405820da [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>
44#include <FL/Fl_Return_Button.H>
45
Pierre Ossmand463b572011-05-16 12:04:43 +000046using namespace std;
47using namespace rdr;
48using namespace rfb;
49
Pierre Ossman0c41e1d2011-05-17 09:36:04 +000050std::map<OptionsCallback*, void*> OptionsDialog::callbacks;
51
Pierre Ossmand463b572011-05-16 12:04:43 +000052OptionsDialog::OptionsDialog()
53 : Fl_Window(450, 450, _("VNC Viewer: Connection Options"))
54{
55 int x, y;
56 Fl_Button *button;
57
58 Fl_Tabs *tabs = new Fl_Tabs(OUTER_MARGIN, OUTER_MARGIN,
59 w() - OUTER_MARGIN*2,
60 h() - OUTER_MARGIN*2 - INNER_MARGIN - BUTTON_HEIGHT);
61
62 {
63 int tx, ty, tw, th;
64
65 tabs->client_area(tx, ty, tw, th, TABS_HEIGHT);
66
67 createCompressionPage(tx, ty, tw, th);
68 createSecurityPage(tx, ty, tw, th);
69 createInputPage(tx, ty, tw, th);
Pierre Ossman1c2189b2012-07-05 09:23:03 +000070 createScreenPage(tx, ty, tw, th);
Pierre Ossmand463b572011-05-16 12:04:43 +000071 createMiscPage(tx, ty, tw, th);
72 }
73
74 tabs->end();
75
76 x = w() - BUTTON_WIDTH * 2 - INNER_MARGIN - OUTER_MARGIN;
77 y = h() - BUTTON_HEIGHT - OUTER_MARGIN;
78
79 button = new Fl_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Cancel"));
80 button->callback(this->handleCancel, this);
81
82 x += BUTTON_WIDTH + INNER_MARGIN;
83
84 button = new Fl_Return_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("OK"));
85 button->callback(this->handleOK, this);
86
87 callback(this->handleCancel, this);
88
89 set_modal();
90}
91
92
93OptionsDialog::~OptionsDialog()
94{
95}
96
97
98void OptionsDialog::showDialog(void)
99{
100 static OptionsDialog *dialog = NULL;
101
102 if (!dialog)
103 dialog = new OptionsDialog();
104
105 if (dialog->shown())
106 return;
107
108 dialog->show();
109}
110
111
Pierre Ossman0c41e1d2011-05-17 09:36:04 +0000112void OptionsDialog::addCallback(OptionsCallback *cb, void *data)
113{
114 callbacks[cb] = data;
115}
116
117
118void OptionsDialog::removeCallback(OptionsCallback *cb)
119{
120 callbacks.erase(cb);
121}
122
123
Pierre Ossmand463b572011-05-16 12:04:43 +0000124void OptionsDialog::show(void)
125{
Pierre Ossman33a233b2011-09-30 12:21:58 +0000126 /* show() gets called for raise events as well */
127 if (!shown())
128 loadOptions();
Pierre Ossmand463b572011-05-16 12:04:43 +0000129
130 Fl_Window::show();
131}
132
133
134void OptionsDialog::loadOptions(void)
135{
136 /* Compression */
137 autoselectCheckbox->value(autoSelect);
138
139 int encNum = encodingNum(preferredEncoding);
140
141 switch (encNum) {
142 case encodingTight:
143 tightButton->setonly();
144 break;
145 case encodingZRLE:
146 zrleButton->setonly();
147 break;
148 case encodingHextile:
149 hextileButton->setonly();
150 break;
151 case encodingRaw:
152 rawButton->setonly();
153 break;
154 }
155
156 if (fullColour)
157 fullcolorCheckbox->setonly();
158 else {
159 switch (lowColourLevel) {
160 case 0:
Pierre Ossmancf836f22011-07-14 14:34:09 +0000161 verylowcolorCheckbox->setonly();
Pierre Ossmand463b572011-05-16 12:04:43 +0000162 break;
163 case 1:
164 lowcolorCheckbox->setonly();
165 break;
166 case 2:
Pierre Ossmancf836f22011-07-14 14:34:09 +0000167 mediumcolorCheckbox->setonly();
Pierre Ossmand463b572011-05-16 12:04:43 +0000168 break;
169 }
170 }
171
172 char digit[2] = "0";
173
174 compressionCheckbox->value(customCompressLevel);
175 jpegCheckbox->value(!noJpeg);
176 digit[0] = '0' + compressLevel;
177 compressionInput->value(digit);
178 digit[0] = '0' + qualityLevel;
179 jpegInput->value(digit);
180
181 handleAutoselect(autoselectCheckbox, this);
182 handleCompression(compressionCheckbox, this);
183 handleJpeg(jpegCheckbox, this);
184
185#ifdef HAVE_GNUTLS
186 /* Security */
187 Security security(SecurityClient::secTypes);
188
189 list<U8> secTypes;
190 list<U8>::iterator iter;
191
192 list<U32> secTypesExt;
193 list<U32>::iterator iterExt;
194
Pierre Ossmand463b572011-05-16 12:04:43 +0000195 encNoneCheckbox->value(false);
196 encTLSCheckbox->value(false);
197 encX509Checkbox->value(false);
198
199 authNoneCheckbox->value(false);
200 authVncCheckbox->value(false);
201 authPlainCheckbox->value(false);
202
203 secTypes = security.GetEnabledSecTypes();
204 for (iter = secTypes.begin(); iter != secTypes.end(); ++iter) {
205 switch (*iter) {
Pierre Ossmand463b572011-05-16 12:04:43 +0000206 case secTypeNone:
207 encNoneCheckbox->value(true);
208 authNoneCheckbox->value(true);
209 break;
210 case secTypeVncAuth:
211 encNoneCheckbox->value(true);
212 authVncCheckbox->value(true);
213 break;
214 }
215 }
216
217 secTypesExt = security.GetEnabledExtSecTypes();
218 for (iterExt = secTypesExt.begin(); iterExt != secTypesExt.end(); ++iterExt) {
219 switch (*iterExt) {
220 case secTypePlain:
221 encNoneCheckbox->value(true);
222 authPlainCheckbox->value(true);
223 break;
224 case secTypeTLSNone:
225 encTLSCheckbox->value(true);
226 authNoneCheckbox->value(true);
227 break;
228 case secTypeTLSVnc:
229 encTLSCheckbox->value(true);
230 authVncCheckbox->value(true);
231 break;
232 case secTypeTLSPlain:
233 encTLSCheckbox->value(true);
234 authPlainCheckbox->value(true);
235 break;
236 case secTypeX509None:
237 encX509Checkbox->value(true);
238 authNoneCheckbox->value(true);
239 break;
240 case secTypeX509Vnc:
241 encX509Checkbox->value(true);
242 authVncCheckbox->value(true);
243 break;
244 case secTypeX509Plain:
245 encX509Checkbox->value(true);
246 authPlainCheckbox->value(true);
247 break;
248 }
249 }
250
251 caInput->value(CSecurityTLS::x509ca);
252 crlInput->value(CSecurityTLS::x509crl);
253
Pierre Ossmand463b572011-05-16 12:04:43 +0000254 handleX509(encX509Checkbox, this);
255#endif
256
257 /* Input */
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000258 const char *menuKeyBuf;
259
Pierre Ossmand463b572011-05-16 12:04:43 +0000260 viewOnlyCheckbox->value(viewOnly);
261 acceptClipboardCheckbox->value(acceptClipboard);
262 sendClipboardCheckbox->value(sendClipboard);
263 sendPrimaryCheckbox->value(sendPrimary);
Pierre Ossman407a5c32011-05-26 14:48:29 +0000264 systemKeysCheckbox->value(fullscreenSystemKeys);
Pierre Ossmand463b572011-05-16 12:04:43 +0000265
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000266 menuKeyChoice->value(0);
267
268 menuKeyBuf = menuKey;
Martin Koegler498ef462011-09-04 07:04:43 +0000269 for (int i = 0; i < getMenuKeySymbolCount(); i++)
270 if (!strcmp(getMenuKeySymbols()[i].name, menuKeyBuf))
271 menuKeyChoice->value(i + 1);
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000272
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000273 /* Screen */
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000274 int width, height;
275
276 if (sscanf(desktopSize.getValueStr(), "%dx%d", &width, &height) != 2) {
277 desktopSizeCheckbox->value(false);
278 desktopWidthInput->value("1024");
279 desktopHeightInput->value("768");
280 } else {
281 char buf[32];
282 desktopSizeCheckbox->value(true);
283 snprintf(buf, sizeof(buf), "%d", width);
284 desktopWidthInput->value(buf);
285 snprintf(buf, sizeof(buf), "%d", height);
286 desktopHeightInput->value(buf);
287 }
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000288 fullScreenCheckbox->value(fullScreen);
289
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000290 handleDesktopSize(desktopSizeCheckbox, this);
291
Pierre Ossmand463b572011-05-16 12:04:43 +0000292 /* Misc. */
293 sharedCheckbox->value(shared);
Pierre Ossmand463b572011-05-16 12:04:43 +0000294 dotCursorCheckbox->value(dotWhenNoCursor);
295}
296
297
298void OptionsDialog::storeOptions(void)
299{
Pierre Ossman61fd4862011-05-16 12:46:51 +0000300 /* Compression */
301 autoSelect.setParam(autoselectCheckbox->value());
302
303 if (tightButton->value())
304 preferredEncoding.setParam(encodingName(encodingTight));
305 else if (zrleButton->value())
306 preferredEncoding.setParam(encodingName(encodingZRLE));
307 else if (hextileButton->value())
308 preferredEncoding.setParam(encodingName(encodingHextile));
309 else if (rawButton->value())
310 preferredEncoding.setParam(encodingName(encodingRaw));
311
312 fullColour.setParam(fullcolorCheckbox->value());
Pierre Ossmancf836f22011-07-14 14:34:09 +0000313 if (verylowcolorCheckbox->value())
Pierre Ossman61fd4862011-05-16 12:46:51 +0000314 lowColourLevel.setParam(0);
315 else if (lowcolorCheckbox->value())
316 lowColourLevel.setParam(1);
Pierre Ossmancf836f22011-07-14 14:34:09 +0000317 else if (mediumcolorCheckbox->value())
Pierre Ossman61fd4862011-05-16 12:46:51 +0000318 lowColourLevel.setParam(2);
319
320 customCompressLevel.setParam(compressionCheckbox->value());
321 noJpeg.setParam(!jpegCheckbox->value());
322 compressLevel.setParam(atoi(compressionInput->value()));
323 qualityLevel.setParam(atoi(jpegInput->value()));
324
325#ifdef HAVE_GNUTLS
326 /* Security */
327 Security security;
328
329 /* Process security types which don't use encryption */
330 if (encNoneCheckbox->value()) {
331 if (authNoneCheckbox->value())
332 security.EnableSecType(secTypeNone);
333 if (authVncCheckbox->value())
334 security.EnableSecType(secTypeVncAuth);
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000335 if (authPlainCheckbox->value())
336 security.EnableSecType(secTypePlain);
Pierre Ossman61fd4862011-05-16 12:46:51 +0000337 }
338
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000339 /* Process security types which use TLS encryption */
340 if (encTLSCheckbox->value()) {
341 if (authNoneCheckbox->value())
342 security.EnableSecType(secTypeTLSNone);
343 if (authVncCheckbox->value())
344 security.EnableSecType(secTypeTLSVnc);
345 if (authPlainCheckbox->value())
346 security.EnableSecType(secTypeTLSPlain);
347 }
Pierre Ossman61fd4862011-05-16 12:46:51 +0000348
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000349 /* Process security types which use X509 encryption */
350 if (encX509Checkbox->value()) {
351 if (authNoneCheckbox->value())
352 security.EnableSecType(secTypeX509None);
353 if (authVncCheckbox->value())
354 security.EnableSecType(secTypeX509Vnc);
355 if (authPlainCheckbox->value())
356 security.EnableSecType(secTypeX509Plain);
Pierre Ossman61fd4862011-05-16 12:46:51 +0000357 }
358
Pierre Ossman5535fe62011-09-30 12:11:52 +0000359 SecurityClient::secTypes.setParam(security.ToString());
360
Pierre Ossman61fd4862011-05-16 12:46:51 +0000361 CSecurityTLS::x509ca.setParam(caInput->value());
362 CSecurityTLS::x509crl.setParam(crlInput->value());
363#endif
364
365 /* Input */
366 viewOnly.setParam(viewOnlyCheckbox->value());
367 acceptClipboard.setParam(acceptClipboardCheckbox->value());
368 sendClipboard.setParam(sendClipboardCheckbox->value());
369 sendPrimary.setParam(sendPrimaryCheckbox->value());
Pierre Ossman407a5c32011-05-26 14:48:29 +0000370 fullscreenSystemKeys.setParam(systemKeysCheckbox->value());
Pierre Ossman61fd4862011-05-16 12:46:51 +0000371
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000372 if (menuKeyChoice->value() == 0)
373 menuKey.setParam("");
374 else {
Martin Koegler498ef462011-09-04 07:04:43 +0000375 menuKey.setParam(menuKeyChoice->text());
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000376 }
377
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000378 /* Screen */
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000379 int width, height;
380
381 if (desktopSizeCheckbox->value() &&
382 (sscanf(desktopWidthInput->value(), "%d", &width) == 1) &&
383 (sscanf(desktopHeightInput->value(), "%d", &height) == 1)) {
384 char buf[64];
385 snprintf(buf, sizeof(buf), "%dx%d", width, height);
386 desktopSize.setParam(buf);
387 } else {
388 desktopSize.setParam("");
389 }
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000390 fullScreen.setParam(fullScreenCheckbox->value());
391
Pierre Ossman61fd4862011-05-16 12:46:51 +0000392 /* Misc. */
393 shared.setParam(sharedCheckbox->value());
Pierre Ossman61fd4862011-05-16 12:46:51 +0000394 dotWhenNoCursor.setParam(dotCursorCheckbox->value());
Pierre Ossman0c41e1d2011-05-17 09:36:04 +0000395
396 std::map<OptionsCallback*, void*>::const_iterator iter;
397
398 for (iter = callbacks.begin();iter != callbacks.end();++iter)
399 iter->first(iter->second);
Pierre Ossmand463b572011-05-16 12:04:43 +0000400}
401
402
403void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
404{
405 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Compression"));
406
407 int orig_tx, orig_ty;
408 int half_width, full_width;
409 int width, height;
410
411 tx += OUTER_MARGIN;
412 ty += OUTER_MARGIN;
413
414 full_width = tw - OUTER_MARGIN * 2;
415 half_width = (full_width - INNER_MARGIN) / 2;
416
417 /* AutoSelect checkbox */
418 autoselectCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
419 CHECK_MIN_WIDTH,
420 CHECK_HEIGHT,
421 _("Auto select")));
422 autoselectCheckbox->callback(handleAutoselect, this);
423 ty += CHECK_HEIGHT + INNER_MARGIN;
424
425 /* Two columns */
426 orig_tx = tx;
427 orig_ty = ty;
428
429 /* VNC encoding box */
430 ty += GROUP_LABEL_OFFSET;
431 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
432 encodingGroup = new Fl_Group(tx, ty, half_width, height,
433 _("Preferred encoding"));
434 encodingGroup->box(FL_ENGRAVED_BOX);
435 encodingGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
436
437 {
438 tx += GROUP_MARGIN;
439 ty += GROUP_MARGIN;
440
441 width = encodingGroup->w() - GROUP_MARGIN * 2;
442
443 tightButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
444 RADIO_MIN_WIDTH,
445 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000446 "Tight"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000447 tightButton->type(FL_RADIO_BUTTON);
448 ty += RADIO_HEIGHT + TIGHT_MARGIN;
449
450 zrleButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
451 RADIO_MIN_WIDTH,
452 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000453 "ZRLE"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000454 zrleButton->type(FL_RADIO_BUTTON);
455 ty += RADIO_HEIGHT + TIGHT_MARGIN;
456
457 hextileButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
458 RADIO_MIN_WIDTH,
459 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000460 "Hextile"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000461 hextileButton->type(FL_RADIO_BUTTON);
462 ty += RADIO_HEIGHT + TIGHT_MARGIN;
463
464 rawButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
465 RADIO_MIN_WIDTH,
466 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000467 "Raw"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000468 rawButton->type(FL_RADIO_BUTTON);
469 ty += RADIO_HEIGHT + TIGHT_MARGIN;
470 }
471
472 ty += GROUP_MARGIN - TIGHT_MARGIN;
473
474 encodingGroup->end();
475
476 /* Second column */
477 tx = orig_tx + half_width + INNER_MARGIN;
478 ty = orig_ty;
479
480 /* Color box */
481 ty += GROUP_LABEL_OFFSET;
482 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
483 colorlevelGroup = new Fl_Group(tx, ty, half_width, height, _("Color level"));
484 colorlevelGroup->box(FL_ENGRAVED_BOX);
485 colorlevelGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
486
487 {
488 tx += GROUP_MARGIN;
489 ty += GROUP_MARGIN;
490
491 width = colorlevelGroup->w() - GROUP_MARGIN * 2;
492
493 fullcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
494 RADIO_MIN_WIDTH,
495 RADIO_HEIGHT,
496 _("Full (all available colors)")));
497 fullcolorCheckbox->type(FL_RADIO_BUTTON);
498 ty += RADIO_HEIGHT + TIGHT_MARGIN;
499
500 mediumcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
501 RADIO_MIN_WIDTH,
502 RADIO_HEIGHT,
503 _("Medium (256 colors)")));
504 mediumcolorCheckbox->type(FL_RADIO_BUTTON);
505 ty += RADIO_HEIGHT + TIGHT_MARGIN;
506
507 lowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
508 RADIO_MIN_WIDTH,
509 RADIO_HEIGHT,
510 _("Low (64 colors)")));
511 lowcolorCheckbox->type(FL_RADIO_BUTTON);
512 ty += RADIO_HEIGHT + TIGHT_MARGIN;
513
514 verylowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
515 RADIO_MIN_WIDTH,
516 RADIO_HEIGHT,
517 _("Very low (8 colors)")));
518 verylowcolorCheckbox->type(FL_RADIO_BUTTON);
519 ty += RADIO_HEIGHT + TIGHT_MARGIN;
520 }
521
522 ty += GROUP_MARGIN - TIGHT_MARGIN;
523
524 colorlevelGroup->end();
525
526 /* Back to normal */
527 tx = orig_tx;
528 ty += INNER_MARGIN;
529
530 /* Checkboxes */
531 compressionCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
532 CHECK_MIN_WIDTH,
533 CHECK_HEIGHT,
534 _("Custom compression level:")));
535 compressionCheckbox->callback(handleCompression, this);
536 ty += CHECK_HEIGHT + TIGHT_MARGIN;
537
538 compressionInput = new Fl_Int_Input(tx + INDENT, ty,
539 INPUT_HEIGHT, INPUT_HEIGHT,
DRCba7bc512011-08-17 02:30:34 +0000540 _("level (1=fast, 6=best [4-6 are rarely useful])"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000541 compressionInput->align(FL_ALIGN_RIGHT);
542 ty += INPUT_HEIGHT + INNER_MARGIN;
543
544 jpegCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
545 CHECK_MIN_WIDTH,
546 CHECK_HEIGHT,
547 _("Allow JPEG compression:")));
548 jpegCheckbox->callback(handleJpeg, this);
549 ty += CHECK_HEIGHT + TIGHT_MARGIN;
550
551 jpegInput = new Fl_Int_Input(tx + INDENT, ty,
552 INPUT_HEIGHT, INPUT_HEIGHT,
DRC41036ed2011-08-23 20:36:50 +0000553 _("quality (0=poor, 9=best)"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000554 jpegInput->align(FL_ALIGN_RIGHT);
555 ty += INPUT_HEIGHT + INNER_MARGIN;
556
557 group->end();
558}
559
560
561void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
562{
563#ifdef HAVE_GNUTLS
564 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Security"));
565
566 int orig_tx;
567 int width, height;
568
569 tx += OUTER_MARGIN;
570 ty += OUTER_MARGIN;
571
572 width = tw - OUTER_MARGIN * 2;
573
574 orig_tx = tx;
575
Pierre Ossmand463b572011-05-16 12:04:43 +0000576 /* Encryption */
577 ty += GROUP_LABEL_OFFSET;
578 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 4 + CHECK_HEIGHT * 3 + (INPUT_LABEL_OFFSET + INPUT_HEIGHT) * 2;
579 encryptionGroup = new Fl_Group(tx, ty, width, height, _("Encryption"));
580 encryptionGroup->box(FL_ENGRAVED_BOX);
581 encryptionGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
582
583 {
584 tx += GROUP_MARGIN;
585 ty += GROUP_MARGIN;
586
587 encNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
588 CHECK_MIN_WIDTH,
589 CHECK_HEIGHT,
590 _("None")));
591 ty += CHECK_HEIGHT + TIGHT_MARGIN;
592
593 encTLSCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
594 CHECK_MIN_WIDTH,
595 CHECK_HEIGHT,
596 _("TLS with anonymous certificates")));
597 ty += CHECK_HEIGHT + TIGHT_MARGIN;
598
599 encX509Checkbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
600 CHECK_MIN_WIDTH,
601 CHECK_HEIGHT,
602 _("TLS with X509 certificates")));
603 encX509Checkbox->callback(handleX509, this);
604 ty += CHECK_HEIGHT + TIGHT_MARGIN;
605
606 ty += INPUT_LABEL_OFFSET;
607 caInput = new Fl_Input(tx + INDENT, ty,
608 width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
609 _("Path to X509 CA certificate"));
610 caInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
611 ty += INPUT_HEIGHT + TIGHT_MARGIN;
612
613 ty += INPUT_LABEL_OFFSET;
614 crlInput = new Fl_Input(tx + INDENT, ty,
615 width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
616 _("Path to X509 CRL file"));
617 crlInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
618 ty += INPUT_HEIGHT + TIGHT_MARGIN;
619 }
620
621 ty += GROUP_MARGIN - TIGHT_MARGIN;
622
623 encryptionGroup->end();
624
625 /* Back to normal */
626 tx = orig_tx;
627 ty += INNER_MARGIN;
628
629 /* Authentication */
Pierre Ossmand463b572011-05-16 12:04:43 +0000630 ty += GROUP_LABEL_OFFSET;
631 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 2 + CHECK_HEIGHT * 3;
632 authenticationGroup = new Fl_Group(tx, ty, width, height, _("Authentication"));
633 authenticationGroup->box(FL_ENGRAVED_BOX);
634 authenticationGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
635
636 {
637 tx += GROUP_MARGIN;
638 ty += GROUP_MARGIN;
639
640 authNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
641 CHECK_MIN_WIDTH,
642 CHECK_HEIGHT,
643 _("None")));
644 ty += CHECK_HEIGHT + TIGHT_MARGIN;
645
646 authVncCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
647 CHECK_MIN_WIDTH,
648 CHECK_HEIGHT,
649 _("Standard VNC (insecure without encryption)")));
650 ty += CHECK_HEIGHT + TIGHT_MARGIN;
651
652 authPlainCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
653 CHECK_MIN_WIDTH,
654 CHECK_HEIGHT,
655 _("Username and password (insecure without encryption)")));
656 ty += CHECK_HEIGHT + TIGHT_MARGIN;
657 }
658
659 ty += GROUP_MARGIN - TIGHT_MARGIN;
660
661 authenticationGroup->end();
662
663 /* Back to normal */
664 tx = orig_tx;
665 ty += INNER_MARGIN;
666
667 group->end();
668#endif
669}
670
671
672void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
673{
674 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Input"));
675
676 tx += OUTER_MARGIN;
677 ty += OUTER_MARGIN;
678
679 viewOnlyCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
680 CHECK_MIN_WIDTH,
681 CHECK_HEIGHT,
682 _("View only (ignore mouse and keyboard)")));
683 ty += CHECK_HEIGHT + TIGHT_MARGIN;
684
685 acceptClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
686 CHECK_MIN_WIDTH,
687 CHECK_HEIGHT,
688 _("Accept clipboard from server")));
689 ty += CHECK_HEIGHT + TIGHT_MARGIN;
690
691 sendClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
692 CHECK_MIN_WIDTH,
693 CHECK_HEIGHT,
694 _("Send clipboard to server")));
695 ty += CHECK_HEIGHT + TIGHT_MARGIN;
696
697 sendPrimaryCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
698 CHECK_MIN_WIDTH,
699 CHECK_HEIGHT,
700 _("Send primary selection and cut buffer as clipboard")));
701 ty += CHECK_HEIGHT + TIGHT_MARGIN;
702
Pierre Ossman407a5c32011-05-26 14:48:29 +0000703 systemKeysCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
704 CHECK_MIN_WIDTH,
705 CHECK_HEIGHT,
706 _("Pass system keys directly to server (full screen)")));
707 ty += CHECK_HEIGHT + TIGHT_MARGIN;
708
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000709 menuKeyChoice = new Fl_Choice(LBLLEFT(tx, ty, 150, CHOICE_HEIGHT, _("Menu key")));
710
711 menuKeyChoice->add(_("None"), 0, NULL, (void*)0, FL_MENU_DIVIDER);
Martin Koegler498ef462011-09-04 07:04:43 +0000712 for (int i = 0; i < getMenuKeySymbolCount(); i++)
713 menuKeyChoice->add(getMenuKeySymbols()[i].name, 0, NULL, 0, 0);
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000714
715 ty += CHOICE_HEIGHT + TIGHT_MARGIN;
716
Pierre Ossmand463b572011-05-16 12:04:43 +0000717 group->end();
718}
719
720
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000721void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
722{
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000723 int x;
724
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000725 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Screen"));
726
727 tx += OUTER_MARGIN;
728 ty += OUTER_MARGIN;
729
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000730 desktopSizeCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
731 CHECK_MIN_WIDTH,
732 CHECK_HEIGHT,
733 _("Resize remote session on connect")));
734 desktopSizeCheckbox->callback(handleDesktopSize, this);
735 ty += CHECK_HEIGHT + TIGHT_MARGIN;
736
737 desktopWidthInput = new Fl_Int_Input(tx + INDENT, ty, 50, INPUT_HEIGHT);
738 x = desktopWidthInput->x() + desktopWidthInput->w() + \
739 gui_str_len("x") + 3 * 2;
740 desktopHeightInput = new Fl_Int_Input(x, ty, 50, INPUT_HEIGHT, "x");
741 ty += INPUT_HEIGHT + TIGHT_MARGIN;
742
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000743 fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
744 CHECK_MIN_WIDTH,
745 CHECK_HEIGHT,
746 _("Full-screen mode")));
747 ty += CHECK_HEIGHT + TIGHT_MARGIN;
748
749 group->end();
750}
751
752
Pierre Ossmand463b572011-05-16 12:04:43 +0000753void OptionsDialog::createMiscPage(int tx, int ty, int tw, int th)
754{
755 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Misc."));
756
757 tx += OUTER_MARGIN;
758 ty += OUTER_MARGIN;
759
760 sharedCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
761 CHECK_MIN_WIDTH,
762 CHECK_HEIGHT,
763 _("Shared (don't disconnect other viewers)")));
764 ty += CHECK_HEIGHT + TIGHT_MARGIN;
765
Pierre Ossmand463b572011-05-16 12:04:43 +0000766 dotCursorCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
767 CHECK_MIN_WIDTH,
768 CHECK_HEIGHT,
769 _("Show dot when no cursor")));
770 ty += CHECK_HEIGHT + TIGHT_MARGIN;
771
772 group->end();
773}
774
775
776void OptionsDialog::handleAutoselect(Fl_Widget *widget, void *data)
777{
778 OptionsDialog *dialog = (OptionsDialog*)data;
779
780 if (dialog->autoselectCheckbox->value()) {
781 dialog->encodingGroup->deactivate();
782 dialog->colorlevelGroup->deactivate();
783 } else {
784 dialog->encodingGroup->activate();
785 dialog->colorlevelGroup->activate();
786 }
787
788 // JPEG setting is also affected by autoselection
789 dialog->handleJpeg(dialog->jpegCheckbox, dialog);
790}
791
792
793void OptionsDialog::handleCompression(Fl_Widget *widget, void *data)
794{
795 OptionsDialog *dialog = (OptionsDialog*)data;
796
797 if (dialog->compressionCheckbox->value())
798 dialog->compressionInput->activate();
799 else
800 dialog->compressionInput->deactivate();
801}
802
803
804void OptionsDialog::handleJpeg(Fl_Widget *widget, void *data)
805{
806 OptionsDialog *dialog = (OptionsDialog*)data;
807
808 if (dialog->jpegCheckbox->value() &&
809 !dialog->autoselectCheckbox->value())
810 dialog->jpegInput->activate();
811 else
812 dialog->jpegInput->deactivate();
813}
814
815
Pierre Ossmand463b572011-05-16 12:04:43 +0000816void OptionsDialog::handleX509(Fl_Widget *widget, void *data)
817{
818 OptionsDialog *dialog = (OptionsDialog*)data;
819
820 if (dialog->encX509Checkbox->value()) {
821 dialog->caInput->activate();
822 dialog->crlInput->activate();
823 } else {
824 dialog->caInput->deactivate();
825 dialog->crlInput->deactivate();
826 }
827}
828
829
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000830void OptionsDialog::handleDesktopSize(Fl_Widget *widget, void *data)
831{
832 OptionsDialog *dialog = (OptionsDialog*)data;
833
834 if (dialog->desktopSizeCheckbox->value()) {
835 dialog->desktopWidthInput->activate();
836 dialog->desktopHeightInput->activate();
837 } else {
838 dialog->desktopWidthInput->deactivate();
839 dialog->desktopHeightInput->deactivate();
840 }
841}
842
Pierre Ossmand463b572011-05-16 12:04:43 +0000843void OptionsDialog::handleCancel(Fl_Widget *widget, void *data)
844{
845 OptionsDialog *dialog = (OptionsDialog*)data;
846
847 dialog->hide();
848}
849
850
851void OptionsDialog::handleOK(Fl_Widget *widget, void *data)
852{
853 OptionsDialog *dialog = (OptionsDialog*)data;
854
855 dialog->hide();
856
857 dialog->storeOptions();
858}