66 const QString &specification,
67 const QString &defaultKeymapFile)
69 qCDebug(qLcVxKey,
"Try to create keyboard handler for \"%ls\" \"%ls\"",
70 qUtf16Printable(device), qUtf16Printable(specification));
72 QString keymapFile = defaultKeymapFile;
73 int repeatDelay = 400;
75 bool disableZap =
false;
76 bool enableCompose =
false;
79 const auto args = QStringView{specification}.split(u':');
80 for (
const auto &arg : args) {
81 if (arg.startsWith(
"keymap="_L1))
82 keymapFile = arg.mid(7).toString();
83 else if (arg ==
"disable-zap"_L1)
85 else if (arg ==
"enable-compose"_L1)
87 else if (arg.startsWith(
"repeat-delay="_L1))
88 repeatDelay = arg.mid(13).toInt();
89 else if (arg.startsWith(
"repeat-rate="_L1))
90 repeatRate = arg.mid(12).toInt();
91 else if (arg.startsWith(
"grab="_L1))
92 grab = arg.mid(5).toInt();
95 qCDebug(qLcVxKey,
"Opening keyboard at %ls", qUtf16Printable(device));
97 QFdContainer fd(qt_safe_open(device.toLocal8Bit().constData(), O_RDWR | O_NDELAY, 0));
99 qCDebug(qLcVxKey,
"Keyboard device could not be opened as read-write, trying read-only");
100 fd.reset(qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0));
103 UINT32 kbdMode = EV_DEV_KBD_KEYCODE_MODE;
104 if (ERROR == ioctl (fd.get(), EV_DEV_IO_SET_KBD_MODE, (
char *)&kbdMode)) {
105 qWarning(
"Cannot set keyboard mapping mode to KEYCODE mode: %s", strerror(errno));
109 return std::unique_ptr<QVxKeyboardHandler>(
new QVxKeyboardHandler(device, fd, disableZap, enableCompose, keymapFile));
111 qErrnoWarning(
"Cannot open keyboard input device '%ls'", qUtf16Printable(device));
166 QKeycodeAction result = QKeycodeAction::None;
167 bool first_press = pressed && !autorepeat;
169 const QKeyboardMap::Mapping *map_plain =
nullptr;
170 const QKeyboardMap::Mapping *map_withmod =
nullptr;
172 quint8 modifiers = m_modifiers;
175 for (
int i = 0; i < m_keymap_size && !(map_plain && map_withmod); ++i) {
176 const QKeyboardMap::Mapping *m = m_keymap + i;
177 if (m->keycode == keycode) {
178 if (m->modifiers == 0)
181 quint8 testmods = m_modifiers;
182 if (m_locks[0] && (m->flags & QKeyboardMap::IsLetter))
183 testmods ^= QKeyboardMap::ModShift;
185 testmods ^= QKeyboardMap::ModAltGr;
186 if (m->modifiers == testmods)
191 if (m_locks[0] && map_withmod && (map_withmod->flags & QKeyboardMap::IsLetter))
192 modifiers ^= QKeyboardMap::ModShift;
194 qCDebug(qLcVxKeyMap,
"Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d | plain=%d, withmod=%d, size=%d",
195 keycode, modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0,
196 int(map_plain ? map_plain - m_keymap : -1),
197 int(map_withmod ? map_withmod - m_keymap : -1),
200 const QKeyboardMap::Mapping *it = map_withmod ? map_withmod : map_plain;
204 qCDebug(qLcVxKeyMap,
"Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, modifiers);
209 quint16 unicode = it->unicode;
210 quint32 qtcode = it->qtcode;
212 if ((it->flags & QKeyboardMap::IsModifier) && it->special) {
215 m_modifiers |= quint8(it->special);
217 m_modifiers &= ~quint8(it->special);
221 quint8 &lock = m_locks[qtcode - Qt::Key_CapsLock];
225 case Qt::Key_CapsLock : result = lock ? QKeycodeAction::CapsLockOn : QKeycodeAction::CapsLockOff;
break;
226 case Qt::Key_NumLock : result = lock ? QKeycodeAction::NumLockOn : QKeycodeAction::NumLockOff;
break;
227 case Qt::Key_ScrollLock: result = lock ? QKeycodeAction::ScrollLockOn : QKeycodeAction::ScrollLockOff;
break;
231 }
else if ((it->flags & QKeyboardMap::IsSystem) && it->special && first_press) {
232 switch (it->special) {
233 case QKeyboardMap::SystemReboot:
234 result = QKeycodeAction::Reboot;
237 case QKeyboardMap::SystemZap:
242 case QKeyboardMap::SystemConsolePrevious:
243 result = QKeycodeAction::PreviousConsole;
246 case QKeyboardMap::SystemConsoleNext:
247 result = QKeycodeAction::NextConsole;
251 if (it->special >= QKeyboardMap::SystemConsoleFirst &&
252 it->special <= QKeyboardMap::SystemConsoleLast) {
253 result = QKeycodeAction(
254 static_cast<
int>(QKeycodeAction::SwitchConsoleFirst)
255 + ((it->special &
static_cast<
int>(QKeyboardMap::SystemConsoleMask))
256 &
static_cast<
int>(QKeycodeAction::SwitchConsoleMask)));
267 }
else if ((it->flags & QKeyboardMap::IsDead) && m_do_compose) {
269 if (first_press && m_composing == 1 && m_dead_unicode == unicode) {
272 }
else if (first_press && unicode != 0xffff) {
273 m_dead_unicode = unicode;
288 if ((it == map_plain && it != map_withmod) ||
289 (map_withmod && !(map_withmod->qtcode & modmask))) {
290 qtcode |= QVxKeyboardHandler::toQtModifiers(modifiers);
293 if (m_composing == 2 && first_press && !(it->flags & QKeyboardMap::IsModifier)) {
295 if (unicode != 0xffff) {
298 for ( ; idx < m_keycompose_size; ++idx) {
299 if (m_keycompose[idx].first == unicode)
302 if (idx < m_keycompose_size) {
304 m_dead_unicode = unicode;
314 }
else if (m_composing == 1 && first_press && !(it->flags & QKeyboardMap::IsModifier)) {
317 if (unicode != 0xffff) {
320 for ( ; idx < m_keycompose_size; ++idx) {
321 if (m_keycompose[idx].first == m_dead_unicode && m_keycompose[idx].second == unicode)
324 if (idx < m_keycompose_size) {
325 quint16 composed = m_keycompose[idx].result;
326 if (composed != 0xffff) {
334 unicode = m_dead_unicode;
342 Qt::KeyboardModifiers qtmods = Qt::KeyboardModifiers(qtcode & modmask);
347 qCDebug(qLcVxKeyMap,
"Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode,
int(qtmods));
350 if (!m_locks[1] && (qtmods & Qt::KeypadModifier) &&
399 processKeyEvent(keycode, unicode, qtcode, qtmods, pressed, autorepeat);
430 qCDebug(qLcVxKey,
"Loading keymap %ls", qUtf16Printable(file));
434 if (!f.open(QIODevice::ReadOnly)) {
435 qWarning(
"Could not open keymap file '%ls'", qUtf16Printable(file));
447 quint32 qmap_magic, qmap_version, qmap_keymap_size, qmap_keycompose_size;
451 ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size;
453 if (ds.status() != QDataStream::Ok || qmap_magic != QKeyboardMap::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) {
454 qWarning(
"'%ls' is not a valid .qmap keymap file", qUtf16Printable(file));
458 QKeyboardMap::Mapping *qmap_keymap =
new QKeyboardMap::Mapping[qmap_keymap_size];
459 QKeyboardMap::Composing *qmap_keycompose = qmap_keycompose_size ?
new QKeyboardMap::Composing[qmap_keycompose_size] : 0;
461 for (quint32 i = 0; i < qmap_keymap_size; ++i)
462 ds >> qmap_keymap[i];
463 for (quint32 i = 0; i < qmap_keycompose_size; ++i)
464 ds >> qmap_keycompose[i];
466 if (ds.status() != QDataStream::Ok) {
467 delete [] qmap_keymap;
468 delete [] qmap_keycompose;
470 qWarning(
"Keymap file '%ls' cannot be loaded.", qUtf16Printable(file));
477 m_keymap = qmap_keymap;
478 m_keymap_size = qmap_keymap_size;
479 m_keycompose = qmap_keycompose;
480 m_keycompose_size = qmap_keycompose_size;