Provide kxbk config through kwinApp
Summary: So far KWin parsed the kxbkrc at multiple places (once in Xkb, once in KeyboardLayout). This is now replaced by one KSharedConfigPtr hold by kwinApp, just like the normal kwinrc. The KSharedConfigPtr is now passed to Xkb. As a nice side effect this makes it easier to test keyboard layout changes as we can now properly mock the keyboard configuration. Thus this change also comes with an autotest for loading keyboard layout configuration. This is becoming more and more a need as we start getting bug reports for layout specific issues like global shortcuts not working with Greek layout. Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D4315
This commit is contained in:
parent
c35aae2c4f
commit
8d9c4acf4d
7 changed files with 132 additions and 3 deletions
|
@ -43,6 +43,7 @@ integrationTest(NAME testTabBox SRCS tabbox_test.cpp)
|
|||
integrationTest(NAME testGlobalShortcuts SRCS globalshortcuts_test.cpp)
|
||||
integrationTest(NAME testWindowSelection SRCS window_selection_test.cpp)
|
||||
integrationTest(NAME testPointerConstraints SRCS pointer_constraints_test.cpp)
|
||||
integrationTest(NAME testKeyboardLayout SRCS keyboard_layout_test.cpp)
|
||||
|
||||
if (XCB_ICCCM_FOUND)
|
||||
integrationTest(NAME testMoveResize SRCS move_resize_window_test.cpp LIBS XCB::ICCCM)
|
||||
|
|
103
autotests/integration/keyboard_layout_test.cpp
Normal file
103
autotests/integration/keyboard_layout_test.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2017 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "kwin_wayland_test.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "platform.h"
|
||||
#include "wayland_server.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
|
||||
using namespace KWin;
|
||||
using namespace KWayland::Client;
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_keyboard_laout-0");
|
||||
|
||||
class KeyboardLayoutTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testReconfigure();
|
||||
};
|
||||
|
||||
void KeyboardLayoutTest::initTestCase()
|
||||
{
|
||||
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
|
||||
QVERIFY(workspaceCreatedSpy.isValid());
|
||||
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
|
||||
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
|
||||
|
||||
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
kwinApp()->setKxkbConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
|
||||
kwinApp()->start();
|
||||
QVERIFY(workspaceCreatedSpy.wait());
|
||||
waylandServer()->initWorkspace();
|
||||
}
|
||||
|
||||
void KeyboardLayoutTest::init()
|
||||
{
|
||||
}
|
||||
|
||||
void KeyboardLayoutTest::cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
void KeyboardLayoutTest::testReconfigure()
|
||||
{
|
||||
// verifies that we can change the keymap
|
||||
|
||||
// default should be a keymap with only us layout
|
||||
auto xkb = input()->keyboard()->xkb();
|
||||
QCOMPARE(xkb->numberOfLayouts(), 1u);
|
||||
QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
||||
auto layouts = xkb->layoutNames();
|
||||
QCOMPARE(layouts.size(), 1);
|
||||
QVERIFY(layouts.contains(0));
|
||||
QCOMPARE(layouts[0], QStringLiteral("English (US)"));
|
||||
|
||||
// create a new keymap
|
||||
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
||||
layoutGroup.writeEntry("LayoutList", QStringLiteral("de,us"));
|
||||
layoutGroup.sync();
|
||||
|
||||
// create DBus signal to reload
|
||||
QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/Layouts"), QStringLiteral("org.kde.keyboard"), QStringLiteral("reloadConfig"));
|
||||
QDBusConnection::sessionBus().send(message);
|
||||
// now we should have two layouts
|
||||
QTRY_COMPARE(xkb->numberOfLayouts(), 2u);
|
||||
// default layout is German
|
||||
QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
|
||||
layouts = xkb->layoutNames();
|
||||
QCOMPARE(layouts.size(), 2);
|
||||
QVERIFY(layouts.contains(0));
|
||||
QVERIFY(layouts.contains(1));
|
||||
QCOMPARE(layouts[0], QStringLiteral("German"));
|
||||
QCOMPARE(layouts[1], QStringLiteral("English (US)"));
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(KeyboardLayoutTest)
|
||||
#include "keyboard_layout_test.moc"
|
|
@ -168,7 +168,10 @@ void Xkb::reconfigure()
|
|||
xkb_keymap *Xkb::loadKeymapFromConfig()
|
||||
{
|
||||
// load config
|
||||
const KConfigGroup config = KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals)->group("Layout");
|
||||
if (!m_config) {
|
||||
return nullptr;
|
||||
}
|
||||
const KConfigGroup config = m_config->group("Layout");
|
||||
const QByteArray model = config.readEntry("Model", "pc104").toLocal8Bit();
|
||||
const QByteArray layout = config.readEntry("LayoutList", "").toLocal8Bit();
|
||||
const QByteArray options = config.readEntry("Options", "").toLocal8Bit();
|
||||
|
@ -598,11 +601,14 @@ void KeyboardInputRedirection::init()
|
|||
{
|
||||
Q_ASSERT(!m_inited);
|
||||
m_inited = true;
|
||||
const auto config = kwinApp()->kxkbConfig();
|
||||
m_xkb->setConfig(config);
|
||||
|
||||
m_input->installInputEventSpy(new KeyStateChangedSpy(m_input));
|
||||
m_modifiersChangedSpy = new ModifiersChangedSpy(m_input);
|
||||
m_input->installInputEventSpy(m_modifiersChangedSpy);
|
||||
m_keyboardLayout = new KeyboardLayout(m_xkb.data());
|
||||
m_keyboardLayout->setConfig(KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals));
|
||||
m_keyboardLayout->setConfig(config);
|
||||
m_keyboardLayout->init();
|
||||
m_input->installInputEventSpy(m_keyboardLayout);
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QLoggingCategory>
|
||||
Q_DECLARE_LOGGING_CATEGORY(KWIN_XKB)
|
||||
|
||||
#include <KSharedConfig>
|
||||
|
||||
class QWindow;
|
||||
struct xkb_context;
|
||||
struct xkb_keymap;
|
||||
|
@ -58,6 +60,9 @@ class KWIN_EXPORT Xkb
|
|||
public:
|
||||
Xkb(InputRedirection *input);
|
||||
~Xkb();
|
||||
void setConfig(KSharedConfigPtr config) {
|
||||
m_config = config;
|
||||
}
|
||||
void reconfigure();
|
||||
|
||||
void installKeymap(int fd, uint32_t size);
|
||||
|
@ -136,6 +141,7 @@ private:
|
|||
xkb_compose_state *state = nullptr;
|
||||
} m_compose;
|
||||
LEDs m_leds;
|
||||
KSharedConfigPtr m_config;
|
||||
};
|
||||
|
||||
class KWIN_EXPORT KeyboardInputRedirection : public QObject
|
||||
|
|
|
@ -140,10 +140,10 @@ void KeyboardLayout::switchToLayout(xkb_layout_index_t index)
|
|||
|
||||
void KeyboardLayout::reconfigure()
|
||||
{
|
||||
m_xkb->reconfigure();
|
||||
if (m_config) {
|
||||
m_config->reparseConfiguration();
|
||||
}
|
||||
m_xkb->reconfigure();
|
||||
resetLayout();
|
||||
}
|
||||
|
||||
|
|
4
main.cpp
4
main.cpp
|
@ -104,6 +104,7 @@ Application::Application(Application::OperationMode mode, int &argc, char **argv
|
|||
, m_eventFilter(new XcbEventFilter())
|
||||
, m_configLock(false)
|
||||
, m_config()
|
||||
, m_kxkbConfig()
|
||||
, m_operationMode(mode)
|
||||
{
|
||||
qRegisterMetaType<Options::WindowOperation>("Options::WindowOperation");
|
||||
|
@ -144,6 +145,9 @@ void Application::start()
|
|||
//config->setReadOnly( true );
|
||||
m_config->reparseConfiguration();
|
||||
}
|
||||
if (!m_kxkbConfig) {
|
||||
m_kxkbConfig = KSharedConfig::openConfig(QStringLiteral("kxkbrc"), KConfig::NoGlobals);
|
||||
}
|
||||
|
||||
performStartup();
|
||||
}
|
||||
|
|
9
main.h
9
main.h
|
@ -55,6 +55,7 @@ class KWIN_EXPORT Application : public QApplication
|
|||
Q_PROPERTY(void *x11Connection READ x11Connection NOTIFY x11ConnectionChanged)
|
||||
Q_PROPERTY(int x11ScreenNumber READ x11ScreenNumber CONSTANT)
|
||||
Q_PROPERTY(KSharedConfigPtr config READ config WRITE setConfig)
|
||||
Q_PROPERTY(KSharedConfigPtr kxkbConfig READ kxkbConfig WRITE setKxkbConfig)
|
||||
public:
|
||||
/**
|
||||
* @brief This enum provides the various operation modes of KWin depending on the available
|
||||
|
@ -88,6 +89,13 @@ public:
|
|||
m_config = config;
|
||||
}
|
||||
|
||||
KSharedConfigPtr kxkbConfig() const {
|
||||
return m_kxkbConfig;
|
||||
}
|
||||
void setKxkbConfig(KSharedConfigPtr config) {
|
||||
m_kxkbConfig = config;
|
||||
}
|
||||
|
||||
void start();
|
||||
/**
|
||||
* @brief The operation mode used by KWin.
|
||||
|
@ -223,6 +231,7 @@ private:
|
|||
QScopedPointer<XcbEventFilter> m_eventFilter;
|
||||
bool m_configLock;
|
||||
KSharedConfigPtr m_config;
|
||||
KSharedConfigPtr m_kxkbConfig;
|
||||
OperationMode m_operationMode;
|
||||
xcb_timestamp_t m_x11Time = XCB_TIME_CURRENT_TIME;
|
||||
xcb_window_t m_rootWindow = XCB_WINDOW_NONE;
|
||||
|
|
Loading…
Reference in a new issue