aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer/OptionsDialog.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vncviewer/OptionsDialog.cxx')
-rw-r--r--vncviewer/OptionsDialog.cxx208
1 files changed, 183 insertions, 25 deletions
diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx
index 9ff3285c..3ba6fba1 100644
--- a/vncviewer/OptionsDialog.cxx
+++ b/vncviewer/OptionsDialog.cxx
@@ -1,4 +1,4 @@
-/* Copyright 2011-2021 Pierre Ossman <ossman@cendio.se> for Cendio AB
+/* Copyright 2011-2025 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
@@ -24,6 +24,8 @@
#include <stdlib.h>
#include <list>
+#include <core/string.h>
+
#include <rfb/encodings.h>
#if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE)
@@ -35,8 +37,8 @@
#endif
#include "OptionsDialog.h"
+#include "ShortcutHandler.h"
#include "i18n.h"
-#include "menukey.h"
#include "parameters.h"
#include "fltk/layout.h"
@@ -44,12 +46,18 @@
#include "fltk/Fl_Monitor_Arrangement.h"
#include "fltk/Fl_Navigation.h"
+#ifdef __APPLE__
+#include "cocoa.h"
+#endif
+
#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Round_Button.H>
+#include <FL/Fl_Toggle_Button.H>
#include <FL/Fl_Int_Input.H>
#include <FL/Fl_Choice.H>
@@ -82,6 +90,7 @@ OptionsDialog::OptionsDialog()
createCompressionPage(tx, ty, tw, th);
createSecurityPage(tx, ty, tw, th);
createInputPage(tx, ty, tw, th);
+ createShortcutsPage(tx, ty, tw, th);
createDisplayPage(tx, ty, tw, th);
createMiscPage(tx, ty, tw, th);
}
@@ -311,11 +320,19 @@ void OptionsDialog::loadOptions(void)
#endif
systemKeysCheckbox->value(fullscreenSystemKeys);
- menuKeyChoice->value(0);
+ /* Keyboard shortcuts */
+ unsigned modifierMask;
+
+ modifierMask = 0;
+ for (core::EnumListEntry key : shortcutModifiers)
+ modifierMask |= ShortcutHandler::parseModifier(key.getValueStr().c_str());
- for (int idx = 0; idx < getMenuKeySymbolCount(); idx++)
- if (menuKey == getMenuKeySymbols()[idx].name)
- menuKeyChoice->value(idx + 1);
+ ctrlButton->value(modifierMask & ShortcutHandler::Control);
+ shiftButton->value(modifierMask & ShortcutHandler::Shift);
+ altButton->value(modifierMask & ShortcutHandler::Alt);
+ superButton->value(modifierMask & ShortcutHandler::Super);
+
+ handleModifier(nullptr, this);
/* Display */
if (!fullScreen) {
@@ -452,11 +469,23 @@ void OptionsDialog::storeOptions(void)
#endif
fullscreenSystemKeys.setParam(systemKeysCheckbox->value());
- if (menuKeyChoice->value() == 0)
- menuKey.setParam("None");
- else {
- menuKey.setParam(menuKeyChoice->text());
- }
+ /* Keyboard shortcuts */
+ std::list<std::string> modifierList;
+
+ if (ctrlButton->value())
+ modifierList.push_back(
+ ShortcutHandler::modifierString(ShortcutHandler::Control));
+ if (shiftButton->value())
+ modifierList.push_back(
+ ShortcutHandler::modifierString(ShortcutHandler::Shift));
+ if (altButton->value())
+ modifierList.push_back(
+ ShortcutHandler::modifierString(ShortcutHandler::Alt));
+ if (superButton->value())
+ modifierList.push_back(
+ ShortcutHandler::modifierString(ShortcutHandler::Super));
+
+ shortcutModifiers.setParam(modifierList);
/* Display */
if (windowedButton->value()) {
@@ -879,21 +908,11 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
tx += INDENT;
ty += TIGHT_MARGIN;
- systemKeysCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
- CHECK_MIN_WIDTH,
- CHECK_HEIGHT,
- _("Pass system keys directly to server (full screen)")));
+ systemKeysCheckbox = new Fl_Check_Button(
+ LBLRIGHT(tx, ty, CHECK_MIN_WIDTH, CHECK_HEIGHT,
+ _("Always send all keyboard input in full screen")));
+ systemKeysCheckbox->callback(handleSystemKeys, this);
ty += CHECK_HEIGHT + TIGHT_MARGIN;
-
- menuKeyChoice = new Fl_Choice(LBLLEFT(tx, ty, 150, CHOICE_HEIGHT, _("Menu key")));
-
- fltk_menu_add(menuKeyChoice, _("None"), 0, nullptr, nullptr, FL_MENU_DIVIDER);
- for (int idx = 0; idx < getMenuKeySymbolCount(); idx++)
- fltk_menu_add(menuKeyChoice, getMenuKeySymbols()[idx].name, 0, nullptr, nullptr, 0);
-
- fltk_adjust_choice(menuKeyChoice);
-
- ty += CHOICE_HEIGHT + TIGHT_MARGIN;
}
ty -= TIGHT_MARGIN;
@@ -962,6 +981,76 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th)
}
+void OptionsDialog::createShortcutsPage(int tx, int ty, int tw, int th)
+{
+ Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Keyboard shortcuts"));
+
+ tx += OUTER_MARGIN;
+ ty += OUTER_MARGIN;
+
+ Fl_Box *intro = new Fl_Box(tx, ty, tw - OUTER_MARGIN * 2, INPUT_HEIGHT);
+ intro->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
+ intro->label(_("Modifier keys for keyboard shortcuts:"));
+
+ ty += INPUT_HEIGHT + INNER_MARGIN;
+
+ int width;
+
+ width = (tw - OUTER_MARGIN * 2 - INNER_MARGIN * 3) / 4;
+
+ ctrlButton = new Fl_Toggle_Button(tx, ty,
+ /*
+ * TRANSLATORS: This refers to the
+ * keyboard key
+ * */
+ width, BUTTON_HEIGHT, _("Ctrl"));
+ ctrlButton->selection_color(FL_SELECTION_COLOR);
+ ctrlButton->callback(handleModifier, this);
+ shiftButton = new Fl_Toggle_Button(tx + width + INNER_MARGIN, ty,
+ /*
+ * TRANSLATORS: This refers to the
+ * keyboard key
+ * */
+ width, BUTTON_HEIGHT, _("Shift"));
+ shiftButton->selection_color(FL_SELECTION_COLOR);
+ shiftButton->callback(handleModifier, this);
+ altButton = new Fl_Toggle_Button(tx + width * 2 + INNER_MARGIN * 2, ty,
+ /*
+ * TRANSLATORS: This refers to the
+ * keyboard key
+ * */
+ width, BUTTON_HEIGHT, _("Alt"));
+ altButton->selection_color(FL_SELECTION_COLOR);
+ altButton->callback(handleModifier, this);
+ superButton = new Fl_Toggle_Button(tx + width * 3 + INNER_MARGIN * 3, ty,
+ /*
+ * TRANSLATORS: This refers to the
+ * keyboard key
+ * */
+ width, BUTTON_HEIGHT, _("Win"));
+ superButton->selection_color(FL_SELECTION_COLOR);
+ superButton->callback(handleModifier, this);
+
+#ifdef __APPLE__
+ /* TRANSLATORS: This refers to the keyboard key */
+ ctrlButton->label(_("⌃ Ctrl"));
+ /* TRANSLATORS: This refers to the keyboard key */
+ shiftButton->label(_("⇧ Shift"));
+ /* TRANSLATORS: This refers to the keyboard key */
+ altButton->label(_("⌥ Option"));
+ /* TRANSLATORS: This refers to the keyboard key */
+ superButton->label(_("⌘ Cmd"));
+#endif
+
+ ty += BUTTON_HEIGHT + INNER_MARGIN;
+
+ shortcutsText = new Fl_Box(tx, ty, tw - OUTER_MARGIN * 2, th - ty - OUTER_MARGIN);
+ shortcutsText->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+
+ group->end();
+}
+
+
void OptionsDialog::createDisplayPage(int tx, int ty, int tw, int th)
{
Fl_Group *group = new Fl_Group(tx, ty, tw, th, _("Display"));
@@ -1130,6 +1219,20 @@ void OptionsDialog::handleRSAAES(Fl_Widget* /*widget*/, void *data)
}
+void OptionsDialog::handleSystemKeys(Fl_Widget* /*widget*/, void* data)
+{
+#ifdef __APPLE__
+ OptionsDialog* dialog = (OptionsDialog*)data;
+
+ // Pop up the access dialog if needed
+ if (dialog->systemKeysCheckbox->value())
+ cocoa_is_trusted(true);
+#else
+ (void)data;
+#endif
+}
+
+
void OptionsDialog::handleClipboard(Fl_Widget* /*widget*/, void *data)
{
(void)data;
@@ -1147,6 +1250,61 @@ void OptionsDialog::handleClipboard(Fl_Widget* /*widget*/, void *data)
#endif
}
+void OptionsDialog::handleModifier(Fl_Widget* /*widget*/, void *data)
+{
+ OptionsDialog *dialog = (OptionsDialog*)data;
+ unsigned mask;
+
+ mask = 0;
+ if (dialog->ctrlButton->value())
+ mask |= ShortcutHandler::Control;
+ if (dialog->shiftButton->value())
+ mask |= ShortcutHandler::Shift;
+ if (dialog->altButton->value())
+ mask |= ShortcutHandler::Alt;
+ if (dialog->superButton->value())
+ mask |= ShortcutHandler::Super;
+
+ if (mask == 0) {
+ dialog->shortcutsText->copy_label(
+ _("All keyboard shortcuts are disabled."));
+ } else {
+ char prefix[256];
+ char prefix_noplus[256];
+
+ std::string label;
+
+ strcpy(prefix, ShortcutHandler::modifierPrefix(mask));
+ strcpy(prefix_noplus, ShortcutHandler::modifierPrefix(mask, true));
+
+ label += core::format(
+ _("To release keyboard control from the session, press %s."),
+ prefix_noplus);
+ label += "\n\n";
+
+ label += core::format(
+ _("To pass all keyboard input to the session, press %sG."),
+ prefix);
+ label += "\n\n";
+
+ label += core::format(
+ _("To toggle full-screen mode, press %sEnter."), prefix);
+ label += "\n\n";
+
+ label += core::format(
+ _("To open the session context menu, press %sM."), prefix);
+ label += "\n\n";
+
+ label += core::format(
+ _("To send a key combination that includes %s directly to the "
+ "session, press %sSpace, release the space bar without "
+ "releasing %s, and press the desired key."),
+ prefix_noplus, prefix, prefix_noplus);
+
+ dialog->shortcutsText->copy_label(label.c_str());
+ }
+}
+
void OptionsDialog::handleFullScreenMode(Fl_Widget* /*widget*/, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;