Kirigami2

tabletmodewatcher.cpp
1/*
2 * SPDX-FileCopyrightText: 2018 Marco Martin <mart@kde.org>
3 * SPDX-FileCopyrightText: 2023 Harald Sitter <sitter@kde.org>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "tabletmodewatcher.h"
9#include <QCoreApplication>
10
11#if defined(KIRIGAMI_ENABLE_DBUS)
12#include "settings_interface.h"
13#include <QDBusConnection>
14#endif
15
16using namespace Qt::Literals::StringLiterals;
17
18// TODO: All the dbus stuff should be conditional, optional win32 support
19
20namespace Kirigami
21{
22namespace Platform
23{
24
25class TabletModeWatcherSingleton
26{
27public:
28 TabletModeWatcher self;
29};
30
31Q_GLOBAL_STATIC(TabletModeWatcherSingleton, privateTabletModeWatcherSelf)
32
33class TabletModeWatcherPrivate
34{
35 static constexpr auto PORTAL_GROUP = "org.kde.TabletMode"_L1;
36 static constexpr auto KEY_AVAILABLE = "available"_L1;
37 static constexpr auto KEY_ENABLED = "enabled"_L1;
38
39public:
40 TabletModeWatcherPrivate(TabletModeWatcher *watcher)
41 : q(watcher)
42 {
43 // Called here to avoid collisions with application event types so we should use
44 // registerEventType for generating the event types.
45 TabletModeChangedEvent::type = QEvent::Type(QEvent::registerEventType());
46#if !defined(KIRIGAMI_ENABLE_DBUS) && (defined(Q_OS_ANDROID) || defined(Q_OS_IOS))
47 isTabletModeAvailable = true;
48 isTabletMode = true;
49#elif defined(KIRIGAMI_ENABLE_DBUS)
50 // Mostly for debug purposes and for platforms which are always mobile,
51 // such as Plasma Mobile
52 if (qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_MOBILE") || qEnvironmentVariableIsSet("KDE_KIRIGAMI_TABLET_MODE")) {
53 isTabletMode = (QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QLatin1String("1")
54 || QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QLatin1String("true"))
55 || (QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QLatin1String("1")
56 || QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QLatin1String("true"));
57 isTabletModeAvailable = isTabletMode;
58 } else if (qEnvironmentVariableIsSet("QT_NO_XDG_DESKTOP_PORTAL")) {
59 isTabletMode = false;
60 } else {
61 qDBusRegisterMetaType<VariantMapMap>();
62 auto portal = new OrgFreedesktopPortalSettingsInterface(u"org.freedesktop.portal.Desktop"_s,
63 u"/org/freedesktop/portal/desktop"_s,
65 q);
66
67 QObject::connect(portal,
68 &OrgFreedesktopPortalSettingsInterface::SettingChanged,
69 q,
70 [this](const QString &group, const QString &key, const QDBusVariant &value) {
71 if (group != PORTAL_GROUP) {
72 return;
73 }
74 if (key == KEY_AVAILABLE) {
75 Q_EMIT q->tabletModeAvailableChanged(value.variant().toBool());
76 } else if (key == KEY_ENABLED) {
77 setIsTablet(value.variant().toBool());
78 }
79 });
80
81 const auto reply = portal->ReadAll({PORTAL_GROUP});
82 auto watcher = new QDBusPendingCallWatcher(reply, q);
83 QObject::connect(watcher, &QDBusPendingCallWatcher::finished, q, [this, watcher]() {
84 watcher->deleteLater();
85 QDBusPendingReply<VariantMapMap> reply = *watcher;
86 const auto properties = reply.value().value(PORTAL_GROUP);
87 Q_EMIT q->tabletModeAvailableChanged(properties[KEY_AVAILABLE].toBool());
88 setIsTablet(properties[KEY_ENABLED].toBool());
89 });
90 }
91// TODO: case for Windows
92#endif
93 }
94 ~TabletModeWatcherPrivate() = default;
95 void setIsTablet(bool tablet);
96
97 TabletModeWatcher *q;
98 QList<QObject *> watchers;
99 bool isTabletModeAvailable = false;
100 bool isTabletMode = false;
101};
102
103void TabletModeWatcherPrivate::setIsTablet(bool tablet)
104{
105 if (isTabletMode == tablet) {
106 return;
107 }
108
109 isTabletMode = tablet;
110 TabletModeChangedEvent event{tablet};
111 Q_EMIT q->tabletModeChanged(tablet);
112 for (auto *w : watchers) {
114 }
115}
116
117TabletModeWatcher::TabletModeWatcher(QObject *parent)
118 : QObject(parent)
119 , d(new TabletModeWatcherPrivate(this))
120{
121}
122
123TabletModeWatcher::~TabletModeWatcher()
124{
125 delete d;
126}
127
128TabletModeWatcher *TabletModeWatcher::self()
129{
130 return &privateTabletModeWatcherSelf()->self;
131}
132
133bool TabletModeWatcher::isTabletModeAvailable() const
134{
135 return d->isTabletModeAvailable;
136}
137
138bool TabletModeWatcher::isTabletMode() const
139{
140 return d->isTabletMode;
141}
142
143void TabletModeWatcher::addWatcher(QObject *watcher)
144{
145 d->watchers.append(watcher);
146}
147
148void TabletModeWatcher::removeWatcher(QObject *watcher)
149{
150 d->watchers.removeAll(watcher);
151}
152
153}
154}
155
156#include "moc_tabletmodewatcher.cpp"
KGuiItem properties()
bool sendEvent(QObject *receiver, QEvent *event)
QDBusConnection sessionBus()
void finished(QDBusPendingCallWatcher *self)
typename Select< 0 >::Type value() const const
QVariant variant() const const
int registerEventType(int hint)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString fromLatin1(QByteArrayView str)
bool toBool() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:21 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.