feat: using xkbregistry instead of manually parsing evdev.xml
This commit is contained in:
parent
22a4b135f0
commit
7a90a30ec8
10 changed files with 81 additions and 247 deletions
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||
# SPDX-FileCopyrightText: (C) 2024 - 2026 Chris Rizzitello <sithlord48@gmail.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
|
|
@ -35,8 +36,8 @@ runs:
|
|||
if [ ${{inputs.like}} == "debian" ]; then
|
||||
apt update -qqq > /dev/null
|
||||
apt install -qqq cmake build-essential ninja-build \
|
||||
xorg-dev libx11-dev libxtst-dev libssl-dev \
|
||||
libxkbfile-dev qt6-base-dev qt6-tools-dev libxkbcommon-dev \
|
||||
xorg-dev libx11-dev libxtst-dev libssl-dev libxkbfile-dev \
|
||||
qt6-base-dev qt6-tools-dev libxkbregistry-dev libxkbcommon-dev \
|
||||
libei-dev libportal-dev help2man -y >/dev/null
|
||||
elif [ ${{inputs.like}} == "fedora" ]; then
|
||||
dnf install -y cmake make ninja-build gcc-c++ rpm-build openssl-devel \
|
||||
|
|
@ -47,7 +48,7 @@ runs:
|
|||
zypper install -y --force-resolution \
|
||||
cmake make ninja gcc-c++ rpm-build libopenssl-devel \
|
||||
libXtst-devel libxkbfile-devel qt6-base-devel qt6-tools-devel \
|
||||
qt6-linguist-devel libxkbcommon-devel libxkbcommon-x11-devel \
|
||||
qt6-linguist-devel libxkbcommon-devel libxkbcommon-x11-devel libxkbregistry-devel \
|
||||
libei-devel libportal-devel help2man libXinerama-devel libXrandr-devel
|
||||
elif [ ${{ inputs.like }} == "arch" ]; then
|
||||
pacman -Syu --noconfirm base-devel cmake ninja \
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ add_definitions(-DQT_NO_KEYWORDS)
|
|||
#Find and setup Qt
|
||||
find_package(Qt6 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Widgets Network)
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Qt6 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS DBus Xml)
|
||||
find_package(Qt6 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS DBus)
|
||||
endif()
|
||||
|
||||
# Define the location of Qt deployment tool
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: (C) 2024 - 2025 Deskflow Developers
|
||||
# SPDX-FileCopyrightText: (C) 2024 - 2026 Deskflow Developers
|
||||
# SPDX-FileCopyrightText: (C) 2024 Symless Ltd
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
|
|
@ -97,9 +97,12 @@ macro(configure_unix_libs)
|
|||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(LIBXKBCOMMON REQUIRED xkbcommon)
|
||||
message(STATUS "xkbcommon version: ${LIBXKBCOMMON_VERSION}")
|
||||
include_directories(${LIBXKBCOMMON_INCLUDE_DIRS})
|
||||
|
||||
message(STATUS "xkbcommon version: ${LIBXKBCOMMON_VERSION}")
|
||||
pkg_check_modules(LIBXKBREGISTRY REQUIRED xkbregistry)
|
||||
message(STATUS "xkbregistry version: ${LIBXKBREGISTRY_VERSION}")
|
||||
include_directories(${LIBXKBREGISTRY_INCLUDE_DIRS})
|
||||
else()
|
||||
message(WARNING "pkg-config not found, skipping wayland libraries")
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||
# SPDX-FileCopyrightText: (C) 2024 - 2026 Chris Rizzitello <sithlord48@gmail.com>
|
||||
# SPDX-FileCopyrightText: (C) 2012 - 2025 Symless Ltd
|
||||
# SPDX-FileCopyrightText: (C) 2009 - 2012 Nick Bolton
|
||||
|
|
@ -95,8 +96,8 @@ target_link_libraries(${lib_name}
|
|||
Qt6::Network
|
||||
PRIVATE
|
||||
platform
|
||||
)
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(${lib_name} PRIVATE server Qt6::Xml)
|
||||
target_link_libraries(${lib_name} PRIVATE server ${LIBXKBREGISTRY_LINK_LIBRARIES})
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -18,8 +19,6 @@
|
|||
#include <platform/OSXAutoTypes.h>
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
AppUtilUnix::AppUtilUnix(const IEventQueue *)
|
||||
{
|
||||
// do nothing
|
||||
|
|
@ -45,17 +44,7 @@ std::vector<std::string> AppUtilUnix::getKeyboardLayoutList()
|
|||
std::vector<std::string> layoutLangCodes;
|
||||
|
||||
#if WINAPI_XWINDOWS
|
||||
// Check /usr/local first used on bsd and some systems
|
||||
std::vector<std::string> evdev_candidate = {
|
||||
"/usr/share/X11/xkb/rules/evdev.xml", // Linux
|
||||
"/usr/local/share/X11/xkb/rules/evdev.xml", // FreeBSD, DragonFlyBSD
|
||||
"/usr/X11R7/lib/X11/xkb/rules/evdev.xml", // NetBSD
|
||||
"/usr/X11R6/share/X11/xkb/rules/evdev.xml", // OpenBSD
|
||||
};
|
||||
|
||||
for (auto it = evdev_candidate.begin(); it != evdev_candidate.end() && !std::filesystem::exists(m_evdev = *it); it++)
|
||||
;
|
||||
layoutLangCodes = X11LayoutsParser::getX11LanguageList(m_evdev);
|
||||
layoutLangCodes = X11LayoutsParser::getX11LanguageList();
|
||||
|
||||
#elif defined(Q_OS_MAC)
|
||||
CFStringRef keys[] = {kTISPropertyInputSourceCategory};
|
||||
|
|
@ -151,7 +140,7 @@ std::string AppUtilUnix::getCurrentLanguageCode()
|
|||
XFree(kbdDescr);
|
||||
XCloseDisplay(display);
|
||||
|
||||
result = X11LayoutsParser::convertLayoutToISO(m_evdev, result);
|
||||
result = X11LayoutsParser::convertLayoutToISO(result);
|
||||
|
||||
#elif defined(Q_OS_MAC)
|
||||
AutoTISInputSourceRef source(nullptr, CFRelease);
|
||||
|
|
|
|||
|
|
@ -23,5 +23,4 @@ public:
|
|||
void startNode() override;
|
||||
std::vector<std::string> getKeyboardLayoutList() override;
|
||||
std::string getCurrentLanguageCode() override;
|
||||
std::string m_evdev;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -9,13 +10,13 @@
|
|||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QFile>
|
||||
#include "base/Log.h"
|
||||
|
||||
#include "DeskflowXkbKeyboard.h"
|
||||
#include "ISO639Table.h"
|
||||
#include "X11LayoutsParser.h"
|
||||
#include "base/Log.h"
|
||||
|
||||
#include <xkbcommon/xkbregistry.h>
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -31,63 +32,52 @@ void splitLine(std::vector<std::string> &parts, const std::string &line, char de
|
|||
|
||||
} // namespace
|
||||
|
||||
bool X11LayoutsParser::readXMLConfigItemElem(const QDomNode &node, std::vector<Lang> &langList)
|
||||
{
|
||||
auto configItemElem = node.firstChildElement("configItem");
|
||||
if (configItemElem.isNull()) {
|
||||
LOG_WARN("failed to read \"configItem\" in xml file");
|
||||
return false;
|
||||
}
|
||||
|
||||
langList.emplace_back();
|
||||
if (auto nameElem = configItemElem.firstChildElement("name"); !nameElem.isNull())
|
||||
langList.back().name = nameElem.toElement().text().toStdString();
|
||||
|
||||
if (auto languageListElem = configItemElem.elementsByTagName("languageList"); !languageListElem.isEmpty()) {
|
||||
for (int i = 0; i < languageListElem.count(); i++) {
|
||||
const auto isoElem = languageListElem.at(i).namedItem("iso639Id").toElement();
|
||||
langList.back().layoutBaseISO639_2.emplace_back(isoElem.text().toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<X11LayoutsParser::Lang> X11LayoutsParser::getAllLanguageData(const std::string &pathToEvdevFile)
|
||||
std::vector<X11LayoutsParser::Lang> X11LayoutsParser::getAllLanguageData()
|
||||
{
|
||||
std::vector<Lang> allCodes;
|
||||
|
||||
QFile inFile(QString::fromStdString(pathToEvdevFile));
|
||||
if (!inFile.open(QIODevice::ReadOnly)) {
|
||||
LOG_WARN("unable to open %s", pathToEvdevFile.c_str());
|
||||
rxkb_context *ctx = rxkb_context_new(RXKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
if (!ctx) {
|
||||
LOG_WARN("failed to create xkb registry context");
|
||||
return allCodes;
|
||||
}
|
||||
|
||||
QDomDocument xmlDoc;
|
||||
xmlDoc.setContent(inFile.readAll());
|
||||
|
||||
const auto xkbConfigElem = xmlDoc.firstChildElement("xkbConfigRegistry");
|
||||
if (xkbConfigElem.isNull()) {
|
||||
LOG_WARN("failed to read xkbConfigRegistry in %s", pathToEvdevFile.c_str());
|
||||
if (!rxkb_context_parse_default_ruleset(ctx)) {
|
||||
LOG_WARN("failed to parse xkb registry ruleset");
|
||||
rxkb_context_unref(ctx);
|
||||
return allCodes;
|
||||
}
|
||||
|
||||
auto layoutListElem = xkbConfigElem.firstChildElement("layoutList");
|
||||
if (layoutListElem.isNull()) {
|
||||
LOG_WARN("failed to read layoutList in %s", pathToEvdevFile.c_str());
|
||||
return allCodes;
|
||||
for (rxkb_layout *layout = rxkb_layout_first((ctx)); layout; layout = rxkb_layout_next(layout)) {
|
||||
const char *name = rxkb_layout_get_name(layout);
|
||||
const char *variant = rxkb_layout_get_variant(layout);
|
||||
|
||||
std::vector<std::string> isoCodes;
|
||||
for (rxkb_iso639_code *isoCode = rxkb_layout_get_iso639_first(layout); isoCode;
|
||||
isoCode = rxkb_iso639_code_next(isoCode)) {
|
||||
if (const char *code = rxkb_iso639_code_get_code(isoCode)) {
|
||||
isoCodes.emplace_back(code);
|
||||
}
|
||||
}
|
||||
|
||||
const auto layouts = layoutListElem.elementsByTagName("layout");
|
||||
for (int i = 0; i < layouts.count(); i++) {
|
||||
auto item = layouts.at(i);
|
||||
if (!readXMLConfigItemElem(item, allCodes))
|
||||
if (!variant) {
|
||||
allCodes.emplace_back();
|
||||
allCodes.back().name = name ? name : "";
|
||||
allCodes.back().layoutBaseISO639_2 = std::move(isoCodes);
|
||||
} else {
|
||||
auto requiredName = name ? name : std::string{};
|
||||
auto iterator = std::ranges::find_if(allCodes, [&](const Lang &l) { return l.name == requiredName; });
|
||||
if (iterator == allCodes.end())
|
||||
continue;
|
||||
|
||||
auto variantListElem = item.namedItem("variantList").childNodes();
|
||||
for (int j = 0; j < variantListElem.count(); j++)
|
||||
readXMLConfigItemElem(variantListElem.at(j), allCodes.back().variants);
|
||||
iterator->variants.emplace_back();
|
||||
iterator->variants.back().name = variant;
|
||||
iterator->variants.back().layoutBaseISO639_2 = std::move(isoCodes);
|
||||
}
|
||||
}
|
||||
|
||||
rxkb_context_unref(ctx);
|
||||
return allCodes;
|
||||
}
|
||||
|
||||
|
|
@ -101,13 +91,13 @@ void X11LayoutsParser::appendVectorUniq(const std::vector<std::string> &source,
|
|||
}
|
||||
|
||||
void X11LayoutsParser::convertLayoutToISO639_2(
|
||||
const std::string &pathToEvdevFile, bool needToReloadEvdev, const std::vector<std::string> &layoutNames,
|
||||
const std::vector<std::string> &layoutVariantNames, std::vector<std::string> &iso639_2Codes
|
||||
const std::vector<std::string> &layoutNames, const std::vector<std::string> &layoutVariantNames,
|
||||
std::vector<std::string> &iso639_2Codes
|
||||
)
|
||||
{
|
||||
static std::vector<X11LayoutsParser::Lang> allLang;
|
||||
if (allLang.empty() || needToReloadEvdev) {
|
||||
allLang = getAllLanguageData(pathToEvdevFile);
|
||||
if (allLang.empty()) {
|
||||
allLang = getAllLanguageData();
|
||||
}
|
||||
for (size_t i = 0; i < layoutNames.size(); i++) {
|
||||
const auto &layoutName = layoutNames[i];
|
||||
|
|
@ -154,7 +144,7 @@ void X11LayoutsParser::convertLayoutToISO639_2(
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> X11LayoutsParser::getX11LanguageList(const std::string &pathToEvdevFile)
|
||||
std::vector<std::string> X11LayoutsParser::getX11LanguageList()
|
||||
{
|
||||
std::vector<std::string> layoutNames;
|
||||
std::vector<std::string> layoutVariantNames;
|
||||
|
|
@ -165,13 +155,11 @@ std::vector<std::string> X11LayoutsParser::getX11LanguageList(const std::string
|
|||
|
||||
std::vector<std::string> iso639_2Codes;
|
||||
iso639_2Codes.reserve(layoutNames.size());
|
||||
convertLayoutToISO639_2(pathToEvdevFile, true, layoutNames, layoutVariantNames, iso639_2Codes);
|
||||
convertLayoutToISO639_2(layoutNames, layoutVariantNames, iso639_2Codes);
|
||||
return convertISO639_2ToISO639_1(iso639_2Codes);
|
||||
}
|
||||
|
||||
std::string X11LayoutsParser::convertLayoutToISO(
|
||||
const std::string &pathToEvdevFile, const std::string &layoutLangCode, bool needToReloadFiles
|
||||
)
|
||||
std::string X11LayoutsParser::convertLayoutToISO(const std::string &layoutLangCode)
|
||||
{
|
||||
if (layoutLangCode.empty()) {
|
||||
LOG_VERBOSE("skip converting empty layout lang code");
|
||||
|
|
@ -179,7 +167,7 @@ std::string X11LayoutsParser::convertLayoutToISO(
|
|||
}
|
||||
|
||||
std::vector<std::string> iso639_2Codes;
|
||||
convertLayoutToISO639_2(pathToEvdevFile, needToReloadFiles, {layoutLangCode}, {""}, iso639_2Codes);
|
||||
convertLayoutToISO639_2({layoutLangCode}, {""}, iso639_2Codes);
|
||||
if (iso639_2Codes.empty()) {
|
||||
LOG_WARN("failed to convert layout lang code: \"%s\"", layoutLangCode.c_str());
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -11,15 +12,11 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class QDomNode;
|
||||
|
||||
class X11LayoutsParser
|
||||
{
|
||||
public:
|
||||
static std::vector<std::string> getX11LanguageList(const std::string &pathToEvdevFile);
|
||||
static std::string convertLayoutToISO(
|
||||
const std::string &pathToEvdevFile, const std::string &layoutLangCode, bool needToReloadFiles = false
|
||||
);
|
||||
static std::vector<std::string> getX11LanguageList();
|
||||
static std::string convertLayoutToISO(const std::string &layoutLangCode);
|
||||
|
||||
private:
|
||||
struct Lang
|
||||
|
|
@ -29,15 +26,13 @@ private:
|
|||
std::vector<Lang> variants;
|
||||
};
|
||||
|
||||
static bool readXMLConfigItemElem(const QDomNode &node, std::vector<Lang> &langList);
|
||||
|
||||
static std::vector<Lang> getAllLanguageData(const std::string &pathToEvdevFile);
|
||||
static std::vector<Lang> getAllLanguageData();
|
||||
|
||||
static void appendVectorUniq(const std::vector<std::string> &source, std::vector<std::string> &dst);
|
||||
|
||||
static void convertLayoutToISO639_2(
|
||||
const std::string &pathToEvdevFile, bool needToReloadEvdev, const std::vector<std::string> &layoutNames,
|
||||
const std::vector<std::string> &layoutVariantNames, std::vector<std::string> &iso639_2Codes
|
||||
const std::vector<std::string> &layoutNames, const std::vector<std::string> &layoutVariantNames,
|
||||
std::vector<std::string> &iso639_2Codes
|
||||
);
|
||||
|
||||
static std::vector<std::string> convertISO639_2ToISO639_1(const std::vector<std::string> &iso639_2Codes);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
||||
* SPDX-FileCopyrightText: (C) 2014 - 2016 Synergy App Ltd
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -9,77 +10,17 @@
|
|||
|
||||
#include "deskflow/unix/X11LayoutsParser.h"
|
||||
|
||||
void X11LayoutParserTests::initTestCase()
|
||||
{
|
||||
QDir dir;
|
||||
QVERIFY(dir.mkpath(kTestDir));
|
||||
|
||||
QFile correctEvdevFile(kTestCorrectFile);
|
||||
QVERIFY(correctEvdevFile.open(QIODevice::WriteOnly));
|
||||
correctEvdevFile.write(kCorrectEvContents.toUtf8());
|
||||
correctEvdevFile.close();
|
||||
|
||||
QVERIFY(correctEvdevFile.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(correctEvdevFile.readAll(), kCorrectEvContents);
|
||||
correctEvdevFile.close();
|
||||
|
||||
QFile futureEvdevFile(kTestFutureFile);
|
||||
QVERIFY(futureEvdevFile.open(QIODevice::WriteOnly));
|
||||
futureEvdevFile.write(kFutureEvContents.toUtf8());
|
||||
futureEvdevFile.close();
|
||||
|
||||
QVERIFY(futureEvdevFile.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(futureEvdevFile.readAll(), kFutureEvContents);
|
||||
futureEvdevFile.close();
|
||||
|
||||
QFile badEvdevFile1(kTestBadFile1);
|
||||
QVERIFY(badEvdevFile1.open(QIODevice::WriteOnly));
|
||||
badEvdevFile1.write(kBadEv1Contents.toUtf8());
|
||||
badEvdevFile1.close();
|
||||
|
||||
QVERIFY(badEvdevFile1.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(badEvdevFile1.readAll(), kBadEv1Contents);
|
||||
badEvdevFile1.close();
|
||||
|
||||
QFile badEvdevFile2(kTestBadFile2);
|
||||
QVERIFY(badEvdevFile2.open(QIODevice::WriteOnly));
|
||||
badEvdevFile2.write(kBadEv2Contents.toUtf8());
|
||||
badEvdevFile2.close();
|
||||
|
||||
QVERIFY(badEvdevFile2.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(badEvdevFile2.readAll(), kBadEv2Contents);
|
||||
badEvdevFile2.close();
|
||||
|
||||
QFile badEvdevFile3(kTestBadFile3);
|
||||
QVERIFY(badEvdevFile3.open(QIODevice::WriteOnly));
|
||||
badEvdevFile3.write(kBadEv3Contents.toUtf8());
|
||||
badEvdevFile3.close();
|
||||
|
||||
QVERIFY(badEvdevFile3.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(badEvdevFile3.readAll(), kBadEv3Contents);
|
||||
badEvdevFile3.close();
|
||||
}
|
||||
|
||||
void X11LayoutParserTests::xmlParse()
|
||||
{
|
||||
const QString badPath = QStringLiteral("%1/%2").arg(kTestDir, "notafile");
|
||||
QVERIFY(X11LayoutsParser::getX11LanguageList(badPath.toStdString()).empty());
|
||||
|
||||
// we would like to check the method
|
||||
// X11LayoutsParser::getAllLanguageData(kTestCorrectFile.toStdString());
|
||||
// however it's logic is flawed making as the return list size is based on number of languges host has installed
|
||||
// this is correct on a real system but makes it hard to test the method
|
||||
|
||||
QVERIFY(X11LayoutsParser::getX11LanguageList(kTestBadFile1.toStdString()).empty());
|
||||
QVERIFY(X11LayoutsParser::getX11LanguageList(kTestBadFile2.toStdString()).empty());
|
||||
QVERIFY(X11LayoutsParser::getX11LanguageList(kTestBadFile3.toStdString()).empty());
|
||||
}
|
||||
|
||||
void X11LayoutParserTests::convertLayouts()
|
||||
{
|
||||
QCOMPARE(X11LayoutsParser::convertLayoutToISO(kTestCorrectFile.toStdString(), "us", true), "en");
|
||||
QCOMPARE(X11LayoutsParser::convertLayoutToISO(kTestBadFile1.toStdString(), "us", true), "");
|
||||
QCOMPARE(X11LayoutsParser::convertLayoutToISO(kTestFutureFile.toStdString(), "us", true), "");
|
||||
// An empty layout name yields an empty result.
|
||||
QCOMPARE(X11LayoutsParser::convertLayoutToISO(""), "");
|
||||
|
||||
// An unknown layout name is not present in the registry.
|
||||
QCOMPARE(X11LayoutsParser::convertLayoutToISO("notARealLayout"), "");
|
||||
|
||||
// A well-known layout resolves to its ISO 639-1 code. "us" is always
|
||||
// present in the xkeyboard-config data and maps to "eng" -> "en".
|
||||
QCOMPARE(X11LayoutsParser::convertLayoutToISO("us"), "en");
|
||||
}
|
||||
|
||||
QTEST_MAIN(X11LayoutParserTests)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
|
@ -13,92 +14,8 @@ class X11LayoutParserTests : public QObject
|
|||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
// Test are run in order top to bottom
|
||||
void initTestCase();
|
||||
void xmlParse();
|
||||
void convertLayouts();
|
||||
|
||||
private:
|
||||
Log m_log;
|
||||
const QString kTestDir = "tmp/test";
|
||||
const QString kTestCorrectFile = "tmp/test/correctEvdev.xml";
|
||||
const QString kTestFutureFile = "tmp/test/evdevFromFuture.xml";
|
||||
const QString kTestBadFile1 = "tmp/test/evdevBad1.xml";
|
||||
const QString kTestBadFile2 = "tmp/test/evdevBad2.xml";
|
||||
const QString kTestBadFile3 = "tmp/test/evdevBad3.xml";
|
||||
|
||||
const QString kCorrectEvContents = QStringLiteral(
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<xkbConfigRegistry version=\"1.1\">\n"
|
||||
" <layoutList>\n"
|
||||
" <layout>\n"
|
||||
" <configItem>\n"
|
||||
" <name>us</name>\n"
|
||||
" <!-- Keyboard indicator for English layouts -->\n"
|
||||
" <shortDescription>en</shortDescription>\n"
|
||||
" <description>English (US)</description>\n"
|
||||
" <languageList>\n"
|
||||
" <iso639Id>eng</iso639Id>\n"
|
||||
" </languageList>\n"
|
||||
" </configItem>\n"
|
||||
" <variantList>\n"
|
||||
" <variant>\n"
|
||||
" <configItem>\n"
|
||||
" <name>eng</name>\n"
|
||||
" <shortDescription>eng</shortDescription>\n"
|
||||
" <description>Cherokee</description>\n"
|
||||
" <languageList>\n"
|
||||
" <iso639Id>eng</iso639Id>\n"
|
||||
" </languageList>\n"
|
||||
" </configItem>\n"
|
||||
" </variant>\n"
|
||||
" </variantList>\n"
|
||||
" </layout>\n"
|
||||
" <layout>\n"
|
||||
" <configItem>\n"
|
||||
" <name>ru</name>\n"
|
||||
" <!-- Keyboard indicator for Russian layouts -->\n"
|
||||
" <shortDescription>ru</shortDescription>\n"
|
||||
" <description>Russian</description>\n"
|
||||
" <languageList>\n"
|
||||
" <iso639Id>rus</iso639Id>\n"
|
||||
" </languageList>\n"
|
||||
" </configItem>\n"
|
||||
" </layout>\n"
|
||||
" </layoutList>\n"
|
||||
"</xkbConfigRegistry>\n"
|
||||
);
|
||||
|
||||
const QString kFutureEvContents = QStringLiteral(
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<xkbConfigRegistry version=\"1.1\">\n"
|
||||
" <layoutList>\n"
|
||||
" <layout>\n"
|
||||
" <configItem>\n"
|
||||
" <name>futureLangName</name>\n"
|
||||
" <languageList>\n"
|
||||
" <iso639Id>fln</iso639Id>\n"
|
||||
" </languageList>\n"
|
||||
" </configItem>\n"
|
||||
" </layout>\n"
|
||||
" </layoutList>\n"
|
||||
"</xkbConfigRegistry>\n"
|
||||
);
|
||||
|
||||
const QString kBadEv1Contents = QStringLiteral("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
|
||||
const QString kBadEv2Contents = QStringLiteral(
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<xkbConfigRegistry version=\"1.1\">\n"
|
||||
"</xkbConfigRegistry>"
|
||||
);
|
||||
|
||||
const QString kBadEv3Contents = QStringLiteral(
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<xkbConfigRegistry version=\"1.1\">\n"
|
||||
" <layoutList>\n"
|
||||
" <layout>\n"
|
||||
" </layout>\n"
|
||||
" </layoutList>\n"
|
||||
"</xkbConfigRegistry>\n"
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue