1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QEVDEVKEYBOARDHANDLER_P_H
41#define QEVDEVKEYBOARDHANDLER_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <qobject.h>
55#include <QTimer>
56#include <QDataStream>
57
58#include <memory>
59
60QT_BEGIN_NAMESPACE
61
62class QSocketNotifier;
63
64namespace QEvdevKeyboardMap {
65 const quint32 FileMagic = 0x514d4150; // 'QMAP'
66
67 struct Mapping {
68 quint16 keycode;
69 quint16 unicode;
70 quint32 qtcode;
71 quint8 modifiers;
72 quint8 flags;
73 quint16 special;
74
75 };
76
77 enum Flags {
78 IsDead = 0x01,
79 IsLetter = 0x02,
80 IsModifier = 0x04,
81 IsSystem = 0x08
82 };
83
84 enum System {
85 SystemConsoleFirst = 0x0100,
86 SystemConsoleMask = 0x007f,
87 SystemConsoleLast = 0x017f,
88 SystemConsolePrevious = 0x0180,
89 SystemConsoleNext = 0x0181,
90 SystemReboot = 0x0200,
91 SystemZap = 0x0300
92 };
93
94 struct Composing {
95 quint16 first;
96 quint16 second;
97 quint16 result;
98 };
99
100 enum Modifiers {
101 ModPlain = 0x00,
102 ModShift = 0x01,
103 ModAltGr = 0x02,
104 ModControl = 0x04,
105 ModAlt = 0x08,
106 ModShiftL = 0x10,
107 ModShiftR = 0x20,
108 ModCtrlL = 0x40,
109 ModCtrlR = 0x80
110 // ModCapsShift = 0x100, // not supported!
111 };
112}
113
114inline QDataStream &operator>>(QDataStream &ds, QEvdevKeyboardMap::Mapping &m)
115{
116 return ds >> m.keycode >> m.unicode >> m.qtcode >> m.modifiers >> m.flags >> m.special;
117}
118
119inline QDataStream &operator<<(QDataStream &ds, const QEvdevKeyboardMap::Mapping &m)
120{
121 return ds << m.keycode << m.unicode << m.qtcode << m.modifiers << m.flags << m.special;
122}
123
124inline QDataStream &operator>>(QDataStream &ds, QEvdevKeyboardMap::Composing &c)
125{
126 return ds >> c.first >> c.second >> c.result;
127}
128
129inline QDataStream &operator<<(QDataStream &ds, const QEvdevKeyboardMap::Composing &c)
130{
131 return ds << c.first << c.second << c.result;
132}
133
134class QFdContainer
135{
136 int m_fd;
137 Q_DISABLE_COPY_MOVE(QFdContainer);
138public:
139 explicit QFdContainer(int fd = -1) noexcept : m_fd(fd) {}
140 ~QFdContainer() { reset(); }
141
142 int get() const noexcept { return m_fd; }
143
144 int release() noexcept { int result = m_fd; m_fd = -1; return result; }
145 void reset() noexcept;
146};
147
148class QEvdevKeyboardHandler : public QObject
149{
150public:
151 QEvdevKeyboardHandler(const QString &device, QFdContainer &fd, bool disableZap, bool enableCompose, const QString &keymapFile);
152 ~QEvdevKeyboardHandler();
153
154 enum KeycodeAction {
155 None = 0,
156
157 CapsLockOff = 0x01000000,
158 CapsLockOn = 0x01000001,
159 NumLockOff = 0x02000000,
160 NumLockOn = 0x02000001,
161 ScrollLockOff = 0x03000000,
162 ScrollLockOn = 0x03000001,
163
164 Reboot = 0x04000000,
165
166 PreviousConsole = 0x05000000,
167 NextConsole = 0x05000001,
168 SwitchConsoleFirst = 0x06000000,
169 SwitchConsoleLast = 0x0600007f,
170 SwitchConsoleMask = 0x0000007f
171 };
172
173 static std::unique_ptr<QEvdevKeyboardHandler> create(const QString &device,
174 const QString &specification,
175 const QString &defaultKeymapFile = QString());
176
177 static Qt::KeyboardModifiers toQtModifiers(quint8 mod)
178 {
179 Qt::KeyboardModifiers qtmod = Qt::NoModifier;
180
181 if (mod & (QEvdevKeyboardMap::ModShift | QEvdevKeyboardMap::ModShiftL | QEvdevKeyboardMap::ModShiftR))
182 qtmod |= Qt::ShiftModifier;
183 if (mod & (QEvdevKeyboardMap::ModControl | QEvdevKeyboardMap::ModCtrlL | QEvdevKeyboardMap::ModCtrlR))
184 qtmod |= Qt::ControlModifier;
185 if (mod & QEvdevKeyboardMap::ModAlt)
186 qtmod |= Qt::AltModifier;
187
188 return qtmod;
189 }
190
191 bool loadKeymap(const QString &file);
192 void unloadKeymap();
193
194 void readKeycode();
195 KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat);
196
197 void switchLang();
198
199private:
200 void processKeyEvent(int nativecode, int unicode, int qtcode,
201 Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat);
202 void switchLed(int, bool);
203
204 QString m_device;
205 QFdContainer m_fd;
206 QSocketNotifier *m_notify;
207
208 // keymap handling
209 quint8 m_modifiers;
210 quint8 m_locks[3];
211 int m_composing;
212 quint16 m_dead_unicode;
213 quint8 m_langLock;
214
215 bool m_no_zap;
216 bool m_do_compose;
217
218 const QEvdevKeyboardMap::Mapping *m_keymap;
219 int m_keymap_size;
220 const QEvdevKeyboardMap::Composing *m_keycompose;
221 int m_keycompose_size;
222
223 static const QEvdevKeyboardMap::Mapping s_keymap_default[];
224 static const QEvdevKeyboardMap::Composing s_keycompose_default[];
225};
226
227
228QT_END_NAMESPACE
229
230#endif // QEVDEVKEYBOARDHANDLER_P_H
231