fix: keyboard layout applet: no flag if Display Name is set

If user set custom name for the layout, country flag is not displayed.
Instead, Display Name is shown in the applet.

This reveals shortcomings in current DBus API design.
We need more data to pass over DBus to fix this.
Then, multiple improvements are possible:
- fix aforementioned bug
- add flags to context menu
- display correct translated Layout Name in the context menu
- simpler, cleaner DBus API and applet implementation
- etc.
icc-effect-5.26.4
Andrey Butirsky 2021-01-06 19:25:03 +03:00
parent d425e78cab
commit d2da79cb8d
5 changed files with 83 additions and 55 deletions

View File

@ -106,8 +106,7 @@ void KeyboardInputRedirection::init()
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(config);
m_keyboardLayout = new KeyboardLayout(m_xkb.data(), config);
m_keyboardLayout->init();
m_input->installInputEventSpy(m_keyboardLayout);

View File

@ -13,20 +13,21 @@
#include "main.h"
#include "platform.h"
#include <KConfigGroup>
#include <KGlobalAccel>
#include <KLocalizedString>
#include <QAction>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusPendingCall>
#include <QDBusMetaType>
namespace KWin
{
KeyboardLayout::KeyboardLayout(Xkb *xkb)
KeyboardLayout::KeyboardLayout(Xkb *xkb, const KSharedConfigPtr &config)
: QObject()
, m_xkb(xkb)
, m_configGroup(config->group("Layout"))
{
}
@ -70,7 +71,7 @@ void KeyboardLayout::initDBusInterface()
if (m_dbusInterface) {
return;
}
m_dbusInterface = new KeyboardLayoutDBusInterface(m_xkb, this);
m_dbusInterface = new KeyboardLayoutDBusInterface(m_xkb, m_configGroup, this);
connect(this, &KeyboardLayout::layoutChanged, m_dbusInterface,
[this] {
emit m_dbusInterface->layoutChanged(m_xkb->layoutName());
@ -103,14 +104,13 @@ void KeyboardLayout::switchToLayout(xkb_layout_index_t index)
void KeyboardLayout::reconfigure()
{
if (m_config) {
m_config->reparseConfiguration();
const KConfigGroup layoutGroup = m_config->group("Layout");
const QString policyKey = layoutGroup.readEntry("SwitchMode", QStringLiteral("Global"));
if (m_configGroup.isValid()) {
m_configGroup.config()->reparseConfiguration();
const QString policyKey = m_configGroup.readEntry("SwitchMode", QStringLiteral("Global"));
m_xkb->reconfigure();
if (!m_policy || m_policy->name() != policyKey) {
delete m_policy;
m_policy = KeyboardLayoutSwitching::Policy::create(m_xkb, this, layoutGroup, policyKey);
m_policy = KeyboardLayoutSwitching::Policy::create(m_xkb, this, m_configGroup, policyKey);
}
} else {
m_xkb->reconfigure();
@ -181,11 +181,16 @@ void KeyboardLayout::notifyLayoutChange()
static const QString s_keyboardService = QStringLiteral("org.kde.keyboard");
static const QString s_keyboardObject = QStringLiteral("/Layouts");
KeyboardLayoutDBusInterface::KeyboardLayoutDBusInterface(Xkb *xkb, KeyboardLayout *parent)
KeyboardLayoutDBusInterface::KeyboardLayoutDBusInterface(Xkb *xkb, const KConfigGroup &configGroup, KeyboardLayout *parent)
: QObject(parent)
, m_xkb(xkb)
, m_configGroup(configGroup)
, m_keyboardLayout(parent)
{
qRegisterMetaType<QVector<LayoutNames>>("QVector<LayoutNames>");
qDBusRegisterMetaType<LayoutNames>();
qDBusRegisterMetaType<QVector<LayoutNames>>();
QDBusConnection::sessionBus().registerService(s_keyboardService);
QDBusConnection::sessionBus().registerObject(s_keyboardObject, this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals);
}
@ -228,24 +233,43 @@ QString KeyboardLayoutDBusInterface::getLayout() const
return m_xkb->layoutName();
}
QString KeyboardLayoutDBusInterface::getLayoutDisplayName() const
{
return m_xkb->layoutShortName();
}
QString KeyboardLayoutDBusInterface::getLayoutLongName() const
{
return translatedLayout(m_xkb->layoutName());
}
QStringList KeyboardLayoutDBusInterface::getLayoutsList() const
QVector<KeyboardLayoutDBusInterface::LayoutNames> KeyboardLayoutDBusInterface::getLayoutsList() const
{
const auto layouts = m_xkb->layoutNames();
QStringList ret;
for (auto it = layouts.begin(); it != layouts.end(); it++) {
ret << it.value();
const QStringList &shortNames = m_xkb->layoutShortNames();
// TODO: - should be handled by layout applet itself, it has nothing to do with KWin
const QStringList displayNames = m_configGroup.readEntry("DisplayNames", QStringList());
QVector<LayoutNames> ret;
const int layoutsSize = layouts.size();
const int displayNamesSize = displayNames.size();
for (int i = 0; i < layoutsSize; ++i) {
const QString &id = layouts[i];
ret.append( {id, shortNames.at(i), i < displayNamesSize ? displayNames.at(i) : QString(), translatedLayout(id)} );
}
return ret;
}
QDBusArgument &operator<<(QDBusArgument &argument, const KeyboardLayoutDBusInterface::LayoutNames &layoutNames)
{
argument.beginStructure();
argument << layoutNames.id << layoutNames.shortName << layoutNames.displayName << layoutNames.longName;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, KeyboardLayoutDBusInterface::LayoutNames &layoutNames)
{
argument.beginStructure();
argument >> layoutNames.id >> layoutNames.shortName >> layoutNames.displayName >> layoutNames.longName;
argument.endStructure();
return argument;
}
}

View File

@ -14,9 +14,11 @@
#include <QVector>
#include <KSharedConfig>
#include <KConfigGroup>
typedef uint32_t xkb_layout_index_t;
class QAction;
class QDBusArgument;
namespace KWin
{
@ -32,12 +34,9 @@ class KeyboardLayout : public QObject, public InputEventSpy
{
Q_OBJECT
public:
explicit KeyboardLayout(Xkb *xkb);
~KeyboardLayout() override;
explicit KeyboardLayout(Xkb *xkb, const KSharedConfigPtr &config);
void setConfig(KSharedConfigPtr config) {
m_config = config;
}
~KeyboardLayout() override;
void init();
@ -60,7 +59,7 @@ private:
void loadShortcuts();
Xkb *m_xkb;
xkb_layout_index_t m_layout = 0;
KSharedConfigPtr m_config;
KConfigGroup m_configGroup;
QVector<QAction*> m_layoutShortcuts;
KeyboardLayoutDBusInterface *m_dbusInterface = nullptr;
KeyboardLayoutSwitching::Policy *m_policy = nullptr;
@ -72,17 +71,24 @@ class KeyboardLayoutDBusInterface : public QObject
Q_CLASSINFO("D-Bus Interface", "org.kde.KeyboardLayouts")
public:
explicit KeyboardLayoutDBusInterface(Xkb *xkb, KeyboardLayout *parent);
explicit KeyboardLayoutDBusInterface(Xkb *xkb, const KConfigGroup &configGroup, KeyboardLayout *parent);
~KeyboardLayoutDBusInterface() override;
struct LayoutNames
{
QString id;
QString shortName;
QString displayName;
QString longName;
};
public Q_SLOTS:
void switchToNextLayout();
void switchToPreviousLayout();
bool setLayout(const QString &layout);
QString getLayout() const;
QString getLayoutDisplayName() const;
QString getLayoutLongName() const;
QStringList getLayoutsList() const;
QVector<LayoutNames> getLayoutsList() const;
Q_SIGNALS:
void layoutChanged(QString layout);
@ -90,9 +96,14 @@ Q_SIGNALS:
private:
Xkb *m_xkb;
const KConfigGroup &m_configGroup;
KeyboardLayout *m_keyboardLayout;
};
QDBusArgument &operator<<(QDBusArgument &argument, const KeyboardLayoutDBusInterface::LayoutNames &layoutNames);
const QDBusArgument &operator>>(const QDBusArgument &argument, KeyboardLayoutDBusInterface::LayoutNames &layoutNames);
}
Q_DECLARE_METATYPE(KWin::KeyboardLayoutDBusInterface::LayoutNames)
#endif

32
xkb.cpp
View File

@ -113,6 +113,14 @@ Xkb::~Xkb()
xkb_context_unref(m_context);
}
void Xkb::setConfig(const KSharedConfigPtr &config) {
m_configGroup = config->group("Layout");
}
void Xkb::setNumLockConfig(const KSharedConfigPtr &config) {
m_numLockConfig = config;
}
void Xkb::reconfigure()
{
if (!m_context) {
@ -169,14 +177,13 @@ void Xkb::applyEnvironmentRules(xkb_rule_names &ruleNames)
xkb_keymap *Xkb::loadKeymapFromConfig()
{
// load config
if (!m_config) {
if (!m_configGroup.isValid()) {
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 variant = config.readEntry("VariantList").toLatin1();
const QByteArray options = config.readEntry("Options", "").toLocal8Bit();
const QByteArray model = m_configGroup.readEntry("Model", "pc104").toLatin1();
const QByteArray layout = m_configGroup.readEntry("LayoutList").toLatin1();
const QByteArray variant = m_configGroup.readEntry("VariantList").toLatin1();
const QByteArray options = m_configGroup.readEntry("Options").toLatin1();
xkb_rule_names ruleNames = {
.rules = nullptr,
@ -187,15 +194,6 @@ xkb_keymap *Xkb::loadKeymapFromConfig()
};
applyEnvironmentRules(ruleNames);
const QStringList displayNames = config.readEntry("DisplayNames", QStringList());
const int range = qMin(m_layoutList.size(), displayNames.size());
for (int i = 0; i < range; ++i) {
const QString &displayName = displayNames.at(i);
if ( !displayName.isEmpty() ) {
m_layoutList.replace(i, displayName);
}
}
return xkb_keymap_new_from_names(m_context, &ruleNames, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
@ -397,9 +395,9 @@ QString Xkb::layoutName() const
return layoutName(m_currentLayout);
}
const QString &Xkb::layoutShortName() const
const QStringList &Xkb::layoutShortNames() const
{
return m_layoutList.at(m_currentLayout);
return m_layoutList;
}
QString Xkb::layoutName(xkb_layout_index_t layout) const

14
xkb.h
View File

@ -13,7 +13,7 @@
#include <kwin_export.h>
#include <KSharedConfig>
#include <KConfigGroup>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(KWIN_XKB)
@ -42,12 +42,8 @@ class KWIN_EXPORT Xkb : public QObject
public:
Xkb(QObject *parent = nullptr);
~Xkb() override;
void setConfig(KSharedConfigPtr config) {
m_config = std::move(config);
}
void setNumLockConfig(KSharedConfigPtr config) {
m_numLockConfig = std::move(config);
}
void setConfig(const KSharedConfigPtr &config);
void setNumLockConfig(const KSharedConfigPtr &config);
void reconfigure();
void installKeymap(int fd, uint32_t size);
@ -91,7 +87,7 @@ public:
return m_currentLayout;
}
QString layoutName() const;
const QString &layoutShortName() const;
const QStringList &layoutShortNames() const;
QMap<xkb_layout_index_t, QString> layoutNames() const;
quint32 numberOfLayouts() const;
@ -137,7 +133,7 @@ private:
xkb_compose_state *state = nullptr;
} m_compose;
LEDs m_leds;
KSharedConfigPtr m_config;
KConfigGroup m_configGroup;
KSharedConfigPtr m_numLockConfig;
struct {