blob: c82079f57165f611eca2b014f1f27968dbd9d923 [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 Ossman99197012012-07-05 11:06:18 +0000288 remoteResizeCheckbox->value(remoteResize);
Pierre Ossman2441e822012-07-10 11:11:23 +0000289#ifdef HAVE_FLTK_FULLSCREEN
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000290 fullScreenCheckbox->value(fullScreen);
Pierre Ossman2441e822012-07-10 11:11:23 +0000291#endif // HAVE_FLTK_FULLSCREEN
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000292
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000293 handleDesktopSize(desktopSizeCheckbox, this);
294
Pierre Ossmand463b572011-05-16 12:04:43 +0000295 /* Misc. */
296 sharedCheckbox->value(shared);
Pierre Ossmand463b572011-05-16 12:04:43 +0000297 dotCursorCheckbox->value(dotWhenNoCursor);
298}
299
300
301void OptionsDialog::storeOptions(void)
302{
Pierre Ossman61fd4862011-05-16 12:46:51 +0000303 /* Compression */
304 autoSelect.setParam(autoselectCheckbox->value());
305
306 if (tightButton->value())
307 preferredEncoding.setParam(encodingName(encodingTight));
308 else if (zrleButton->value())
309 preferredEncoding.setParam(encodingName(encodingZRLE));
310 else if (hextileButton->value())
311 preferredEncoding.setParam(encodingName(encodingHextile));
312 else if (rawButton->value())
313 preferredEncoding.setParam(encodingName(encodingRaw));
314
315 fullColour.setParam(fullcolorCheckbox->value());
Pierre Ossmancf836f22011-07-14 14:34:09 +0000316 if (verylowcolorCheckbox->value())
Pierre Ossman61fd4862011-05-16 12:46:51 +0000317 lowColourLevel.setParam(0);
318 else if (lowcolorCheckbox->value())
319 lowColourLevel.setParam(1);
Pierre Ossmancf836f22011-07-14 14:34:09 +0000320 else if (mediumcolorCheckbox->value())
Pierre Ossman61fd4862011-05-16 12:46:51 +0000321 lowColourLevel.setParam(2);
322
323 customCompressLevel.setParam(compressionCheckbox->value());
324 noJpeg.setParam(!jpegCheckbox->value());
325 compressLevel.setParam(atoi(compressionInput->value()));
326 qualityLevel.setParam(atoi(jpegInput->value()));
327
328#ifdef HAVE_GNUTLS
329 /* Security */
330 Security security;
331
332 /* Process security types which don't use encryption */
333 if (encNoneCheckbox->value()) {
334 if (authNoneCheckbox->value())
335 security.EnableSecType(secTypeNone);
336 if (authVncCheckbox->value())
337 security.EnableSecType(secTypeVncAuth);
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000338 if (authPlainCheckbox->value())
339 security.EnableSecType(secTypePlain);
Pierre Ossman61fd4862011-05-16 12:46:51 +0000340 }
341
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000342 /* Process security types which use TLS encryption */
343 if (encTLSCheckbox->value()) {
344 if (authNoneCheckbox->value())
345 security.EnableSecType(secTypeTLSNone);
346 if (authVncCheckbox->value())
347 security.EnableSecType(secTypeTLSVnc);
348 if (authPlainCheckbox->value())
349 security.EnableSecType(secTypeTLSPlain);
350 }
Pierre Ossman61fd4862011-05-16 12:46:51 +0000351
Pierre Ossmanc1764bd2011-09-30 12:26:25 +0000352 /* Process security types which use X509 encryption */
353 if (encX509Checkbox->value()) {
354 if (authNoneCheckbox->value())
355 security.EnableSecType(secTypeX509None);
356 if (authVncCheckbox->value())
357 security.EnableSecType(secTypeX509Vnc);
358 if (authPlainCheckbox->value())
359 security.EnableSecType(secTypeX509Plain);
Pierre Ossman61fd4862011-05-16 12:46:51 +0000360 }
361
Pierre Ossman5535fe62011-09-30 12:11:52 +0000362 SecurityClient::secTypes.setParam(security.ToString());
363
Pierre Ossman61fd4862011-05-16 12:46:51 +0000364 CSecurityTLS::x509ca.setParam(caInput->value());
365 CSecurityTLS::x509crl.setParam(crlInput->value());
366#endif
367
368 /* Input */
369 viewOnly.setParam(viewOnlyCheckbox->value());
370 acceptClipboard.setParam(acceptClipboardCheckbox->value());
371 sendClipboard.setParam(sendClipboardCheckbox->value());
372 sendPrimary.setParam(sendPrimaryCheckbox->value());
Pierre Ossman407a5c32011-05-26 14:48:29 +0000373 fullscreenSystemKeys.setParam(systemKeysCheckbox->value());
Pierre Ossman61fd4862011-05-16 12:46:51 +0000374
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000375 if (menuKeyChoice->value() == 0)
376 menuKey.setParam("");
377 else {
Martin Koegler498ef462011-09-04 07:04:43 +0000378 menuKey.setParam(menuKeyChoice->text());
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000379 }
380
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000381 /* Screen */
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000382 int width, height;
383
384 if (desktopSizeCheckbox->value() &&
385 (sscanf(desktopWidthInput->value(), "%d", &width) == 1) &&
386 (sscanf(desktopHeightInput->value(), "%d", &height) == 1)) {
387 char buf[64];
388 snprintf(buf, sizeof(buf), "%dx%d", width, height);
389 desktopSize.setParam(buf);
390 } else {
391 desktopSize.setParam("");
392 }
Pierre Ossman99197012012-07-05 11:06:18 +0000393 remoteResize.setParam(remoteResizeCheckbox->value());
Pierre Ossman2441e822012-07-10 11:11:23 +0000394#ifdef HAVE_FLTK_FULLSCREEN
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000395 fullScreen.setParam(fullScreenCheckbox->value());
Pierre Ossman2441e822012-07-10 11:11:23 +0000396#endif // HAVE_FLTK_FULLSCREEN
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000397
Pierre Ossman61fd4862011-05-16 12:46:51 +0000398 /* Misc. */
399 shared.setParam(sharedCheckbox->value());
Pierre Ossman61fd4862011-05-16 12:46:51 +0000400 dotWhenNoCursor.setParam(dotCursorCheckbox->value());
Pierre Ossman0c41e1d2011-05-17 09:36:04 +0000401
402 std::map<OptionsCallback*, void*>::const_iterator iter;
403
404 for (iter = callbacks.begin();iter != callbacks.end();++iter)
405 iter->first(iter->second);
Pierre Ossmand463b572011-05-16 12:04:43 +0000406}
407
408
409void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
410{
411 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Compression"));
412
413 int orig_tx, orig_ty;
414 int half_width, full_width;
415 int width, height;
416
417 tx += OUTER_MARGIN;
418 ty += OUTER_MARGIN;
419
420 full_width = tw - OUTER_MARGIN * 2;
421 half_width = (full_width - INNER_MARGIN) / 2;
422
423 /* AutoSelect checkbox */
424 autoselectCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
425 CHECK_MIN_WIDTH,
426 CHECK_HEIGHT,
427 _("Auto select")));
428 autoselectCheckbox->callback(handleAutoselect, this);
429 ty += CHECK_HEIGHT + INNER_MARGIN;
430
431 /* Two columns */
432 orig_tx = tx;
433 orig_ty = ty;
434
435 /* VNC encoding box */
436 ty += GROUP_LABEL_OFFSET;
437 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
438 encodingGroup = new Fl_Group(tx, ty, half_width, height,
439 _("Preferred encoding"));
440 encodingGroup->box(FL_ENGRAVED_BOX);
441 encodingGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
442
443 {
444 tx += GROUP_MARGIN;
445 ty += GROUP_MARGIN;
446
447 width = encodingGroup->w() - GROUP_MARGIN * 2;
448
449 tightButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
450 RADIO_MIN_WIDTH,
451 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000452 "Tight"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000453 tightButton->type(FL_RADIO_BUTTON);
454 ty += RADIO_HEIGHT + TIGHT_MARGIN;
455
456 zrleButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
457 RADIO_MIN_WIDTH,
458 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000459 "ZRLE"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000460 zrleButton->type(FL_RADIO_BUTTON);
461 ty += RADIO_HEIGHT + TIGHT_MARGIN;
462
463 hextileButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
464 RADIO_MIN_WIDTH,
465 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000466 "Hextile"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000467 hextileButton->type(FL_RADIO_BUTTON);
468 ty += RADIO_HEIGHT + TIGHT_MARGIN;
469
470 rawButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
471 RADIO_MIN_WIDTH,
472 RADIO_HEIGHT,
Peter Åstrand4c446002011-08-15 12:33:06 +0000473 "Raw"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000474 rawButton->type(FL_RADIO_BUTTON);
475 ty += RADIO_HEIGHT + TIGHT_MARGIN;
476 }
477
478 ty += GROUP_MARGIN - TIGHT_MARGIN;
479
480 encodingGroup->end();
481
482 /* Second column */
483 tx = orig_tx + half_width + INNER_MARGIN;
484 ty = orig_ty;
485
486 /* Color box */
487 ty += GROUP_LABEL_OFFSET;
488 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
489 colorlevelGroup = new Fl_Group(tx, ty, half_width, height, _("Color level"));
490 colorlevelGroup->box(FL_ENGRAVED_BOX);
491 colorlevelGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
492
493 {
494 tx += GROUP_MARGIN;
495 ty += GROUP_MARGIN;
496
497 width = colorlevelGroup->w() - GROUP_MARGIN * 2;
498
499 fullcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
500 RADIO_MIN_WIDTH,
501 RADIO_HEIGHT,
502 _("Full (all available colors)")));
503 fullcolorCheckbox->type(FL_RADIO_BUTTON);
504 ty += RADIO_HEIGHT + TIGHT_MARGIN;
505
506 mediumcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
507 RADIO_MIN_WIDTH,
508 RADIO_HEIGHT,
509 _("Medium (256 colors)")));
510 mediumcolorCheckbox->type(FL_RADIO_BUTTON);
511 ty += RADIO_HEIGHT + TIGHT_MARGIN;
512
513 lowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
514 RADIO_MIN_WIDTH,
515 RADIO_HEIGHT,
516 _("Low (64 colors)")));
517 lowcolorCheckbox->type(FL_RADIO_BUTTON);
518 ty += RADIO_HEIGHT + TIGHT_MARGIN;
519
520 verylowcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
521 RADIO_MIN_WIDTH,
522 RADIO_HEIGHT,
523 _("Very low (8 colors)")));
524 verylowcolorCheckbox->type(FL_RADIO_BUTTON);
525 ty += RADIO_HEIGHT + TIGHT_MARGIN;
526 }
527
528 ty += GROUP_MARGIN - TIGHT_MARGIN;
529
530 colorlevelGroup->end();
531
532 /* Back to normal */
533 tx = orig_tx;
534 ty += INNER_MARGIN;
535
536 /* Checkboxes */
537 compressionCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
538 CHECK_MIN_WIDTH,
539 CHECK_HEIGHT,
540 _("Custom compression level:")));
541 compressionCheckbox->callback(handleCompression, this);
542 ty += CHECK_HEIGHT + TIGHT_MARGIN;
543
544 compressionInput = new Fl_Int_Input(tx + INDENT, ty,
545 INPUT_HEIGHT, INPUT_HEIGHT,
DRCba7bc512011-08-17 02:30:34 +0000546 _("level (1=fast, 6=best [4-6 are rarely useful])"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000547 compressionInput->align(FL_ALIGN_RIGHT);
548 ty += INPUT_HEIGHT + INNER_MARGIN;
549
550 jpegCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
551 CHECK_MIN_WIDTH,
552 CHECK_HEIGHT,
553 _("Allow JPEG compression:")));
554 jpegCheckbox->callback(handleJpeg, this);
555 ty += CHECK_HEIGHT + TIGHT_MARGIN;
556
557 jpegInput = new Fl_Int_Input(tx + INDENT, ty,
558 INPUT_HEIGHT, INPUT_HEIGHT,
DRC41036ed2011-08-23 20:36:50 +0000559 _("quality (0=poor, 9=best)"));
Pierre Ossmand463b572011-05-16 12:04:43 +0000560 jpegInput->align(FL_ALIGN_RIGHT);
561 ty += INPUT_HEIGHT + INNER_MARGIN;
562
563 group->end();
564}
565
566
567void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
568{
569#ifdef HAVE_GNUTLS
570 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Security"));
571
572 int orig_tx;
573 int width, height;
574
575 tx += OUTER_MARGIN;
576 ty += OUTER_MARGIN;
577
578 width = tw - OUTER_MARGIN * 2;
579
580 orig_tx = tx;
581
Pierre Ossmand463b572011-05-16 12:04:43 +0000582 /* Encryption */
583 ty += GROUP_LABEL_OFFSET;
584 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 4 + CHECK_HEIGHT * 3 + (INPUT_LABEL_OFFSET + INPUT_HEIGHT) * 2;
585 encryptionGroup = new Fl_Group(tx, ty, width, height, _("Encryption"));
586 encryptionGroup->box(FL_ENGRAVED_BOX);
587 encryptionGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
588
589 {
590 tx += GROUP_MARGIN;
591 ty += GROUP_MARGIN;
592
593 encNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
594 CHECK_MIN_WIDTH,
595 CHECK_HEIGHT,
596 _("None")));
597 ty += CHECK_HEIGHT + TIGHT_MARGIN;
598
599 encTLSCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
600 CHECK_MIN_WIDTH,
601 CHECK_HEIGHT,
602 _("TLS with anonymous certificates")));
603 ty += CHECK_HEIGHT + TIGHT_MARGIN;
604
605 encX509Checkbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
606 CHECK_MIN_WIDTH,
607 CHECK_HEIGHT,
608 _("TLS with X509 certificates")));
609 encX509Checkbox->callback(handleX509, this);
610 ty += CHECK_HEIGHT + TIGHT_MARGIN;
611
612 ty += INPUT_LABEL_OFFSET;
613 caInput = new Fl_Input(tx + INDENT, ty,
614 width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
615 _("Path to X509 CA certificate"));
616 caInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
617 ty += INPUT_HEIGHT + TIGHT_MARGIN;
618
619 ty += INPUT_LABEL_OFFSET;
620 crlInput = new Fl_Input(tx + INDENT, ty,
621 width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
622 _("Path to X509 CRL file"));
623 crlInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
624 ty += INPUT_HEIGHT + TIGHT_MARGIN;
625 }
626
627 ty += GROUP_MARGIN - TIGHT_MARGIN;
628
629 encryptionGroup->end();
630
631 /* Back to normal */
632 tx = orig_tx;
633 ty += INNER_MARGIN;
634
635 /* Authentication */
Pierre Ossmand463b572011-05-16 12:04:43 +0000636 ty += GROUP_LABEL_OFFSET;
637 height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 2 + CHECK_HEIGHT * 3;
638 authenticationGroup = new Fl_Group(tx, ty, width, height, _("Authentication"));
639 authenticationGroup->box(FL_ENGRAVED_BOX);
640 authenticationGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
641
642 {
643 tx += GROUP_MARGIN;
644 ty += GROUP_MARGIN;
645
646 authNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
647 CHECK_MIN_WIDTH,
648 CHECK_HEIGHT,
649 _("None")));
650 ty += CHECK_HEIGHT + TIGHT_MARGIN;
651
652 authVncCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
653 CHECK_MIN_WIDTH,
654 CHECK_HEIGHT,
655 _("Standard VNC (insecure without encryption)")));
656 ty += CHECK_HEIGHT + TIGHT_MARGIN;
657
658 authPlainCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
659 CHECK_MIN_WIDTH,
660 CHECK_HEIGHT,
661 _("Username and password (insecure without encryption)")));
662 ty += CHECK_HEIGHT + TIGHT_MARGIN;
663 }
664
665 ty += GROUP_MARGIN - TIGHT_MARGIN;
666
667 authenticationGroup->end();
668
669 /* Back to normal */
670 tx = orig_tx;
671 ty += INNER_MARGIN;
672
673 group->end();
674#endif
675}
676
677
678void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
679{
680 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Input"));
681
682 tx += OUTER_MARGIN;
683 ty += OUTER_MARGIN;
684
685 viewOnlyCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
686 CHECK_MIN_WIDTH,
687 CHECK_HEIGHT,
688 _("View only (ignore mouse and keyboard)")));
689 ty += CHECK_HEIGHT + TIGHT_MARGIN;
690
691 acceptClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
692 CHECK_MIN_WIDTH,
693 CHECK_HEIGHT,
694 _("Accept clipboard from server")));
695 ty += CHECK_HEIGHT + TIGHT_MARGIN;
696
697 sendClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
698 CHECK_MIN_WIDTH,
699 CHECK_HEIGHT,
700 _("Send clipboard to server")));
701 ty += CHECK_HEIGHT + TIGHT_MARGIN;
702
703 sendPrimaryCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
704 CHECK_MIN_WIDTH,
705 CHECK_HEIGHT,
706 _("Send primary selection and cut buffer as clipboard")));
707 ty += CHECK_HEIGHT + TIGHT_MARGIN;
708
Pierre Ossman407a5c32011-05-26 14:48:29 +0000709 systemKeysCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
710 CHECK_MIN_WIDTH,
711 CHECK_HEIGHT,
712 _("Pass system keys directly to server (full screen)")));
713 ty += CHECK_HEIGHT + TIGHT_MARGIN;
714
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000715 menuKeyChoice = new Fl_Choice(LBLLEFT(tx, ty, 150, CHOICE_HEIGHT, _("Menu key")));
716
717 menuKeyChoice->add(_("None"), 0, NULL, (void*)0, FL_MENU_DIVIDER);
Martin Koegler498ef462011-09-04 07:04:43 +0000718 for (int i = 0; i < getMenuKeySymbolCount(); i++)
719 menuKeyChoice->add(getMenuKeySymbols()[i].name, 0, NULL, 0, 0);
Pierre Ossman4e7271e2011-05-24 12:47:12 +0000720
721 ty += CHOICE_HEIGHT + TIGHT_MARGIN;
722
Pierre Ossmand463b572011-05-16 12:04:43 +0000723 group->end();
724}
725
726
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000727void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
728{
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000729 int x;
730
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000731 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Screen"));
732
733 tx += OUTER_MARGIN;
734 ty += OUTER_MARGIN;
735
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000736 desktopSizeCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
737 CHECK_MIN_WIDTH,
738 CHECK_HEIGHT,
739 _("Resize remote session on connect")));
740 desktopSizeCheckbox->callback(handleDesktopSize, this);
741 ty += CHECK_HEIGHT + TIGHT_MARGIN;
742
743 desktopWidthInput = new Fl_Int_Input(tx + INDENT, ty, 50, INPUT_HEIGHT);
744 x = desktopWidthInput->x() + desktopWidthInput->w() + \
745 gui_str_len("x") + 3 * 2;
746 desktopHeightInput = new Fl_Int_Input(x, ty, 50, INPUT_HEIGHT, "x");
747 ty += INPUT_HEIGHT + TIGHT_MARGIN;
748
Pierre Ossman99197012012-07-05 11:06:18 +0000749 remoteResizeCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
750 CHECK_MIN_WIDTH,
751 CHECK_HEIGHT,
752 _("Resize remote session to the local window")));
753 ty += CHECK_HEIGHT + TIGHT_MARGIN;
754
Pierre Ossman2441e822012-07-10 11:11:23 +0000755#ifdef HAVE_FLTK_FULLSCREEN
756
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000757 fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
758 CHECK_MIN_WIDTH,
759 CHECK_HEIGHT,
760 _("Full-screen mode")));
761 ty += CHECK_HEIGHT + TIGHT_MARGIN;
762
Pierre Ossman2441e822012-07-10 11:11:23 +0000763#endif // HAVE_FLTK_FULLSCREEN
764
Pierre Ossman1c2189b2012-07-05 09:23:03 +0000765 group->end();
766}
767
768
Pierre Ossmand463b572011-05-16 12:04:43 +0000769void OptionsDialog::createMiscPage(int tx, int ty, int tw, int th)
770{
771 Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Misc."));
772
773 tx += OUTER_MARGIN;
774 ty += OUTER_MARGIN;
775
776 sharedCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
777 CHECK_MIN_WIDTH,
778 CHECK_HEIGHT,
779 _("Shared (don't disconnect other viewers)")));
780 ty += CHECK_HEIGHT + TIGHT_MARGIN;
781
Pierre Ossmand463b572011-05-16 12:04:43 +0000782 dotCursorCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
783 CHECK_MIN_WIDTH,
784 CHECK_HEIGHT,
785 _("Show dot when no cursor")));
786 ty += CHECK_HEIGHT + TIGHT_MARGIN;
787
788 group->end();
789}
790
791
792void OptionsDialog::handleAutoselect(Fl_Widget *widget, void *data)
793{
794 OptionsDialog *dialog = (OptionsDialog*)data;
795
796 if (dialog->autoselectCheckbox->value()) {
797 dialog->encodingGroup->deactivate();
798 dialog->colorlevelGroup->deactivate();
799 } else {
800 dialog->encodingGroup->activate();
801 dialog->colorlevelGroup->activate();
802 }
803
804 // JPEG setting is also affected by autoselection
805 dialog->handleJpeg(dialog->jpegCheckbox, dialog);
806}
807
808
809void OptionsDialog::handleCompression(Fl_Widget *widget, void *data)
810{
811 OptionsDialog *dialog = (OptionsDialog*)data;
812
813 if (dialog->compressionCheckbox->value())
814 dialog->compressionInput->activate();
815 else
816 dialog->compressionInput->deactivate();
817}
818
819
820void OptionsDialog::handleJpeg(Fl_Widget *widget, void *data)
821{
822 OptionsDialog *dialog = (OptionsDialog*)data;
823
824 if (dialog->jpegCheckbox->value() &&
825 !dialog->autoselectCheckbox->value())
826 dialog->jpegInput->activate();
827 else
828 dialog->jpegInput->deactivate();
829}
830
831
Pierre Ossmand463b572011-05-16 12:04:43 +0000832void OptionsDialog::handleX509(Fl_Widget *widget, void *data)
833{
834 OptionsDialog *dialog = (OptionsDialog*)data;
835
836 if (dialog->encX509Checkbox->value()) {
837 dialog->caInput->activate();
838 dialog->crlInput->activate();
839 } else {
840 dialog->caInput->deactivate();
841 dialog->crlInput->deactivate();
842 }
843}
844
845
Pierre Ossman9ff733a2012-07-05 11:01:23 +0000846void OptionsDialog::handleDesktopSize(Fl_Widget *widget, void *data)
847{
848 OptionsDialog *dialog = (OptionsDialog*)data;
849
850 if (dialog->desktopSizeCheckbox->value()) {
851 dialog->desktopWidthInput->activate();
852 dialog->desktopHeightInput->activate();
853 } else {
854 dialog->desktopWidthInput->deactivate();
855 dialog->desktopHeightInput->deactivate();
856 }
857}
858
Pierre Ossmand463b572011-05-16 12:04:43 +0000859void OptionsDialog::handleCancel(Fl_Widget *widget, void *data)
860{
861 OptionsDialog *dialog = (OptionsDialog*)data;
862
863 dialog->hide();
864}
865
866
867void OptionsDialog::handleOK(Fl_Widget *widget, void *data)
868{
869 OptionsDialog *dialog = (OptionsDialog*)data;
870
871 dialog->hide();
872
873 dialog->storeOptions();
874}