aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2022-12-22 13:43:02 +0100
committerPierre Ossman <ossman@cendio.se>2022-12-22 13:43:02 +0100
commit1d82602177aa0b0131232982a57b246643c2490b (patch)
treeaf86483cd23d63de7c883a063b0b0e9d23b1b752 /vncviewer
parent3810ff42fe413f28ddc91162ad5b9f4ba4813178 (diff)
parent9bc9e442329b77127296adbf2e4b51b6009d2235 (diff)
downloadtigervnc-1d82602177aa0b0131232982a57b246643c2490b.tar.gz
tigervnc-1d82602177aa0b0131232982a57b246643c2490b.zip
Merge branch 'newoptions' of https://github.com/CendioOssman/tigervnc
Diffstat (limited to 'vncviewer')
-rw-r--r--vncviewer/CMakeLists.txt4
-rw-r--r--vncviewer/OptionsDialog.cxx180
-rw-r--r--vncviewer/OptionsDialog.h4
-rw-r--r--vncviewer/ServerDialog.cxx72
-rw-r--r--vncviewer/UserDialog.cxx54
-rw-r--r--vncviewer/Viewport.cxx3
-rw-r--r--vncviewer/fltk/Fl_Monitor_Arrangement.cxx (renamed from vncviewer/MonitorArrangement.cxx)56
-rw-r--r--vncviewer/fltk/Fl_Monitor_Arrangement.h (renamed from vncviewer/MonitorArrangement.h)14
-rw-r--r--vncviewer/fltk/Fl_Navigation.cxx198
-rw-r--r--vncviewer/fltk/Fl_Navigation.h58
-rw-r--r--vncviewer/fltk/layout.h91
-rw-r--r--vncviewer/fltk/theme.cxx88
-rw-r--r--vncviewer/fltk/theme.h29
-rw-r--r--vncviewer/fltk/util.h110
-rw-r--r--vncviewer/fltk_layout.h172
-rw-r--r--vncviewer/vncviewer.cxx28
16 files changed, 789 insertions, 372 deletions
diff --git a/vncviewer/CMakeLists.txt b/vncviewer/CMakeLists.txt
index bcb20f0f..87ab5f47 100644
--- a/vncviewer/CMakeLists.txt
+++ b/vncviewer/CMakeLists.txt
@@ -4,6 +4,9 @@ include_directories(${GETTEXT_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/common)
add_executable(vncviewer
+ fltk/Fl_Monitor_Arrangement.cxx
+ fltk/Fl_Navigation.cxx
+ fltk/theme.cxx
menukey.cxx
BaseTouchHandler.cxx
CConn.cxx
@@ -18,7 +21,6 @@ add_executable(vncviewer
parameters.cxx
keysym2ucs.c
touch.cxx
- MonitorArrangement.cxx
MonitorIndicesParameter.cxx
vncviewer.cxx)
diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx
index a589fb74..32781598 100644
--- a/vncviewer/OptionsDialog.cxx
+++ b/vncviewer/OptionsDialog.cxx
@@ -36,11 +36,14 @@
#endif
#include "OptionsDialog.h"
-#include "fltk_layout.h"
#include "i18n.h"
#include "menukey.h"
#include "parameters.h"
-#include "MonitorArrangement.h"
+
+#include "fltk/layout.h"
+#include "fltk/util.h"
+#include "fltk/Fl_Monitor_Arrangement.h"
+#include "fltk/Fl_Navigation.h"
#include <FL/Fl.H>
#include <FL/Fl_Tabs.H>
@@ -60,19 +63,26 @@ std::map<OptionsCallback*, void*> OptionsDialog::callbacks;
static std::set<OptionsDialog *> instances;
OptionsDialog::OptionsDialog()
- : Fl_Window(450, 460, _("VNC Viewer: Connection Options"))
+ : Fl_Window(580, 420, _("TigerVNC Options"))
{
int x, y;
+ Fl_Navigation *navigation;
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);
-
+ // Odd dimensions to get rid of extra borders
+ // FIXME: We need to retain the top border on Windows as they don't
+ // have any separator for the caption, which looks odd
+#ifdef WIN32
+ navigation = new Fl_Navigation(-1, 0, w()+2,
+ h() - OUTER_MARGIN - BUTTON_HEIGHT - OUTER_MARGIN);
+#else
+ navigation = new Fl_Navigation(-1, -1, w()+2,
+ h()+1 - OUTER_MARGIN - BUTTON_HEIGHT - OUTER_MARGIN);
+#endif
{
int tx, ty, tw, th;
- tabs->client_area(tx, ty, tw, th, TABS_HEIGHT);
+ navigation->client_area(tx, ty, tw, th, 150);
createCompressionPage(tx, ty, tw, th);
createSecurityPage(tx, ty, tw, th);
@@ -81,7 +91,7 @@ OptionsDialog::OptionsDialog()
createMiscPage(tx, ty, tw, th);
}
- tabs->end();
+ navigation->end();
x = w() - BUTTON_WIDTH * 2 - INNER_MARGIN - OUTER_MARGIN;
y = h() - BUTTON_HEIGHT - OUTER_MARGIN;
@@ -332,7 +342,7 @@ void OptionsDialog::loadOptions(void)
}
}
- monitorArrangement->set(fullScreenSelectedMonitors.getParam());
+ monitorArrangement->value(fullScreenSelectedMonitors.getParam());
handleFullScreenMode(selectedMonitorsButton, this);
@@ -465,7 +475,7 @@ void OptionsDialog::storeOptions(void)
}
}
- fullScreenSelectedMonitors.setParam(monitorArrangement->get());
+ fullScreenSelectedMonitors.setParam(monitorArrangement->value());
/* Misc. */
shared.setParam(sharedCheckbox->value());
@@ -486,7 +496,6 @@ void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
int orig_tx, orig_ty;
int col1_ty, col2_ty;
int half_width, full_width;
- int height;
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
@@ -508,18 +517,15 @@ void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
/* VNC encoding box */
ty += GROUP_LABEL_OFFSET;
- height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 3 + RADIO_HEIGHT * 4;
-#ifdef HAVE_H264
- height += TIGHT_MARGIN + RADIO_HEIGHT;
-#endif
- encodingGroup = new Fl_Group(tx, ty, half_width, height,
+ encodingGroup = new Fl_Group(tx, ty, half_width, 0,
_("Preferred encoding"));
- encodingGroup->box(FL_ENGRAVED_BOX);
+ encodingGroup->box(FL_FLAT_BOX);
+ encodingGroup->labelfont(FL_BOLD);
encodingGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
tightButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
@@ -559,9 +565,12 @@ void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
ty += RADIO_HEIGHT + TIGHT_MARGIN;
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
encodingGroup->end();
+ /* Needed for resize to work sanely */
+ encodingGroup->resizable(NULL);
+ encodingGroup->size(encodingGroup->w(), ty - encodingGroup->y());
col1_ty = ty;
/* Second column */
@@ -570,14 +579,14 @@ void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
/* 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 = new Fl_Group(tx, ty, half_width, 0, _("Color level"));
+ colorlevelGroup->labelfont(FL_BOLD);
+ colorlevelGroup->box(FL_FLAT_BOX);
colorlevelGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
fullcolorCheckbox = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
@@ -608,9 +617,13 @@ void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
ty += RADIO_HEIGHT + TIGHT_MARGIN;
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
colorlevelGroup->end();
+ /* Needed for resize to work sanely */
+ colorlevelGroup->resizable(NULL);
+ colorlevelGroup->size(colorlevelGroup->w(),
+ ty - colorlevelGroup->y());
col2_ty = ty;
/* Back to normal */
@@ -622,6 +635,7 @@ void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Custom compression level:")));
+ compressionCheckbox->labelfont(FL_BOLD);
compressionCheckbox->callback(handleCompression, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
@@ -635,6 +649,7 @@ void OptionsDialog::createCompressionPage(int tx, int ty, int tw, int th)
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("Allow JPEG compression:")));
+ jpegCheckbox->labelfont(FL_BOLD);
jpegCheckbox->callback(handleJpeg, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
@@ -654,7 +669,7 @@ void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Security"));
int orig_tx;
- int width, height;
+ int width;
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
@@ -665,21 +680,14 @@ void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
/* Encryption */
ty += GROUP_LABEL_OFFSET;
-
-#if defined(HAVE_GNUTLS) && defined(HAVE_NETTLE)
- height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 5 + CHECK_HEIGHT * 4 + (INPUT_LABEL_OFFSET + INPUT_HEIGHT) * 2;
-#elif defined(HAVE_GNUTLS)
- height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 4 + CHECK_HEIGHT * 3 + (INPUT_LABEL_OFFSET + INPUT_HEIGHT) * 2;
-#elif defined(HAVE_NETTLE)
- height = GROUP_MARGIN * 2 + TIGHT_MARGIN * 1 + CHECK_HEIGHT * 2;
-#endif
- encryptionGroup = new Fl_Group(tx, ty, width, height, _("Encryption"));
- encryptionGroup->box(FL_ENGRAVED_BOX);
+ encryptionGroup = new Fl_Group(tx, ty, width, 0, _("Encryption"));
+ encryptionGroup->labelfont(FL_BOLD);
+ encryptionGroup->box(FL_FLAT_BOX);
encryptionGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
encNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
@@ -703,14 +711,14 @@ void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
ty += INPUT_LABEL_OFFSET;
caInput = new Fl_Input(tx + INDENT, ty,
- width - GROUP_MARGIN*2 - INDENT, INPUT_HEIGHT,
+ width - INDENT * 2, 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,
+ width - INDENT * 2, INPUT_HEIGHT,
_("Path to X509 CRL file"));
crlInput->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
ty += INPUT_HEIGHT + TIGHT_MARGIN;
@@ -725,9 +733,13 @@ void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
#endif
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
encryptionGroup->end();
+ /* Needed for resize to work sanely */
+ encryptionGroup->resizable(NULL);
+ encryptionGroup->size(encryptionGroup->w(),
+ ty - encryptionGroup->y());
/* Back to normal */
tx = orig_tx;
@@ -735,14 +747,14 @@ void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
/* 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 = new Fl_Group(tx, ty, width, 0, _("Authentication"));
+ authenticationGroup->labelfont(FL_BOLD);
+ authenticationGroup->box(FL_FLAT_BOX);
authenticationGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
authNoneCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
@@ -763,9 +775,13 @@ void OptionsDialog::createSecurityPage(int tx, int ty, int tw, int th)
ty += CHECK_HEIGHT + TIGHT_MARGIN;
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
authenticationGroup->end();
+ /* Needed for resize to work sanely */
+ authenticationGroup->resizable(NULL);
+ authenticationGroup->size(authenticationGroup->w(),
+ ty - authenticationGroup->y());
/* Back to normal */
tx = orig_tx;
@@ -792,22 +808,20 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
CHECK_MIN_WIDTH,
CHECK_HEIGHT,
_("View only (ignore mouse and keyboard)")));
- ty += CHECK_HEIGHT + TIGHT_MARGIN;
+ ty += CHECK_HEIGHT + INNER_MARGIN;
orig_tx = tx;
/* Mouse */
ty += GROUP_LABEL_OFFSET;
mouseGroup = new Fl_Group(tx, ty, width, 0, _("Mouse"));
- mouseGroup->box(FL_ENGRAVED_BOX);
+ mouseGroup->labelfont(FL_BOLD);
+ mouseGroup->box(FL_FLAT_BOX);
mouseGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
- /* Needed for final resize to work sanely */
- mouseGroup->resizable(NULL);
-
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
emulateMBCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
@@ -821,9 +835,11 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
_("Show dot when no cursor")));
ty += CHECK_HEIGHT + TIGHT_MARGIN;
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
mouseGroup->end();
+ /* Needed for resize to work sanely */
+ mouseGroup->resizable(NULL);
mouseGroup->size(mouseGroup->w(), ty - mouseGroup->y());
/* Back to normal */
@@ -833,15 +849,13 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
/* Keyboard */
ty += GROUP_LABEL_OFFSET;
keyboardGroup = new Fl_Group(tx, ty, width, 0, _("Keyboard"));
- keyboardGroup->box(FL_ENGRAVED_BOX);
+ keyboardGroup->labelfont(FL_BOLD);
+ keyboardGroup->box(FL_FLAT_BOX);
keyboardGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
- /* Needed for final resize to work sanely */
- keyboardGroup->resizable(NULL);
-
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
systemKeysCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
@@ -857,9 +871,11 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
ty += CHOICE_HEIGHT + TIGHT_MARGIN;
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
keyboardGroup->end();
+ /* Needed for resize to work sanely */
+ keyboardGroup->resizable(NULL);
keyboardGroup->size(keyboardGroup->w(), ty - keyboardGroup->y());
/* Back to normal */
@@ -869,15 +885,13 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
/* Clipboard */
ty += GROUP_LABEL_OFFSET;
clipboardGroup = new Fl_Group(tx, ty, width, 0, _("Clipboard"));
- clipboardGroup->box(FL_ENGRAVED_BOX);
+ clipboardGroup->labelfont(FL_BOLD);
+ clipboardGroup->box(FL_FLAT_BOX);
clipboardGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
- /* Needed for final resize to work sanely */
- clipboardGroup->resizable(NULL);
-
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
acceptClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
CHECK_MIN_WIDTH,
@@ -909,9 +923,11 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
ty += CHECK_HEIGHT + TIGHT_MARGIN;
#endif
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
clipboardGroup->end();
+ /* Needed for resize to work sanely */
+ clipboardGroup->resizable(NULL);
clipboardGroup->size(clipboardGroup->w(), ty - clipboardGroup->y());
/* Back to normal */
@@ -939,16 +955,14 @@ void OptionsDialog::createDisplayPage(int tx, int ty, int tw, int th)
/* Display mode */
ty += GROUP_LABEL_OFFSET;
displayModeGroup = new Fl_Group(tx, ty, width, 0, _("Display mode"));
- displayModeGroup->box(FL_ENGRAVED_BOX);
+ displayModeGroup->labelfont(FL_BOLD);
+ displayModeGroup->box(FL_FLAT_BOX);
displayModeGroup->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
- /* Needed for final resize to work sanely */
- displayModeGroup->resizable(NULL);
-
{
- tx += GROUP_MARGIN;
- ty += GROUP_MARGIN;
- width -= GROUP_MARGIN * 2;
+ tx += INDENT;
+ ty += TIGHT_MARGIN;
+ width -= INDENT;
windowedButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
@@ -982,14 +996,16 @@ void OptionsDialog::createDisplayPage(int tx, int ty, int tw, int th)
selectedMonitorsButton->callback(handleFullScreenMode, this);
ty += RADIO_HEIGHT + TIGHT_MARGIN;
- monitorArrangement = new MonitorArrangement(
+ monitorArrangement = new Fl_Monitor_Arrangement(
tx + INDENT, ty,
width - INDENT, 150);
ty += 150 + TIGHT_MARGIN;
}
- ty += GROUP_MARGIN - TIGHT_MARGIN;
+ ty -= TIGHT_MARGIN;
displayModeGroup->end();
+ /* Needed for resize to work sanely */
+ displayModeGroup->resizable(NULL);
displayModeGroup->size(displayModeGroup->w(),
ty - displayModeGroup->y());
@@ -1004,7 +1020,7 @@ void OptionsDialog::createDisplayPage(int tx, int ty, int tw, int th)
void OptionsDialog::createMiscPage(int tx, int ty, int tw, int th)
{
- Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Misc."));
+ Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Miscellaneous"));
tx += OUTER_MARGIN;
ty += OUTER_MARGIN;
@@ -1156,5 +1172,5 @@ void OptionsDialog::handleScreenConfigTimeout(void *data)
assert(self);
- self->monitorArrangement->set(fullScreenSelectedMonitors.getParam());
+ self->monitorArrangement->value(fullScreenSelectedMonitors.getParam());
}
diff --git a/vncviewer/OptionsDialog.h b/vncviewer/OptionsDialog.h
index 14cfe619..be08620d 100644
--- a/vncviewer/OptionsDialog.h
+++ b/vncviewer/OptionsDialog.h
@@ -30,7 +30,7 @@ class Fl_Round_Button;
class Fl_Input;
class Fl_Int_Input;
class Fl_Choice;
-class MonitorArrangement;
+class Fl_Monitor_Arrangement;
typedef void (OptionsCallback)(void*);
@@ -135,7 +135,7 @@ protected:
Fl_Round_Button *currentMonitorButton;
Fl_Round_Button *allMonitorsButton;
Fl_Round_Button *selectedMonitorsButton;
- MonitorArrangement *monitorArrangement;
+ Fl_Monitor_Arrangement *monitorArrangement;
/* Misc. */
Fl_Check_Button *sharedCheckbox;
diff --git a/vncviewer/ServerDialog.cxx b/vncviewer/ServerDialog.cxx
index f2f4113a..54c34b4f 100644
--- a/vncviewer/ServerDialog.cxx
+++ b/vncviewer/ServerDialog.cxx
@@ -39,9 +39,9 @@
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
+#include "fltk/layout.h"
#include "ServerDialog.h"
#include "OptionsDialog.h"
-#include "fltk_layout.h"
#include "i18n.h"
#include "vncviewer.h"
#include "parameters.h"
@@ -55,63 +55,63 @@ static LogWriter vlog("ServerDialog");
const char* SERVER_HISTORY="tigervnc.history";
ServerDialog::ServerDialog()
- : Fl_Window(450, 160, _("VNC Viewer: Connection Details"))
+ : Fl_Window(450, 0, _("VNC Viewer: Connection Details"))
{
- int x, y;
+ int x, y, x2;
Fl_Button *button;
Fl_Box *divider;
- int margin = 20;
- int server_label_width = gui_str_len(_("VNC server:"));
-
- x = margin + server_label_width;
- y = margin;
-
- serverName = new Fl_Input_Choice(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
usedDir = NULL;
- int adjust = (w() - 20) / 4;
- int button_width = adjust - margin/2;
+ x = OUTER_MARGIN;
+ y = OUTER_MARGIN;
- x = margin;
- y = margin + margin/2 + INPUT_HEIGHT;
+ serverName = new Fl_Input_Choice(LBLLEFT(x, y, w() - OUTER_MARGIN*2,
+ INPUT_HEIGHT, _("VNC server:")));
+ y += INPUT_HEIGHT + INNER_MARGIN;
- y += margin/2;
+ x2 = x;
- button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Options..."));
+ button = new Fl_Button(x2, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Options..."));
button->callback(this->handleOptions, this);
-
- x += adjust;
-
- button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Load..."));
- button->callback(this->handleLoad, this);
+ x2 += BUTTON_WIDTH + INNER_MARGIN;
- x += adjust;
+ button = new Fl_Button(x2, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Load..."));
+ button->callback(this->handleLoad, this);
+ x2 += BUTTON_WIDTH + INNER_MARGIN;
- button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Save As..."));
+ button = new Fl_Button(x2, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Save As..."));
button->callback(this->handleSaveAs, this);
-
- x = 0;
- y += margin/2 + BUTTON_HEIGHT;
+ x2 += BUTTON_WIDTH + INNER_MARGIN;
- divider = new Fl_Box(x, y, w(), 2);
+ y += BUTTON_HEIGHT + INNER_MARGIN;
+
+ divider = new Fl_Box(0, y, w(), 2);
divider->box(FL_THIN_DOWN_FRAME);
-
- x += margin;
- y += margin/2;
- button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("About..."));
+ y += divider->h() + INNER_MARGIN;
+
+ // Symmetric margin around bottom button bar
+ y += OUTER_MARGIN - INNER_MARGIN;
+
+ button = new Fl_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("About..."));
button->callback(this->handleAbout, this);
- x = w() - margin - adjust - button_width - 20;
+ x2 = w() - OUTER_MARGIN - BUTTON_WIDTH*2 - INNER_MARGIN*1;
- button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Cancel"));
+ button = new Fl_Button(x2, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Cancel"));
button->callback(this->handleCancel, this);
+ x2 += BUTTON_WIDTH + INNER_MARGIN;
- x += adjust;
-
- button = new Fl_Return_Button(x, y, button_width+20, BUTTON_HEIGHT, _("Connect"));
+ button = new Fl_Return_Button(x2, y, BUTTON_WIDTH, BUTTON_HEIGHT, _("Connect"));
button->callback(this->handleConnect, this);
+ x2 += BUTTON_WIDTH + INNER_MARGIN;
+
+ y += BUTTON_HEIGHT + INNER_MARGIN;
+
+ /* Needed for resize to work sanely */
+ resizable(NULL);
+ h(y-INNER_MARGIN+OUTER_MARGIN);
callback(this->handleCancel, this);
}
diff --git a/vncviewer/UserDialog.cxx b/vncviewer/UserDialog.cxx
index 1d90cc50..87844639 100644
--- a/vncviewer/UserDialog.cxx
+++ b/vncviewer/UserDialog.cxx
@@ -38,8 +38,9 @@
#include <rfb/Password.h>
#include <rfb/Exception.h>
+#include "fltk/layout.h"
+#include "fltk/util.h"
#include "i18n.h"
-#include "fltk_layout.h"
#include "parameters.h"
#include "UserDialog.h"
@@ -113,9 +114,9 @@ void UserDialog::getUserPasswd(bool secure, char** user, char** password)
Fl_Box *icon;
Fl_Button *button;
- int y;
+ int x, y;
- win = new Fl_Window(410, 145, _("VNC authentication"));
+ win = new Fl_Window(410, 0, _("VNC authentication"));
win->callback(button_cb,(void *)0);
banner = new Fl_Box(0, 0, win->w(), 20);
@@ -131,23 +132,26 @@ void UserDialog::getUserPasswd(bool secure, char** user, char** password)
banner->image(insecure_icon);
}
- y = 20 + 10;
+ x = OUTER_MARGIN;
+ y = banner->h() + OUTER_MARGIN;
- icon = new Fl_Box(10, y, 50, 50, "?");
+ /* Mimic a fl_ask() box */
+ icon = new Fl_Box(x, y, 50, 50, "?");
icon->box(FL_UP_BOX);
icon->labelfont(FL_TIMES_BOLD);
icon->labelsize(34);
icon->color(FL_WHITE);
icon->labelcolor(FL_BLUE);
- y += 5;
+ x += icon->w() + INNER_MARGIN;
+ y += INNER_MARGIN;
if (user) {
- (new Fl_Box(70, y, win->w()-70-10, 20, _("Username:")))
- ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
- y += 20 + 5;
- username = new Fl_Input(70, y, win->w()-70-10, 25);
- y += 25 + 5;
+ y += INPUT_LABEL_OFFSET;
+ username = new Fl_Input(x, y, win->w()- x - OUTER_MARGIN,
+ INPUT_HEIGHT, _("Username:"));
+ username->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
+ y += INPUT_HEIGHT + INNER_MARGIN;
} else {
/*
* Compiler is not bright enough to understand that
@@ -156,24 +160,30 @@ void UserDialog::getUserPasswd(bool secure, char** user, char** password)
username = NULL;
}
- (new Fl_Box(70, y, win->w()-70-10, 20, _("Password:")))
- ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
- y += 20 + 5;
- passwd = new Fl_Secret_Input(70, y, win->w()-70-10, 25);
- y += 25 + 5;
+ y += INPUT_LABEL_OFFSET;
+ passwd = new Fl_Secret_Input(x, y, win->w()- x - OUTER_MARGIN,
+ INPUT_HEIGHT, _("Password:"));
+ passwd->align(FL_ALIGN_LEFT | FL_ALIGN_TOP);
+ y += INPUT_HEIGHT + INNER_MARGIN;
- y += 5;
+ x = win->w() - OUTER_MARGIN;
+ y += OUTER_MARGIN - INNER_MARGIN;
- button = new Fl_Return_Button(310, y, 90, 25, fl_ok);
- button->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ x -= BUTTON_WIDTH;
+ button = new Fl_Return_Button(x, y, BUTTON_WIDTH,
+ BUTTON_HEIGHT, fl_ok);
button->callback(button_cb, (void*)0);
+ x -= INNER_MARGIN;
- button = new Fl_Button(210, y, 90, 25, fl_cancel);
- button->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ x -= BUTTON_WIDTH;
+ button = new Fl_Button(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, fl_cancel);
button->callback(button_cb, (void*)1);
button->shortcut(FL_Escape);
+ x -= INNER_MARGIN;
- y += 25 + 10;
+ y += BUTTON_HEIGHT;
+
+ y += OUTER_MARGIN;
win->end();
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 83872ced..6d970f12 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -55,12 +55,13 @@
#define MAPVK_VK_TO_VSC 0
#endif
+#include "fltk/layout.h"
+#include "fltk/util.h"
#include "Viewport.h"
#include "CConn.h"
#include "OptionsDialog.h"
#include "DesktopWindow.h"
#include "i18n.h"
-#include "fltk_layout.h"
#include "parameters.h"
#include "keysym2ucs.h"
#include "menukey.h"
diff --git a/vncviewer/MonitorArrangement.cxx b/vncviewer/fltk/Fl_Monitor_Arrangement.cxx
index 7910ab88..ce61b1e7 100644
--- a/vncviewer/MonitorArrangement.cxx
+++ b/vncviewer/fltk/Fl_Monitor_Arrangement.cxx
@@ -53,12 +53,12 @@
#include <IOKit/hidsystem/IOHIDParameter.h>
#endif
-#include "MonitorArrangement.h"
+#include "Fl_Monitor_Arrangement.h"
-static std::set<MonitorArrangement *> instances;
+static std::set<Fl_Monitor_Arrangement *> instances;
static const Fl_Boxtype FL_CHECKERED_BOX = FL_FREE_BOXTYPE;
-MonitorArrangement::MonitorArrangement(
+Fl_Monitor_Arrangement::Fl_Monitor_Arrangement(
int x, int y, int w, int h)
: Fl_Group(x, y, w, h),
SELECTION_COLOR(fl_lighter(FL_BLUE)),
@@ -77,7 +77,7 @@ MonitorArrangement::MonitorArrangement(
end();
}
-MonitorArrangement::~MonitorArrangement()
+Fl_Monitor_Arrangement::~Fl_Monitor_Arrangement()
{
instances.erase(this);
@@ -85,7 +85,7 @@ MonitorArrangement::~MonitorArrangement()
Fl::remove_handler(fltk_event_handler);
}
-std::set<int> MonitorArrangement::get()
+std::set<int> Fl_Monitor_Arrangement::value() const
{
std::set<int> indices;
MonitorMap::const_iterator iter;
@@ -98,18 +98,24 @@ std::set<int> MonitorArrangement::get()
return indices;
}
-void MonitorArrangement::set(std::set<int> indices)
+int Fl_Monitor_Arrangement::value(std::set<int> indices)
{
MonitorMap::const_iterator iter;
+ bool changed;
+ changed = false;
for (iter = monitors.begin(); iter != monitors.end(); ++iter) {
bool selected = std::find(indices.begin(), indices.end(),
iter->first) != indices.end();
- iter->second->value(selected ? 1 : 0);
+ if (iter->second->value() != selected)
+ changed = true;
+ iter->second->value(selected);
}
+
+ return changed;
}
-void MonitorArrangement::draw()
+void Fl_Monitor_Arrangement::draw()
{
MonitorMap::const_iterator iter;
@@ -129,7 +135,7 @@ void MonitorArrangement::draw()
Fl_Group::draw();
}
-void MonitorArrangement::layout()
+void Fl_Monitor_Arrangement::layout()
{
int x, y, w, h;
double scale = this->scale();
@@ -173,12 +179,12 @@ void MonitorArrangement::layout()
}
}
-void MonitorArrangement::refresh()
+void Fl_Monitor_Arrangement::refresh()
{
// The selection state is only saved persistently when "OK" is
// pressed. We need to manually restore the current selection
// when the widget is refreshed.
- std::set<int> indices = get();
+ std::set<int> indices = value();
monitors.clear();
// FLTK recursively deletes all children for us.
@@ -188,18 +194,18 @@ void MonitorArrangement::refresh()
end();
// Restore the current selection state.
- set(indices);
+ value(indices);
redraw();
}
-bool MonitorArrangement::is_required(int m)
+bool Fl_Monitor_Arrangement::is_required(int m)
{
// A selected monitor is never required.
if (monitors[m]->value() == 1)
return false;
// If no monitors are selected, none are required.
- std::set<int> selected = get();
+ std::set<int> selected = value();
if (selected.size() <= 0)
return false;
@@ -258,7 +264,7 @@ bool MonitorArrangement::is_required(int m)
return true;
}
-double MonitorArrangement::scale()
+double Fl_Monitor_Arrangement::scale()
{
const int MARGIN = 20;
std::pair<int, int> size = this->size();
@@ -274,7 +280,7 @@ double MonitorArrangement::scale()
return s_w;
}
-std::pair<int, int> MonitorArrangement::size()
+std::pair<int, int> Fl_Monitor_Arrangement::size()
{
int x, y, w, h;
int top, bottom, left, right;
@@ -305,7 +311,7 @@ std::pair<int, int> MonitorArrangement::size()
return std::make_pair(x_max - x_min, y_max - y_min);
}
-std::pair<int, int> MonitorArrangement::offset()
+std::pair<int, int> Fl_Monitor_Arrangement::offset()
{
double scale = this->scale();
std::pair<int, int> size = this->size();
@@ -317,7 +323,7 @@ std::pair<int, int> MonitorArrangement::offset()
return std::make_pair(offset_x + abs(origin.first)*scale, offset_y + abs(origin.second)*scale);
}
-std::pair<int, int> MonitorArrangement::origin()
+std::pair<int, int> Fl_Monitor_Arrangement::origin()
{
int x, y, w, h, ox, oy;
ox = oy = 0;
@@ -335,7 +341,7 @@ std::pair<int, int> MonitorArrangement::origin()
return std::make_pair(ox, oy);
}
-std::string MonitorArrangement::description(int m)
+std::string Fl_Monitor_Arrangement::description(int m)
{
std::string name;
int x, y, w, h;
@@ -364,7 +370,7 @@ static BOOL CALLBACK EnumDisplayMonitorsCallback(
}
#endif
-std::string MonitorArrangement::get_monitor_name(int m)
+std::string Fl_Monitor_Arrangement::get_monitor_name(int m)
{
#if defined(WIN32)
std::set<HMONITOR> sys_monitors;
@@ -530,9 +536,9 @@ std::string MonitorArrangement::get_monitor_name(int m)
#endif
}
-int MonitorArrangement::fltk_event_handler(int event)
+int Fl_Monitor_Arrangement::fltk_event_handler(int event)
{
- std::set<MonitorArrangement *>::iterator it;
+ std::set<Fl_Monitor_Arrangement *>::iterator it;
if (event != FL_SCREEN_CONFIGURATION_CHANGED)
return 0;
@@ -543,9 +549,9 @@ int MonitorArrangement::fltk_event_handler(int event)
return 0;
}
-void MonitorArrangement::monitor_pressed(Fl_Widget *widget, void *user_data)
+void Fl_Monitor_Arrangement::monitor_pressed(Fl_Widget *widget, void *user_data)
{
- MonitorArrangement *self = (MonitorArrangement *) user_data;
+ Fl_Monitor_Arrangement *self = (Fl_Monitor_Arrangement *) user_data;
// When a monitor is selected, FLTK changes the state of it for us.
// However, selecting a monitor might implicitly change the state of
@@ -555,7 +561,7 @@ void MonitorArrangement::monitor_pressed(Fl_Widget *widget, void *user_data)
self->redraw();
}
-void MonitorArrangement::checkered_pattern_draw(
+void Fl_Monitor_Arrangement::checkered_pattern_draw(
int x, int y, int width, int height, Fl_Color color)
{
bool draw_checker = false;
diff --git a/vncviewer/MonitorArrangement.h b/vncviewer/fltk/Fl_Monitor_Arrangement.h
index d6db2677..b8e9ba78 100644
--- a/vncviewer/MonitorArrangement.h
+++ b/vncviewer/fltk/Fl_Monitor_Arrangement.h
@@ -22,8 +22,8 @@
* SOFTWARE.
*/
-#ifndef __MONITOR_ARRANGEMENT_H__
-#define __MONITOR_ARRANGEMENT_H__
+#ifndef __FL_MONITOR_ARRANGEMENT_H__
+#define __FL_MONITOR_ARRANGEMENT_H__
#include <string>
#include <map>
@@ -33,16 +33,16 @@
class Fl_Button;
-class MonitorArrangement: public Fl_Group {
+class Fl_Monitor_Arrangement: public Fl_Group {
public:
- MonitorArrangement(int x, int y, int w, int h);
- ~MonitorArrangement();
+ Fl_Monitor_Arrangement(int x, int y, int w, int h);
+ ~Fl_Monitor_Arrangement();
// Get selected indices.
- std::set<int> get();
+ std::set<int> value() const;
// Set selected indices.
- void set(std::set<int> indices);
+ int value(std::set<int> indices);
protected:
virtual void draw();
diff --git a/vncviewer/fltk/Fl_Navigation.cxx b/vncviewer/fltk/Fl_Navigation.cxx
new file mode 100644
index 00000000..603c69ce
--- /dev/null
+++ b/vncviewer/fltk/Fl_Navigation.cxx
@@ -0,0 +1,198 @@
+/* Copyright 2022 Pierre Ossman for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Scroll.H>
+
+#include "Fl_Navigation.h"
+
+Fl_Navigation::Fl_Navigation(int x, int y, int w, int h)
+ : Fl_Group(x, y, w, h)
+{
+ int dummy;
+
+ scroll = new Fl_Scroll(x, y, 1, 1);
+ scroll->type(Fl_Scroll::VERTICAL);
+ scroll->color(FL_BACKGROUND2_COLOR);
+
+ labels = new Fl_Group(x, y, 1, 1);
+ labels->end();
+
+ scroll->end();
+
+ pages = new Fl_Group(x, y, 1, 1);
+ pages->end();
+
+ Fl_Group::end();
+
+ // Just to resize things, and avoid code duplication
+ client_area(dummy, dummy, dummy, dummy, w/10);
+
+ begin();
+}
+
+Fl_Navigation::~Fl_Navigation()
+{
+}
+
+Fl_Widget *Fl_Navigation::value()
+{
+ int i;
+
+ for (i = 0;i < pages->children();i++) {
+ if (pages->child(i)->visible())
+ return pages->child(i);
+ }
+
+ return NULL;
+}
+
+int Fl_Navigation::value(Fl_Widget *newpage)
+{
+ int i;
+ int found;
+
+ assert(labels->children() == pages->children());
+
+ found = 0;
+ for (i = 0;i < pages->children();i++) {
+ if (pages->child(i) == newpage) {
+ pages->child(i)->show();
+ ((Fl_Button*)labels->child(i))->setonly();
+ found = 1;
+ } else {
+ pages->child(i)->hide();
+ }
+ }
+
+ return found;
+}
+
+void Fl_Navigation::client_area(int &rx, int &ry,
+ int &rw, int &rh, int lw)
+{
+ if (!pages->children()) {
+ int cx, cy, cw, ch;
+
+ cx = x() + 1;
+ cy = y() + 1;
+ cw = w() - 2;
+ ch = h() - 2;
+
+ scroll->resize(cx, cy, lw, ch);
+ labels->resize(cx, cy, lw, ch);
+ pages->resize(cx + lw + 1, cy, cw - lw - 1, ch);
+ }
+
+ rx = pages->x();
+ ry = pages->y();
+ rw = pages->w();
+ rh = pages->h();
+}
+
+void Fl_Navigation::draw()
+{
+ draw_box(FL_BORDER_FRAME, x(), y(),
+ labels->w()+2, h(), FL_DARK3);
+ draw_box(FL_BORDER_FRAME, x()+1+labels->w(), y(),
+ w() - (labels->w()+1), h(), FL_DARK3);
+ Fl_Group::draw();
+}
+
+void Fl_Navigation::begin()
+{
+ pages->begin();
+}
+
+void Fl_Navigation::end()
+{
+ pages->end();
+ Fl_Group::end();
+
+ update_labels();
+}
+
+void Fl_Navigation::update_labels()
+{
+ int i, offset;
+
+ labels->clear();
+ labels->resizable(NULL);
+
+ if (!pages->children())
+ return;
+
+ offset = 0;
+ for (i = 0;i < pages->children();i++) {
+ Fl_Widget *page;
+ Fl_Button *btn;
+
+ page = pages->child(i);
+
+ btn = new Fl_Button(labels->x(), labels->y() + offset,
+ labels->w(), page->labelsize() * 3,
+ page->label());
+ btn->box(FL_FLAT_BOX);
+ btn->type(FL_RADIO_BUTTON);
+ btn->color(FL_BACKGROUND2_COLOR);
+ btn->selection_color(FL_SELECTION_COLOR);
+ btn->labelsize(page->labelsize());
+ btn->labelfont(page->labelfont());
+ btn->image(page->image());
+ btn->deimage(page->deimage());
+ btn->callback(label_pressed, this);
+
+ labels->add(btn);
+ offset += page->labelsize() * 3;
+ }
+ labels->size(labels->w(), offset);
+
+ // FIXME: Retain selection
+ value(pages->child(0));
+}
+
+void Fl_Navigation::label_pressed(Fl_Widget *widget, void *user_data)
+{
+ Fl_Navigation *self = (Fl_Navigation *) user_data;
+
+ int i, idx;
+
+ idx = -1;
+ for (i = 0;i < self->labels->children();i++) {
+ if (self->labels->child(i) == widget)
+ idx = i;
+ }
+
+ assert(idx >= 0);
+ assert(idx < self->pages->children());
+
+ self->value(self->pages->child(idx));
+}
diff --git a/vncviewer/fltk/Fl_Navigation.h b/vncviewer/fltk/Fl_Navigation.h
new file mode 100644
index 00000000..7f5e44ac
--- /dev/null
+++ b/vncviewer/fltk/Fl_Navigation.h
@@ -0,0 +1,58 @@
+/* Copyright 2022 Pierre Ossman for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __FL_NAVIGATION_H__
+#define __FL_NAVIGATION_H__
+
+#include <FL/Fl_Group.H>
+
+class Fl_Scroll;
+
+class Fl_Navigation: private Fl_Group {
+public:
+ Fl_Navigation(int x, int y, int w, int h);
+ ~Fl_Navigation();
+
+ Fl_Widget *value();
+ int value(Fl_Widget*);
+
+ void client_area(int &rx, int &ry, int &rw, int &rh, int lw);
+
+ virtual void draw();
+
+ // Delegation to underlying widget
+ void begin();
+ void end();
+
+private:
+ void update_labels();
+
+ static void label_pressed(Fl_Widget *widget, void *user_data);
+
+private:
+ Fl_Scroll *scroll;
+ Fl_Group *labels;
+ Fl_Group *pages;
+};
+
+#endif
diff --git a/vncviewer/fltk/layout.h b/vncviewer/fltk/layout.h
new file mode 100644
index 00000000..01dc73e6
--- /dev/null
+++ b/vncviewer/fltk/layout.h
@@ -0,0 +1,91 @@
+/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __FLTK_LAYOUT_H__
+#define __FLTK_LAYOUT_H__
+
+#include <FL/fl_draw.H>
+
+/* Calculates the width of a string as printed by FLTK (pixels) */
+static inline int gui_str_len(const char *str)
+{
+ float len;
+
+ fl_font(FL_HELVETICA, FL_NORMAL_SIZE);
+
+ len = fl_width(str);
+
+ return (int)(len + 0.5f);
+}
+
+/**** MARGINS ****/
+
+#define OUTER_MARGIN 15
+#define INNER_MARGIN 10
+
+/* Tighter grouping of related fields */
+#define TIGHT_MARGIN 5
+
+/**** ADJUSTMENTS ****/
+#define INDENT 10
+
+/**** FLTK WIDGETS ****/
+
+/* Fl_Input */
+#define INPUT_LABEL_OFFSET FL_NORMAL_SIZE
+#define INPUT_HEIGHT 25
+
+/* Fl_Button */
+#define BUTTON_WIDTH 115
+#define BUTTON_HEIGHT 27
+
+/* Fl_Round_Button (padding + focus draw bug) */
+#define RADIO_MIN_WIDTH (FL_NORMAL_SIZE + 4 + 1)
+#define RADIO_HEIGHT (FL_NORMAL_SIZE + 4 + 1)
+
+/* Fl_Check_Button */
+#define CHECK_MIN_WIDTH RADIO_MIN_WIDTH
+#define CHECK_HEIGHT RADIO_HEIGHT
+
+/* Fl_Choice */
+
+#define CHOICE_HEIGHT INPUT_HEIGHT
+
+/* Fl_Group */
+#define GROUP_LABEL_OFFSET FL_NORMAL_SIZE
+
+/**** HELPERS FOR DYNAMIC TEXT ****/
+
+/* Extra space to add after any text line */
+#define TEXT_PADDING 2
+
+/* Use this when the text extends to the right (e.g. checkboxes) */
+#define LBLRIGHT(x, y, w, h, str) \
+ (x), (y), (w) + gui_str_len(str) + TEXT_PADDING, (h), (str)
+
+/* Use this when the space for the label is taken from the left (e.g. input) */
+#define LBLLEFT(x, y, w, h, str) \
+ (x) + (gui_str_len(str) + TEXT_PADDING), (y), \
+ (w) - (gui_str_len(str) + TEXT_PADDING), (h), (str)
+
+#endif
diff --git a/vncviewer/fltk/theme.cxx b/vncviewer/fltk/theme.cxx
new file mode 100644
index 00000000..cb786e4c
--- /dev/null
+++ b/vncviewer/fltk/theme.cxx
@@ -0,0 +1,88 @@
+/* Copyright 2011-2022 Pierre Ossman for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#ifdef __APPLE__
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/fl_ask.H>
+
+#include "theme.h"
+
+void init_theme()
+{
+ // Basic text size (10pt @ 96 dpi => 13px)
+ FL_NORMAL_SIZE = 13;
+
+ // Select a FLTK scheme and background color that looks somewhat
+ // close to modern systems
+ Fl::scheme("gtk+");
+ Fl::background(220, 220, 220);
+
+ // macOS has a slightly brighter default background though
+#ifdef __APPLE__
+ Fl::background(240, 240, 240);
+#endif
+
+ // This makes the "icon" in dialogs rounded, which fits better
+ // with the above schemes.
+ fl_message_icon()->box(FL_UP_BOX);
+
+#if defined(WIN32)
+ NONCLIENTMETRICS metrics;
+ metrics.cbSize = sizeof(metrics);
+ if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
+ sizeof(metrics), &metrics, 0))
+ Fl::set_font(FL_HELVETICA, metrics.lfMessageFont.lfFaceName);
+#elif defined(__APPLE__)
+ CTFontRef font;
+ CFStringRef name;
+ char cname[256];
+
+ font = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 0.0, NULL);
+ if (font != NULL) {
+ name = CTFontCopyFullName(font);
+ if (name != NULL) {
+ CFStringGetCString(name, cname, sizeof(cname),
+ kCFStringEncodingUTF8);
+
+ Fl::set_font(FL_HELVETICA, cname);
+
+ CFRelease(name);
+ }
+ CFRelease(font);
+ }
+#else
+ // FIXME: Get font from GTK or QT
+#endif
+}
diff --git a/vncviewer/fltk/theme.h b/vncviewer/fltk/theme.h
new file mode 100644
index 00000000..aa4b3586
--- /dev/null
+++ b/vncviewer/fltk/theme.h
@@ -0,0 +1,29 @@
+/* Copyright 2022 Pierre Ossman for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __FLTK_THEME_H__
+#define __FLTK_THEME_H__
+
+void init_theme();
+
+#endif
diff --git a/vncviewer/fltk/util.h b/vncviewer/fltk/util.h
new file mode 100644
index 00000000..87765396
--- /dev/null
+++ b/vncviewer/fltk/util.h
@@ -0,0 +1,110 @@
+/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __FLTK_UTIL_H__
+#define __FLTK_UTIL_H__
+
+#include <FL/Fl_Menu_.H>
+
+/* Escapes all @ in text as those have special meaning in labels */
+static inline size_t fltk_escape(const char *in, char *out, size_t maxlen)
+{
+ size_t len;
+
+ len = 0;
+
+ while (*in != '\0') {
+ if (*in == '@') {
+ if (maxlen >= 3) {
+ *out++ = '@';
+ *out++ = '@';
+ maxlen -= 2;
+ }
+
+ len += 2;
+ } else {
+ if (maxlen >= 2) {
+ *out++ = *in;
+ maxlen--;
+ }
+
+ len += 1;
+ }
+
+ in++;
+ }
+
+ if (maxlen)
+ *out = '\0';
+
+ return len;
+}
+
+/* Filter out unsafe characters for menu entries */
+static inline size_t fltk_menu_escape(const char *in, char *out, size_t maxlen)
+{
+ size_t len;
+
+ len = 0;
+
+ while (*in != '\0') {
+ if (*in == '/') {
+ if (maxlen >= 3) {
+ *out++ = '\\';
+ *out++ = '/';
+ maxlen -= 2;
+ }
+
+ len += 2;
+ } else {
+ if (maxlen >= 2) {
+ *out++ = *in;
+ maxlen--;
+ }
+
+ len += 1;
+ }
+
+ in++;
+ }
+
+ if (maxlen)
+ *out = '\0';
+
+ return len;
+}
+
+/* Helper to add menu entries safely */
+static inline void fltk_menu_add(Fl_Menu_ *menu, const char *text,
+ int shortcut, Fl_Callback *cb,
+ void *data = 0, int flags = 0)
+{
+ char buffer[1024];
+
+ if (fltk_menu_escape(text, buffer, sizeof(buffer)) >= sizeof(buffer))
+ return;
+
+ menu->add(buffer, shortcut, cb, data, flags);
+}
+
+#endif
diff --git a/vncviewer/fltk_layout.h b/vncviewer/fltk_layout.h
deleted file mode 100644
index 9e5c2d47..00000000
--- a/vncviewer/fltk_layout.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 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.
- */
-
-#ifndef __FLTK_LAYOUT_H__
-#define __FLTK_LAYOUT_H__
-
-#include <FL/fl_draw.H>
-#include <FL/Fl_Menu_.H>
-
-/* Calculates the width of a string as printed by FLTK (pixels) */
-static inline int gui_str_len(const char *str)
-{
- float len;
-
- fl_font(FL_HELVETICA, FL_NORMAL_SIZE);
-
- len = fl_width(str);
-
- return (int)(len + 0.5f);
-}
-
-/* Escapes all @ in text as those have special meaning in labels */
-static inline size_t fltk_escape(const char *in, char *out, size_t maxlen)
-{
- size_t len;
-
- len = 0;
-
- while (*in != '\0') {
- if (*in == '@') {
- if (maxlen >= 3) {
- *out++ = '@';
- *out++ = '@';
- maxlen -= 2;
- }
-
- len += 2;
- } else {
- if (maxlen >= 2) {
- *out++ = *in;
- maxlen--;
- }
-
- len += 1;
- }
-
- in++;
- }
-
- if (maxlen)
- *out = '\0';
-
- return len;
-}
-
-/* Filter out unsafe characters for menu entries */
-static inline size_t fltk_menu_escape(const char *in, char *out, size_t maxlen)
-{
- size_t len;
-
- len = 0;
-
- while (*in != '\0') {
- if (*in == '/') {
- if (maxlen >= 3) {
- *out++ = '\\';
- *out++ = '/';
- maxlen -= 2;
- }
-
- len += 2;
- } else {
- if (maxlen >= 2) {
- *out++ = *in;
- maxlen--;
- }
-
- len += 1;
- }
-
- in++;
- }
-
- if (maxlen)
- *out = '\0';
-
- return len;
-}
-
-/* Helper to add menu entries safely */
-static inline void fltk_menu_add(Fl_Menu_ *menu, const char *text,
- int shortcut, Fl_Callback *cb,
- void *data = 0, int flags = 0)
-{
- char buffer[1024];
-
- if (fltk_menu_escape(text, buffer, sizeof(buffer)) >= sizeof(buffer))
- return;
-
- menu->add(buffer, shortcut, cb, data, flags);
-}
-
-/**** MARGINS ****/
-
-#define OUTER_MARGIN 10
-#define INNER_MARGIN 10
-
-/* Tighter grouping of related fields */
-#define TIGHT_MARGIN 5
-
-/**** ADJUSTMENTS ****/
-#define INDENT 20
-
-/**** FLTK WIDGETS ****/
-
-/* Fl_Tabs */
-#define TABS_HEIGHT 30
-
-/* Fl_Input */
-#define INPUT_LABEL_OFFSET FL_NORMAL_SIZE
-#define INPUT_HEIGHT 25
-
-/* Fl_Button */
-#define BUTTON_WIDTH 115
-#define BUTTON_HEIGHT 27
-
-/* Fl_Round_Button */
-#define RADIO_MIN_WIDTH (FL_NORMAL_SIZE + 5)
-#define RADIO_HEIGHT (FL_NORMAL_SIZE + 7)
-
-/* Fl_Check_Button */
-#define CHECK_MIN_WIDTH RADIO_MIN_WIDTH
-#define CHECK_HEIGHT RADIO_HEIGHT
-
-/* Fl_Choice */
-
-#define CHOICE_HEIGHT INPUT_HEIGHT
-
-/* Fl_Group */
-#define GROUP_LABEL_OFFSET FL_NORMAL_SIZE
-#define GROUP_MARGIN 12
-
-/**** HELPERS FOR DYNAMIC TEXT ****/
-
-/* Extra space to add after any text line */
-#define TEXT_PADDING 2
-
-/* Use this when the text extends to the right (e.g. checkboxes) */
-#define LBLRIGHT(x, y, w, h, str) \
- (x), (y), (w) + gui_str_len(str) + TEXT_PADDING, (h), (str)
-
-/* Use this when the space for the label is taken from the left (e.g. input) */
-#define LBLLEFT(x, y, w, h, str) \
- (x) + (gui_str_len(str) + TEXT_PADDING), (y), \
- (w) - (gui_str_len(str) + TEXT_PADDING), (h), (str)
-
-#endif
diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx
index 3f30fada..a7e99ffb 100644
--- a/vncviewer/vncviewer.cxx
+++ b/vncviewer/vncviewer.cxx
@@ -60,13 +60,13 @@
#include <network/TcpSocket.h>
#include <os/os.h>
-#include <FL/Fl.H>
-#include <FL/Fl_Widget.H>
#include <FL/Fl_PNG_Image.H>
#include <FL/Fl_Sys_Menu_Bar.H>
#include <FL/fl_ask.H>
#include <FL/x.H>
+#include "fltk/theme.h"
+#include "fltk/util.h"
#include "i18n.h"
#include "parameters.h"
#include "CConn.h"
@@ -74,7 +74,6 @@
#include "UserDialog.h"
#include "touch.h"
#include "vncviewer.h"
-#include "fltk_layout.h"
#ifdef WIN32
#include "resource.h"
@@ -323,18 +322,8 @@ static const char* getlocaledir()
}
static void init_fltk()
{
- // Basic text size (10pt @ 96 dpi => 13px)
- FL_NORMAL_SIZE = 13;
-
- // Select a FLTK scheme and background color that looks somewhat
- // close to modern systems
- Fl::scheme("gtk+");
- Fl::background(220, 220, 220);
-
- // macOS has a slightly brighter default background though
-#ifdef __APPLE__
- Fl::background(240, 240, 240);
-#endif
+ // Adjust look of FLTK
+ init_theme();
// Proper Gnome Shell integration requires that we set a sensible
// WM_CLASS for the window.
@@ -395,21 +384,12 @@ static void init_fltk()
delete icons[i];
#endif
- // This makes the "icon" in dialogs rounded, which fits better
- // with the above schemes.
- fl_message_icon()->box(FL_UP_BOX);
-
// Turn off the annoying behaviour where popups track the mouse.
fl_message_hotspot(false);
// Avoid empty titles for popups
fl_message_title_default(_("TigerVNC Viewer"));
-#ifdef WIN32
- // Most "normal" Windows apps use this font for UI elements.
- Fl::set_font(FL_HELVETICA, "Tahoma");
-#endif
-
// FLTK exposes these so that we can translate them.
fl_no = _("No");
fl_yes = _("Yes");