|
| 1 | +#define WLR_USE_UNSTABLE |
| 2 | + |
| 3 | +#include <unistd.h> |
| 4 | +#include <vector> |
| 5 | + |
| 6 | +#include <hyprland/src/includes.hpp> |
| 7 | +#include <any> |
| 8 | +#include <sstream> |
| 9 | + |
| 10 | +#define private public |
| 11 | +#include <hyprland/src/Compositor.hpp> |
| 12 | +#include <hyprland/src/config/ConfigValue.hpp> |
| 13 | +#include <hyprland/src/helpers/AnimatedVariable.hpp> |
| 14 | +#include <hyprland/src/managers/AnimationManager.hpp> |
| 15 | +#include <hyprland/src/managers/eventLoop/EventLoopManager.hpp> |
| 16 | +#include <hyprland/src/managers/LayoutManager.hpp> |
| 17 | +#include <hyprland/src/config/ConfigManager.hpp> |
| 18 | +#undef private |
| 19 | + |
| 20 | +#include "globals.hpp" |
| 21 | + |
| 22 | +#include <hyprutils/string/VarList.hpp> |
| 23 | +#include <hyprutils/animation/BezierCurve.hpp> |
| 24 | +using namespace Hyprutils::String; |
| 25 | +using namespace Hyprutils::Animation; |
| 26 | + |
| 27 | +// Do NOT change this function. |
| 28 | +APICALL EXPORT std::string PLUGIN_API_VERSION() { |
| 29 | + return HYPRLAND_API_VERSION; |
| 30 | +} |
| 31 | + |
| 32 | +static void onFocusChange(PHLWINDOW window) { |
| 33 | + if (!window) |
| 34 | + return; |
| 35 | + |
| 36 | + static const auto POPACITY = CConfigValue<Hyprlang::FLOAT>("plugin:hyprfocus:fade_opacity"); |
| 37 | + static const auto PBOUNCE = CConfigValue<Hyprlang::FLOAT>("plugin:hyprfocus:bounce_strength"); |
| 38 | + static const auto PSLIDE = CConfigValue<Hyprlang::FLOAT>("plugin:hyprfocus:slide_height"); |
| 39 | + static const auto PMODE = CConfigValue<std::string>("plugin:hyprfocus:mode"); |
| 40 | + const auto PIN = g_pConfigManager->getAnimationPropertyConfig("hyprfocusIn"); |
| 41 | + const auto POUT = g_pConfigManager->getAnimationPropertyConfig("hyprfocusOut"); |
| 42 | + |
| 43 | + if (*PMODE == "flash") { |
| 44 | + window->m_activeInactiveAlpha->setConfig(PIN); |
| 45 | + *window->m_activeInactiveAlpha = std::clamp(*POPACITY, 0.F, 1.F); |
| 46 | + |
| 47 | + window->m_activeInactiveAlpha->setCallbackOnEnd([w = PHLWINDOWREF{window}, POUT](WP<CBaseAnimatedVariable> pav) { |
| 48 | + if (!w) |
| 49 | + return; |
| 50 | + w->m_activeInactiveAlpha->setConfig(POUT); |
| 51 | + g_pCompositor->updateWindowAnimatedDecorationValues(w.lock()); |
| 52 | + w->updateDynamicRules(); |
| 53 | + |
| 54 | + w->m_activeInactiveAlpha->setCallbackOnEnd(nullptr); |
| 55 | + }); |
| 56 | + } else if (*PMODE == "bounce") { |
| 57 | + window->m_realPosition->setConfig(PIN); |
| 58 | + window->m_realSize->setConfig(PIN); |
| 59 | + |
| 60 | + auto box = CBox{window->m_realPosition->goal(), window->m_realSize->goal()}.scaleFromCenter(std::clamp(*PBOUNCE, 0.1F, 1.F)); |
| 61 | + |
| 62 | + *window->m_realPosition = box.pos(); |
| 63 | + *window->m_realSize = box.size(); |
| 64 | + |
| 65 | + window->m_realSize->setCallbackOnEnd([w = PHLWINDOWREF{window}, POUT](WP<CBaseAnimatedVariable> pav) { |
| 66 | + if (!w) |
| 67 | + return; |
| 68 | + w->m_realSize->setConfig(POUT); |
| 69 | + w->m_realPosition->setConfig(POUT); |
| 70 | + |
| 71 | + g_pLayoutManager->getCurrentLayout()->recalculateWindow(w.lock()); |
| 72 | + |
| 73 | + w->m_realSize->setCallbackOnEnd(nullptr); |
| 74 | + }); |
| 75 | + } else if (*PMODE == "slide") { |
| 76 | + window->m_realPosition->setConfig(PIN); |
| 77 | + |
| 78 | + *window->m_realPosition = window->m_realPosition->goal() - Vector2D{0.F, std::clamp(*PSLIDE, 0.F, 150.F)}; |
| 79 | + |
| 80 | + window->m_realPosition->setCallbackOnEnd([w = PHLWINDOWREF{window}, POUT](WP<CBaseAnimatedVariable> pav) { |
| 81 | + if (!w) |
| 82 | + return; |
| 83 | + w->m_realPosition->setConfig(POUT); |
| 84 | + |
| 85 | + g_pLayoutManager->getCurrentLayout()->recalculateWindow(w.lock()); |
| 86 | + |
| 87 | + w->m_realPosition->setCallbackOnEnd(nullptr); |
| 88 | + }); |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { |
| 93 | + PHANDLE = handle; |
| 94 | + |
| 95 | + const std::string HASH = __hyprland_api_get_hash(); |
| 96 | + |
| 97 | + if (HASH != GIT_COMMIT_HASH) { |
| 98 | + HyprlandAPI::addNotification(PHANDLE, "[hyprwinwrap] Failure in initialization: Version mismatch (headers ver is not equal to running hyprland ver)", |
| 99 | + CHyprColor{1.0, 0.2, 0.2, 1.0}, 5000); |
| 100 | + throw std::runtime_error("[hww] Version mismatch"); |
| 101 | + } |
| 102 | + |
| 103 | + // clang-format off |
| 104 | + static auto P = HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onFocusChange(std::any_cast<PHLWINDOW>(data)); }); |
| 105 | + // clang-format on |
| 106 | + |
| 107 | + HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:mode", Hyprlang::STRING{"flash"}); |
| 108 | + HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:fade_opacity", Hyprlang::FLOAT{0.8F}); |
| 109 | + HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:slide_height", Hyprlang::FLOAT{20.F}); |
| 110 | + HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:bounce_strength", Hyprlang::FLOAT{0.95F}); |
| 111 | + |
| 112 | + // this will not be cleaned up after we are unloaded but it doesn't really matter, |
| 113 | + // as if we create this again it will just overwrite the old one. |
| 114 | + g_pConfigManager->m_animationTree.createNode("hyprfocusIn", "windowsIn"); |
| 115 | + g_pConfigManager->m_animationTree.createNode("hyprfocusOut", "windowsOut"); |
| 116 | + |
| 117 | + return {"hyprfocus", "Flashfocus for Hyprland", "Vaxry", "1.0"}; |
| 118 | +} |
| 119 | + |
| 120 | +APICALL EXPORT void PLUGIN_EXIT() { |
| 121 | + // reset the callbacks to avoid crashes |
| 122 | + for (const auto& w : g_pCompositor->m_windows) { |
| 123 | + if (!validMapped(w)) |
| 124 | + continue; |
| 125 | + |
| 126 | + w->m_realSize->setCallbackOnEnd(nullptr); |
| 127 | + w->m_realPosition->setCallbackOnEnd(nullptr); |
| 128 | + w->m_activeInactiveAlpha->setCallbackOnEnd(nullptr); |
| 129 | + } |
| 130 | +} |
0 commit comments