mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 10:52:53 +00:00
555 lines
22 KiB
C++
555 lines
22 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2002 Arend van Beelen jr. <arend@auton.nl>
|
|
** Copyright (C) 2007 - 2012 Urs Wolfer <uwolfer @ kde.org>
|
|
** Copyright (C) 2012 AceLan Kao <acelan @ acelan.idv.tw>
|
|
**
|
|
** This file is part of KDE.
|
|
**
|
|
** This program 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 program 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 program; see the file COPYING. If not, write to
|
|
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
** Boston, MA 02110-1301, USA.
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "rdpview.h"
|
|
|
|
#include "settings.h"
|
|
|
|
#include <KInputDialog>
|
|
#include <KMessageBox>
|
|
#include <KPasswordDialog>
|
|
#include <KShell>
|
|
|
|
#include <QX11EmbedContainer>
|
|
#include <QEvent>
|
|
|
|
RdpView::RdpView(QWidget *parent,
|
|
const KUrl &url,
|
|
KConfigGroup configGroup,
|
|
const QString &user, const QString &password)
|
|
: RemoteView(parent),
|
|
m_user(user),
|
|
m_password(password),
|
|
m_quitFlag(false),
|
|
m_process(NULL)
|
|
{
|
|
m_url = url;
|
|
m_host = url.host();
|
|
m_port = url.port();
|
|
|
|
if (m_port <= 0) {
|
|
m_port = TCP_PORT_RDP;
|
|
}
|
|
|
|
m_container = new QX11EmbedContainer(this);
|
|
m_container->installEventFilter(this);
|
|
|
|
m_hostPreferences = new RdpHostPreferences(configGroup, this);
|
|
}
|
|
|
|
RdpView::~RdpView()
|
|
{
|
|
startQuitting();
|
|
}
|
|
|
|
// filter out key and mouse events to the container if we are view only
|
|
//FIXME: X11 events are passed to the app before getting caught in the Qt event processing
|
|
bool RdpView::eventFilter(QObject *obj, QEvent *event)
|
|
{
|
|
if (m_viewOnly) {
|
|
if (event->type() == QEvent::KeyPress ||
|
|
event->type() == QEvent::KeyRelease ||
|
|
event->type() == QEvent::MouseButtonDblClick ||
|
|
event->type() == QEvent::MouseButtonPress ||
|
|
event->type() == QEvent::MouseButtonRelease ||
|
|
event->type() == QEvent::MouseMove)
|
|
return true;
|
|
}
|
|
return RemoteView::eventFilter(obj, event);
|
|
}
|
|
|
|
QSize RdpView::framebufferSize()
|
|
{
|
|
return m_container->minimumSizeHint();
|
|
}
|
|
|
|
QSize RdpView::sizeHint() const
|
|
{
|
|
return maximumSize();
|
|
}
|
|
|
|
void RdpView::startQuitting()
|
|
{
|
|
kDebug(5012) << "About to quit";
|
|
m_quitFlag = true;
|
|
if (m_process) {
|
|
m_process->terminate();
|
|
m_process->waitForFinished(1000);
|
|
m_container->discardClient();
|
|
}
|
|
}
|
|
|
|
bool RdpView::isQuitting()
|
|
{
|
|
return m_quitFlag;
|
|
}
|
|
|
|
bool RdpView::start()
|
|
{
|
|
m_container->show();
|
|
|
|
if (m_url.userName().isEmpty()) {
|
|
QString userName;
|
|
bool ok = false;
|
|
|
|
userName = KInputDialog::getText(i18n("Enter Username"),
|
|
i18n("Please enter the username you would like to use for login."),
|
|
Settings::defaultRdpUserName(), &ok, this);
|
|
|
|
if (ok) {
|
|
m_url.setUserName(userName);
|
|
}
|
|
}
|
|
|
|
if (!m_url.userName().isEmpty()) {
|
|
const bool useLdapLogin = Settings::recognizeLdapLogins() && m_url.userName().contains('\\');
|
|
kDebug(5012) << "Is LDAP login:" << useLdapLogin << m_url.userName();
|
|
|
|
QString walletPassword = QString();
|
|
if (m_hostPreferences->walletSupport()) {
|
|
walletPassword = readWalletPassword(useLdapLogin);
|
|
}
|
|
if (!walletPassword.isNull()) {
|
|
m_url.setPassword(walletPassword);
|
|
} else {
|
|
KPasswordDialog dialog(this);
|
|
dialog.setPrompt(i18n("Access to the system requires a password."));
|
|
if (dialog.exec() == KPasswordDialog::Accepted) {
|
|
m_url.setPassword(dialog.password());
|
|
|
|
if (m_hostPreferences->walletSupport()) {
|
|
saveWalletPassword(dialog.password(), useLdapLogin);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_process = new QProcess(m_container);
|
|
|
|
QStringList arguments;
|
|
|
|
int width, height;
|
|
if (m_hostPreferences->width() > 0) {
|
|
width = m_hostPreferences->width();
|
|
height = m_hostPreferences->height();
|
|
} else {
|
|
width = this->parentWidget()->size().width();
|
|
height = this->parentWidget()->size().height();
|
|
}
|
|
arguments << "-g" << QString::number(width) + 'x' + QString::number(height);
|
|
|
|
arguments << "-k" << keymapToXfreerdp(m_hostPreferences->keyboardLayout());
|
|
|
|
if (!m_url.userName().isEmpty()) {
|
|
// if username contains a domain, it needs to be set with another parameter
|
|
if (m_url.userName().contains('\\')) {
|
|
const QStringList splittedName = m_url.userName().split('\\');
|
|
arguments << "-d" << splittedName.at(0);
|
|
arguments << "-u" << splittedName.at(1);
|
|
} else {
|
|
arguments << "-u" << m_url.userName();
|
|
}
|
|
} else {
|
|
arguments << "-u" << "";
|
|
}
|
|
|
|
if (!m_url.password().isNull())
|
|
arguments << "-p" << m_url.password();
|
|
|
|
arguments << "-D"; // request the window has no decorations
|
|
arguments << "-X" << QString::number(m_container->winId());
|
|
arguments << "-a" << QString::number((m_hostPreferences->colorDepth() + 1) * 8);
|
|
|
|
switch (m_hostPreferences->sound()) {
|
|
case 1:
|
|
arguments << "-o";
|
|
break;
|
|
case 0:
|
|
arguments << "--plugin" << "rdpsnd";
|
|
break;
|
|
case 2:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!m_hostPreferences->shareMedia().isEmpty()) {
|
|
QStringList shareMedia;
|
|
shareMedia << "--plugin" << "rdpdr" << "--data" << "disk:media:" + m_hostPreferences->shareMedia() << "--";
|
|
arguments += shareMedia;
|
|
}
|
|
|
|
QString performance;
|
|
switch (m_hostPreferences->performance()) {
|
|
case 0:
|
|
performance = 'm';
|
|
break;
|
|
case 1:
|
|
performance = 'b';
|
|
break;
|
|
case 2:
|
|
performance = 'l';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
arguments << "-x" << performance;
|
|
|
|
if (m_hostPreferences->console()) {
|
|
arguments << "-0";
|
|
}
|
|
|
|
if (m_hostPreferences->remoteFX()) {
|
|
arguments << "--rfx";
|
|
}
|
|
|
|
if (!m_hostPreferences->extraOptions().isEmpty()) {
|
|
const QStringList additionalArguments = KShell::splitArgs(m_hostPreferences->extraOptions());
|
|
arguments += additionalArguments;
|
|
}
|
|
|
|
// krdc has no support for certificate management yet; it would not be possbile to connect to any host:
|
|
// "The host key for example.com has changed" ...
|
|
// "Add correct host key in ~/.freerdp/known_hosts to get rid of this message."
|
|
arguments << "--ignore-certificate";
|
|
|
|
// clipboard sharing is activated in KRDC; user can disable it at runtime
|
|
arguments << "--plugin" << "cliprdr";
|
|
|
|
arguments << "-t" << QString::number(m_port);
|
|
arguments << m_host;
|
|
|
|
kDebug(5012) << "Starting xfreerdp with arguments:" << arguments;
|
|
|
|
setStatus(Connecting);
|
|
|
|
connect(m_process, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError)));
|
|
connect(m_process, SIGNAL(readyReadStandardError()), SLOT(receivedStandardError()));
|
|
connect(m_process, SIGNAL(readyReadStandardOutput()), SLOT(receivedStandardOutput()));
|
|
connect(m_container, SIGNAL(clientClosed()), SLOT(connectionClosed()));
|
|
connect(m_container, SIGNAL(clientIsEmbedded()), SLOT(connectionOpened()));
|
|
|
|
m_process->start("xfreerdp", arguments);
|
|
|
|
return true;
|
|
}
|
|
|
|
HostPreferences* RdpView::hostPreferences()
|
|
{
|
|
return m_hostPreferences;
|
|
}
|
|
|
|
void RdpView::switchFullscreen(bool on)
|
|
{
|
|
if (on == true) {
|
|
m_container->grabKeyboard();
|
|
}
|
|
}
|
|
|
|
void RdpView::connectionOpened()
|
|
{
|
|
kDebug(5012) << "Connection opened";
|
|
const QSize size = m_container->minimumSizeHint();
|
|
kDebug(5012) << "Size hint: " << size.width() << " " << size.height();
|
|
setStatus(Connected);
|
|
setFixedSize(size);
|
|
resize(size);
|
|
m_container->setFixedSize(size);
|
|
emit framebufferSizeChanged(size.width(), size.height());
|
|
emit connected();
|
|
setFocus();
|
|
}
|
|
|
|
QPixmap RdpView::takeScreenshot()
|
|
{
|
|
return QPixmap::grabWindow(m_container->clientWinId());
|
|
}
|
|
|
|
void RdpView::connectionClosed()
|
|
{
|
|
emit disconnected();
|
|
setStatus(Disconnected);
|
|
m_quitFlag = true;
|
|
}
|
|
|
|
void RdpView::connectionError()
|
|
{
|
|
emit disconnectedError();
|
|
connectionClosed();
|
|
}
|
|
|
|
void RdpView::processError(QProcess::ProcessError error)
|
|
{
|
|
kDebug(5012) << "processError:" << error;
|
|
if (m_quitFlag) // do not try to show error messages while quitting (prevent crashes)
|
|
return;
|
|
|
|
if (m_status == Connecting) {
|
|
if (error == QProcess::FailedToStart) {
|
|
KMessageBox::error(0, i18n("Could not start \"xfreerdp\"; make sure xfreerdp is properly installed."),
|
|
i18n("RDP Failure"));
|
|
connectionError();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RdpView::receivedStandardError()
|
|
{
|
|
const QString output(m_process->readAllStandardError());
|
|
kDebug(5012) << "receivedStandardError:" << output;
|
|
QString line;
|
|
int i = 0;
|
|
while (!(line = output.section('\n', i, i)).isEmpty()) {
|
|
|
|
// the following error is issued by freerdp because of a bug in freerdp 1.0.1 and below;
|
|
// see: https://github.com/FreeRDP/FreeRDP/pull/576
|
|
//"X Error of failed request: BadWindow (invalid Window parameter)
|
|
// Major opcode of failed request: 7 (X_ReparentWindow)
|
|
// Resource id in failed request: 0x71303348
|
|
// Serial number of failed request: 36
|
|
// Current serial number in output stream: 36"
|
|
if (line.contains(QLatin1String("X_ReparentWindow"))) {
|
|
KMessageBox::error(0, i18n("The version of \"xfreerdp\" you are using is too old.\n"
|
|
"xfreerdp 1.0.2 or greater is required."),
|
|
i18n("RDP Failure"));
|
|
connectionError();
|
|
return;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void RdpView::receivedStandardOutput()
|
|
{
|
|
const QString output(m_process->readAllStandardOutput());
|
|
kDebug(5012) << "receivedStandardOutput:" << output;
|
|
QString line;
|
|
int i = 0;
|
|
while (!(line = output.section('\n', i, i)).isEmpty()) {
|
|
|
|
// full xfreerdp message: "transport_connect: getaddrinfo (Name or service not known)"
|
|
if (line.contains(QLatin1String("Name or service not known"))) {
|
|
KMessageBox::error(0, i18n("Name or service not known."),
|
|
i18n("Connection Failure"));
|
|
connectionError();
|
|
return;
|
|
|
|
// full xfreerdp message: "unable to connect to example.com:3389"
|
|
} else if (line.contains(QLatin1String("unable to connect to"))) {
|
|
KMessageBox::error(0, i18n("Connection attempt to host failed."),
|
|
i18n("Connection Failure"));
|
|
connectionError();
|
|
return;
|
|
|
|
// looks like some generic xfreerdp error message, handle it if nothing was handled:
|
|
// "Error: protocol security negotiation failure"
|
|
} else if (line.contains(QLatin1String("Error: protocol security negotiation failure"))) {
|
|
KMessageBox::error(0, i18n("Connection attempt to host failed."),
|
|
i18n("Connection Failure"));
|
|
connectionError();
|
|
return;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void RdpView::setGrabAllKeys(bool grabAllKeys)
|
|
{
|
|
Q_UNUSED(grabAllKeys);
|
|
// do nothing.. grabKeyboard seems not to be supported in QX11EmbedContainer
|
|
}
|
|
|
|
QString RdpView::keymapToXfreerdp(const QString &keyboadLayout)
|
|
{
|
|
if (keymapToXfreerdpHash.isEmpty()) {
|
|
keymapToXfreerdpHash = initKeymapToXfreerdp();
|
|
}
|
|
return keymapToXfreerdpHash[keyboadLayout];
|
|
}
|
|
|
|
// list of xfreerdp --kbd-list
|
|
// this is a mapping for rdesktop comptibilty (old settings will still work)
|
|
// needs to be completed (when not in message freeze; needs new localization)
|
|
QHash<QString, QString> RdpView::initKeymapToXfreerdp()
|
|
{
|
|
QHash<QString, QString> keymapToXfreerdpHash;
|
|
|
|
// Keyboard Layouts
|
|
keymapToXfreerdpHash["ar"] = "0x00000401"; // Arabic (101)
|
|
// keymapToXfreerdpHash[""] = "0x00000402"; // Bulgarian
|
|
// keymapToXfreerdpHash[""] = "0x00000404"; // Chinese (Traditional) - US Keyboard
|
|
keymapToXfreerdpHash["cs"] = "0x00000405"; // Czech
|
|
keymapToXfreerdpHash["da"] = "0x00000406"; // Danish
|
|
keymapToXfreerdpHash["fo"] = "0x00000406"; // Danish, Faroese; legacy for rdesktop
|
|
keymapToXfreerdpHash["de"] = "0x00000407"; // German
|
|
// keymapToXfreerdpHash[""] = "0x00000408"; // Greek
|
|
keymapToXfreerdpHash["en-us"] = "0x00000409"; // US
|
|
keymapToXfreerdpHash["es"] = "0x0000040A"; // Spanish
|
|
keymapToXfreerdpHash["fi"] = "0x0000040B"; // Finnish
|
|
keymapToXfreerdpHash["fr"] = "0x0000040C"; // French
|
|
keymapToXfreerdpHash["he"] = "0x0000040D"; // Hebrew
|
|
keymapToXfreerdpHash["hu"] = "0x0000040E"; // Hungarian
|
|
keymapToXfreerdpHash["is"] = "0x0000040F"; // Icelandic
|
|
keymapToXfreerdpHash["it"] = "0x00000410"; // Italian
|
|
keymapToXfreerdpHash["ja"] = "0x00000411"; // Japanese
|
|
keymapToXfreerdpHash["ko"] = "0x00000412"; // Korean
|
|
keymapToXfreerdpHash["nl"] = "0x00000413"; // Dutch
|
|
keymapToXfreerdpHash["no"] = "0x00000414"; // Norwegian
|
|
keymapToXfreerdpHash["pl"] = "0x00000415"; // Polish (Programmers)
|
|
keymapToXfreerdpHash["pt-br"] = "0x00000416"; // Portuguese (Brazilian ABNT)
|
|
// keymapToXfreerdpHash[""] = "0x00000418"; // Romanian
|
|
keymapToXfreerdpHash["ru"] = "0x00000419"; // Russian
|
|
keymapToXfreerdpHash["hr"] = "0x0000041A"; // Croatian
|
|
// keymapToXfreerdpHash[""] = "0x0000041B"; // Slovak
|
|
// keymapToXfreerdpHash[""] = "0x0000041C"; // Albanian
|
|
keymapToXfreerdpHash["sv"] = "0x0000041D"; // Swedish
|
|
keymapToXfreerdpHash["th"] = "0x0000041E"; // Thai Kedmanee
|
|
keymapToXfreerdpHash["tr"] = "0x0000041F"; // Turkish Q
|
|
// keymapToXfreerdpHash[""] = "0x00000420"; // Urdu
|
|
// keymapToXfreerdpHash[""] = "0x00000422"; // Ukrainian
|
|
// keymapToXfreerdpHash[""] = "0x00000423"; // Belarusian
|
|
keymapToXfreerdpHash["sl"] = "0x00000424"; // Slovenian
|
|
keymapToXfreerdpHash["et"] = "0x00000425"; // Estonian
|
|
keymapToXfreerdpHash["lv"] = "0x00000426"; // Latvian
|
|
keymapToXfreerdpHash["lt"] = "0x00000427"; // Lithuanian IBM
|
|
// keymapToXfreerdpHash[""] = "0x00000429"; // Farsi
|
|
// keymapToXfreerdpHash[""] = "0x0000042A"; // Vietnamese
|
|
// keymapToXfreerdpHash[""] = "0x0000042B"; // Armenian Eastern
|
|
// keymapToXfreerdpHash[""] = "0x0000042C"; // Azeri Latin
|
|
keymapToXfreerdpHash["mk"] = "0x0000042F"; // FYRO Macedonian
|
|
// keymapToXfreerdpHash[""] = "0x00000437"; // Georgian
|
|
// keymapToXfreerdpHash[""] = "0x00000438"; // Faeroese
|
|
// keymapToXfreerdpHash[""] = "0x00000439"; // Devanagari - INSCRIPT
|
|
// keymapToXfreerdpHash[""] = "0x0000043A"; // Maltese 47-key
|
|
// keymapToXfreerdpHash[""] = "0x0000043B"; // Norwegian with Sami
|
|
// keymapToXfreerdpHash[""] = "0x0000043F"; // Kazakh
|
|
// keymapToXfreerdpHash[""] = "0x00000440"; // Kyrgyz Cyrillic
|
|
// keymapToXfreerdpHash[""] = "0x00000444"; // Tatar
|
|
// keymapToXfreerdpHash[""] = "0x00000445"; // Bengali
|
|
// keymapToXfreerdpHash[""] = "0x00000446"; // Punjabi
|
|
// keymapToXfreerdpHash[""] = "0x00000447"; // Gujarati
|
|
// keymapToXfreerdpHash[""] = "0x00000449"; // Tamil
|
|
// keymapToXfreerdpHash[""] = "0x0000044A"; // Telugu
|
|
// keymapToXfreerdpHash[""] = "0x0000044B"; // Kannada
|
|
// keymapToXfreerdpHash[""] = "0x0000044C"; // Malayalam
|
|
// keymapToXfreerdpHash[""] = "0x0000044E"; // Marathi
|
|
// keymapToXfreerdpHash[""] = "0x00000450"; // Mongolian Cyrillic
|
|
// keymapToXfreerdpHash[""] = "0x00000452"; // United Kingdom Extended
|
|
// keymapToXfreerdpHash[""] = "0x0000045A"; // Syriac
|
|
// keymapToXfreerdpHash[""] = "0x00000461"; // Nepali
|
|
// keymapToXfreerdpHash[""] = "0x00000463"; // Pashto
|
|
// keymapToXfreerdpHash[""] = "0x00000465"; // Divehi Phonetic
|
|
// keymapToXfreerdpHash[""] = "0x0000046E"; // Luxembourgish
|
|
// keymapToXfreerdpHash[""] = "0x00000481"; // Maori
|
|
// keymapToXfreerdpHash[""] = "0x00000804"; // Chinese (Simplified) - US Keyboard
|
|
keymapToXfreerdpHash["de-ch"] = "0x00000807"; // Swiss German
|
|
keymapToXfreerdpHash["en-gb"] = "0x00000809"; // United Kingdom
|
|
// keymapToXfreerdpHash[""] = "0x0000080A"; // Latin American
|
|
keymapToXfreerdpHash["fr-be"] = "0x0000080C"; // Belgian French
|
|
keymapToXfreerdpHash["nl-be"] = "0x00000813"; // Belgian (Period)
|
|
keymapToXfreerdpHash["pt"] = "0x00000816"; // Portuguese
|
|
// keymapToXfreerdpHash[""] = "0x0000081A"; // Serbian (Latin)
|
|
// keymapToXfreerdpHash[""] = "0x0000082C"; // Azeri Cyrillic
|
|
// keymapToXfreerdpHash[""] = "0x0000083B"; // Swedish with Sami
|
|
// keymapToXfreerdpHash[""] = "0x00000843"; // Uzbek Cyrillic
|
|
// keymapToXfreerdpHash[""] = "0x0000085D"; // Inuktitut Latin
|
|
// keymapToXfreerdpHash[""] = "0x00000C0C"; // Canadian French (legacy)
|
|
// keymapToXfreerdpHash[""] = "0x00000C1A"; // Serbian (Cyrillic)
|
|
keymapToXfreerdpHash["fr-ca"] = "0x00001009"; // Canadian French
|
|
keymapToXfreerdpHash["fr-ch"] = "0x0000100C"; // Swiss French
|
|
// keymapToXfreerdpHash[""] = "0x0000141A"; // Bosnian
|
|
// keymapToXfreerdpHash[""] = "0x00001809"; // Irish
|
|
// keymapToXfreerdpHash[""] = "0x0000201A"; // Bosnian Cyrillic
|
|
|
|
// Keyboard Layout Variants
|
|
// keymapToXfreerdpHash[""] = "0x00010401"; // Arabic (102)
|
|
// keymapToXfreerdpHash[""] = "0x00010402"; // Bulgarian (Latin)
|
|
// keymapToXfreerdpHash[""] = "0x00010405"; // Czech (QWERTY)
|
|
// keymapToXfreerdpHash[""] = "0x00010407"; // German (IBM)
|
|
// keymapToXfreerdpHash[""] = "0x00010408"; // Greek (220)
|
|
keymapToXfreerdpHash["en-dv"] = "0x00010409"; // United States-Dvorak
|
|
// keymapToXfreerdpHash[""] = "0x0001040A"; // Spanish Variation
|
|
// keymapToXfreerdpHash[""] = "0x0001040E"; // Hungarian 101-key
|
|
// keymapToXfreerdpHash[""] = "0x00010410"; // Italian (142)
|
|
// keymapToXfreerdpHash[""] = "0x00010415"; // Polish (214)
|
|
// keymapToXfreerdpHash[""] = "0x00010416"; // Portuguese (Brazilian ABNT2)
|
|
// keymapToXfreerdpHash[""] = "0x00010419"; // Russian (Typewriter)
|
|
// keymapToXfreerdpHash[""] = "0x0001041B"; // Slovak (QWERTY)
|
|
// keymapToXfreerdpHash[""] = "0x0001041E"; // Thai Pattachote
|
|
// keymapToXfreerdpHash[""] = "0x0001041F"; // Turkish F
|
|
// keymapToXfreerdpHash[""] = "0x00010426"; // Latvian (QWERTY)
|
|
// keymapToXfreerdpHash[""] = "0x00010427"; // Lithuanian
|
|
// keymapToXfreerdpHash[""] = "0x0001042B"; // Armenian Western
|
|
// keymapToXfreerdpHash[""] = "0x00010439"; // Hindi Traditional
|
|
// keymapToXfreerdpHash[""] = "0x0001043A"; // Maltese 48-key
|
|
// keymapToXfreerdpHash[""] = "0x0001043B"; // Sami Extended Norway
|
|
// keymapToXfreerdpHash[""] = "0x00010445"; // Bengali (Inscript)
|
|
// keymapToXfreerdpHash[""] = "0x0001045A"; // Syriac Phonetic
|
|
// keymapToXfreerdpHash[""] = "0x00010465"; // Divehi Typewriter
|
|
// keymapToXfreerdpHash[""] = "0x0001080C"; // Belgian (Comma)
|
|
// keymapToXfreerdpHash[""] = "0x0001083B"; // Finnish with Sami
|
|
// keymapToXfreerdpHash[""] = "0x00011009"; // Canadian Multilingual Standard
|
|
// keymapToXfreerdpHash[""] = "0x00011809"; // Gaelic
|
|
// keymapToXfreerdpHash[""] = "0x00020401"; // Arabic (102) AZERTY
|
|
// keymapToXfreerdpHash[""] = "0x00020405"; // Czech Programmers
|
|
// keymapToXfreerdpHash[""] = "0x00020408"; // Greek (319)
|
|
// keymapToXfreerdpHash[""] = "0x00020409"; // United States-International
|
|
// keymapToXfreerdpHash[""] = "0x0002041E"; // Thai Kedmanee (non-ShiftLock)
|
|
// keymapToXfreerdpHash[""] = "0x0002083B"; // Sami Extended Finland-Sweden
|
|
// keymapToXfreerdpHash[""] = "0x00030408"; // Greek (220) Latin
|
|
// keymapToXfreerdpHash[""] = "0x00030409"; // United States-Dvorak for left hand
|
|
// keymapToXfreerdpHash[""] = "0x0003041E"; // Thai Pattachote (non-ShiftLock)
|
|
// keymapToXfreerdpHash[""] = "0x00040408"; // Greek (319) Latin
|
|
// keymapToXfreerdpHash[""] = "0x00040409"; // United States-Dvorak for right hand
|
|
// keymapToXfreerdpHash[""] = "0x00050408"; // Greek Latin
|
|
// keymapToXfreerdpHash[""] = "0x00050409"; // US English Table for IBM Arabic 238_L
|
|
// keymapToXfreerdpHash[""] = "0x00060408"; // Greek Polytonic
|
|
// keymapToXfreerdpHash[""] = "0xB0000407"; // German Neo
|
|
|
|
// Keyboard Input Method Editors (IMEs)
|
|
// keymapToXfreerdpHash[""] = "0xE0010404"; // Chinese (Traditional) - Phonetic
|
|
// keymapToXfreerdpHash[""] = "0xE0010411"; // Japanese Input System (MS-IME2002)
|
|
// keymapToXfreerdpHash[""] = "0xE0010412"; // Korean Input System (IME 2000)
|
|
// keymapToXfreerdpHash[""] = "0xE0010804"; // Chinese (Simplified) - QuanPin
|
|
// keymapToXfreerdpHash[""] = "0xE0020404"; // Chinese (Traditional) - ChangJie
|
|
// keymapToXfreerdpHash[""] = "0xE0020804"; // Chinese (Simplified) - ShuangPin
|
|
// keymapToXfreerdpHash[""] = "0xE0030404"; // Chinese (Traditional) - Quick
|
|
// keymapToXfreerdpHash[""] = "0xE0030804"; // Chinese (Simplified) - ZhengMa
|
|
// keymapToXfreerdpHash[""] = "0xE0040404"; // Chinese (Traditional) - Big5 Code
|
|
// keymapToXfreerdpHash[""] = "0xE0050404"; // Chinese (Traditional) - Array
|
|
// keymapToXfreerdpHash[""] = "0xE0050804"; // Chinese (Simplified) - NeiMa
|
|
// keymapToXfreerdpHash[""] = "0xE0060404"; // Chinese (Traditional) - DaYi
|
|
// keymapToXfreerdpHash[""] = "0xE0070404"; // Chinese (Traditional) - Unicode
|
|
// keymapToXfreerdpHash[""] = "0xE0080404"; // Chinese (Traditional) - New Phonetic
|
|
// keymapToXfreerdpHash[""] = "0xE0090404"; // Chinese (Traditional) - New ChangJie
|
|
// keymapToXfreerdpHash[""] = "0xE00E0804"; // Chinese (Traditional) - Microsoft Pinyin IME 3.0
|
|
// keymapToXfreerdpHash[""] = "0xE00F0404"; // Chinese (Traditional) - Alphanumeric
|
|
|
|
return keymapToXfreerdpHash;
|
|
}
|
|
|
|
#include "rdpview.moc"
|