Changeset View
Changeset View
Standalone View
Standalone View
keyboard_input.cpp
Show All 14 Lines | |||||
15 | GNU General Public License for more details. | 15 | GNU General Public License for more details. | ||
16 | 16 | | |||
17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | 19 | *********************************************************************/ | ||
20 | #include "keyboard_input.h" | 20 | #include "keyboard_input.h" | ||
21 | #include "input_event.h" | 21 | #include "input_event.h" | ||
22 | #include "input_event_spy.h" | 22 | #include "input_event_spy.h" | ||
23 | #include "keyboard_layout.h" | ||||
23 | #include "abstract_client.h" | 24 | #include "abstract_client.h" | ||
24 | #include "options.h" | 25 | #include "options.h" | ||
25 | #include "utils.h" | 26 | #include "utils.h" | ||
26 | #include "screenlockerwatcher.h" | 27 | #include "screenlockerwatcher.h" | ||
27 | #include "toplevel.h" | 28 | #include "toplevel.h" | ||
28 | #include "wayland_server.h" | 29 | #include "wayland_server.h" | ||
29 | #include "workspace.h" | 30 | #include "workspace.h" | ||
30 | // KWayland | 31 | // KWayland | ||
▲ Show 20 Lines • Show All 341 Lines • ▼ Show 20 Line(s) | 345 | { | |||
372 | if (m_leds != leds) { | 373 | if (m_leds != leds) { | ||
373 | m_leds = leds; | 374 | m_leds = leds; | ||
374 | emit m_input->keyboard()->ledsChanged(m_leds); | 375 | emit m_input->keyboard()->ledsChanged(m_leds); | ||
375 | } | 376 | } | ||
376 | 377 | | |||
377 | const xkb_layout_index_t layout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE); | 378 | const xkb_layout_index_t layout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE); | ||
378 | if (layout != m_currentLayout) { | 379 | if (layout != m_currentLayout) { | ||
379 | m_currentLayout = layout; | 380 | m_currentLayout = layout; | ||
380 | // notify OSD service about the new layout | | |||
381 | if (kwinApp()->usesLibinput()) { | | |||
382 | // only if kwin is in charge of keyboard input | | |||
383 | QDBusMessage msg = QDBusMessage::createMethodCall( | | |||
384 | QStringLiteral("org.kde.plasmashell"), | | |||
385 | QStringLiteral("/org/kde/osdService"), | | |||
386 | QStringLiteral("org.kde.osdService"), | | |||
387 | QStringLiteral("kbdLayoutChanged")); | | |||
388 | | ||||
389 | msg << QString::fromLocal8Bit(xkb_keymap_layout_get_name(m_keymap, layout)); | | |||
390 | | ||||
391 | QDBusConnection::sessionBus().asyncCall(msg); | | |||
392 | } | | |||
393 | } | 381 | } | ||
394 | if (waylandServer()) { | 382 | if (waylandServer()) { | ||
395 | waylandServer()->seat()->updateKeyboardModifiers(xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_DEPRESSED)), | 383 | waylandServer()->seat()->updateKeyboardModifiers(xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_DEPRESSED)), | ||
396 | xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LATCHED)), | 384 | xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LATCHED)), | ||
397 | xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LOCKED)), | 385 | xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LOCKED)), | ||
398 | layout); | 386 | layout); | ||
399 | } | 387 | } | ||
400 | } | 388 | } | ||
401 | 389 | | |||
390 | QString Xkb::layoutName() const | ||||
391 | { | ||||
392 | return QString::fromLocal8Bit(xkb_keymap_layout_get_name(m_keymap, m_currentLayout)); | ||||
393 | } | ||||
394 | | ||||
402 | void Xkb::updateConsumedModifiers(uint32_t key) | 395 | void Xkb::updateConsumedModifiers(uint32_t key) | ||
403 | { | 396 | { | ||
404 | Qt::KeyboardModifiers mods = Qt::NoModifier; | 397 | Qt::KeyboardModifiers mods = Qt::NoModifier; | ||
405 | if (xkb_state_mod_index_is_consumed2(m_state, key + 8, m_shiftModifier, XKB_CONSUMED_MODE_GTK) == 1) { | 398 | if (xkb_state_mod_index_is_consumed2(m_state, key + 8, m_shiftModifier, XKB_CONSUMED_MODE_GTK) == 1) { | ||
406 | mods |= Qt::ShiftModifier; | 399 | mods |= Qt::ShiftModifier; | ||
407 | } | 400 | } | ||
408 | if (xkb_state_mod_index_is_consumed2(m_state, key + 8, m_altModifier, XKB_CONSUMED_MODE_GTK) == 1) { | 401 | if (xkb_state_mod_index_is_consumed2(m_state, key + 8, m_altModifier, XKB_CONSUMED_MODE_GTK) == 1) { | ||
409 | mods |= Qt::AltModifier; | 402 | mods |= Qt::AltModifier; | ||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Line(s) | 493 | KeyboardInputRedirection::KeyboardInputRedirection(InputRedirection *parent) | |||
501 | : QObject(parent) | 494 | : QObject(parent) | ||
502 | , m_input(parent) | 495 | , m_input(parent) | ||
503 | , m_xkb(new Xkb(parent)) | 496 | , m_xkb(new Xkb(parent)) | ||
504 | { | 497 | { | ||
505 | } | 498 | } | ||
506 | 499 | | |||
507 | KeyboardInputRedirection::~KeyboardInputRedirection() = default; | 500 | KeyboardInputRedirection::~KeyboardInputRedirection() = default; | ||
508 | 501 | | |||
502 | class KeyStateChangedSpy : public InputEventSpy | ||||
bshah: This code seems to be from D4128? | |||||
graesslin: yeah, arc fail on my side. Please ignore :-) | |||||
bshah: Makes kinda hard to see actual change, can you perhaps redo this RR? | |||||
graesslin: I'll push the other change then it hopefully solves by updating | |||||
503 | { | ||||
504 | public: | ||||
505 | KeyStateChangedSpy(InputRedirection *input) | ||||
506 | : m_input(input) | ||||
507 | { | ||||
508 | } | ||||
509 | | ||||
510 | void keyEvent(KeyEvent *event) override | ||||
511 | { | ||||
512 | if (event->isAutoRepeat()) { | ||||
513 | return; | ||||
514 | } | ||||
515 | emit m_input->keyStateChanged(event->nativeScanCode(), event->type() == QEvent::KeyPress ? InputRedirection::KeyboardKeyPressed : InputRedirection::KeyboardKeyReleased); | ||||
516 | } | ||||
517 | | ||||
518 | private: | ||||
519 | InputRedirection *m_input; | ||||
520 | }; | ||||
521 | | ||||
522 | class ModifiersChangedSpy : public InputEventSpy | ||||
523 | { | ||||
524 | public: | ||||
525 | ModifiersChangedSpy(InputRedirection *input) | ||||
526 | : m_input(input) | ||||
527 | , m_modifiers() | ||||
528 | { | ||||
529 | } | ||||
530 | | ||||
531 | void keyEvent(KeyEvent *event) override | ||||
532 | { | ||||
533 | if (event->isAutoRepeat()) { | ||||
534 | return; | ||||
535 | } | ||||
536 | updateModifiers(event->modifiers()); | ||||
537 | } | ||||
538 | | ||||
539 | void updateModifiers(Qt::KeyboardModifiers mods) | ||||
540 | { | ||||
541 | if (mods == m_modifiers) { | ||||
542 | return; | ||||
543 | } | ||||
544 | emit m_input->keyboardModifiersChanged(mods, m_modifiers); | ||||
545 | m_modifiers = mods; | ||||
546 | } | ||||
547 | | ||||
548 | private: | ||||
549 | InputRedirection *m_input; | ||||
550 | Qt::KeyboardModifiers m_modifiers; | ||||
551 | }; | ||||
552 | | ||||
509 | void KeyboardInputRedirection::init() | 553 | void KeyboardInputRedirection::init() | ||
510 | { | 554 | { | ||
511 | Q_ASSERT(!m_inited); | 555 | Q_ASSERT(!m_inited); | ||
512 | m_inited = true; | 556 | m_inited = true; | ||
557 | m_input->installInputEventSpy(new KeyStateChangedSpy(m_input)); | ||||
558 | m_modifiersChangedSpy = new ModifiersChangedSpy(m_input); | ||||
559 | m_input->installInputEventSpy(m_modifiersChangedSpy); | ||||
560 | m_keyboardLayout = new KeyboardLayout(m_xkb.data()); | ||||
561 | m_keyboardLayout->init(); | ||||
562 | m_input->installInputEventSpy(m_keyboardLayout); | ||||
513 | 563 | | |||
514 | // setup key repeat | 564 | // setup key repeat | ||
515 | m_keyRepeat.timer = new QTimer(this); | 565 | m_keyRepeat.timer = new QTimer(this); | ||
516 | connect(m_keyRepeat.timer, &QTimer::timeout, this, | 566 | connect(m_keyRepeat.timer, &QTimer::timeout, this, | ||
517 | [this] { | 567 | [this] { | ||
518 | if (waylandServer()->seat()->keyRepeatRate() != 0) { | 568 | if (waylandServer()->seat()->keyRepeatRate() != 0) { | ||
519 | m_keyRepeat.timer->setInterval(1000 / waylandServer()->seat()->keyRepeatRate()); | 569 | m_keyRepeat.timer->setInterval(1000 / waylandServer()->seat()->keyRepeatRate()); | ||
520 | } | 570 | } | ||
Show All 13 Lines | 583 | } else { | |||
534 | m_activeClientSurfaceChangedConnection = QMetaObject::Connection(); | 584 | m_activeClientSurfaceChangedConnection = QMetaObject::Connection(); | ||
535 | } | 585 | } | ||
536 | update(); | 586 | update(); | ||
537 | } | 587 | } | ||
538 | ); | 588 | ); | ||
539 | if (waylandServer()->hasScreenLockerIntegration()) { | 589 | if (waylandServer()->hasScreenLockerIntegration()) { | ||
540 | connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &KeyboardInputRedirection::update); | 590 | connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &KeyboardInputRedirection::update); | ||
541 | } | 591 | } | ||
542 | | ||||
543 | QAction *switchKeyboardAction = new QAction(this); | | |||
544 | switchKeyboardAction->setObjectName(QStringLiteral("Switch to Next Keyboard Layout")); | | |||
545 | switchKeyboardAction->setProperty("componentName", QStringLiteral("KDE Keyboard Layout Switcher")); | | |||
546 | const QKeySequence sequence = QKeySequence(Qt::ALT+Qt::CTRL+Qt::Key_K); | | |||
547 | KGlobalAccel::self()->setDefaultShortcut(switchKeyboardAction, QList<QKeySequence>({sequence})); | | |||
548 | KGlobalAccel::self()->setShortcut(switchKeyboardAction, QList<QKeySequence>({sequence})); | | |||
549 | m_input->registerShortcut(sequence, switchKeyboardAction); | | |||
550 | connect(switchKeyboardAction, &QAction::triggered, this, | | |||
551 | [this] { | | |||
552 | m_xkb->switchToNextLayout(); | | |||
553 | } | | |||
554 | ); | | |||
555 | | ||||
556 | QDBusConnection::sessionBus().connect(QString(), | | |||
557 | QStringLiteral("/Layouts"), | | |||
558 | QStringLiteral("org.kde.keyboard"), | | |||
559 | QStringLiteral("reloadConfig"), | | |||
560 | this, | | |||
561 | SLOT(reconfigure())); | | |||
562 | | ||||
563 | m_xkb->reconfigure(); | | |||
564 | } | | |||
565 | | ||||
566 | void KeyboardInputRedirection::reconfigure() | | |||
567 | { | | |||
568 | m_xkb->reconfigure(); | | |||
569 | } | 592 | } | ||
570 | 593 | | |||
571 | void KeyboardInputRedirection::update() | 594 | void KeyboardInputRedirection::update() | ||
572 | { | 595 | { | ||
573 | if (!m_inited) { | 596 | if (!m_inited) { | ||
574 | return; | 597 | return; | ||
575 | } | 598 | } | ||
576 | auto seat = waylandServer()->seat(); | 599 | auto seat = waylandServer()->seat(); | ||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Line(s) | 649 | { | |||
639 | case InputRedirection::KeyboardKeyReleased: | 662 | case InputRedirection::KeyboardKeyReleased: | ||
640 | type = QEvent::KeyRelease; | 663 | type = QEvent::KeyRelease; | ||
641 | break; | 664 | break; | ||
642 | default: | 665 | default: | ||
643 | Q_UNREACHABLE(); | 666 | Q_UNREACHABLE(); | ||
644 | } | 667 | } | ||
645 | 668 | | |||
646 | if (!autoRepeat) { | 669 | if (!autoRepeat) { | ||
647 | emit m_input->keyStateChanged(key, state); | | |||
648 | const Qt::KeyboardModifiers oldMods = modifiers(); | | |||
649 | m_xkb->updateKey(key, state); | 670 | m_xkb->updateKey(key, state); | ||
650 | if (oldMods != modifiers()) { | | |||
651 | emit m_input->keyboardModifiersChanged(modifiers(), oldMods); | | |||
652 | } | | |||
653 | } | 671 | } | ||
654 | 672 | | |||
655 | const xkb_keysym_t keySym = m_xkb->currentKeysym(); | 673 | const xkb_keysym_t keySym = m_xkb->currentKeysym(); | ||
656 | KeyEvent event(type, | 674 | KeyEvent event(type, | ||
657 | m_xkb->toQtKey(keySym), | 675 | m_xkb->toQtKey(keySym), | ||
658 | m_xkb->modifiers(), | 676 | m_xkb->modifiers(), | ||
659 | key, | 677 | key, | ||
660 | keySym, | 678 | keySym, | ||
Show All 20 Lines | |||||
681 | } | 699 | } | ||
682 | 700 | | |||
683 | void KeyboardInputRedirection::processModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group) | 701 | void KeyboardInputRedirection::processModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group) | ||
684 | { | 702 | { | ||
685 | if (!m_inited) { | 703 | if (!m_inited) { | ||
686 | return; | 704 | return; | ||
687 | } | 705 | } | ||
688 | // TODO: send to proper Client and also send when active Client changes | 706 | // TODO: send to proper Client and also send when active Client changes | ||
689 | Qt::KeyboardModifiers oldMods = modifiers(); | | |||
690 | m_xkb->updateModifiers(modsDepressed, modsLatched, modsLocked, group); | 707 | m_xkb->updateModifiers(modsDepressed, modsLatched, modsLocked, group); | ||
691 | if (oldMods != modifiers()) { | 708 | m_modifiersChangedSpy->updateModifiers(modifiers()); | ||
I'm not quite follow the check here and whole processModifiers() method: bam: I'm not quite follow the check here and whole processModifiers() method:
it's occurs after… | |||||
bam: Or it's used for nested mode? | |||||
692 | emit m_input->keyboardModifiersChanged(modifiers(), oldMods); | 709 | m_keyboardLayout->checkLayoutChange(); | ||
693 | } | | |||
694 | } | 710 | } | ||
695 | 711 | | |||
696 | void KeyboardInputRedirection::processKeymapChange(int fd, uint32_t size) | 712 | void KeyboardInputRedirection::processKeymapChange(int fd, uint32_t size) | ||
697 | { | 713 | { | ||
698 | if (!m_inited) { | 714 | if (!m_inited) { | ||
699 | return; | 715 | return; | ||
700 | } | 716 | } | ||
701 | // TODO: should we pass the keymap to our Clients? Or only to the currently active one and update | 717 | // TODO: should we pass the keymap to our Clients? Or only to the currently active one and update | ||
702 | m_xkb->installKeymap(fd, size); | 718 | m_xkb->installKeymap(fd, size); | ||
719 | m_keyboardLayout->resetLayout(); | ||||
703 | } | 720 | } | ||
704 | 721 | | |||
705 | } | 722 | } |
This code seems to be from D4128?