diff options
author | Pierre Ossman <ossman@cendio.se> | 2022-12-22 13:43:02 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2022-12-22 13:43:02 +0100 |
commit | 1d82602177aa0b0131232982a57b246643c2490b (patch) | |
tree | af86483cd23d63de7c883a063b0b0e9d23b1b752 /vncviewer | |
parent | 3810ff42fe413f28ddc91162ad5b9f4ba4813178 (diff) | |
parent | 9bc9e442329b77127296adbf2e4b51b6009d2235 (diff) | |
download | tigervnc-1d82602177aa0b0131232982a57b246643c2490b.tar.gz tigervnc-1d82602177aa0b0131232982a57b246643c2490b.zip |
Merge branch 'newoptions' of https://github.com/CendioOssman/tigervnc
Diffstat (limited to 'vncviewer')
-rw-r--r-- | vncviewer/CMakeLists.txt | 4 | ||||
-rw-r--r-- | vncviewer/OptionsDialog.cxx | 180 | ||||
-rw-r--r-- | vncviewer/OptionsDialog.h | 4 | ||||
-rw-r--r-- | vncviewer/ServerDialog.cxx | 72 | ||||
-rw-r--r-- | vncviewer/UserDialog.cxx | 54 | ||||
-rw-r--r-- | vncviewer/Viewport.cxx | 3 | ||||
-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.cxx | 198 | ||||
-rw-r--r-- | vncviewer/fltk/Fl_Navigation.h | 58 | ||||
-rw-r--r-- | vncviewer/fltk/layout.h | 91 | ||||
-rw-r--r-- | vncviewer/fltk/theme.cxx | 88 | ||||
-rw-r--r-- | vncviewer/fltk/theme.h | 29 | ||||
-rw-r--r-- | vncviewer/fltk/util.h | 110 | ||||
-rw-r--r-- | vncviewer/fltk_layout.h | 172 | ||||
-rw-r--r-- | vncviewer/vncviewer.cxx | 28 |
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"); |