mirror of
https://github.com/hyprwm/hyprland-plugins.git
synced 2024-12-22 15:09:47 +01:00
233 lines
8.8 KiB
C++
233 lines
8.8 KiB
C++
#define WLR_USE_UNSTABLE
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <hyprland/src/Compositor.hpp>
|
|
#include <hyprland/src/desktop/Window.hpp>
|
|
#include <hyprland/src/config/ConfigManager.hpp>
|
|
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
|
|
|
#include "globals.hpp"
|
|
#include "overview.hpp"
|
|
|
|
// Methods
|
|
inline CFunctionHook* g_pRenderWorkspaceHook = nullptr;
|
|
inline CFunctionHook* g_pAddDamageHookA = nullptr;
|
|
inline CFunctionHook* g_pAddDamageHookB = nullptr;
|
|
typedef void (*origRenderWorkspace)(void*, PHLMONITOR, PHLWORKSPACE, timespec*, const CBox&);
|
|
typedef void (*origAddDamageA)(void*, const CBox*);
|
|
typedef void (*origAddDamageB)(void*, const pixman_region32_t*);
|
|
|
|
// Do NOT change this function.
|
|
APICALL EXPORT std::string PLUGIN_API_VERSION() {
|
|
return HYPRLAND_API_VERSION;
|
|
}
|
|
|
|
static bool renderingOverview = false;
|
|
|
|
//
|
|
static void hkRenderWorkspace(void* thisptr, PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) {
|
|
if (!g_pOverview || renderingOverview || g_pOverview->blockOverviewRendering || g_pOverview->pMonitor != pMonitor)
|
|
((origRenderWorkspace)(g_pRenderWorkspaceHook->m_pOriginal))(thisptr, pMonitor, pWorkspace, now, geometry);
|
|
else
|
|
g_pOverview->render();
|
|
}
|
|
|
|
static void hkAddDamageA(void* thisptr, const CBox* box) {
|
|
const auto PMONITOR = (CMonitor*)thisptr;
|
|
|
|
if (!g_pOverview || g_pOverview->pMonitor != PMONITOR->self || g_pOverview->blockDamageReporting) {
|
|
((origAddDamageA)g_pAddDamageHookA->m_pOriginal)(thisptr, box);
|
|
return;
|
|
}
|
|
|
|
g_pOverview->onDamageReported();
|
|
}
|
|
|
|
static void hkAddDamageB(void* thisptr, const pixman_region32_t* rg) {
|
|
const auto PMONITOR = (CMonitor*)thisptr;
|
|
|
|
if (!g_pOverview || g_pOverview->pMonitor != PMONITOR->self || g_pOverview->blockDamageReporting) {
|
|
((origAddDamageB)g_pAddDamageHookB->m_pOriginal)(thisptr, rg);
|
|
return;
|
|
}
|
|
|
|
g_pOverview->onDamageReported();
|
|
}
|
|
|
|
static float gestured = 0;
|
|
bool swipeActive = false;
|
|
char swipeDirection = 0; // 0 = no direction, 'v' = vertical, 'h' = horizontal
|
|
|
|
static void swipeBegin(void* self, SCallbackInfo& info, std::any param) {
|
|
swipeActive = false;
|
|
swipeDirection = 0;
|
|
}
|
|
|
|
static void swipeUpdate(void* self, SCallbackInfo& info, std::any param) {
|
|
static auto* const* PENABLE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:enable_gesture")->getDataStaticPtr();
|
|
static auto* const* FINGERS = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:gesture_fingers")->getDataStaticPtr();
|
|
static auto* const* PPOSITIVE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:gesture_positive")->getDataStaticPtr();
|
|
static auto* const* PDISTANCE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprexpo:gesture_distance")->getDataStaticPtr();
|
|
auto e = std::any_cast<IPointer::SSwipeUpdateEvent>(param);
|
|
|
|
if (!swipeDirection) {
|
|
if (std::abs(e.delta.x) > std::abs(e.delta.y))
|
|
swipeDirection = 'h';
|
|
else if (std::abs(e.delta.y) > std::abs(e.delta.x))
|
|
swipeDirection = 'v';
|
|
else
|
|
swipeDirection = 0;
|
|
}
|
|
|
|
if (swipeActive || g_pOverview)
|
|
info.cancelled = true;
|
|
|
|
if (!**PENABLE || e.fingers != **FINGERS || swipeDirection != 'v')
|
|
return;
|
|
|
|
info.cancelled = true;
|
|
if (!swipeActive) {
|
|
if (g_pOverview && (**PPOSITIVE ? 1.0 : -1.0) * e.delta.y <= 0) {
|
|
renderingOverview = true;
|
|
g_pOverview = std::make_unique<COverview>(g_pCompositor->m_pLastMonitor->activeWorkspace, true);
|
|
renderingOverview = false;
|
|
gestured = **PDISTANCE;
|
|
swipeActive = true;
|
|
}
|
|
|
|
else if (!g_pOverview && (**PPOSITIVE ? 1.0 : -1.0) * e.delta.y > 0) {
|
|
renderingOverview = true;
|
|
g_pOverview = std::make_unique<COverview>(g_pCompositor->m_pLastMonitor->activeWorkspace, true);
|
|
renderingOverview = false;
|
|
gestured = 0;
|
|
swipeActive = true;
|
|
}
|
|
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
gestured += (**PPOSITIVE ? 1.0 : -1.0) * e.delta.y;
|
|
if (gestured <= 0.01) // plugin will crash if swipe ends at <= 0
|
|
gestured = 0.01;
|
|
g_pOverview->onSwipeUpdate(gestured);
|
|
}
|
|
|
|
static void swipeEnd(void* self, SCallbackInfo& info, std::any param) {
|
|
if (!g_pOverview)
|
|
return;
|
|
|
|
swipeActive = false;
|
|
info.cancelled = true;
|
|
|
|
g_pOverview->onSwipeEnd();
|
|
}
|
|
|
|
static void onExpoDispatcher(std::string arg) {
|
|
|
|
if (swipeActive)
|
|
return;
|
|
if (arg == "toggle") {
|
|
if (g_pOverview)
|
|
g_pOverview->close();
|
|
else {
|
|
renderingOverview = true;
|
|
g_pOverview = std::make_unique<COverview>(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
|
renderingOverview = false;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (arg == "off" || arg == "close" || arg == "disable") {
|
|
if (g_pOverview)
|
|
g_pOverview->close();
|
|
return;
|
|
}
|
|
|
|
if (g_pOverview)
|
|
return;
|
|
|
|
renderingOverview = true;
|
|
g_pOverview = std::make_unique<COverview>(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
|
renderingOverview = false;
|
|
}
|
|
|
|
static void failNotif(const std::string& reason) {
|
|
HyprlandAPI::addNotification(PHANDLE, "[hyprexpo] Failure in initialization: " + reason, CHyprColor{1.0, 0.2, 0.2, 1.0}, 5000);
|
|
}
|
|
|
|
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
|
PHANDLE = handle;
|
|
|
|
const std::string HASH = __hyprland_api_get_hash();
|
|
|
|
if (HASH != GIT_COMMIT_HASH) {
|
|
failNotif("Version mismatch (headers ver is not equal to running hyprland ver)");
|
|
throw std::runtime_error("[he] Version mismatch");
|
|
}
|
|
|
|
auto FNS = HyprlandAPI::findFunctionsByName(PHANDLE, "renderWorkspace");
|
|
if (FNS.empty()) {
|
|
failNotif("no fns for hook renderWorkspace");
|
|
throw std::runtime_error("[he] No fns for hook renderWorkspace");
|
|
}
|
|
|
|
g_pRenderWorkspaceHook = HyprlandAPI::createFunctionHook(PHANDLE, FNS[0].address, (void*)hkRenderWorkspace);
|
|
|
|
FNS = HyprlandAPI::findFunctionsByName(PHANDLE, "addDamageEPK15pixman_region32");
|
|
if (FNS.empty()) {
|
|
failNotif("no fns for hook addDamageEPK15pixman_region32");
|
|
throw std::runtime_error("[he] No fns for hook addDamageEPK15pixman_region32");
|
|
}
|
|
|
|
g_pAddDamageHookB = HyprlandAPI::createFunctionHook(PHANDLE, FNS[0].address, (void*)hkAddDamageB);
|
|
|
|
FNS = HyprlandAPI::findFunctionsByName(PHANDLE, "addDamageEPKN9Hyprutils4Math4CBoxE");
|
|
if (FNS.empty()) {
|
|
failNotif("no fns for hook addDamageEPKN9Hyprutils4Math4CBoxE");
|
|
throw std::runtime_error("[he] No fns for hook addDamageEPKN9Hyprutils4Math4CBoxE");
|
|
}
|
|
|
|
g_pAddDamageHookA = HyprlandAPI::createFunctionHook(PHANDLE, FNS[0].address, (void*)hkAddDamageA);
|
|
|
|
bool success = g_pRenderWorkspaceHook->hook();
|
|
success = success && g_pAddDamageHookA->hook();
|
|
success = success && g_pAddDamageHookB->hook();
|
|
|
|
if (!success) {
|
|
failNotif("Failed initializing hooks");
|
|
throw std::runtime_error("[he] Failed initializing hooks");
|
|
}
|
|
|
|
static auto P = HyprlandAPI::registerCallbackDynamic(PHANDLE, "preRender", [](void* self, SCallbackInfo& info, std::any param) {
|
|
if (!g_pOverview)
|
|
return;
|
|
g_pOverview->onPreRender();
|
|
});
|
|
|
|
static auto P2 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "swipeBegin", [](void* self, SCallbackInfo& info, std::any data) { swipeBegin(self, info, data); });
|
|
static auto P3 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "swipeEnd", [](void* self, SCallbackInfo& info, std::any data) { swipeEnd(self, info, data); });
|
|
static auto P4 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "swipeUpdate", [](void* self, SCallbackInfo& info, std::any data) { swipeUpdate(self, info, data); });
|
|
|
|
HyprlandAPI::addDispatcher(PHANDLE, "hyprexpo:expo", onExpoDispatcher);
|
|
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:columns", Hyprlang::INT{3});
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:gap_size", Hyprlang::INT{5});
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:bg_col", Hyprlang::INT{0xFF111111});
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:workspace_method", Hyprlang::STRING{"center current"});
|
|
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:enable_gesture", Hyprlang::INT{1});
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:gesture_distance", Hyprlang::INT{200});
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:gesture_positive", Hyprlang::INT{1});
|
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprexpo:gesture_fingers", Hyprlang::INT{4});
|
|
|
|
HyprlandAPI::reloadConfig();
|
|
|
|
return {"hyprexpo", "A plugin for an overview", "Vaxry", "1.0"};
|
|
}
|
|
|
|
APICALL EXPORT void PLUGIN_EXIT() {
|
|
;
|
|
}
|