File indexing completed on 2024-10-27 04:24:10

0001 #include "formfactormanager.h"
0002 
0003 #include "settingsstore.h"
0004 #include "mauimanutils.h"
0005 
0006 #include <QDebug>
0007 #include <QSize>
0008 #include <QScreen>
0009 #include <QGuiApplication>
0010 
0011 #if !defined Q_OS_ANDROID
0012 #include <QDBusInterface>
0013 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0014 #define QT5_BASED
0015 #include <QtSystemInfo/qinputinfo.h>
0016 #else
0017 #define QT6_BASED
0018 #include <QInputDevice>
0019 #endif
0020 #endif
0021 
0022 using namespace MauiMan;
0023 
0024 #if !defined Q_OS_ANDROID
0025 #ifdef QT5_BASE
0026 static QString typeToString(QInputDevice::InputTypeFlags type)
0027 {
0028     qDebug() << type;
0029     QStringList typeString;
0030     if (type.testFlag(QInputDevice::Button))
0031         typeString << QStringLiteral("Button");
0032     if (type.testFlag(QInputDevice::Mouse))
0033         typeString << QStringLiteral("Mouse");
0034     if (type.testFlag(QInputDevice::TouchPad))
0035         typeString << QStringLiteral("TouchPad");
0036     if (type.testFlag(QInputDevice::TouchScreen))
0037         typeString << QStringLiteral("TouchScreen");
0038     if (type.testFlag(QInputDevice::Keyboard))
0039         typeString << QStringLiteral("Keyboard");
0040     if (type.testFlag(QInputDevice::Switch))
0041         typeString << QStringLiteral("Switch");
0042 
0043     if (typeString.isEmpty())
0044         typeString << QStringLiteral("Unknown");
0045     return typeString.join((QStringLiteral(", ")));
0046 }
0047 #elif defined QT6_BASE
0048 static QString typeToString(QInputDevice::DeviceTypes type)
0049 {
0050     qDebug() << type;
0051     QStringList typeString;
0052     if (type.testFlag(QInputDevice::DeviceType::Mouse))
0053         typeString << QStringLiteral("Mouse");
0054     if (type.testFlag(QInputDevice::DeviceType::TouchPad))
0055         typeString << QStringLiteral("TouchPad");
0056     if (type.testFlag(QInputDevice::DeviceType::TouchScreen))
0057         typeString << QStringLiteral("TouchScreen");
0058     if (type.testFlag(QInputDevice::DeviceType::Keyboard))
0059         typeString << QStringLiteral("Keyboard");
0060     if (typeString.isEmpty())
0061         typeString << QStringLiteral("Unknown");
0062     return typeString.join((QStringLiteral(", ")));
0063 }
0064 #endif
0065 #endif
0066 
0067 void FormFactorManager::sync(const QString &key, const QVariant &value)
0068 {
0069     #if !defined Q_OS_ANDROID
0070     if (m_interface && m_interface->isValid())
0071     {
0072         m_interface->call(key, value);
0073     }
0074     #endif
0075 }
0076 
0077 void FormFactorManager::setConnections()
0078 {
0079     #if !defined Q_OS_ANDROID
0080     if(m_interface)
0081     {
0082         m_interface->disconnect();
0083         m_interface->deleteLater();
0084         m_interface = nullptr;
0085     }
0086 
0087     m_interface = new QDBusInterface(QStringLiteral("org.mauiman.Manager"),
0088                                      QStringLiteral("/FormFactor"),
0089                                      QStringLiteral("org.mauiman.FormFactor"),
0090                                      QDBusConnection::sessionBus(), this);
0091 
0092     if (m_interface->isValid())
0093     {
0094         connect(m_interface, SIGNAL(preferredModeChanged(uint)), this, SLOT(onPreferredModeChanged(uint)));
0095     }
0096     #endif
0097 }
0098 
0099 void FormFactorManager::loadSettings()
0100 {
0101     m_settings->beginModule(QStringLiteral("FormFactor"));
0102 
0103     #if !defined Q_OS_ANDROID
0104     if(m_interface && m_interface->isValid())
0105     {
0106         m_preferredMode = m_interface->property("preferredMode").toUInt();
0107         return;
0108     }
0109     #endif
0110 
0111     m_preferredMode = m_settings->load(QStringLiteral("PreferredMode"), m_preferredMode).toUInt();
0112 }
0113 
0114 FormFactorManager::FormFactorManager(QObject *parent) : MauiMan::FormFactorInfo(parent)
0115 ,m_settings(new MauiMan::SettingsStore(this))
0116 ,m_info(new MauiMan::FormFactorInfo(this))
0117 {
0118     qDebug( " INIT FORMFACTOR MANAGER");
0119 
0120     #if !defined Q_OS_ANDROID
0121     auto server = new MauiManUtils(this);
0122     if(server->serverRunning())
0123     {
0124         this->setConnections();
0125     }
0126 
0127     connect(server, &MauiManUtils::serverRunningChanged, [this](bool state)
0128     {
0129         if(state)
0130         {
0131             this->setConnections();
0132         }
0133     });
0134     #endif
0135     m_preferredMode = defaultMode();
0136 
0137     loadSettings();
0138 }
0139 
0140 uint FormFactorManager::preferredMode() const
0141 {
0142     return m_preferredMode;
0143 }
0144 
0145 uint FormFactorInfo::bestMode() const
0146 {
0147     return m_bestMode;
0148 }
0149 
0150 uint FormFactorInfo::defaultMode() const
0151 {
0152     return m_defaultMode;
0153 }
0154 
0155 bool FormFactorInfo::hasKeyboard() const
0156 {
0157     return m_hasKeyboard;
0158 }
0159 
0160 bool FormFactorInfo::hasTouchscreen() const
0161 {
0162     return m_hasTouchscreen;
0163 }
0164 
0165 bool FormFactorInfo::hasMouse() const
0166 {
0167     return m_hasMouse;
0168 }
0169 
0170 bool FormFactorInfo::hasTouchpad() const
0171 {
0172     return m_hasTouchpad;
0173 }
0174 
0175 void FormFactorManager::setPreferredMode(uint preferredMode)
0176 {
0177     if (m_preferredMode == preferredMode)
0178         return;
0179 
0180     m_preferredMode = preferredMode;
0181 
0182     sync(QStringLiteral("setPreferredMode"), m_preferredMode);
0183     m_settings->save(QStringLiteral("PreferredMode"), m_preferredMode);
0184 
0185     Q_EMIT preferredModeChanged(m_preferredMode);
0186 }
0187 
0188 void FormFactorManager::onPreferredModeChanged(uint preferredMode)
0189 {
0190     if (m_preferredMode == preferredMode)
0191         return;
0192 
0193     m_preferredMode = preferredMode;
0194     Q_EMIT preferredModeChanged(m_preferredMode);
0195 }
0196 
0197 void FormFactorInfo::findBestMode()
0198 {
0199     uint bestMode = m_defaultMode;
0200     /*
0201      * 0- desktop
0202      * 1- tablet
0203      * 2- phone
0204      * */
0205 
0206     if(m_hasTouchscreen)
0207     {
0208         if(m_screenSize.width() > 1500)
0209         {
0210             if(m_hasKeyboard || m_hasMouse || m_hasTouchpad)
0211             {
0212                 bestMode = 0; //A big touch screen and with keyboard/mouse/trackpad
0213             }else
0214             {
0215                 bestMode = 1; //A big touch screen alone
0216             }
0217         }
0218         else if(m_screenSize.width()  > 500)
0219         {
0220             bestMode = 1; //A tablet size touch screen
0221         }
0222         else
0223         {
0224             bestMode = 2; //A mobile size touch screen
0225         }
0226 
0227     }else
0228     {
0229 
0230         if(m_screenSize.width() > 1500)
0231         {
0232             bestMode = 0; // A big screen
0233 
0234         }
0235         else if(m_screenSize.width()  > 500)
0236         {
0237             if(m_hasTouchpad)
0238             {
0239                 bestMode = 1; // A small screen with a trackpad
0240             }else
0241             {
0242                 bestMode = 0;
0243             }
0244         }
0245         else
0246         {
0247             bestMode = 1; //A mobile size touch screen
0248         }
0249     }
0250 
0251     m_bestMode = bestMode;
0252     Q_EMIT bestModeChanged(m_bestMode);
0253 }
0254 
0255 QRect FormFactorInfo::screenSize()
0256 {
0257     QScreen *screen = qApp->primaryScreen();
0258     return screen->geometry();
0259 }
0260 
0261 Qt::ScreenOrientation FormFactorInfo::screenOrientation()
0262 {
0263     QScreen *screen = qApp->primaryScreen();
0264     return screen->orientation();
0265 }
0266 
0267 #ifdef QT5_BASE
0268 void FormFactorInfo::checkInputs(const QInputInfoManager *inputManager)
0269 {
0270     #if !defined Q_OS_ANDROID
0271 
0272     //        qDebug() <<"Found"<<  inputDeviceManager->deviceMap().count() << "input devices";
0273     //        QMapIterator<QString, QInputDevice*> i(inputDeviceManager->deviceMap());
0274     //        while (i.hasNext())
0275     //        {
0276     //            i.next();
0277     //            qDebug() << i.value()->name() << i.value()->identifier();
0278     //            qDebug() << "buttons count"<< i.value()->buttons().count();
0279     //            qDebug() << "switch count"<< i.value()->switches().count();
0280     //            qDebug() << "relativeAxes count"<< i.value()->relativeAxes().count();
0281     //            qDebug() << "absoluteAxes count"<< i.value()->absoluteAxes().count();
0282     //            qDebug() << "type" << typeToString(i.value()->types());
0283 
0284     //            qDebug();
0285     //            //       qDebug() << i.value()->name();
0286     //        }
0287 
0288     const int keyboardsCount = inputManager->count(QInputDevice::Keyboard);
0289     const int mouseCount = inputManager->count(QInputDevice::Mouse);
0290     const int touchCount = inputManager->count(QInputDevice::TouchScreen);
0291     const int trackpadCount = inputManager->count(QInputDevice::TouchPad);
0292 
0293     m_hasKeyboard = keyboardsCount > 0;
0294     m_hasMouse = mouseCount > 0;
0295     m_hasTouchscreen = touchCount > 0;
0296     m_hasTouchpad = trackpadCount > 0;
0297 
0298     Q_EMIT hasKeyboardChanged(m_hasKeyboard);
0299     Q_EMIT hasMouseChanged(m_hasMouse);
0300     Q_EMIT hasTouchscreenChanged(m_hasTouchscreen);
0301     Q_EMIT hasTouchpadChanged(m_hasTouchpad);
0302 
0303     qDebug() << "Number of keyboards:" << keyboardsCount;
0304     qDebug() << "Number of mice:" << mouseCount;
0305     qDebug() << "Number of touchscreens:" << touchCount;
0306     qDebug() << "Number of touchpads:" << trackpadCount;
0307     #endif
0308 }
0309 #elif defined QT6_BASE
0310 void FormFactorInfo::checkInputs(const QList<const QInputDevice *> &devices)
0311 {
0312     auto hasType = [devices](QInputDevice::DeviceType type) -> bool
0313     {
0314         auto res= std::find_if(devices.constBegin(), devices.constEnd(), [type](const QInputDevice *device)
0315         {
0316             return device->type() == type;
0317         });
0318 
0319         return res != std::end(devices);
0320     };
0321 
0322     m_hasKeyboard = hasType(QInputDevice::DeviceType::Keyboard);
0323     m_hasMouse =  hasType(QInputDevice::DeviceType::Mouse);
0324     m_hasTouchscreen =  hasType(QInputDevice::DeviceType::TouchScreen);
0325     m_hasTouchpad =  hasType(QInputDevice::DeviceType::TouchPad);
0326 
0327     Q_EMIT hasKeyboardChanged(m_hasKeyboard);
0328     Q_EMIT hasMouseChanged(m_hasMouse);
0329     Q_EMIT hasTouchscreenChanged(m_hasTouchscreen);
0330     Q_EMIT hasTouchpadChanged(m_hasTouchpad);
0331 }
0332 #endif
0333 
0334 FormFactorInfo::FormFactorInfo(QObject *parent) : QObject(parent)
0335 {
0336     qDebug( " INIT FORMFACTOR INFO");
0337 
0338     #if !defined Q_OS_ANDROID
0339 
0340     #ifdef QT5_BASED
0341     auto inputDeviceManager = new QInputInfoManager(this);
0342     connect(inputDeviceManager, &QInputInfoManager::ready,[ inputDeviceManager]()
0343     {
0344         inputDeviceManager->setFilter(QInputDevice::Mouse | QInputDevice::Keyboard | QInputDevice::TouchScreen | QInputDevice::TouchPad);
0345     });
0346 
0347     connect(inputDeviceManager, &QInputInfoManager::filterChanged,this,[this, inputDeviceManager](QInputDevice::InputTypeFlags )
0348     {
0349         checkInputs(inputDeviceManager);
0350         findBestMode();
0351     });
0352 
0353     connect(inputDeviceManager, &QInputInfoManager::deviceAdded,[this, inputDeviceManager](QInputDevice *)
0354     {
0355         checkInputs(inputDeviceManager);
0356         findBestMode();
0357     });
0358 
0359     connect(inputDeviceManager, &QInputInfoManager::deviceRemoved,[this, inputDeviceManager](QString)
0360     {
0361         checkInputs(inputDeviceManager);
0362         findBestMode();
0363     });
0364     #elif defined QT6_BASE
0365     checkInputs(QInputDevice::devices());
0366     #endif
0367     findBestMode();
0368     #endif
0369 
0370 }