Plugin System (#1590)
--------- Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
This commit is contained in:
parent
74a10f26a4
commit
8b81f41e52
45 changed files with 1691 additions and 85 deletions
|
|
@ -1,44 +1,79 @@
|
|||
#include "HookSystemManager.hpp"
|
||||
|
||||
#include "../plugins/PluginSystem.hpp"
|
||||
|
||||
CHookSystemManager::CHookSystemManager() {
|
||||
; //
|
||||
}
|
||||
|
||||
// returns the pointer to the function
|
||||
HOOK_CALLBACK_FN* CHookSystemManager::hookDynamic(const std::string& event, HOOK_CALLBACK_FN fn) {
|
||||
HOOK_CALLBACK_FN* CHookSystemManager::hookDynamic(const std::string& event, HOOK_CALLBACK_FN fn, HANDLE handle) {
|
||||
const auto PVEC = getVecForEvent(event);
|
||||
const auto PFN = &m_lCallbackFunctions.emplace_back(fn);
|
||||
PVEC->emplace_back(PFN);
|
||||
PVEC->emplace_back(SCallbackFNPtr{PFN, handle});
|
||||
return PFN;
|
||||
}
|
||||
|
||||
void CHookSystemManager::hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn) {
|
||||
void CHookSystemManager::hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn, HANDLE handle) {
|
||||
const auto PVEC = getVecForEvent(event);
|
||||
PVEC->emplace_back(fn);
|
||||
PVEC->emplace_back(SCallbackFNPtr{fn, handle});
|
||||
}
|
||||
|
||||
void CHookSystemManager::unhook(HOOK_CALLBACK_FN* fn) {
|
||||
std::erase_if(m_lCallbackFunctions, [&](const auto& other) { return &other == fn; });
|
||||
for (auto& [k, v] : m_lpRegisteredHooks) {
|
||||
std::erase_if(v, [&](const auto& other) { return other == fn; });
|
||||
std::erase_if(v, [&](const auto& other) { return other.fn == fn; });
|
||||
}
|
||||
}
|
||||
|
||||
void CHookSystemManager::emit(const std::vector<HOOK_CALLBACK_FN*>* callbacks, std::any data) {
|
||||
void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, std::any data) {
|
||||
if (callbacks->empty())
|
||||
return;
|
||||
|
||||
for (auto& cb : *callbacks)
|
||||
(*cb)(cb, data);
|
||||
std::vector<HANDLE> faultyHandles;
|
||||
|
||||
for (auto& cb : *callbacks) {
|
||||
|
||||
m_bCurrentEventPlugin = false;
|
||||
|
||||
if (!cb.handle) {
|
||||
// we don't guard hl hooks
|
||||
(*cb.fn)(cb.fn, data);
|
||||
continue;
|
||||
}
|
||||
|
||||
m_bCurrentEventPlugin = true;
|
||||
|
||||
if (std::find(faultyHandles.begin(), faultyHandles.end(), cb.handle) != faultyHandles.end())
|
||||
continue;
|
||||
|
||||
try {
|
||||
if (!setjmp(m_jbHookFaultJumpBuf))
|
||||
(*cb.fn)(cb.fn, data);
|
||||
else {
|
||||
// this module crashed.
|
||||
throw std::exception();
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
// TODO: this works only once...?
|
||||
faultyHandles.push_back(cb.handle);
|
||||
Debug::log(ERR, " [hookSystem] Hook from plugin %lx caused a SIGSEGV, queueing for unloading.", cb.handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (!faultyHandles.empty()) {
|
||||
for (auto& h : faultyHandles)
|
||||
g_pPluginSystem->unloadPlugin(g_pPluginSystem->getPluginByHandle(h), true);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<HOOK_CALLBACK_FN*>* CHookSystemManager::getVecForEvent(const std::string& event) {
|
||||
std::vector<SCallbackFNPtr>* CHookSystemManager::getVecForEvent(const std::string& event) {
|
||||
auto IT = std::find_if(m_lpRegisteredHooks.begin(), m_lpRegisteredHooks.end(), [&](const auto& other) { return other.first == event; });
|
||||
|
||||
if (IT != m_lpRegisteredHooks.end())
|
||||
return &IT->second;
|
||||
|
||||
Debug::log(LOG, "[hookSystem] New hook event registered: %s", event.c_str());
|
||||
Debug::log(LOG, " [hookSystem] New hook event registered: %s", event.c_str());
|
||||
|
||||
return &m_lpRegisteredHooks.emplace_back(std::make_pair<>(event, std::vector<HOOK_CALLBACK_FN*>{})).second;
|
||||
return &m_lpRegisteredHooks.emplace_back(std::make_pair<>(event, std::vector<SCallbackFNPtr>{})).second;
|
||||
}
|
||||
|
|
@ -4,11 +4,21 @@
|
|||
|
||||
#include <unordered_map>
|
||||
#include <any>
|
||||
#include <array>
|
||||
#include <list>
|
||||
|
||||
#include <csetjmp>
|
||||
|
||||
#include "../plugins/PluginAPI.hpp"
|
||||
|
||||
// global typedef for hooked functions. Passes itself as a ptr when called, and `data` additionally.
|
||||
typedef std::function<void(void*, std::any)> HOOK_CALLBACK_FN;
|
||||
|
||||
struct SCallbackFNPtr {
|
||||
HOOK_CALLBACK_FN* fn = nullptr;
|
||||
HANDLE handle = nullptr;
|
||||
};
|
||||
|
||||
#define EMIT_HOOK_EVENT(name, param) \
|
||||
{ \
|
||||
static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \
|
||||
|
|
@ -20,17 +30,20 @@ class CHookSystemManager {
|
|||
CHookSystemManager();
|
||||
|
||||
// returns the pointer to the function
|
||||
HOOK_CALLBACK_FN* hookDynamic(const std::string& event, HOOK_CALLBACK_FN fn);
|
||||
void hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn);
|
||||
void unhook(HOOK_CALLBACK_FN* fn);
|
||||
HOOK_CALLBACK_FN* hookDynamic(const std::string& event, HOOK_CALLBACK_FN fn, HANDLE handle = nullptr);
|
||||
void hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn, HANDLE handle = nullptr);
|
||||
void unhook(HOOK_CALLBACK_FN* fn);
|
||||
|
||||
void emit(const std::vector<HOOK_CALLBACK_FN*>* callbacks, std::any data = 0);
|
||||
std::vector<HOOK_CALLBACK_FN*>* getVecForEvent(const std::string& event);
|
||||
void emit(const std::vector<SCallbackFNPtr>* callbacks, std::any data = 0);
|
||||
std::vector<SCallbackFNPtr>* getVecForEvent(const std::string& event);
|
||||
|
||||
bool m_bCurrentEventPlugin = false;
|
||||
jmp_buf m_jbHookFaultJumpBuf;
|
||||
|
||||
private:
|
||||
// todo: this is slow. Maybe static ptrs should be somehow allowed. unique ptr for vec?
|
||||
std::list<std::pair<std::string, std::vector<HOOK_CALLBACK_FN*>>> m_lpRegisteredHooks;
|
||||
std::list<HOOK_CALLBACK_FN> m_lCallbackFunctions;
|
||||
std::list<std::pair<std::string, std::vector<SCallbackFNPtr>>> m_lpRegisteredHooks;
|
||||
std::list<HOOK_CALLBACK_FN> m_lCallbackFunctions;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHookSystemManager> g_pHookSystem;
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
class CInputManager;
|
||||
class CConfigManager;
|
||||
class CPluginSystem;
|
||||
|
||||
struct SKeybind {
|
||||
std::string key = "";
|
||||
|
|
|
|||
|
|
@ -1,29 +1,51 @@
|
|||
#include "LayoutManager.hpp"
|
||||
|
||||
IHyprLayout* CLayoutManager::getCurrentLayout() {
|
||||
switch (m_iCurrentLayoutID) {
|
||||
case LAYOUT_DWINDLE: return &m_cDwindleLayout;
|
||||
case LAYOUT_MASTER: return &m_cMasterLayout;
|
||||
}
|
||||
CLayoutManager::CLayoutManager() {
|
||||
m_vLayouts.emplace_back(std::make_pair<>("dwindle", &m_cDwindleLayout));
|
||||
m_vLayouts.emplace_back(std::make_pair<>("master", &m_cMasterLayout));
|
||||
}
|
||||
|
||||
// fallback
|
||||
return &m_cDwindleLayout;
|
||||
IHyprLayout* CLayoutManager::getCurrentLayout() {
|
||||
return m_vLayouts[m_iCurrentLayoutID].second;
|
||||
}
|
||||
|
||||
void CLayoutManager::switchToLayout(std::string layout) {
|
||||
if (layout == "dwindle") {
|
||||
if (m_iCurrentLayoutID != LAYOUT_DWINDLE) {
|
||||
for (size_t i = 0; i < m_vLayouts.size(); ++i) {
|
||||
if (m_vLayouts[i].first == layout) {
|
||||
getCurrentLayout()->onDisable();
|
||||
m_iCurrentLayoutID = LAYOUT_DWINDLE;
|
||||
m_iCurrentLayoutID = i;
|
||||
getCurrentLayout()->onEnable();
|
||||
return;
|
||||
}
|
||||
} else if (layout == "master") {
|
||||
if (m_iCurrentLayoutID != LAYOUT_MASTER) {
|
||||
getCurrentLayout()->onDisable();
|
||||
m_iCurrentLayoutID = LAYOUT_MASTER;
|
||||
getCurrentLayout()->onEnable();
|
||||
}
|
||||
} else {
|
||||
Debug::log(ERR, "Unknown layout %s!", layout.c_str());
|
||||
}
|
||||
|
||||
Debug::log(ERR, "Unknown layout!");
|
||||
}
|
||||
|
||||
bool CLayoutManager::addLayout(const std::string& name, IHyprLayout* layout) {
|
||||
if (std::find_if(m_vLayouts.begin(), m_vLayouts.end(), [&](const auto& other) { return other.first == name || other.second == layout; }) != m_vLayouts.end())
|
||||
return false;
|
||||
|
||||
m_vLayouts.emplace_back(std::make_pair<>(name, layout));
|
||||
|
||||
Debug::log(LOG, "Added new layout %s at %lx", name.c_str(), layout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLayoutManager::removeLayout(IHyprLayout* layout) {
|
||||
const auto IT = std::find_if(m_vLayouts.begin(), m_vLayouts.end(), [&](const auto& other) { return other.second == layout; });
|
||||
|
||||
if (IT == m_vLayouts.end() || IT->first == "dwindle" || IT->first == "master")
|
||||
return false;
|
||||
|
||||
if (m_iCurrentLayoutID == IT - m_vLayouts.begin()) {
|
||||
switchToLayout("dwindle");
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Removed a layout %s at %lx", IT->first.c_str(), layout);
|
||||
|
||||
std::erase(m_vLayouts, *IT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,28 @@
|
|||
|
||||
class CLayoutManager {
|
||||
public:
|
||||
CLayoutManager();
|
||||
|
||||
IHyprLayout* getCurrentLayout();
|
||||
|
||||
void switchToLayout(std::string);
|
||||
|
||||
bool addLayout(const std::string& name, IHyprLayout* layout);
|
||||
bool removeLayout(IHyprLayout* layout);
|
||||
|
||||
private:
|
||||
enum HYPRLAYOUTS {
|
||||
enum HYPRLAYOUTS
|
||||
{
|
||||
LAYOUT_DWINDLE = 0,
|
||||
LAYOUT_MASTER
|
||||
};
|
||||
|
||||
HYPRLAYOUTS m_iCurrentLayoutID = LAYOUT_DWINDLE;
|
||||
int m_iCurrentLayoutID = LAYOUT_DWINDLE;
|
||||
|
||||
CHyprDwindleLayout m_cDwindleLayout;
|
||||
CHyprMasterLayout m_cMasterLayout;
|
||||
CHyprDwindleLayout m_cDwindleLayout;
|
||||
CHyprMasterLayout m_cMasterLayout;
|
||||
|
||||
std::vector<std::pair<std::string, IHyprLayout*>> m_vLayouts;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CLayoutManager> g_pLayoutManager;
|
||||
Loading…
Add table
Add a link
Reference in a new issue