swift
Loading...
Searching...
No Matches
contextapplicationproxy.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
6#include <QDBusConnection>
7#include <QLatin1String>
8#include <QObject>
9#include <QtGlobal>
10
11#include "core/application.h"
12#include "misc/dbus.h"
13#include "misc/dbusserver.h"
15#include "misc/identifierlist.h"
16#include "misc/loghandler.h"
17
18using namespace swift::misc;
19
20namespace swift::core::context
21{
24 : IContextApplication(mode, runtime)
25 {
26 m_dBusInterface = new CGenericDBusInterface(serviceName, IContextApplication::ObjectPath(),
27 IContextApplication::InterfaceName(), connection, this);
28 this->relaySignals(serviceName, connection);
29
31 &CContextApplicationProxy::processRemoteHotkeyActionCall);
32
33 m_pingTimer.setObjectName(serviceName + "::m_pingTimer");
34 connect(&m_pingTimer, &QTimer::timeout, this, &CContextApplicationProxy::reRegisterApplications);
35 m_pingTimer.start(PingIdentifiersMs);
36 }
37
38 void CContextApplicationProxy::relaySignals(const QString &serviceName, QDBusConnection &connection)
39 {
40 // signals originating from impl side
41 bool s = connection.connect(serviceName, IContextApplication::ObjectPath(),
42 IContextApplication::InterfaceName(), "settingsChanged", this,
44 Q_ASSERT(s);
46 "registrationChanged", this, SIGNAL(registrationChanged()));
47 Q_ASSERT(s);
49 "hotkeyActionsRegistered", this,
51 Q_ASSERT(s);
53 "remoteHotkeyAction", this,
55 Q_ASSERT(s);
56 Q_UNUSED(s);
57 this->relayBaseClassSignals(serviceName, connection, IContextApplication::ObjectPath(),
59 }
60
62 {
63 m_dBusInterface->callDBus(QLatin1String("changeSettings"), settings, origin);
64 }
65
67 {
68 return m_dBusInterface->callDBusRet<swift::misc::CValueCachePacket>(QLatin1String("getAllSettings"));
69 }
70
72 {
73 return m_dBusInterface->callDBusRet<QStringList>(QLatin1String("getUnsavedSettingsKeys"));
74 }
75
77 {
78 auto result =
79 m_dBusInterface->callDBusRet<CSettingsDictionary>(QLatin1String("getUnsavedSettingsKeysDescribed"));
80 for (auto it = result.begin(); it != result.end(); ++it)
81 {
82 // consolidate with local names to fill any gaps in remote names
83 if (it.value().isEmpty())
84 {
85 it.value() = CSettingsCache::instance()->getHumanReadableName(it.key());
86 }
87 }
88 return result;
89 }
90
92 {
93 // note this proxy method does not call synchronizeLocalSettings in core
95 }
96
98 {
99 return m_dBusInterface->callDBusRet<swift::misc::CStatusMessage>(QLatin1String("saveSettings"), keyPrefix);
100 }
101
103 {
104 return m_dBusInterface->callDBusRet<swift::misc::CStatusMessage>(QLatin1String("saveSettingsByKey"), keys);
105 }
106
108 {
109 return m_dBusInterface->callDBusRet<swift::misc::CStatusMessage>(QLatin1String("loadSettings"));
110 }
111
113 {
114 m_dBusInterface->callDBus(QLatin1String("registerHotkeyActions"), actions, origin);
115 }
116
118 const CIdentifier &origin)
119 {
120 m_dBusInterface->callDBus(QLatin1String("callHotkeyActionRemotely"), action, argument, origin);
121 }
122
124 {
125 m_proxyPingIdentifiers.insert(application);
126 if (m_pingTimer.isActive())
127 {
128 m_pingTimer.start();
129 } // restart, no need to ping again
130 return m_dBusInterface->callDBusRet<swift::misc::CIdentifier>(QLatin1String("registerApplication"),
131 application);
132 }
133
135 {
136 m_proxyPingIdentifiers.remove(application);
137 m_dBusInterface->callDBus(QLatin1String("unregisterApplication"), application);
138 }
139
141 {
142 return m_dBusInterface->callDBusRet<swift::misc::CIdentifierList>(QLatin1String("getRegisteredApplications"));
143 }
144
146 {
147 return m_dBusInterface->callDBusRet<swift::misc::CIdentifier>(QLatin1String("getApplicationIdentifier"));
148 }
149
150 void CContextApplicationProxy::reRegisterApplications()
151 {
152 if (!m_dBusInterface)
153 {
154 return;
155 }
156 if (m_proxyPingIdentifiers.isEmpty())
157 {
158 return;
159 }
160 const QSet<swift::misc::CIdentifier> identifiers = m_proxyPingIdentifiers; // copy so member can be modified
161 for (const CIdentifier &identifier : identifiers)
162 {
163 this->registerApplication(identifier);
164 }
165 }
166
167 bool CContextApplicationProxy::isContextResponsive(const QString &dBusAddress, QString &msg, int timeoutMs)
168 {
169 const bool connected = CDBusServer::isDBusAvailable(dBusAddress, msg, timeoutMs);
170 if (!connected)
171 {
172 return false;
173 }
174
175 static const QString dBusName("contexttest");
176 QDBusConnection connection = CDBusServer::connectToDBus(dBusAddress, dBusName);
179 const CIdentifier id("swift proxy test");
180 const CIdentifier pingId = proxy.registerApplication(id);
181 const bool ok = (id == pingId);
182 if (ok)
183 {
184 proxy.unregisterApplication(id);
185 }
186 else
187 {
188 msg = "Mismatch in proxy ping, context not ready.";
189 }
190 CDBusServer::disconnectFromDBus(connection, dBusAddress);
191 return ok;
192 }
193
194 void CContextApplicationProxy::processRemoteHotkeyActionCall(const QString &action, bool argument,
195 const CIdentifier &origin)
196 {
197 if (!sApp || origin.isFromLocalMachine())
198 {
199 return;
200 }
201 sApp->getInputManager()->callFunctionsBy(action, argument);
203 << "Calling function" << action << "from origin" << origin.getMachineName();
204 }
205} // namespace swift::core::context
ContextMode
How to handle a given context.
@ Remote
context runs in a different process.
The class providing facades (the contexts) for all DBus relevant operations.
Definition corefacade.h:57
void changeSettings(const swift::misc::CValueCachePacket &settings, const swift::misc::CIdentifier &origin)
Ratify some settings changed by another process.
CContextApplicationProxy(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime)
Constructor.
QStringList getUnsavedSettingsKeys() const
Get keys of all unsaved settings currently in core settings cache.
swift::misc::CIdentifier getApplicationIdentifier() const
Identifier of application, remote side if distributed.
swift::misc::CStatusMessage loadSettings()
Load core settings from disk.
swift::misc::CStatusMessage saveSettings(const QString &keyPrefix={})
Save core settings to disk.
void unregisterApplication(const swift::misc::CIdentifier &application)
Unregister application.
void synchronizeLocalSettings()
Update local settings with settings from core.
swift::core::context::CSettingsDictionary getUnsavedSettingsKeysDescribed() const
Get keys and descriptions of all unsaved settings currently in core settings cache.
swift::misc::CStatusMessage saveSettingsByKey(const QStringList &keys)
Save core settings to disk.
static bool isContextResponsive(const QString &dbusAddress, QString &msg, int timeoutMs=1500)
Used to test if there is a core running?
swift::misc::CIdentifier registerApplication(const swift::misc::CIdentifier &application)
Register application, can also be used for ping.
swift::misc::CIdentifierList getRegisteredApplications() const
All registered applications.
swift::misc::CValueCachePacket getAllSettings() const
Get all settings currently in core settings cache.
void registerHotkeyActions(const QStringList &actions, const swift::misc::CIdentifier &origin)
Register hotkey action implemented by another process.
void callHotkeyActionRemotely(const QString &action, bool argument, const swift::misc::CIdentifier &origin)
Call a hotkey action on a remote process.
void remoteHotkeyAction(const QString &action, bool argument, const swift::misc::CIdentifier &origin)
Call a hotkey action on a remote process.
static const QString & ObjectPath()
Service path.
void registrationChanged()
A component changes.
void hotkeyActionsRegistered(const QStringList &actions, const swift::misc::CIdentifier &origin)
New action was registered.
static constexpr int PingIdentifiersMs
how often identifiers are pinged
void settingsChanged(const swift::misc::CValueCachePacket &settings, const swift::misc::CIdentifier &origin)
One or more settings were changed.
static const QString & InterfaceName()
Service name.
void relayBaseClassSignals(const QString &serviceName, QDBusConnection &connection, const QString &objectPath, const QString &interfaceName)
Relay signals from this class.
Definition context.cpp:64
static void disconnectFromDBus(const QDBusConnection &connection, const QString &dBusAddress)
Disconnect from Bus/Peer to peer.
static QDBusConnection connectToDBus(const QString &dbusAddress, const QString &name={})
Connect to DBus.
static bool isDBusAvailable(const QString &host, int port, int timeoutMs=1500)
Is there a DBus server running at the given address?
static const QString & coreServiceName()
Default service name.
Used for hand written interface based on virtual methods.
Value object encapsulating information identifying a component of a modular distributed swift process...
Definition identifier.h:29
const QString & getMachineName() const
Machine name.
Definition identifier.h:103
bool isFromLocalMachine() const
Check if originating from the same local machine.
static const CIdentifier & null()
Null (empty) identifier.
Value object encapsulating a list of object identifiers.
static const QString & contextSlot()
Context slots.
Class for emitting a log message.
Definition logmessage.h:27
Derived & debug()
Set the severity to debug.
static CSettingsCache * instance()
Return the singleton instance.
Streamable status message, e.g.
void changeValuesFromRemote(const swift::misc::CValueCachePacket &values, const swift::misc::CIdentifier &originator)
Notify this cache that values have been changed by one of the duplicate caches in the multi-process e...
QString getHumanReadableName(const QString &key) const
Return the human readable name of the given key, or the raw key string if there is none.
Value class used for signalling changed values in the cache.
Definition valuecache.h:67
swift::misc::CDictionary< QString, QString, QMap > CSettingsDictionary
Value type for settings keys with descriptions.
Free functions in swift::misc.
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool isEmpty() const const
void timeout()