1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qevdevkeyboardmanager_p.h" |
5 | |
6 | #include <QtInputSupport/private/qevdevutil_p.h> |
7 | |
8 | #include <QStringList> |
9 | #include <QCoreApplication> |
10 | #include <QLoggingCategory> |
11 | |
12 | #include <private/qguiapplication_p.h> |
13 | #include <private/qinputdevicemanager_p_p.h> |
14 | |
15 | QT_BEGIN_NAMESPACE |
16 | |
17 | using namespace Qt::StringLiterals; |
18 | |
19 | Q_DECLARE_LOGGING_CATEGORY(qLcEvdevKey) |
20 | |
21 | QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent) |
22 | : QObject(parent) |
23 | { |
24 | Q_UNUSED(key); |
25 | |
26 | |
27 | QString spec = QString::fromLocal8Bit(ba: qgetenv(varName: "QT_QPA_EVDEV_KEYBOARD_PARAMETERS" )); |
28 | |
29 | if (spec.isEmpty()) |
30 | spec = specification; |
31 | |
32 | auto parsed = QEvdevUtil::parseSpecification(specification: spec); |
33 | m_spec = std::move(parsed.spec); |
34 | |
35 | // add all keyboards for devices specified in the argument list |
36 | for (const QString &device : std::as_const(t&: parsed.devices)) |
37 | addKeyboard(deviceNode: device); |
38 | |
39 | if (parsed.devices.isEmpty()) { |
40 | qCDebug(qLcEvdevKey, "evdevkeyboard: Using device discovery" ); |
41 | if (auto deviceDiscovery = QDeviceDiscovery::create(type: QDeviceDiscovery::Device_Keyboard, parent: this)) { |
42 | // scan and add already connected keyboards |
43 | const QStringList devices = deviceDiscovery->scanConnectedDevices(); |
44 | for (const QString &device : devices) |
45 | addKeyboard(deviceNode: device); |
46 | |
47 | connect(sender: deviceDiscovery, signal: &QDeviceDiscovery::deviceDetected, |
48 | context: this, slot: &QEvdevKeyboardManager::addKeyboard); |
49 | connect(sender: deviceDiscovery, signal: &QDeviceDiscovery::deviceRemoved, |
50 | context: this, slot: &QEvdevKeyboardManager::removeKeyboard); |
51 | } |
52 | } |
53 | } |
54 | |
55 | QEvdevKeyboardManager::~QEvdevKeyboardManager() |
56 | { |
57 | } |
58 | |
59 | void QEvdevKeyboardManager::addKeyboard(const QString &deviceNode) |
60 | { |
61 | qCDebug(qLcEvdevKey, "Adding keyboard at %ls" , qUtf16Printable(deviceNode)); |
62 | auto keyboard = QEvdevKeyboardHandler::create(device: deviceNode, specification: m_spec, defaultKeymapFile: m_defaultKeymapFile); |
63 | if (keyboard) { |
64 | m_keyboards.add(deviceNode, handler: std::move(keyboard)); |
65 | updateDeviceCount(); |
66 | } else { |
67 | qWarning(msg: "Failed to open keyboard device %ls" , qUtf16Printable(deviceNode)); |
68 | } |
69 | } |
70 | |
71 | void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode) |
72 | { |
73 | if (m_keyboards.remove(deviceNode)) { |
74 | qCDebug(qLcEvdevKey, "Removing keyboard at %ls" , qUtf16Printable(deviceNode)); |
75 | updateDeviceCount(); |
76 | } |
77 | } |
78 | |
79 | void QEvdevKeyboardManager::updateDeviceCount() |
80 | { |
81 | QInputDeviceManagerPrivate::get(mgr: QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( |
82 | type: QInputDeviceManager::DeviceTypeKeyboard, count: m_keyboards.count()); |
83 | } |
84 | |
85 | void QEvdevKeyboardManager::loadKeymap(const QString &file) |
86 | { |
87 | m_defaultKeymapFile = file; |
88 | |
89 | if (file.isEmpty()) { |
90 | // Restore the default, which is either the built-in keymap or |
91 | // the one given in the plugin spec. |
92 | QString keymapFromSpec; |
93 | const auto specs = QStringView{m_spec}.split(sep: u':'); |
94 | for (const auto &arg : specs) { |
95 | if (arg.startsWith(s: "keymap="_L1 )) |
96 | keymapFromSpec = arg.mid(pos: 7).toString(); |
97 | } |
98 | for (const auto &keyboard : m_keyboards) { |
99 | if (keymapFromSpec.isEmpty()) |
100 | keyboard.handler->unloadKeymap(); |
101 | else |
102 | keyboard.handler->loadKeymap(file: keymapFromSpec); |
103 | } |
104 | } else { |
105 | for (const auto &keyboard : m_keyboards) |
106 | keyboard.handler->loadKeymap(file); |
107 | } |
108 | } |
109 | |
110 | void QEvdevKeyboardManager::switchLang() |
111 | { |
112 | for (const auto &keyboard : m_keyboards) |
113 | keyboard.handler->switchLang(); |
114 | } |
115 | |
116 | QT_END_NAMESPACE |
117 | |