Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ set(libinputactions_SRCS
libinputactions/scripting/promises/FulfillablePromise.cpp
libinputactions/scripting/promises/Promise.cpp
libinputactions/scripting/promises/PromiseException.cpp
libinputactions/scripting/signals/EmittableJSSignal.cpp
libinputactions/scripting/signals/JSSignal.cpp
libinputactions/scripting/signals/Signal.h
libinputactions/scripting/JSFunctionAction.cpp
libinputactions/scripting/JSFunctionCondition.cpp
libinputactions/scripting/ModuleScriptMetadata.cpp
Expand Down Expand Up @@ -157,7 +160,7 @@ target_link_libraries(libinputactions PUBLIC
Qt6::Qml
${LIBEVDEV_LIBRARIES}
)
target_compile_definitions(libinputactions PUBLIC TEST_VIRTUAL=$<IF:$<BOOL:${BUILD_TESTS}>,virtual,>)
target_compile_definitions(libinputactions PUBLIC QT_NO_EMIT TEST_VIRTUAL=$<IF:$<BOOL:${BUILD_TESTS}>,virtual,>)
target_include_directories(libinputactions PRIVATE libinputactions libinputactions/. ${LIBEVDEV_INCLUDE_DIRS})
set_target_properties(libinputactions PROPERTIES PREFIX "")
target_link_libraries(libinputactions PRIVATE yaml-cpp)
Expand Down
25 changes: 4 additions & 21 deletions src/libinputactions/InputActionsMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include "actions/ActionExecutor.h"
#include "config/ConfigIssueManager.h"
#include "config/ConfigLoader.h"
#include "config/ConfigProvider.h"
#include "config/GlobalConfig.h"
#include "dbus/MainDBusInterface.h"
#include "input/StrokeRecorder.h"
Expand Down Expand Up @@ -45,37 +44,23 @@ InputActionsMain::~InputActionsMain()
g_configIssueManager.reset();
g_configLoader.reset();
g_globalConfig.reset();
g_configProvider.reset();
g_inputBackend.reset();
g_mainDbusInterface.reset();
g_scriptingEngine.reset();
g_strokeRecorder.reset();
g_variableRegistry.reset();
}

void InputActionsMain::suspend()
{
g_inputBackend->reset();
}

void InputActionsMain::initialize()
{
connect(g_configProvider.get(), &ConfigProvider::configChanged, this, &InputActionsMain::onConfigChanged);
registerGlobalVariables(g_variableRegistry.get());

g_configLoader->loadEmpty(); // Initialize default values
}

void InputActionsMain::onConfigChanged(const QString &config)
{
if (g_globalConfig->autoReload()) {
g_configLoader->load();
}
g_configLoader->load({
.empty = true,
});
}

void InputActionsMain::setMissingImplementations()
{
setMissingImplementation(g_configProvider);
setMissingImplementation(g_cursorShapeProvider);
setMissingImplementation(g_notificationManager);
setMissingImplementation(g_onScreenMessageManager);
Expand All @@ -94,9 +79,7 @@ void InputActionsMain::setMissingImplementations()
setMissingImplementation(g_strokeRecorder);
setMissingImplementation(g_variableRegistry);

if (!g_scriptingEngine) {
g_scriptingEngine = std::make_shared<ScriptingEngine>(*g_inputBackend, *g_variableRegistry);
}
g_scriptingEngine = std::make_unique<ScriptingEngine>(g_inputBackend, g_variableRegistry);
}

void InputActionsMain::registerGlobalVariables(VariableRegistry *variableRegistry, std::shared_ptr<PointerPositionGetter> pointerPositionGetter,
Expand Down
9 changes: 5 additions & 4 deletions src/libinputactions/InputActionsMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ class InputActionsMain : public QObject

void setMissingImplementations();
void initialize();
void suspend();

bool inTestEnvironment() const { return m_inTestEnvironment; }
void setInTestEnvironment(bool value) { m_inTestEnvironment = value; }

virtual void registerGlobalVariables(VariableRegistry *variableRegistry, std::shared_ptr<PointerPositionGetter> pointerPositionGetter = {},
std::shared_ptr<WindowProvider> windowProvider = {});

private slots:
void onConfigChanged(const QString &config);

private:
template<typename T1, typename T2>
void setMissingImplementation(std::shared_ptr<T1> &member)
Expand Down Expand Up @@ -77,6 +76,8 @@ private slots:
member = std::make_unique<T>();
}
}

bool m_inTestEnvironment{};
};

inline InputActionsMain *g_inputActions;
Expand Down
351 changes: 203 additions & 148 deletions src/libinputactions/config/ConfigLoader.cpp

Large diffs are not rendered by default.

33 changes: 26 additions & 7 deletions src/libinputactions/config/ConfigLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#pragma once

#include "ConfigProvider.h"
#include <QObject>
#include <QString>
#include <memory>
#include <optional>
Expand All @@ -29,28 +31,45 @@ struct ConfigData;

struct ConfigLoadSettings
{
/**
* Whether to load an empty configuration. If no configuration has been loaded previously, this is an instant operation.
*/
bool empty{};
/**
* Whether the reload was manually initiated using the control tool.
*/
bool manual{};
};

class ConfigLoader
class ConfigLoader : public QObject
{
Q_OBJECT

public:
ConfigLoader();

/**
* @return Whether the operation was successful. Errors may be obtained from ConfigIssueManager.
* The returned future never fails. Errors may be obtained from ConfigIssueManager.
*/
bool load(const ConfigLoadSettings &settings = {});
QFuture<void> load(const ConfigLoadSettings &settings = {});

/**
* Loads an empty config with default values without initializing any components.
* Whether loading non-empty configurations should be permitted. This is only used in the standalone implementation.
*/
void loadEmpty();
void setAllowNonEmptyConfigs(bool value) { m_allowNonEmptyConfigs = value; }

private slots:
void onConfigChanged();

private:
ConfigData createConfig(const QString &raw);
void activateConfig(ConfigData config, bool initialize);
QFuture<void> doLoad(const ConfigLoadSettings &settings);
QFuture<std::shared_ptr<ConfigData>> createConfig(const QString &raw);
QFuture<void> activateConfig(std::shared_ptr<ConfigData> config, bool initialize);

QFuture<void> m_currentFuture;

ConfigProvider m_configProvider;
bool m_allowNonEmptyConfigs = true;
};

inline std::shared_ptr<ConfigLoader> g_configLoader;
Expand Down
2 changes: 1 addition & 1 deletion src/libinputactions/config/ConfigProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ void ConfigProvider::tryReadConfig(bool retryIfEmpty)

if (config != m_config) {
m_config = config;
Q_EMIT configChanged(config);
Q_EMIT configChanged();
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/libinputactions/config/ConfigProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ConfigProvider : public QObject
const QString &currentPath() const { return m_path; }

signals:
void configChanged(const QString &config);
void configChanged();

private slots:
void onReadyRead();
Expand All @@ -61,6 +61,4 @@ private slots:
QTimer m_retryTimer;
};

inline std::shared_ptr<ConfigProvider> g_configProvider;

}
40 changes: 22 additions & 18 deletions src/libinputactions/dbus/MainDBusInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

#include "MainDBusInterface.h"
#include <QRegularExpression>
#include <libinputactions/InputActionsMain.h>
#include <libinputactions/config/ConfigIssueManager.h>
#include <libinputactions/config/ConfigLoader.h>
#include <libinputactions/config/GlobalConfig.h>
Expand Down Expand Up @@ -81,28 +80,33 @@ void MainDBusInterface::recordStroke(const QDBusMessage &message)
});
}

QString MainDBusInterface::reloadConfig()
void MainDBusInterface::reloadConfig(const QDBusMessage &message)
{
if (!m_allowConfigLoading) {
sendErrorReply(QDBusError::Failed, "Loading the configuration is not allowed while the client is inactive.");
return {};
}
message.setDelayedReply(true);

g_configLoader->load({
.manual = true,
});
return g_configIssueManager->issuesToString();
const auto handler = [this, reply = message.createReply()]() mutable {
reply << g_configIssueManager->issuesToString();
m_bus.send(reply);
};
g_configLoader
->load({
.manual = true,
})
.then(handler)
.onFailed(handler);
}

QString MainDBusInterface::suspend()
void MainDBusInterface::suspend(const QDBusMessage &message)
{
if (!m_allowConfigLoading) {
sendErrorReply(QDBusError::Failed, "Suspending is not allowed while the client is inactive.");
return {};
}

g_inputActions->suspend();
return "success";
message.setDelayedReply(true);
g_configLoader
->load({
.empty = true,
.manual = true,
})
.then([this, reply = message.createReply()]() mutable {
m_bus.send(reply);
});
}

QString MainDBusInterface::variables(QString filter)
Expand Down
11 changes: 2 additions & 9 deletions src/libinputactions/dbus/MainDBusInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,19 @@ class MainDBusInterface
*/
~MainDBusInterface() override;

/**
* Sets whether loading the config and suspending InputActions through the DBus interface is allowed. This is only used in the standalone implementation.
*/
void setAllowConfigLoading(bool value) { m_allowConfigLoading = value; }

public slots:
QString deviceList();
QString issues();
Q_NOREPLY void recordStroke(const QDBusMessage &message);
QString reloadConfig();
QString suspend();
Q_NOREPLY void reloadConfig(const QDBusMessage &message);
Q_NOREPLY void suspend(const QDBusMessage &message);
QString variables(QString filter = "");

private:
static QString strokeToBase64(const Stroke &stroke);

QDBusConnection m_bus;
QDBusMessage m_reply;

bool m_allowConfigLoading = true;
};

inline std::shared_ptr<MainDBusInterface> g_mainDbusInterface;
Expand Down
7 changes: 5 additions & 2 deletions src/libinputactions/input/backends/InputBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#include "InputBackend.h"
#include <QObject>
#include <libinputactions/InputActionsMain.h>
#include <libinputactions/config/ConfigLoader.h>
#include <libinputactions/globals.h>
#include <libinputactions/handlers/KeyboardTriggerHandler.h>
#include <libinputactions/handlers/MotionTriggerHandler.h>
Expand Down Expand Up @@ -246,7 +246,10 @@ bool InputBackend::handleEvent(const InputEvent &event)
void InputBackend::onEmergencyCombinationTimerTimeout()
{
g_notificationManager->sendNotification("Emergency combination", "Emergency combination triggered, suspending may take up to a few seconds");
g_inputActions->suspend();
g_configLoader->load({
.empty = true,
.manual = true,
});
}

void InputBackend::setDeviceRules(std::vector<InputDeviceRule> rules)
Expand Down
2 changes: 1 addition & 1 deletion src/libinputactions/input/backends/InputBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,6 @@ private slots:
std::set<KeyboardKey> m_emergencyCombination; // Default value defined in Config
};

inline std::unique_ptr<InputBackend> g_inputBackend;
inline std::shared_ptr<InputBackend> g_inputBackend;

}
5 changes: 5 additions & 0 deletions src/libinputactions/interfaces/NotificationManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@
#include "NotificationManager.h"
#include <QDBusInterface>
#include <QThreadPool>
#include <libinputactions/InputActionsMain.h>
#include <libinputactions/helpers/QDBusConnection.h>

namespace InputActions
{

void NotificationManager::sendNotification(const QString &title, const QString &content)
{
if (g_inputActions->inTestEnvironment()) {
return;
}

// Run in another thread because QDBusInterface's constructor can freeze the compositor if a notification is sent as soon as the plugin loads. Good enough
// for now.
QThreadPool::globalInstance()->start([title = std::move(title), content = std::move(content)] {
Expand Down
Loading
Loading