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
icc-effect-5.14.5
Martin Gräßlin 2017-01-27 17:15:32 +01:00
parent c35aae2c4f
commit 8d9c4acf4d
7 changed files with 132 additions and 3 deletions

View File

@ -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)

View 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"

View File

@ -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);

View File

@ -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

View File

@ -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();
}

View File

@ -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
View File

@ -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;