Support enabling numlock on startup
Summary: This change brings improved num lock support to KWin. The modifier state is read and also mapped to Qt::KeyboardModifiers. Furthermore the input config is read and the NumLock key is evaluated. If the requested state does not match the current num lock state the state is swapped. BUG: 375708 FIXED-IN: 5.15 Test Plan: New unit test added, no manual test due to lack of hardware Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D16428
This commit is contained in:
parent
7e8facc3fd
commit
7c3a851b04
4 changed files with 83 additions and 0 deletions
|
@ -60,6 +60,7 @@ private Q_SLOTS:
|
|||
void testVirtualDesktopPolicy();
|
||||
void testWindowPolicy();
|
||||
void testApplicationPolicy();
|
||||
void testNumLock();
|
||||
|
||||
private:
|
||||
void reconfigureLayouts();
|
||||
|
@ -83,6 +84,7 @@ void KeyboardLayoutTest::initTestCase()
|
|||
|
||||
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
kwinApp()->setKxkbConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
kwinApp()->setInputConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
|
||||
kwinApp()->start();
|
||||
QVERIFY(workspaceCreatedSpy.wait());
|
||||
|
@ -457,5 +459,46 @@ void KeyboardLayoutTest::testApplicationPolicy()
|
|||
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
||||
}
|
||||
|
||||
void KeyboardLayoutTest::testNumLock()
|
||||
{
|
||||
qputenv("KWIN_FORCE_NUM_LOCK_EVALUATION", "1");
|
||||
auto xkb = input()->keyboard()->xkb();
|
||||
// by default not set
|
||||
QVERIFY(!xkb->modifiers().testFlag(Qt::KeypadModifier));
|
||||
quint32 timestamp = 0;
|
||||
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
||||
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
||||
// now it should be on
|
||||
QVERIFY(xkb->modifiers().testFlag(Qt::KeypadModifier));
|
||||
// and back to off
|
||||
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
||||
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
||||
QVERIFY(!xkb->modifiers().testFlag(Qt::KeypadModifier));
|
||||
|
||||
// let's reconfigure to enable through config
|
||||
auto group = kwinApp()->inputConfig()->group("Keyboard");
|
||||
group.writeEntry("NumLock", 0);
|
||||
group.sync();
|
||||
xkb->reconfigure();
|
||||
// now it should be on
|
||||
QVERIFY(xkb->modifiers().testFlag(Qt::KeypadModifier));
|
||||
// pressing should result in it being off
|
||||
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
||||
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
||||
QVERIFY(!xkb->modifiers().testFlag(Qt::KeypadModifier));
|
||||
|
||||
// pressing again should enable it
|
||||
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
||||
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
||||
QVERIFY(xkb->modifiers().testFlag(Qt::KeypadModifier));
|
||||
|
||||
// now reconfigure to disable on load
|
||||
group.writeEntry("NumLock", 1);
|
||||
group.sync();
|
||||
xkb->reconfigure();
|
||||
QVERIFY(!xkb->modifiers().testFlag(Qt::KeypadModifier));
|
||||
}
|
||||
|
||||
|
||||
WAYLANDTEST_MAIN(KeyboardLayoutTest)
|
||||
#include "keyboard_layout_test.moc"
|
||||
|
|
|
@ -111,6 +111,7 @@ void KeyboardInputRedirection::init()
|
|||
Q_ASSERT(!m_inited);
|
||||
m_inited = true;
|
||||
const auto config = kwinApp()->kxkbConfig();
|
||||
m_xkb->setNumLockConfig(kwinApp()->inputConfig());
|
||||
m_xkb->setConfig(config);
|
||||
|
||||
m_input->installInputEventSpy(new KeyStateChangedSpy(m_input));
|
||||
|
|
28
xkb.cpp
28
xkb.cpp
|
@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// system
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <bitset>
|
||||
|
||||
Q_LOGGING_CATEGORY(KWIN_XKB, "kwin_xkbcommon", QtCriticalMsg)
|
||||
|
||||
|
@ -75,6 +76,7 @@ Xkb::Xkb(QObject *parent)
|
|||
, m_controlModifier(0)
|
||||
, m_altModifier(0)
|
||||
, m_metaModifier(0)
|
||||
, m_numModifier(0)
|
||||
, m_numLock(0)
|
||||
, m_capsLock(0)
|
||||
, m_scrollLock(0)
|
||||
|
@ -214,6 +216,7 @@ void Xkb::installKeymap(int fd, uint32_t size)
|
|||
qCDebug(KWIN_XKB) << "Could not map keymap from file";
|
||||
return;
|
||||
}
|
||||
m_ownership = Ownership::Client;
|
||||
updateKeymap(keymap);
|
||||
}
|
||||
|
||||
|
@ -238,6 +241,7 @@ 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_numModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_NUM);
|
||||
|
||||
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);
|
||||
|
@ -249,8 +253,29 @@ void Xkb::updateKeymap(xkb_keymap *keymap)
|
|||
m_modifierState.latched = xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LATCHED));
|
||||
m_modifierState.locked = xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LOCKED));
|
||||
|
||||
static bool s_startup = true;
|
||||
if (s_startup || qEnvironmentVariableIsSet("KWIN_FORCE_NUM_LOCK_EVALUATION")) {
|
||||
s_startup = false;
|
||||
if (m_ownership == Ownership::Server && m_numModifier != XKB_MOD_INVALID && m_numLockConfig) {
|
||||
const KConfigGroup config = m_numLockConfig->group("Keyboard");
|
||||
// STATE_ON = 0, STATE_OFF = 1, STATE_UNCHANGED = 2, see plasma-desktop/kcms/keyboard/kcmmisc.h
|
||||
const auto setting = config.readEntry("NumLock", 2);
|
||||
const bool numLockIsOn = xkb_state_mod_index_is_active(m_state, m_numModifier, XKB_STATE_MODS_LOCKED);
|
||||
if ((setting == 0 && !numLockIsOn) || (setting == 1 && numLockIsOn)) {
|
||||
std::bitset<sizeof(xkb_mod_mask_t)*8> mask{m_modifierState.locked};
|
||||
if (mask.size() > m_numModifier) {
|
||||
mask[m_numModifier] = (setting == 0);
|
||||
m_modifierState.locked = mask.to_ulong();
|
||||
xkb_state_update_mask(m_state, m_modifierState.depressed, m_modifierState.latched, m_modifierState.locked, 0, 0, m_currentLayout);
|
||||
m_modifierState.locked = xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LOCKED));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createKeymapFile();
|
||||
forwardModifiers();
|
||||
updateModifiers();
|
||||
}
|
||||
|
||||
void Xkb::createKeymapFile()
|
||||
|
@ -344,6 +369,9 @@ void Xkb::updateModifiers()
|
|||
if (xkb_state_mod_index_is_active(m_state, m_metaModifier, XKB_STATE_MODS_EFFECTIVE) == 1) {
|
||||
mods |= Qt::MetaModifier;
|
||||
}
|
||||
if (xkb_state_mod_index_is_active(m_state, m_numModifier, XKB_STATE_MODS_EFFECTIVE) == 1) {
|
||||
mods |= Qt::KeypadModifier;
|
||||
}
|
||||
m_modifiers = mods;
|
||||
|
||||
// update LEDs
|
||||
|
|
11
xkb.h
11
xkb.h
|
@ -58,6 +58,9 @@ public:
|
|||
void setConfig(KSharedConfigPtr config) {
|
||||
m_config = config;
|
||||
}
|
||||
void setNumLockConfig(KSharedConfigPtr config) {
|
||||
m_numLockConfig = config;
|
||||
}
|
||||
void reconfigure();
|
||||
|
||||
void installKeymap(int fd, uint32_t size);
|
||||
|
@ -130,6 +133,7 @@ private:
|
|||
xkb_mod_index_t m_controlModifier;
|
||||
xkb_mod_index_t m_altModifier;
|
||||
xkb_mod_index_t m_metaModifier;
|
||||
xkb_mod_index_t m_numModifier;
|
||||
xkb_led_index_t m_numLock;
|
||||
xkb_led_index_t m_capsLock;
|
||||
xkb_led_index_t m_scrollLock;
|
||||
|
@ -144,6 +148,7 @@ private:
|
|||
} m_compose;
|
||||
LEDs m_leds;
|
||||
KSharedConfigPtr m_config;
|
||||
KSharedConfigPtr m_numLockConfig;
|
||||
|
||||
struct {
|
||||
xkb_mod_index_t depressed = 0;
|
||||
|
@ -151,6 +156,12 @@ private:
|
|||
xkb_mod_index_t locked = 0;
|
||||
} m_modifierState;
|
||||
|
||||
enum class Ownership {
|
||||
Server,
|
||||
Client
|
||||
};
|
||||
Ownership m_ownership = Ownership::Server;
|
||||
|
||||
QPointer<KWayland::Server::SeatInterface> m_seat;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue