File indexing completed on 2024-05-12 15:42:38
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Marco Martin <mart@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "tabletmodewatcher.h" 0008 #include <QCoreApplication> 0009 0010 #if defined(KIRIGAMI_ENABLE_DBUS) 0011 #include "tabletmodemanager_interface.h" 0012 #include <QDBusConnection> 0013 #endif 0014 0015 // TODO: All the dbus stuff should be conditional, optional win32 support 0016 0017 namespace Kirigami 0018 { 0019 KIRIGAMI2_EXPORT QEvent::Type TabletModeChangedEvent::type = QEvent::None; 0020 0021 class TabletModeWatcherSingleton 0022 { 0023 public: 0024 TabletModeWatcher self; 0025 }; 0026 0027 Q_GLOBAL_STATIC(TabletModeWatcherSingleton, privateTabletModeWatcherSelf) 0028 0029 class TabletModeWatcherPrivate 0030 { 0031 public: 0032 TabletModeWatcherPrivate(TabletModeWatcher *watcher) 0033 : q(watcher) 0034 { 0035 // Called here to avoid collisions with application event types so we should use 0036 // registerEventType for generating the event types. 0037 TabletModeChangedEvent::type = QEvent::Type(QEvent::registerEventType()); 0038 #if !defined(KIRIGAMI_ENABLE_DBUS) && (defined(Q_OS_ANDROID) || defined(Q_OS_IOS)) 0039 isTabletModeAvailable = true; 0040 isTabletMode = true; 0041 #elif defined(KIRIGAMI_ENABLE_DBUS) 0042 // Mostly for debug purposes and for platforms which are always mobile, 0043 // such as Plasma Mobile 0044 if (qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_MOBILE") || qEnvironmentVariableIsSet("KDE_KIRIGAMI_TABLET_MODE")) { 0045 /* clang-format off */ 0046 isTabletMode = 0047 (QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("1") 0048 || QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("true")) 0049 || (QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QStringLiteral("1") 0050 || QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QStringLiteral("true")); 0051 /* clang-format on */ 0052 isTabletModeAvailable = isTabletMode; 0053 } else { 0054 m_interface = 0055 new OrgKdeKWinTabletModeManagerInterface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin"), QDBusConnection::sessionBus(), q); 0056 0057 if (m_interface->isValid()) { 0058 // NOTE: the initial call is actually sync, because is better a tiny freeze than having the ui always recalculated and changed at the start 0059 QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), 0060 QStringLiteral("/org/kde/KWin"), 0061 QStringLiteral("org.freedesktop.DBus.Properties"), 0062 QStringLiteral("GetAll")); 0063 message.setArguments({m_interface->interface()}); 0064 QDBusReply<QVariantMap> propsReply = QDBusConnection::sessionBus().call(message); 0065 isTabletModeAvailable = propsReply.value()[QLatin1String("tabletModeAvailable")].toBool(); 0066 isTabletMode = propsReply.value()[QLatin1String("tabletMode")].toBool(); 0067 QObject::connect(m_interface, &OrgKdeKWinTabletModeManagerInterface::tabletModeChanged, q, [this](bool tabletMode) { 0068 setIsTablet(tabletMode); 0069 }); 0070 QObject::connect(m_interface, &OrgKdeKWinTabletModeManagerInterface::tabletModeAvailableChanged, q, [this](bool avail) { 0071 isTabletModeAvailable = avail; 0072 Q_EMIT q->tabletModeAvailableChanged(avail); 0073 }); 0074 } else { 0075 isTabletModeAvailable = false; 0076 isTabletMode = false; 0077 } 0078 } 0079 // TODO: case for Windows 0080 #else 0081 isTabletModeAvailable = false; 0082 isTabletMode = false; 0083 #endif 0084 } 0085 ~TabletModeWatcherPrivate(){}; 0086 void setIsTablet(bool tablet); 0087 0088 TabletModeWatcher *q; 0089 #if defined(KIRIGAMI_ENABLE_DBUS) 0090 OrgKdeKWinTabletModeManagerInterface *m_interface = nullptr; 0091 #endif 0092 QVector<QObject *> watchers; 0093 bool isTabletModeAvailable = false; 0094 bool isTabletMode = false; 0095 }; 0096 0097 void TabletModeWatcherPrivate::setIsTablet(bool tablet) 0098 { 0099 if (isTabletMode == tablet) { 0100 return; 0101 } 0102 0103 isTabletMode = tablet; 0104 TabletModeChangedEvent event{tablet}; 0105 Q_EMIT q->tabletModeChanged(tablet); 0106 for (auto *w : watchers) { 0107 QCoreApplication::sendEvent(w, &event); 0108 } 0109 } 0110 0111 TabletModeWatcher::TabletModeWatcher(QObject *parent) 0112 : QObject(parent) 0113 , d(new TabletModeWatcherPrivate(this)) 0114 { 0115 } 0116 0117 TabletModeWatcher::~TabletModeWatcher() 0118 { 0119 delete d; 0120 } 0121 0122 TabletModeWatcher *TabletModeWatcher::self() 0123 { 0124 return &privateTabletModeWatcherSelf()->self; 0125 } 0126 0127 bool TabletModeWatcher::isTabletModeAvailable() const 0128 { 0129 return d->isTabletModeAvailable; 0130 } 0131 0132 bool TabletModeWatcher::isTabletMode() const 0133 { 0134 return d->isTabletMode; 0135 } 0136 0137 void TabletModeWatcher::addWatcher(QObject *watcher) 0138 { 0139 d->watchers.append(watcher); 0140 } 0141 0142 void TabletModeWatcher::removeWatcher(QObject *watcher) 0143 { 0144 d->watchers.removeAll(watcher); 0145 } 0146 } 0147 0148 #include "moc_tabletmodewatcher.cpp"