[keyboard] Add support for setting the layout via locale1
setxkbmap only works on X11/XWayland, and even on XWayland does not correctly change the Wayland keyboard layout. The "modern" way to control the system keyboard layout is via the locale1 DBus interface (or the localectl frontend). On compositors like KWin, this will update the keyboard layout on the fly, which is what we want. Implement support for setting the layout/model configs using locale1. This is enabled by default when Calamares runs under Wayland, and can be controlled via a config setting. Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
f53b064296
commit
812d861307
@ -3,6 +3,9 @@
|
|||||||
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
|
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
#
|
#
|
||||||
|
|
||||||
|
find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED Core DBus)
|
||||||
|
|
||||||
calamares_add_plugin(keyboard
|
calamares_add_plugin(keyboard
|
||||||
TYPE viewmodule
|
TYPE viewmodule
|
||||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||||
@ -19,6 +22,8 @@ calamares_add_plugin(keyboard
|
|||||||
RESOURCES
|
RESOURCES
|
||||||
keyboard.qrc
|
keyboard.qrc
|
||||||
SHARED_LIB
|
SHARED_LIB
|
||||||
|
LINK_LIBRARIES
|
||||||
|
Qt5::DBus
|
||||||
)
|
)
|
||||||
|
|
||||||
calamares_add_test(keyboardtest SOURCES Tests.cpp SetKeyboardLayoutJob.cpp RESOURCES keyboard.qrc)
|
calamares_add_test(keyboardtest SOURCES Tests.cpp SetKeyboardLayoutJob.cpp RESOURCES keyboard.qrc)
|
||||||
|
@ -23,9 +23,14 @@
|
|||||||
#include "utils/Variant.h"
|
#include "utils/Variant.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QGuiApplication>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <QtDBus/QDBusConnection>
|
||||||
|
#include <QtDBus/QDBusInterface>
|
||||||
|
#include <QtDBus/QDBusReply>
|
||||||
|
|
||||||
/* Returns stringlist with suitable setxkbmap command-line arguments
|
/* Returns stringlist with suitable setxkbmap command-line arguments
|
||||||
* to set the given @p model.
|
* to set the given @p model.
|
||||||
*/
|
*/
|
||||||
@ -163,7 +168,14 @@ Config::Config( QObject* parent )
|
|||||||
{
|
{
|
||||||
// Set Xorg keyboard model
|
// Set Xorg keyboard model
|
||||||
m_selectedModel = m_keyboardModelsModel->key( index );
|
m_selectedModel = m_keyboardModelsModel->key( index );
|
||||||
QProcess::execute( "setxkbmap", xkbmap_model_args( m_selectedModel ) );
|
if ( m_useLocale1 )
|
||||||
|
{
|
||||||
|
locale1Apply();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QProcess::execute( "setxkbmap", xkbmap_model_args( m_selectedModel ) );
|
||||||
|
}
|
||||||
emit prettyStatusChanged();
|
emit prettyStatusChanged();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
@ -201,12 +213,55 @@ Config::xkbChanged( int index )
|
|||||||
m_setxkbmapTimer.disconnect( this );
|
m_setxkbmapTimer.disconnect( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
connect( &m_setxkbmapTimer, &QTimer::timeout, this, &Config::xkbApply );
|
if ( m_useLocale1 )
|
||||||
|
{
|
||||||
|
connect( &m_setxkbmapTimer, &QTimer::timeout, this, &Config::locale1Apply );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connect( &m_setxkbmapTimer, &QTimer::timeout, this, &Config::xkbApply );
|
||||||
|
}
|
||||||
|
|
||||||
m_setxkbmapTimer.start( QApplication::keyboardInputInterval() );
|
m_setxkbmapTimer.start( QApplication::keyboardInputInterval() );
|
||||||
emit prettyStatusChanged();
|
emit prettyStatusChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::locale1Apply()
|
||||||
|
{
|
||||||
|
m_additionalLayoutInfo = getAdditionalLayoutInfo( m_selectedLayout );
|
||||||
|
|
||||||
|
QString layout = m_selectedLayout;
|
||||||
|
QString variant = m_selectedVariant;
|
||||||
|
QString option;
|
||||||
|
|
||||||
|
if ( !m_additionalLayoutInfo.additionalLayout.isEmpty() )
|
||||||
|
{
|
||||||
|
layout = m_additionalLayoutInfo.additionalLayout + "," + layout;
|
||||||
|
variant = m_additionalLayoutInfo.additionalVariant + "," + layout;
|
||||||
|
option = m_additionalLayoutInfo.groupSwitcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDBusInterface locale1( "org.freedesktop.locale1",
|
||||||
|
"/org/freedesktop/locale1",
|
||||||
|
"org.freedesktop.locale1",
|
||||||
|
QDBusConnection::systemBus() );
|
||||||
|
if ( !locale1.isValid() )
|
||||||
|
{
|
||||||
|
cWarning() << "Interface" << locale1.interface() << "is not valid.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using convert=true, this also updates the VConsole config
|
||||||
|
{
|
||||||
|
QDBusReply< void > r = locale1.call( "SetX11Keyboard", layout, m_selectedModel, variant, option, true, false );
|
||||||
|
if ( !r.isValid() )
|
||||||
|
{
|
||||||
|
cWarning() << "Could not set keyboard config through org.freedesktop.locale1.X11Keyboard." << r.error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Config::xkbApply()
|
Config::xkbApply()
|
||||||
{
|
{
|
||||||
@ -561,6 +616,7 @@ void
|
|||||||
Config::setConfigurationMap( const QVariantMap& configurationMap )
|
Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||||
{
|
{
|
||||||
using namespace CalamaresUtils;
|
using namespace CalamaresUtils;
|
||||||
|
bool isX11 = QGuiApplication::platformName() == "xcb";
|
||||||
|
|
||||||
const auto xorgConfDefault = QStringLiteral( "00-keyboard.conf" );
|
const auto xorgConfDefault = QStringLiteral( "00-keyboard.conf" );
|
||||||
m_xOrgConfFileName = getString( configurationMap, "xOrgConfFileName", xorgConfDefault );
|
m_xOrgConfFileName = getString( configurationMap, "xOrgConfFileName", xorgConfDefault );
|
||||||
@ -570,6 +626,7 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
|
|||||||
}
|
}
|
||||||
m_convertedKeymapPath = getString( configurationMap, "convertedKeymapPath" );
|
m_convertedKeymapPath = getString( configurationMap, "convertedKeymapPath" );
|
||||||
m_writeEtcDefaultKeyboard = getBool( configurationMap, "writeEtcDefaultKeyboard", true );
|
m_writeEtcDefaultKeyboard = getBool( configurationMap, "writeEtcDefaultKeyboard", true );
|
||||||
|
m_useLocale1 = getBool( configurationMap, "useLocale1", !isX11 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -89,6 +89,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
void xkbChanged( int index );
|
void xkbChanged( int index );
|
||||||
void xkbApply();
|
void xkbApply();
|
||||||
|
void locale1Apply();
|
||||||
|
|
||||||
KeyboardModelsModel* m_keyboardModelsModel;
|
KeyboardModelsModel* m_keyboardModelsModel;
|
||||||
KeyboardLayoutModel* m_keyboardLayoutsModel;
|
KeyboardLayoutModel* m_keyboardLayoutsModel;
|
||||||
@ -107,6 +108,7 @@ private:
|
|||||||
QString m_xOrgConfFileName;
|
QString m_xOrgConfFileName;
|
||||||
QString m_convertedKeymapPath;
|
QString m_convertedKeymapPath;
|
||||||
bool m_writeEtcDefaultKeyboard = true;
|
bool m_writeEtcDefaultKeyboard = true;
|
||||||
|
bool m_useLocale1;
|
||||||
|
|
||||||
// The state determines whether we guess settings or preserve them:
|
// The state determines whether we guess settings or preserve them:
|
||||||
// - Initial -> Guessing
|
// - Initial -> Guessing
|
||||||
|
@ -21,3 +21,9 @@ convertedKeymapPath: "/lib/kbd/keymaps/xkb"
|
|||||||
# found on Debian-related systems.
|
# found on Debian-related systems.
|
||||||
# Defaults to true if nothing is set.
|
# Defaults to true if nothing is set.
|
||||||
#writeEtcDefaultKeyboard: true
|
#writeEtcDefaultKeyboard: true
|
||||||
|
|
||||||
|
# Use the Locale1 service instead of directly managing configuration files.
|
||||||
|
# This is the modern mechanism for configuring the systemwide keyboard layout,
|
||||||
|
# and works on Wayland compositors to set the current layout.
|
||||||
|
# Defaults to false on X11 and true otherwise.
|
||||||
|
#useLocale1: true
|
||||||
|
@ -8,6 +8,8 @@ if(NOT WITH_QML)
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED Core DBus)
|
||||||
|
|
||||||
set(_keyboard ${CMAKE_CURRENT_SOURCE_DIR}/../keyboard)
|
set(_keyboard ${CMAKE_CURRENT_SOURCE_DIR}/../keyboard)
|
||||||
|
|
||||||
include_directories(${_keyboard})
|
include_directories(${_keyboard})
|
||||||
@ -24,4 +26,6 @@ calamares_add_plugin(keyboardq
|
|||||||
RESOURCES
|
RESOURCES
|
||||||
keyboardq.qrc
|
keyboardq.qrc
|
||||||
SHARED_LIB
|
SHARED_LIB
|
||||||
|
LINK_LIBRARIES
|
||||||
|
Qt5::DBus
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user