Support LEDs in Xkb and libinput
Summary: The Xkb implementation starts to track the state of the LEDs in the keymap and emits a signal whenever the LEDs change. This signal is connected to a method in LibInput::Connection which updates the led state on all devices and uses it to init the state of the led when a new device gets connected. BUG: 369214 FIXED-IN: 5.8.2 Test Plan: Connected a keyboard with LEDs and enabled NumLock and ScrollLock. Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2943
This commit is contained in:
parent
1c3cc6239e
commit
4c7752c965
5 changed files with 87 additions and 0 deletions
|
@ -1233,7 +1233,9 @@ void InputRedirection::setupLibInput()
|
|||
m_libInput = conn;
|
||||
if (conn) {
|
||||
conn->setInputConfig(m_inputConfig);
|
||||
conn->updateLEDs(m_keyboard->xkb()->leds());
|
||||
conn->setup();
|
||||
connect(m_keyboard, &KeyboardInputRedirection::ledsChanged, conn, &LibInput::Connection::updateLEDs);
|
||||
connect(conn, &LibInput::Connection::eventsRead, this,
|
||||
[this] {
|
||||
m_libInput->processEvents();
|
||||
|
|
|
@ -90,10 +90,15 @@ Xkb::Xkb(InputRedirection *input)
|
|||
, m_controlModifier(0)
|
||||
, m_altModifier(0)
|
||||
, m_metaModifier(0)
|
||||
, m_numLock(0)
|
||||
, m_capsLock(0)
|
||||
, m_scrollLock(0)
|
||||
, m_modifiers(Qt::NoModifier)
|
||||
, m_consumedModifiers(Qt::NoModifier)
|
||||
, m_keysym(XKB_KEY_NoSymbol)
|
||||
, m_leds()
|
||||
{
|
||||
qRegisterMetaType<KWin::Xkb::LEDs>();
|
||||
if (!m_context) {
|
||||
qCDebug(KWIN_XKB) << "Could not create xkb context";
|
||||
} else {
|
||||
|
@ -219,6 +224,11 @@ void Xkb::updateKeymap(xkb_keymap *keymap)
|
|||
m_controlModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_CTRL);
|
||||
m_altModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT);
|
||||
m_metaModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO);
|
||||
|
||||
m_numLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_NUM);
|
||||
m_capsLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_CAPS);
|
||||
m_scrollLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_SCROLL);
|
||||
|
||||
m_currentLayout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
|
||||
createKeymapFile();
|
||||
|
@ -346,6 +356,23 @@ void Xkb::updateModifiers()
|
|||
mods |= Qt::MetaModifier;
|
||||
}
|
||||
m_modifiers = mods;
|
||||
|
||||
// update LEDs
|
||||
LEDs leds;
|
||||
if (xkb_state_led_index_is_active(m_state, m_numLock) == 1) {
|
||||
leds = leds | LED::NumLock;
|
||||
}
|
||||
if (xkb_state_led_index_is_active(m_state, m_capsLock) == 1) {
|
||||
leds = leds | LED::CapsLock;
|
||||
}
|
||||
if (xkb_state_led_index_is_active(m_state, m_scrollLock) == 1) {
|
||||
leds = leds | LED::ScrollLock;
|
||||
}
|
||||
if (m_leds != leds) {
|
||||
m_leds = leds;
|
||||
emit m_input->keyboard()->ledsChanged(m_leds);
|
||||
}
|
||||
|
||||
const xkb_layout_index_t layout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
if (layout != m_currentLayout) {
|
||||
m_currentLayout = layout;
|
||||
|
|
|
@ -36,6 +36,7 @@ struct xkb_state;
|
|||
struct xkb_compose_table;
|
||||
struct xkb_compose_state;
|
||||
typedef uint32_t xkb_mod_index_t;
|
||||
typedef uint32_t xkb_led_index_t;
|
||||
typedef uint32_t xkb_keysym_t;
|
||||
|
||||
namespace KWin
|
||||
|
@ -71,6 +72,16 @@ public:
|
|||
|
||||
void switchToNextLayout();
|
||||
|
||||
enum class LED {
|
||||
NumLock = 1 << 0,
|
||||
CapsLock = 1 << 1,
|
||||
ScrollLock = 1 << 2
|
||||
};
|
||||
Q_DECLARE_FLAGS(LEDs, LED)
|
||||
LEDs leds() const {
|
||||
return m_leds;
|
||||
}
|
||||
|
||||
private:
|
||||
xkb_keymap *loadKeymapFromConfig();
|
||||
xkb_keymap *loadDefaultKeymap();
|
||||
|
@ -87,6 +98,9 @@ private:
|
|||
xkb_mod_index_t m_controlModifier;
|
||||
xkb_mod_index_t m_altModifier;
|
||||
xkb_mod_index_t m_metaModifier;
|
||||
xkb_led_index_t m_numLock;
|
||||
xkb_led_index_t m_capsLock;
|
||||
xkb_led_index_t m_scrollLock;
|
||||
Qt::KeyboardModifiers m_modifiers;
|
||||
Qt::KeyboardModifiers m_consumedModifiers;
|
||||
xkb_keysym_t m_keysym;
|
||||
|
@ -100,6 +114,7 @@ private:
|
|||
xkb_compose_table *table = nullptr;
|
||||
xkb_compose_state *state = nullptr;
|
||||
} m_compose;
|
||||
LEDs m_leds;
|
||||
};
|
||||
|
||||
class KeyboardInputRedirection : public QObject
|
||||
|
@ -133,6 +148,9 @@ public:
|
|||
return m_xkb->modifiers();
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void ledsChanged(KWin::Xkb::LEDs);
|
||||
|
||||
private Q_SLOTS:
|
||||
void reconfigure();
|
||||
|
||||
|
@ -156,4 +174,7 @@ Qt::KeyboardModifiers Xkb::modifiers() const
|
|||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(KWin::Xkb::LED)
|
||||
Q_DECLARE_METATYPE(KWin::Xkb::LEDs)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,21 @@ QThread *Connection::s_thread = nullptr;
|
|||
|
||||
static Context *s_context = nullptr;
|
||||
|
||||
static quint32 toLibinputLEDS(Xkb::LEDs leds)
|
||||
{
|
||||
quint32 libinputLeds = 0;
|
||||
if (leds.testFlag(Xkb::LED::NumLock)) {
|
||||
libinputLeds = libinputLeds | LIBINPUT_LED_NUM_LOCK;
|
||||
}
|
||||
if (leds.testFlag(Xkb::LED::CapsLock)) {
|
||||
libinputLeds = libinputLeds | LIBINPUT_LED_CAPS_LOCK;
|
||||
}
|
||||
if (leds.testFlag(Xkb::LED::ScrollLock)) {
|
||||
libinputLeds = libinputLeds | LIBINPUT_LED_SCROLL_LOCK;
|
||||
}
|
||||
return libinputLeds;
|
||||
}
|
||||
|
||||
Connection::Connection(QObject *parent)
|
||||
: Connection(nullptr, parent)
|
||||
{
|
||||
|
@ -95,6 +110,7 @@ Connection::Connection(Context *input, QObject *parent)
|
|||
, m_input(input)
|
||||
, m_notifier(nullptr)
|
||||
, m_mutex(QMutex::Recursive)
|
||||
, m_leds()
|
||||
{
|
||||
Q_ASSERT(m_input);
|
||||
|
||||
|
@ -246,6 +262,10 @@ void Connection::processEvents()
|
|||
}
|
||||
}
|
||||
applyDeviceConfig(device);
|
||||
|
||||
// enable possible leds
|
||||
libinput_device_led_update(device->device(), static_cast<libinput_led>(toLibinputLEDS(m_leds)));
|
||||
|
||||
emit deviceAdded(device);
|
||||
break;
|
||||
}
|
||||
|
@ -513,5 +533,18 @@ void Connection::toggleTouchpads()
|
|||
}
|
||||
}
|
||||
|
||||
void Connection::updateLEDs(Xkb::LEDs leds)
|
||||
{
|
||||
if (m_leds == leds) {
|
||||
return;
|
||||
}
|
||||
m_leds = leds;
|
||||
// update on devices
|
||||
const libinput_led l = static_cast<libinput_led>(toLibinputLEDS(leds));
|
||||
for (auto it = m_devices.constBegin(), end = m_devices.constEnd(); it != end; ++it) {
|
||||
libinput_device_led_update((*it)->device(), l);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define KWIN_LIBINPUT_CONNECTION_H
|
||||
|
||||
#include "../input.h"
|
||||
#include "../keyboard_input.h"
|
||||
#include <kwinglobals.h>
|
||||
|
||||
#include <QObject>
|
||||
|
@ -82,6 +83,8 @@ public:
|
|||
return m_devices;
|
||||
}
|
||||
|
||||
void updateLEDs(KWin::Xkb::LEDs leds);
|
||||
|
||||
Q_SIGNALS:
|
||||
void keyChanged(quint32 key, KWin::InputRedirection::KeyboardKeyState, quint32 time, KWin::LibInput::Device *device);
|
||||
void pointerButtonChanged(quint32 button, KWin::InputRedirection::PointerButtonState state, quint32 time, KWin::LibInput::Device *device);
|
||||
|
@ -135,6 +138,7 @@ private:
|
|||
QVector<Device*> m_devices;
|
||||
KSharedConfigPtr m_config;
|
||||
bool m_touchpadsEnabled = true;
|
||||
Xkb::LEDs m_leds;
|
||||
|
||||
KWIN_SINGLETON(Connection)
|
||||
static QThread *s_thread;
|
||||
|
|
Loading…
Reference in a new issue