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:
Martin Gräßlin 2016-10-05 11:50:20 +02:00
parent 1c3cc6239e
commit 4c7752c965
5 changed files with 87 additions and 0 deletions

View file

@ -1233,7 +1233,9 @@ void InputRedirection::setupLibInput()
m_libInput = conn; m_libInput = conn;
if (conn) { if (conn) {
conn->setInputConfig(m_inputConfig); conn->setInputConfig(m_inputConfig);
conn->updateLEDs(m_keyboard->xkb()->leds());
conn->setup(); conn->setup();
connect(m_keyboard, &KeyboardInputRedirection::ledsChanged, conn, &LibInput::Connection::updateLEDs);
connect(conn, &LibInput::Connection::eventsRead, this, connect(conn, &LibInput::Connection::eventsRead, this,
[this] { [this] {
m_libInput->processEvents(); m_libInput->processEvents();

View file

@ -90,10 +90,15 @@ Xkb::Xkb(InputRedirection *input)
, m_controlModifier(0) , m_controlModifier(0)
, m_altModifier(0) , m_altModifier(0)
, m_metaModifier(0) , m_metaModifier(0)
, m_numLock(0)
, m_capsLock(0)
, m_scrollLock(0)
, m_modifiers(Qt::NoModifier) , m_modifiers(Qt::NoModifier)
, m_consumedModifiers(Qt::NoModifier) , m_consumedModifiers(Qt::NoModifier)
, m_keysym(XKB_KEY_NoSymbol) , m_keysym(XKB_KEY_NoSymbol)
, m_leds()
{ {
qRegisterMetaType<KWin::Xkb::LEDs>();
if (!m_context) { if (!m_context) {
qCDebug(KWIN_XKB) << "Could not create xkb context"; qCDebug(KWIN_XKB) << "Could not create xkb context";
} else { } 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_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_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_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); m_currentLayout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
createKeymapFile(); createKeymapFile();
@ -346,6 +356,23 @@ void Xkb::updateModifiers()
mods |= Qt::MetaModifier; mods |= Qt::MetaModifier;
} }
m_modifiers = mods; 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); const xkb_layout_index_t layout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
if (layout != m_currentLayout) { if (layout != m_currentLayout) {
m_currentLayout = layout; m_currentLayout = layout;

View file

@ -36,6 +36,7 @@ struct xkb_state;
struct xkb_compose_table; struct xkb_compose_table;
struct xkb_compose_state; struct xkb_compose_state;
typedef uint32_t xkb_mod_index_t; typedef uint32_t xkb_mod_index_t;
typedef uint32_t xkb_led_index_t;
typedef uint32_t xkb_keysym_t; typedef uint32_t xkb_keysym_t;
namespace KWin namespace KWin
@ -71,6 +72,16 @@ public:
void switchToNextLayout(); 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: private:
xkb_keymap *loadKeymapFromConfig(); xkb_keymap *loadKeymapFromConfig();
xkb_keymap *loadDefaultKeymap(); xkb_keymap *loadDefaultKeymap();
@ -87,6 +98,9 @@ private:
xkb_mod_index_t m_controlModifier; xkb_mod_index_t m_controlModifier;
xkb_mod_index_t m_altModifier; xkb_mod_index_t m_altModifier;
xkb_mod_index_t m_metaModifier; 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_modifiers;
Qt::KeyboardModifiers m_consumedModifiers; Qt::KeyboardModifiers m_consumedModifiers;
xkb_keysym_t m_keysym; xkb_keysym_t m_keysym;
@ -100,6 +114,7 @@ private:
xkb_compose_table *table = nullptr; xkb_compose_table *table = nullptr;
xkb_compose_state *state = nullptr; xkb_compose_state *state = nullptr;
} m_compose; } m_compose;
LEDs m_leds;
}; };
class KeyboardInputRedirection : public QObject class KeyboardInputRedirection : public QObject
@ -133,6 +148,9 @@ public:
return m_xkb->modifiers(); return m_xkb->modifiers();
} }
Q_SIGNALS:
void ledsChanged(KWin::Xkb::LEDs);
private Q_SLOTS: private Q_SLOTS:
void reconfigure(); void reconfigure();
@ -156,4 +174,7 @@ Qt::KeyboardModifiers Xkb::modifiers() const
} }
Q_DECLARE_METATYPE(KWin::Xkb::LED)
Q_DECLARE_METATYPE(KWin::Xkb::LEDs)
#endif #endif

View file

@ -47,6 +47,21 @@ QThread *Connection::s_thread = nullptr;
static Context *s_context = 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::Connection(QObject *parent)
: Connection(nullptr, parent) : Connection(nullptr, parent)
{ {
@ -95,6 +110,7 @@ Connection::Connection(Context *input, QObject *parent)
, m_input(input) , m_input(input)
, m_notifier(nullptr) , m_notifier(nullptr)
, m_mutex(QMutex::Recursive) , m_mutex(QMutex::Recursive)
, m_leds()
{ {
Q_ASSERT(m_input); Q_ASSERT(m_input);
@ -246,6 +262,10 @@ void Connection::processEvents()
} }
} }
applyDeviceConfig(device); applyDeviceConfig(device);
// enable possible leds
libinput_device_led_update(device->device(), static_cast<libinput_led>(toLibinputLEDS(m_leds)));
emit deviceAdded(device); emit deviceAdded(device);
break; 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);
}
}
} }
} }

View file

@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KWIN_LIBINPUT_CONNECTION_H #define KWIN_LIBINPUT_CONNECTION_H
#include "../input.h" #include "../input.h"
#include "../keyboard_input.h"
#include <kwinglobals.h> #include <kwinglobals.h>
#include <QObject> #include <QObject>
@ -82,6 +83,8 @@ public:
return m_devices; return m_devices;
} }
void updateLEDs(KWin::Xkb::LEDs leds);
Q_SIGNALS: Q_SIGNALS:
void keyChanged(quint32 key, KWin::InputRedirection::KeyboardKeyState, quint32 time, KWin::LibInput::Device *device); 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); void pointerButtonChanged(quint32 button, KWin::InputRedirection::PointerButtonState state, quint32 time, KWin::LibInput::Device *device);
@ -135,6 +138,7 @@ private:
QVector<Device*> m_devices; QVector<Device*> m_devices;
KSharedConfigPtr m_config; KSharedConfigPtr m_config;
bool m_touchpadsEnabled = true; bool m_touchpadsEnabled = true;
Xkb::LEDs m_leds;
KWIN_SINGLETON(Connection) KWIN_SINGLETON(Connection)
static QThread *s_thread; static QThread *s_thread;