--- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -57,6 +57,7 @@ target_link_libraries(sddm Qt5::DBus Qt5::Network Qt5::Qml + udev ${LIBXCB_LIBRARIES}) if(PAM_FOUND) target_link_libraries(sddm ${PAM_LIBRARIES}) --- a/src/daemon/Greeter.h +++ b/src/daemon/Greeter.h @@ -62,6 +62,7 @@ namespace SDDM { private: bool m_started { false }; + int m_hw_keyboards { -1 }; Display *m_display { nullptr }; QString m_authPath; @@ -73,6 +74,8 @@ namespace SDDM { Auth *m_auth { nullptr }; QProcess *m_process { nullptr }; + QString getInputMethod(); + bool hwKeyboardPresent(); static void insertEnvironmentList(QStringList names, QProcessEnvironment sourceEnv, QProcessEnvironment &targetEnv); }; } --- a/src/daemon/Greeter.cpp +++ b/src/daemon/Greeter.cpp @@ -31,6 +31,8 @@ #include #include +#include + namespace SDDM { Greeter::Greeter(QObject *parent) : QObject(parent) { m_metadata = new ThemeMetadata(QString()); @@ -114,7 +116,7 @@ namespace SDDM { env.insert(QStringLiteral("DISPLAY"), m_display->name()); env.insert(QStringLiteral("XAUTHORITY"), m_authPath); env.insert(QStringLiteral("XCURSOR_THEME"), xcursorTheme); - env.insert(QStringLiteral("QT_IM_MODULE"), mainConfig.InputMethod.get()); + env.insert(QStringLiteral("QT_IM_MODULE"), getInputMethod()); m_process->setProcessEnvironment(env); // start greeter @@ -180,7 +182,7 @@ namespace SDDM { env.insert(QStringLiteral("XDG_VTNR"), QString::number(m_display->terminalId())); env.insert(QStringLiteral("XDG_SESSION_CLASS"), QStringLiteral("greeter")); env.insert(QStringLiteral("XDG_SESSION_TYPE"), m_display->sessionType()); - env.insert(QStringLiteral("QT_IM_MODULE"), mainConfig.InputMethod.get()); + env.insert(QStringLiteral("QT_IM_MODULE"), getInputMethod()); QFile localeFile(QStringLiteral("/etc/sysconfig/i18n")); if (localeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -309,4 +311,52 @@ namespace SDDM { Q_UNUSED(error); qWarning() << "Error from greeter session:" << message; } + + QString Greeter::getInputMethod() { + QString input_method(mainConfig.InputMethod.get()); + if( input_method.isEmpty() ) { + if( hwKeyboardPresent() ) { + return QStringLiteral(); + } else { + return QStringLiteral("qtvirtualkeyboard"); + } + } else { + return input_method; + } + } + + bool Greeter::hwKeyboardPresent() { + if( m_hw_keyboards < 0 ) { + // detect hardware keyboard + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + + udev = udev_new(); + if( udev ) { + m_hw_keyboards = 0; + enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_property(enumerate, "ID_INPUT_KEYBOARD", "1"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path, *devnode; + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev, path); + devnode = udev_device_get_devnode(dev); + if (devnode) { + m_hw_keyboards++; + } + udev_device_unref(dev); + } + udev_enumerate_unref(enumerate); + udev_unref(udev); + } else { + m_hw_keyboards = 1; // have hardware keyboard by default + qWarning() << "Can't create udev handle."; + } + } + return (m_hw_keyboards > 0)? true: false; + } }