Skip to content

Instantly share code, notes, and snippets.

@danieloneill
Last active June 15, 2023 22:04
Show Gist options
  • Save danieloneill/8ccfab375a8819c61adb5883a0cd7c97 to your computer and use it in GitHub Desktop.
Save danieloneill/8ccfab375a8819c61adb5883a0cd7c97 to your computer and use it in GitHub Desktop.
CLI Keyboard tool for KDE Plasma
Just a little keyboard layout tool for KDE Plasma.
I wrote this so I could swap between Dvorak and US when gaming. It isn't strictly necessary since
all my games run on Proton which renders via Xwayland (which you change the layout using setxkbmap),
but I like consistency, so I swap the layout for both Wayland and Xwayland at the same time.
Steam -> Launch Options:
setxkbmap us; kdekbtool -i 1; %command%; setxkbmap dvorak; kdekbtool -i 0
Requires Qt, written/tested with Qt 6.5.2 and Plasma 5.27.5 (Qt 5.15.9) on Fedora 38
Just put both files into a directory then run "qmake . && make".
[doneill@galena build]$ ./kdekbtool -h
Usage: ./kdekbtool [options]
KDE Plasma Keyboard Tool
Options:
-h, --help Displays help on commandline options.
--help-all Displays help including Qt specific options.
-v, --version Displays version information.
-q Get current keyboard layout
-l Get list of keyboard layouts
-i, --layout_id <layout_id> Set current keyboard layout to <layout_id>.
The layout listing format is:
index : layout : variant : name (user specified)
[doneill@galena build]$ kdekbtool -l
0 : us : dv : English (Dvorak)
1 : us : : English (US)
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDBusReply>
#include <QDBusVariant>
#include <QDebug>
#include <QCommandLineOption>
#include <QCommandLineParser>
#include <QCoreApplication>
int getCurrentLayoutID()
{
QDBusInterface query( "org.kde.keyboard", "/Layouts" );
QDBusReply<quint32> reply = query.call("getLayout");
if ( reply.isValid() )
return reply.value();
qInfo() << reply.error();
return -1;
}
void setLayoutID(quint32 id)
{
QDBusInterface query( "org.kde.keyboard", "/Layouts" );
QDBusReply<bool> reply = query.call("setLayout", id);
if( !reply.isValid() )
qInfo() << reply.error();
}
QList< QMap<QString, QString> > getLayoutsList()
{
QList< QMap<QString, QString> > result;
QDBusInterface query( "org.kde.keyboard", "/Layouts" );
QDBusMessage msg = query.call(QDBus::AutoDetect, "getLayoutsList");
if( msg.type() != QDBusMessage::ReplyMessage )
{
qWarning() << "Invalid Reply";
return QList< QMap<QString, QString> >();
}
QList< QVariant > args = msg.arguments();
for( QVariant varg : args )
{
int x = 0;
const QDBusArgument dbusarg = varg.value<QDBusArgument>();
dbusarg.beginArray();
while( !dbusarg.atEnd() && x++ < 20 )
{
dbusarg.beginStructure();
QMap<QString, QString> ent;
QString blarg, blorg, blag;
dbusarg >> blarg >> blorg >> blag;
dbusarg.endStructure();
ent["layout"] = blarg;
ent["variant"] = blorg;
ent["name"] = blag;
result.append( ent );
}
dbusarg.endArray();
}
return result;
}
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName("kdekbtool");
QCoreApplication::setApplicationVersion("1.0");
auto connection = QDBusConnection::sessionBus();
if (!connection.isConnected()) {
qWarning("Cannot connect to the D-Bus session bus.\n"
"To start it, run:\n"
"\teval `dbus-launch --auto-syntax`\n");
return 1;
}
QCommandLineParser parser;
parser.setApplicationDescription("KDE Plasma Keyboard Tool");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption queryCurrentOption("q", QCoreApplication::translate("main", "Get current keyboard layout"));
parser.addOption(queryCurrentOption);
QCommandLineOption queryLayouts("l", QCoreApplication::translate("main", "Get list of keyboard layouts"));
parser.addOption(queryLayouts);
QCommandLineOption setLayoutOption(QStringList() << "i" << "layout_id",
QCoreApplication::translate("main", "Set current keyboard layout to <layout_id>."),
QCoreApplication::translate("main", "layout_id"));
parser.addOption(setLayoutOption);
parser.process(app);
if( parser.isSet(setLayoutOption) )
{
const QString idxOption = parser.value(setLayoutOption);
quint32 idx = idxOption.toInt();
setLayoutID(idx);
}
if( parser.isSet(queryCurrentOption) )
{
int curId = getCurrentLayoutID();
QList< QMap< QString, QString > > layouts = getLayoutsList();
int x=0;
for( QMap< QString, QString > ent : layouts )
{
if( curId != x )
{
x++;
continue;
}
printf("%d : %s : %s : %s\n",
x,
ent["layout"].toStdString().c_str(),
ent["variant"].toStdString().c_str(),
ent["name"].toStdString().c_str());
x++;
}
}
if( parser.isSet(queryLayouts) )
{
QList< QMap< QString, QString > > layouts = getLayoutsList();
int x=0;
for( QMap< QString, QString > ent : layouts )
{
printf("%d : %s : %s : %s\n",
x++,
ent["layout"].toStdString().c_str(),
ent["variant"].toStdString().c_str(),
ent["name"].toStdString().c_str());
}
}
return 0;
}
TARGET = kdekbtool
QT += core dbus
QT -= gui
SOURCES += kdekbtool.cpp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment