Kirigami2

tabletmodewatcher.cpp
1 /*
2  * SPDX-FileCopyrightText: 2018 Marco Martin <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 #include "tabletmodewatcher.h"
8 #include <QCoreApplication>
9 
10 #if defined(KIRIGAMI_ENABLE_DBUS)
11 #include "tabletmodemanager_interface.h"
12 #include <QDBusConnection>
13 #endif
14 
15 // TODO: All the dbus stuff should be conditional, optional win32 support
16 
17 namespace Kirigami
18 {
19 KIRIGAMI2_EXPORT QEvent::Type TabletModeChangedEvent::type = QEvent::None;
20 
21 class TabletModeWatcherSingleton
22 {
23 public:
24  TabletModeWatcher self;
25 };
26 
27 Q_GLOBAL_STATIC(TabletModeWatcherSingleton, privateTabletModeWatcherSelf)
28 
29 class TabletModeWatcherPrivate
30 {
31 public:
32  TabletModeWatcherPrivate(TabletModeWatcher *watcher)
33  : q(watcher)
34  {
35  // Called here to avoid collisions with application event types so we should use
36  // registerEventType for generating the event types.
37  TabletModeChangedEvent::type = QEvent::Type(QEvent::registerEventType());
38 #if !defined(KIRIGAMI_ENABLE_DBUS) && (defined(Q_OS_ANDROID) || defined(Q_OS_IOS))
39  isTabletModeAvailable = true;
40  isTabletMode = true;
41 #elif defined(KIRIGAMI_ENABLE_DBUS)
42  // Mostly for debug purposes and for platforms which are always mobile,
43  // such as Plasma Mobile
44  if (qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_MOBILE") || qEnvironmentVariableIsSet("KDE_KIRIGAMI_TABLET_MODE")) {
45  /* clang-format off */
46  isTabletMode =
47  (QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("1")
48  || QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_MOBILE")) == QStringLiteral("true"))
49  || (QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QStringLiteral("1")
50  || QString::fromLatin1(qgetenv("KDE_KIRIGAMI_TABLET_MODE")) == QStringLiteral("true"));
51  /* clang-format on */
52  isTabletModeAvailable = isTabletMode;
53  } else {
54  m_interface =
55  new OrgKdeKWinTabletModeManagerInterface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin"), QDBusConnection::sessionBus(), q);
56 
57  if (m_interface->isValid()) {
58  // NOTE: the initial call is actually sync, because is better a tiny freeze than having the ui always recalculated and changed at the start
59  QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
60  QStringLiteral("/org/kde/KWin"),
61  QStringLiteral("org.freedesktop.DBus.Properties"),
62  QStringLiteral("GetAll"));
63  message.setArguments({m_interface->interface()});
65  isTabletModeAvailable = propsReply.value()[QLatin1String("tabletModeAvailable")].toBool();
66  isTabletMode = propsReply.value()[QLatin1String("tabletMode")].toBool();
67  QObject::connect(m_interface, &OrgKdeKWinTabletModeManagerInterface::tabletModeChanged, q, [this](bool tabletMode) {
68  setIsTablet(tabletMode);
69  });
70  QObject::connect(m_interface, &OrgKdeKWinTabletModeManagerInterface::tabletModeAvailableChanged, q, [this](bool avail) {
71  isTabletModeAvailable = avail;
72  Q_EMIT q->tabletModeAvailableChanged(avail);
73  });
74  } else {
75  isTabletModeAvailable = false;
76  isTabletMode = false;
77  }
78  }
79 // TODO: case for Windows
80 #else
81  isTabletModeAvailable = false;
82  isTabletMode = false;
83 #endif
84  }
85  ~TabletModeWatcherPrivate(){};
86  void setIsTablet(bool tablet);
87 
88  TabletModeWatcher *q;
89 #if defined(KIRIGAMI_ENABLE_DBUS)
90  OrgKdeKWinTabletModeManagerInterface *m_interface = nullptr;
91 #endif
92  QVector<QObject *> watchers;
93  bool isTabletModeAvailable = false;
94  bool isTabletMode = false;
95 };
96 
97 void TabletModeWatcherPrivate::setIsTablet(bool tablet)
98 {
99  if (isTabletMode == tablet) {
100  return;
101  }
102 
103  isTabletMode = tablet;
104  TabletModeChangedEvent event{tablet};
105  Q_EMIT q->tabletModeChanged(tablet);
106  for (auto *w : watchers) {
107  QCoreApplication::sendEvent(w, &event);
108  }
109 }
110 
111 TabletModeWatcher::TabletModeWatcher(QObject *parent)
112  : QObject(parent)
113  , d(new TabletModeWatcherPrivate(this))
114 {
115 }
116 
117 TabletModeWatcher::~TabletModeWatcher()
118 {
119  delete d;
120 }
121 
122 TabletModeWatcher *TabletModeWatcher::self()
123 {
124  return &privateTabletModeWatcherSelf()->self;
125 }
126 
127 bool TabletModeWatcher::isTabletModeAvailable() const
128 {
129  return d->isTabletModeAvailable;
130 }
131 
132 bool TabletModeWatcher::isTabletMode() const
133 {
134  return d->isTabletMode;
135 }
136 
137 void TabletModeWatcher::addWatcher(QObject *watcher)
138 {
139  d->watchers.append(watcher);
140 }
141 
142 void TabletModeWatcher::removeWatcher(QObject *watcher)
143 {
144  d->watchers.removeAll(watcher);
145 }
146 }
147 
148 #include "moc_tabletmodewatcher.cpp"
QDBusMessage call(const QDBusMessage &message, QDBus::CallMode mode, int timeout) const const
int registerEventType(int hint)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Q_GLOBAL_STATIC(Internal::StaticControl, s_instance) class ControlPrivate
QDBusConnection sessionBus()
bool sendEvent(QObject *receiver, QEvent *event)
QDBusMessage createMethodCall(const QString &service, const QString &path, const QString &interface, const QString &method)
QString fromLatin1(const char *str, int size)
QString message
QDBusReply::Type value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Jan 29 2023 04:11:03 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.