From a61eb7694df25a75f45502ed64b1536fda370c1d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Oct 2023 14:52:43 +0100 Subject: [PATCH] hooksystem: add callbackinfo struct and cancellable events --- example/examplePlugin/main.cpp | 4 ++-- src/SharedDefs.hpp | 4 ++++ src/debug/HyprNotificationOverlay.cpp | 2 +- src/hyprerror/HyprError.cpp | 4 ++-- src/managers/HookSystemManager.cpp | 6 +++--- src/managers/HookSystemManager.hpp | 17 ++++++++++++++--- src/managers/KeybindManager.cpp | 2 +- src/managers/input/InputManager.cpp | 10 +++++----- src/managers/input/InputMethodRelay.cpp | 2 +- src/plugins/PluginAPI.hpp | 2 +- src/protocols/Screencopy.cpp | 2 +- src/protocols/XDGOutput.cpp | 6 +++--- src/render/OpenGL.cpp | 2 +- 13 files changed, 39 insertions(+), 24 deletions(-) diff --git a/example/examplePlugin/main.cpp b/example/examplePlugin/main.cpp index 560af387..f2cd1075 100644 --- a/example/examplePlugin/main.cpp +++ b/example/examplePlugin/main.cpp @@ -58,8 +58,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000); - HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, std::any data) { onActiveWindowChange(self, data); }); - HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, std::any data) { onNewWindow(self, data); }); + HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onActiveWindowChange(self, data); }); + HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(self, data); }); g_pCustomLayout = std::make_unique(); diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 53a9850a..068d61f6 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -22,4 +22,8 @@ enum eRenderStage RENDER_POST_MIRROR, /* After rendering a mirror */ RENDER_PRE_WINDOW, /* Before rendering a window (any pass) Note some windows (e.g. tiled) may have 2 passes (main & popup) */ RENDER_POST_WINDOW, /* After rendering a window (any pass) */ +}; + +struct SCallbackInfo { + bool cancelled = false; /* on cancellable events, will cancel the event. */ }; \ No newline at end of file diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index b4ed38c3..f82ca9bb 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -3,7 +3,7 @@ #include CHyprNotificationOverlay::CHyprNotificationOverlay() { - g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) { + g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { if (m_dNotifications.size() == 0) return; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index b72f0589..4f916139 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -5,7 +5,7 @@ CHyprError::CHyprError() { m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_NONE); m_fFadeOpacity.registerVar(); - g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) { + g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { if (!m_bIsCreated) return; @@ -13,7 +13,7 @@ CHyprError::CHyprError() { m_bMonitorChanged = true; }); - g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any param) { + g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any param) { if (!m_bIsCreated) return; diff --git a/src/managers/HookSystemManager.cpp b/src/managers/HookSystemManager.cpp index 567286d6..48c300cb 100644 --- a/src/managers/HookSystemManager.cpp +++ b/src/managers/HookSystemManager.cpp @@ -26,7 +26,7 @@ void CHookSystemManager::unhook(HOOK_CALLBACK_FN* fn) { } } -void CHookSystemManager::emit(const std::vector* callbacks, std::any data) { +void CHookSystemManager::emit(const std::vector* callbacks, SCallbackInfo& info, std::any data) { if (callbacks->empty()) return; @@ -38,7 +38,7 @@ void CHookSystemManager::emit(const std::vector* callbacks, std: if (!cb.handle) { // we don't guard hl hooks - (*cb.fn)(cb.fn, data); + (*cb.fn)(cb.fn, info, data); continue; } @@ -49,7 +49,7 @@ void CHookSystemManager::emit(const std::vector* callbacks, std: try { if (!setjmp(m_jbHookFaultJumpBuf)) - (*cb.fn)(cb.fn, data); + (*cb.fn)(cb.fn, info, data); else { // this module crashed. throw std::exception(); diff --git a/src/managers/HookSystemManager.hpp b/src/managers/HookSystemManager.hpp index 66edd1c0..ca8e9006 100644 --- a/src/managers/HookSystemManager.hpp +++ b/src/managers/HookSystemManager.hpp @@ -12,7 +12,8 @@ #include "../plugins/PluginAPI.hpp" // global typedef for hooked functions. Passes itself as a ptr when called, and `data` additionally. -typedef std::function HOOK_CALLBACK_FN; + +typedef std::function HOOK_CALLBACK_FN; struct SCallbackFNPtr { HOOK_CALLBACK_FN* fn = nullptr; @@ -22,7 +23,17 @@ struct SCallbackFNPtr { #define EMIT_HOOK_EVENT(name, param) \ { \ static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \ - g_pHookSystem->emit(PEVENTVEC, param); \ + SCallbackInfo info; \ + g_pHookSystem->emit(PEVENTVEC, info, param); \ + } + +#define EMIT_HOOK_EVENT_CANCELLABLE(name, param) \ + { \ + static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \ + SCallbackInfo info; \ + g_pHookSystem->emit(PEVENTVEC, info, param); \ + if (info.cancelled) \ + return; \ } class CHookSystemManager { @@ -34,7 +45,7 @@ class CHookSystemManager { void hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn, HANDLE handle = nullptr); void unhook(HOOK_CALLBACK_FN* fn); - void emit(const std::vector* callbacks, std::any data = 0); + void emit(const std::vector* callbacks, SCallbackInfo& info, std::any data = 0); std::vector* getVecForEvent(const std::string& event); bool m_bCurrentEventPlugin = false; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7e0b7620..321409cc 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -77,7 +77,7 @@ CKeybindManager::CKeybindManager() { m_tScrollTimer.reset(); - g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, std::any param) { + g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd m_pActiveKeybind = nullptr; m_vPressedSpecialBinds.clear(); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index ab5be4bc..1d8b5135 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -97,11 +97,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) return; + EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED); + if (time) g_pCompositor->notifyIdleActivity(); - EMIT_HOOK_EVENT("mouseMove", MOUSECOORDSFLOORED); - m_vLastCursorPosFloored = MOUSECOORDSFLOORED; const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); @@ -422,9 +422,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } void CInputManager::onMouseButton(wlr_pointer_button_event* e) { - g_pCompositor->notifyIdleActivity(); + EMIT_HOOK_EVENT_CANCELLABLE("mouseButton", e); - EMIT_HOOK_EVENT("mouseButton", e); + g_pCompositor->notifyIdleActivity(); m_tmrLastCursorMovement.reset(); @@ -1580,7 +1580,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 58ad2a2d..4af17096 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -3,7 +3,7 @@ #include "../../Compositor.hpp" CInputMethodRelay::CInputMethodRelay() { - g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, std::any param) { onKeyboardFocus(std::any_cast(param)); }); + g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast(param)); }); } void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index a406f2e6..36cdbe63 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -29,7 +29,7 @@ Feel like the API is missing something you'd like to use in your plugin? Open an #include #include -typedef std::function HOOK_CALLBACK_FN; +typedef std::function HOOK_CALLBACK_FN; typedef struct { std::string name; std::string description; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 9839b660..a84f853f 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -119,7 +119,7 @@ CScreencopyClient::~CScreencopyClient() { CScreencopyClient::CScreencopyClient() { lastMeasure.reset(); lastFrame.reset(); - tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, std::any data) { onTick(); }); + tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, SCallbackInfo& info, std::any data) { onTick(); }); } void CScreencopyClient::onTick() { diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 94839e20..2ef0c3a6 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -58,9 +58,9 @@ void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver } CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { - g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, std::any param) { this->updateAllOutputs(); }); - g_pHookSystem->hookDynamic("configReloaded", [this](void* self, std::any param) { this->updateAllOutputs(); }); - g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, std::any param) { + g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); + g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); + g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { const auto PMONITOR = std::any_cast(param); std::erase_if(m_vXDGOutputs, [&](const auto& other) { const auto REMOVE = other->monitor == PMONITOR; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 705d92a8..4a5b70dd 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -37,7 +37,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!"); #endif - g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any data) { preRender(std::any_cast(data)); }); + g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");