diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -371,6 +371,7 @@ input_event_spy.cpp keyboard_input.cpp keyboard_layout.cpp + keyboard_repeat.cpp pointer_input.cpp touch_input.cpp netinfo.cpp diff --git a/keyboard_input.h b/keyboard_input.h --- a/keyboard_input.h +++ b/keyboard_input.h @@ -180,11 +180,6 @@ bool m_inited = false; QScopedPointer m_xkb; QMetaObject::Connection m_activeClientSurfaceChangedConnection; - struct { - quint32 key = 0; - quint32 time = 0; - QTimer *timer = nullptr; - } m_keyRepeat; ModifiersChangedSpy *m_modifiersChangedSpy = nullptr; KeyboardLayout *m_keyboardLayout = nullptr; }; diff --git a/keyboard_input.cpp b/keyboard_input.cpp --- a/keyboard_input.cpp +++ b/keyboard_input.cpp @@ -21,6 +21,7 @@ #include "input_event.h" #include "input_event_spy.h" #include "keyboard_layout.h" +#include "keyboard_repeat.h" #include "abstract_client.h" #include "options.h" #include "utils.h" @@ -605,17 +606,10 @@ m_keyboardLayout->init(); m_input->installInputEventSpy(m_keyboardLayout); - // setup key repeat - m_keyRepeat.timer = new QTimer(this); - connect(m_keyRepeat.timer, &QTimer::timeout, this, - [this] { - if (waylandServer()->seat()->keyRepeatRate() != 0) { - m_keyRepeat.timer->setInterval(1000 / waylandServer()->seat()->keyRepeatRate()); - } - // TODO: better time - processKey(m_keyRepeat.key, InputRedirection::KeyboardKeyAutoRepeat, m_keyRepeat.time); - } - ); + KeyboardRepeat *keyRepeatSpy = new KeyboardRepeat(m_xkb.data()); + connect(keyRepeatSpy, &KeyboardRepeat::keyRepeat, this, + std::bind(&KeyboardInputRedirection::processKey, this, std::placeholders::_1, InputRedirection::KeyboardKeyAutoRepeat, std::placeholders::_2, nullptr)); + m_input->installInputEventSpy(keyRepeatSpy); connect(workspace(), &QObject::destroyed, this, [this] { m_inited = false; }); connect(waylandServer(), &QObject::destroyed, this, [this] { m_inited = false; }); @@ -725,18 +719,6 @@ time, device); event.setModifiersRelevantForGlobalShortcuts(m_xkb->modifiersRelevantForGlobalShortcuts()); - if (state == InputRedirection::KeyboardKeyPressed) { - if (m_xkb->shouldKeyRepeat(key) && waylandServer()->seat()->keyRepeatDelay() != 0) { - m_keyRepeat.timer->setInterval(waylandServer()->seat()->keyRepeatDelay()); - m_keyRepeat.key = key; - m_keyRepeat.time = time; - m_keyRepeat.timer->start(); - } - } else if (state == InputRedirection::KeyboardKeyReleased) { - if (key == m_keyRepeat.key) { - m_keyRepeat.timer->stop(); - } - } m_input->processSpies(std::bind(&InputEventSpy::keyEvent, std::placeholders::_1, &event)); m_input->processFilters(std::bind(&InputEventFilter::keyEvent, std::placeholders::_1, &event)); diff --git a/keyboard_repeat.h b/keyboard_repeat.h new file mode 100644 --- /dev/null +++ b/keyboard_repeat.h @@ -0,0 +1,56 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2016, 2017 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWIN_KEYBOARD_REPEAT +#define KWIN_KEYBOARD_REPEAT + +#include "input_event_spy.h" + +#include + +class QTimer; + +namespace KWin +{ +class Xkb; + +class KeyboardRepeat : public QObject, public InputEventSpy +{ + Q_OBJECT +public: + explicit KeyboardRepeat(Xkb *xkb); + ~KeyboardRepeat() override; + + void keyEvent(KeyEvent *event) override; + +Q_SIGNALS: + void keyRepeat(quint32 key, quint32 time); + +private: + void handleKeyRepeat(); + QTimer *m_timer; + Xkb *m_xkb; + quint32 m_time; + quint32 m_key; +}; + + +} + +#endif diff --git a/keyboard_repeat.cpp b/keyboard_repeat.cpp new file mode 100644 --- /dev/null +++ b/keyboard_repeat.cpp @@ -0,0 +1,73 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2016, 2017 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "keyboard_repeat.h" +#include "keyboard_input.h" +#include "input_event.h" +#include "wayland_server.h" + +#include + +#include + +namespace KWin +{ + +KeyboardRepeat::KeyboardRepeat(Xkb *xkb) + : QObject() + , m_timer(new QTimer) + , m_xkb(xkb) +{ + connect(m_timer, &QTimer::timeout, this, &KeyboardRepeat::handleKeyRepeat); +} + +KeyboardRepeat::~KeyboardRepeat() = default; + +void KeyboardRepeat::handleKeyRepeat() +{ + // TODO: don't depend on WaylandServer + if (waylandServer()->seat()->keyRepeatRate() != 0) { + m_timer->setInterval(1000 / waylandServer()->seat()->keyRepeatRate()); + } + // TODO: better time + emit keyRepeat(m_key, m_time); +} + +void KeyboardRepeat::keyEvent(KeyEvent *event) +{ + if (event->isAutoRepeat()) { + return; + } + const quint32 key = event->nativeScanCode(); + if (event->type() == QEvent::KeyPress) { + // TODO: don't get these values from WaylandServer + if (m_xkb->shouldKeyRepeat(key) && waylandServer()->seat()->keyRepeatDelay() != 0) { + m_timer->setInterval(waylandServer()->seat()->keyRepeatDelay()); + m_key = key; + m_time = event->timestamp(); + m_timer->start(); + } + } else if (event->type() == QEvent::KeyRelease) { + if (key == m_key) { + m_timer->stop(); + } + } +} + +}