Include org.freedesktop.locale1 support

Makes it possible to follow the dbus service for locale configuration,
making it possible to have third parties integrate with Plasma.

This is done opt-in for now, it can be adopted generally in the future,
if necessary.
This commit is contained in:
Aleix Pol 2022-09-09 00:18:12 +02:00
parent 96cfc411f0
commit 8417492781
7 changed files with 88 additions and 2 deletions

View file

@ -206,6 +206,7 @@ set(testXkb_SRCS
../src/xkb.cpp
test_xkb.cpp
)
qt_add_dbus_interface(testXkb_SRCS ${CMAKE_SOURCE_DIR}/src/org.freedesktop.DBus.Properties.xml dbusproperties_interface)
add_executable(testXkb ${testXkb_SRCS})
target_link_libraries(testXkb
kwin

View file

@ -238,6 +238,7 @@ qt_add_dbus_adaptor(kwin_dbus_SRCS ${kwin_effects_dbus_xml} effects.h KWin::Effe
qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.VirtualDesktopManager.xml dbusinterface.h KWin::VirtualDesktopManagerDBusInterface)
qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.Session.xml sm.h KWin::SessionManager)
qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.Plugins.xml dbusinterface.h KWin::PluginManagerDBusInterface)
qt_add_dbus_interface(kwin_dbus_SRCS org.freedesktop.DBus.Properties.xml dbusproperties_interface)
if (KWIN_BUILD_SCREENLOCKER)
qt_add_dbus_interface(kwin_dbus_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/kf5_org.freedesktop.ScreenSaver.xml screenlocker_interface)

View file

@ -225,6 +225,14 @@ public:
return m_session.get();
}
void setSession(std::unique_ptr<Session> &&session);
void setFollowLocale1(bool follow)
{
m_followLocale1 = follow;
}
bool followLocale1() const
{
return m_followLocale1;
}
bool isTerminating() const
{
@ -289,6 +297,7 @@ private:
QList<QPointer<X11EventFilterContainer>> m_eventFilters;
QList<QPointer<X11EventFilterContainer>> m_genericEventFilters;
std::unique_ptr<XcbEventFilter> m_eventFilter;
bool m_followLocale1 = false;
bool m_configLock;
KSharedConfigPtr m_config;
KSharedConfigPtr m_kxkbConfig;

View file

@ -47,6 +47,7 @@
#include <sched.h>
#include <sys/resource.h>
#include "keyboard_input.h"
#include <iomanip>
#include <iostream>
@ -365,6 +366,7 @@ int main(int argc, char *argv[])
i18n("Exits this instance so it can be restarted by kwin_wayland_wrapper."));
QCommandLineOption drmOption(QStringLiteral("drm"), i18n("Render through drm node."));
QCommandLineOption locale1Option(QStringLiteral("locale1"), i18n("Extract locale information from locale1 rather than the user's configuration"));
QCommandLineParser parser;
a.setupCommandLine(&parser);
@ -383,6 +385,7 @@ int main(int argc, char *argv[])
parser.addOption(scaleOption);
parser.addOption(outputCountOption);
parser.addOption(drmOption);
parser.addOption(locale1Option);
QCommandLineOption inputMethodOption(QStringLiteral("inputmethod"),
i18n("Input method that KWin starts."),
@ -476,6 +479,10 @@ int main(int argc, char *argv[])
}
}
if (parser.isSet(locale1Option)) {
a.setFollowLocale1(true);
}
bool ok = false;
const int width = parser.value(widthOption).toInt(&ok);
if (!ok) {

View file

@ -0,0 +1,27 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface_name" direction="in" type="s"/>
<arg name="property_name" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="GetAll">
<arg name="interface_name" direction="in" type="s"/>
<arg name="props" direction="out" type="a{sv}"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap" />
</method>
<method name="Set">
<arg name="interface_name" direction="in" type="s"/>
<arg name="property_name" direction="in" type="s"/>
<arg name="value" direction="in" type="v"/>
</method>
<signal name="PropertiesChanged">
<arg type="s" name="interface_name"/>
<arg type="a{sv}" name="changed_properties"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap" />
<arg type="as" name="invalidated_properties"/>
</signal>
</interface>
</node>

View file

@ -7,6 +7,7 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "xkb.h"
#include "dbusproperties_interface.h"
#include "utils/c_ptr.h"
#include "utils/common.h"
#include "wayland/keyboard_interface.h"
@ -25,6 +26,7 @@
#include <xkbcommon/xkbcommon-compose.h>
#include <xkbcommon/xkbcommon-keysyms.h>
// system
#include "main.h"
#include <bitset>
#include <linux/input-event-codes.h>
#include <sys/mman.h>
@ -35,6 +37,7 @@ Q_LOGGING_CATEGORY(KWIN_XKB, "kwin_xkbcommon", QtWarningMsg)
/* The offset between KEY_* numbering, and keycodes in the XKB evdev
* dataset. */
static const int EVDEV_OFFSET = 8;
static const char *s_locale1Interface = "org.freedesktop.locale1";
namespace KWin
{
@ -86,6 +89,7 @@ Xkb::Xkb(QObject *parent)
, m_consumedModifiers(Qt::NoModifier)
, m_keysym(XKB_KEY_NoSymbol)
, m_leds()
, m_followLocale1(kwinApp()->followLocale1())
{
qRegisterMetaType<KWin::LEDs>();
if (!m_context) {
@ -112,6 +116,16 @@ Xkb::Xkb(QObject *parent)
m_compose.state = xkb_compose_state_new(m_compose.table, XKB_COMPOSE_STATE_NO_FLAGS);
}
}
if (m_followLocale1) {
bool connected = QDBusConnection::systemBus().connect(s_locale1Interface, "/org/freedesktop/locale1", QStringLiteral("org.freedesktop.DBus.Properties"),
QStringLiteral("PropertiesChanged"),
this,
SLOT(reconfigure()));
if (!connected) {
qCWarning(KWIN_XKB) << "Could not connect to org.freedesktop.locale1";
}
}
}
Xkb::~Xkb()
@ -141,7 +155,11 @@ void Xkb::reconfigure()
xkb_keymap *keymap = nullptr;
if (!qEnvironmentVariableIsSet("KWIN_XKB_DEFAULT_KEYMAP")) {
keymap = loadKeymapFromConfig();
if (m_followLocale1) {
keymap = loadKeymapFromLocale1();
} else {
keymap = loadKeymapFromConfig();
}
}
if (!keymap) {
qCDebug(KWIN_XKB) << "Could not create xkb keymap from configuration";
@ -222,6 +240,23 @@ xkb_keymap *Xkb::loadDefaultKeymap()
return xkb_keymap_new_from_names(m_context, &ruleNames, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
xkb_keymap *Xkb::loadKeymapFromLocale1()
{
OrgFreedesktopDBusPropertiesInterface locale1Properties(s_locale1Interface, "/org/freedesktop/locale1", QDBusConnection::systemBus(), this);
const QVariantMap properties = locale1Properties.GetAll(s_locale1Interface);
const QString layouts = properties["X11Layout"].toString();
xkb_rule_names ruleNames = {
nullptr,
qPrintable(properties["X11Model"].toString()),
qPrintable(layouts),
qPrintable(properties["X11Variant"].toString()),
qPrintable(properties["X11Options"].toString()),
};
applyEnvironmentRules(ruleNames);
m_layoutList = layouts.split(QLatin1Char(','));
return xkb_keymap_new_from_names(m_context, &ruleNames, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
void Xkb::installKeymap(int fd, uint32_t size)
{
if (!m_context) {

View file

@ -47,7 +47,6 @@ public:
~Xkb() override;
void setConfig(const KSharedConfigPtr &config);
void setNumLockConfig(const KSharedConfigPtr &config);
void reconfigure();
void installKeymap(int fd, uint32_t size);
void updateModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group);
@ -109,6 +108,11 @@ public:
std::optional<int> keycodeFromKeysym(xkb_keysym_t keysym);
void setFollowLocale1(bool follow);
public Q_SLOTS:
void reconfigure();
Q_SIGNALS:
void ledsChanged(const LEDs &leds);
void modifierStateChanged();
@ -117,6 +121,7 @@ private:
void applyEnvironmentRules(xkb_rule_names &);
xkb_keymap *loadKeymapFromConfig();
xkb_keymap *loadDefaultKeymap();
xkb_keymap *loadKeymapFromLocale1();
void updateKeymap(xkb_keymap *keymap);
void createKeymapFile();
void updateModifiers();
@ -162,6 +167,7 @@ private:
Ownership m_ownership = Ownership::Server;
QPointer<KWaylandServer::SeatInterface> m_seat;
const bool m_followLocale1;
};
inline Qt::KeyboardModifiers Xkb::modifiers() const