File indexing completed on 2024-04-21 04:58:35

0001 /*
0002     SPDX-FileCopyrightText: 2007-2012 Urs Wolfer <uwolfer@kde.org>
0003     SPDX-FileCopyrightText: 2012 AceLan Kao <acelan@acelan.idv.tw>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "rdphostpreferences.h"
0009 
0010 #include "settings.h"
0011 
0012 #include <QGuiApplication>
0013 #include <QScreen>
0014 #include <QWindow>
0015 
0016 #include <freerdp/locale/keyboard.h>
0017 
0018 // clang-format off
0019 static const QStringList keymaps = (QStringList()
0020     << QStringLiteral("ar")
0021     << QStringLiteral("cs")
0022     << QStringLiteral("da")
0023     << QStringLiteral("de")
0024     << QStringLiteral("de-ch")
0025     << QStringLiteral("en-dv")
0026     << QStringLiteral("en-gb")
0027     << QStringLiteral("en-us")
0028     << QStringLiteral("es")
0029     << QStringLiteral("et")
0030     << QStringLiteral("fi")
0031     << QStringLiteral("fo")
0032     << QStringLiteral("fr")
0033     << QStringLiteral("fr-be")
0034     << QStringLiteral("fr-ca")
0035     << QStringLiteral("fr-ch")
0036     << QStringLiteral("he")
0037     << QStringLiteral("hr")
0038     << QStringLiteral("hu")
0039     << QStringLiteral("is")
0040     << QStringLiteral("it")
0041     << QStringLiteral("ja")
0042     << QStringLiteral("ko")
0043     << QStringLiteral("lt")
0044     << QStringLiteral("lv")
0045     << QStringLiteral("mk")
0046     << QStringLiteral("nl")
0047     << QStringLiteral("nl-be")
0048     << QStringLiteral("no")
0049     << QStringLiteral("pl")
0050     << QStringLiteral("pt")
0051     << QStringLiteral("pt-br")
0052     << QStringLiteral("ru")
0053     << QStringLiteral("sl")
0054     << QStringLiteral("sv")
0055     << QStringLiteral("th")
0056     << QStringLiteral("tr")
0057 );
0058 // clang-format on
0059 
0060 static const QHash<QString, int> rdpLayouts = {
0061     {QStringLiteral("ar"), KBD_ARABIC_101},
0062     {QStringLiteral("cs"), KBD_CZECH},
0063     {QStringLiteral("da"), KBD_DANISH},
0064     {QStringLiteral("de"), KBD_GERMAN},
0065     {QStringLiteral("de-ch"), KBD_SWISS_GERMAN},
0066     {QStringLiteral("en-dv"), KBD_UNITED_STATES_DVORAK},
0067     {QStringLiteral("en-gb"), KBD_UNITED_KINGDOM},
0068     {QStringLiteral("en-us"), KBD_UNITED_STATES_INTERNATIONAL},
0069     {QStringLiteral("es"), KBD_SPANISH},
0070     {QStringLiteral("et"), KBD_ESTONIAN},
0071     {QStringLiteral("fi"), KBD_FINNISH},
0072     {QStringLiteral("fo"), KBD_DANISH},
0073     {QStringLiteral("fr"), KBD_FRENCH},
0074     {QStringLiteral("fr-be"), KBD_BELGIAN_FRENCH},
0075     {QStringLiteral("fr-ca"), KBD_CANADIAN_FRENCH},
0076     {QStringLiteral("fr-ch"), KBD_SWISS_FRENCH},
0077     {QStringLiteral("he"), KBD_HEBREW},
0078     {QStringLiteral("hr"), KBD_CROATIAN},
0079     {QStringLiteral("hu"), KBD_HUNGARIAN},
0080     {QStringLiteral("is"), KBD_ICELANDIC},
0081     {QStringLiteral("it"), KBD_ITALIAN},
0082     {QStringLiteral("ja"), KBD_JAPANESE},
0083     {QStringLiteral("ko"), KBD_KOREAN},
0084     {QStringLiteral("lt"), KBD_LITHUANIAN_IBM},
0085     {QStringLiteral("lv"), KBD_LATVIAN},
0086     {QStringLiteral("mk"), KBD_FYRO_MACEDONIAN},
0087     {QStringLiteral("nl"), KBD_DUTCH},
0088     {QStringLiteral("nl-be"), KBD_BELGIAN_PERIOD},
0089     {QStringLiteral("no"), KBD_NORWEGIAN},
0090     {QStringLiteral("pl"), KBD_POLISH_PROGRAMMERS},
0091     {QStringLiteral("pt"), KBD_PORTUGUESE},
0092     {QStringLiteral("pt-br"), KBD_PORTUGUESE_BRAZILIAN_ABNT},
0093     {QStringLiteral("ru"), KBD_RUSSIAN},
0094     {QStringLiteral("sl"), KBD_SLOVENIAN},
0095     {QStringLiteral("sv"), KBD_SWEDISH},
0096     {QStringLiteral("th"), KBD_THAI_KEDMANEE},
0097     {QStringLiteral("tr"), KBD_TURKISH_Q},
0098 };
0099 
0100 static const int defaultKeymap = 7; // en-us
0101 
0102 inline int keymap2int(const QString &keymap)
0103 {
0104     const int index = keymaps.lastIndexOf(keymap);
0105     return (index == -1) ? defaultKeymap : index;
0106 }
0107 
0108 inline QString int2keymap(int layout)
0109 {
0110     if (layout >= 0 && layout < keymaps.count())
0111         return keymaps.at(layout);
0112     else
0113         return keymaps.at(defaultKeymap);
0114 }
0115 
0116 RdpHostPreferences::RdpHostPreferences(KConfigGroup configGroup, QObject *parent)
0117     : HostPreferences(configGroup, parent)
0118 {
0119 }
0120 
0121 RdpHostPreferences::~RdpHostPreferences()
0122 {
0123 }
0124 
0125 QWidget *RdpHostPreferences::createProtocolSpecificConfigPage()
0126 {
0127     QWidget *rdpPage = new QWidget();
0128     rdpUi.setupUi(rdpPage);
0129 
0130     rdpUi.kcfg_ScaleToSize->setChecked(scaleToSize());
0131     rdpUi.kcfg_Height->setValue(height());
0132     rdpUi.kcfg_Width->setValue(width());
0133     rdpUi.kcfg_Resolution->setCurrentIndex(int(resolution()));
0134     rdpUi.kcfg_Acceleration->setCurrentIndex(int(acceleration()));
0135     rdpUi.kcfg_ColorDepth->setCurrentIndex(int(colorDepth()));
0136     rdpUi.kcfg_KeyboardLayout->setCurrentIndex(keymap2int(keyboardLayout()));
0137     rdpUi.kcfg_ShareMedia->setText(shareMedia());
0138     rdpUi.kcfg_TlsSecLevel->setCurrentIndex(int(tlsSecLevel()));
0139 
0140     // Have to call updateWidthHeight() here
0141     // We leverage the final part of this function to enable/disable kcfg_Height and kcfg_Width
0142     updateWidthHeight(resolution());
0143 
0144     connect(rdpUi.kcfg_Resolution, &QComboBox::currentIndexChanged, this, [this](int index) {
0145         updateWidthHeight(Resolution(index));
0146     });
0147 
0148     // Color depth depends on acceleration method, with the better ones only working with 32-bit
0149     // color. So ensure we reflect that in the settings UI.
0150     updateColorDepth(acceleration());
0151     connect(rdpUi.kcfg_Acceleration, &QComboBox::currentIndexChanged, this, [this](int index) {
0152         updateColorDepth(Acceleration(index));
0153     });
0154 
0155     return rdpPage;
0156 }
0157 
0158 void RdpHostPreferences::updateWidthHeight(Resolution resolution)
0159 {
0160     switch (resolution) {
0161     case Resolution::Small:
0162         rdpUi.kcfg_Width->setValue(1280);
0163         rdpUi.kcfg_Height->setValue(720);
0164         break;
0165     case Resolution::Medium:
0166         rdpUi.kcfg_Width->setValue(1600);
0167         rdpUi.kcfg_Height->setValue(900);
0168         break;
0169     case Resolution::Large:
0170         rdpUi.kcfg_Width->setValue(1920);
0171         rdpUi.kcfg_Height->setValue(1080);
0172         break;
0173     case Resolution::MatchWindow: {
0174         auto *window = qApp->activeWindow();
0175         if (window->parentWidget()) {
0176             window = window->parentWidget();
0177         }
0178         rdpUi.kcfg_Width->setValue(window->width());
0179         rdpUi.kcfg_Height->setValue(window->height());
0180         break;
0181     }
0182     case Resolution::MatchScreen: {
0183         QWindow *window = rdpUi.kcfg_Width->window()->windowHandle();
0184         QScreen *screen = window ? window->screen() : qGuiApp->primaryScreen();
0185         const QSize size = screen->size() * screen->devicePixelRatio();
0186 
0187         rdpUi.kcfg_Width->setValue(size.width());
0188         rdpUi.kcfg_Height->setValue(size.height());
0189         break;
0190     }
0191     case Resolution::Custom:
0192     default:
0193         break;
0194     }
0195 
0196     const bool enabled = resolution == Resolution::Custom;
0197 
0198     rdpUi.kcfg_Height->setEnabled(enabled);
0199     rdpUi.kcfg_Width->setEnabled(enabled);
0200     rdpUi.heightLabel->setEnabled(enabled);
0201     rdpUi.widthLabel->setEnabled(enabled);
0202 }
0203 
0204 void RdpHostPreferences::acceptConfig()
0205 {
0206     HostPreferences::acceptConfig();
0207 
0208     setScaleToSize(rdpUi.kcfg_ScaleToSize->isChecked());
0209     setWidth(rdpUi.kcfg_Width->value());
0210     setHeight(rdpUi.kcfg_Height->value());
0211     setResolution(Resolution(rdpUi.kcfg_Resolution->currentIndex()));
0212     setAcceleration(Acceleration(rdpUi.kcfg_Acceleration->currentIndex()));
0213     setColorDepth(ColorDepth(rdpUi.kcfg_ColorDepth->currentIndex()));
0214     setKeyboardLayout(int2keymap(rdpUi.kcfg_KeyboardLayout->currentIndex()));
0215     setSound(Sound(rdpUi.kcfg_Sound->currentIndex()));
0216     setShareMedia(rdpUi.kcfg_ShareMedia->text());
0217     setTlsSecLevel(TlsSecLevel(rdpUi.kcfg_TlsSecLevel->currentIndex()));
0218 }
0219 
0220 bool RdpHostPreferences::scaleToSize() const
0221 {
0222     return m_configGroup.readEntry("scaleToSize", true);
0223 }
0224 
0225 void RdpHostPreferences::setScaleToSize(bool scale)
0226 {
0227     m_configGroup.writeEntry("scaleToSize", scale);
0228 }
0229 
0230 RdpHostPreferences::Resolution RdpHostPreferences::resolution() const
0231 {
0232     return Resolution(m_configGroup.readEntry("resolution", Settings::resolution()));
0233 }
0234 
0235 void RdpHostPreferences::setResolution(Resolution resolution)
0236 {
0237     m_configGroup.writeEntry("resolution", int(resolution));
0238 }
0239 
0240 RdpHostPreferences::Acceleration RdpHostPreferences::acceleration() const
0241 {
0242     return Acceleration(m_configGroup.readEntry("acceleration", Settings::acceleration()));
0243 }
0244 
0245 void RdpHostPreferences::setAcceleration(Acceleration acceleration)
0246 {
0247     m_configGroup.writeEntry("acceleration", int(acceleration));
0248 }
0249 
0250 void RdpHostPreferences::setColorDepth(ColorDepth colorDepth)
0251 {
0252     m_configGroup.writeEntry("colorDepth", int(colorDepth));
0253 }
0254 
0255 RdpHostPreferences::ColorDepth RdpHostPreferences::colorDepth() const
0256 {
0257     return ColorDepth(m_configGroup.readEntry("colorDepth", Settings::colorDepth()));
0258 }
0259 
0260 void RdpHostPreferences::setKeyboardLayout(const QString &keyboardLayout)
0261 {
0262     if (!keyboardLayout.isNull())
0263         m_configGroup.writeEntry("keyboardLayout", keymap2int(keyboardLayout));
0264 }
0265 
0266 QString RdpHostPreferences::keyboardLayout() const
0267 {
0268     return int2keymap(m_configGroup.readEntry("keyboardLayout", Settings::keyboardLayout()));
0269 }
0270 
0271 int RdpHostPreferences::rdpKeyboardLayout() const
0272 {
0273     auto layout = keyboardLayout();
0274     return rdpLayouts.value(layout, KBD_UNITED_STATES_INTERNATIONAL);
0275 }
0276 
0277 void RdpHostPreferences::setSound(Sound sound)
0278 {
0279     m_configGroup.writeEntry("sound", int(sound));
0280 }
0281 
0282 RdpHostPreferences::Sound RdpHostPreferences::sound() const
0283 {
0284     return Sound(m_configGroup.readEntry("sound", Settings::sound()));
0285 }
0286 
0287 void RdpHostPreferences::setShareMedia(const QString &shareMedia)
0288 {
0289     if (!shareMedia.isNull())
0290         m_configGroup.writeEntry("shareMedia", shareMedia);
0291 }
0292 
0293 QString RdpHostPreferences::shareMedia() const
0294 {
0295     return m_configGroup.readEntry("shareMedia", Settings::shareMedia());
0296 }
0297 
0298 void RdpHostPreferences::updateColorDepth(Acceleration acceleration)
0299 {
0300     switch (acceleration) {
0301     case Acceleration::ForceGraphicsPipeline:
0302     case Acceleration::ForceRemoteFx:
0303         rdpUi.kcfg_ColorDepth->setEnabled(false);
0304         rdpUi.kcfg_ColorDepth->setCurrentIndex(0);
0305         break;
0306     case Acceleration::Disabled:
0307     case Acceleration::Auto:
0308         rdpUi.kcfg_ColorDepth->setEnabled(true);
0309     }
0310 }
0311 
0312 void RdpHostPreferences::setTlsSecLevel(TlsSecLevel tlsSecLevel)
0313 {
0314     m_configGroup.writeEntry("tlsSecLevel", int(tlsSecLevel));
0315 }
0316 
0317 RdpHostPreferences::TlsSecLevel RdpHostPreferences::tlsSecLevel() const
0318 {
0319     return TlsSecLevel(m_configGroup.readEntry("tlsSecLevel", Settings::tlsSecLevel()));
0320 }