File indexing completed on 2024-05-05 09:12:56

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