mirror of
https://github.com/hyprwm/hyprland-plugins.git
synced 2024-11-08 12:35:59 +01:00
156 lines
5.1 KiB
C++
156 lines
5.1 KiB
C++
|
#define WLR_USE_UNSTABLE
|
||
|
|
||
|
#include <unistd.h>
|
||
|
#include <vector>
|
||
|
|
||
|
#include <hyprland/src/includes.hpp>
|
||
|
#include <any>
|
||
|
|
||
|
#define private public
|
||
|
#include <hyprland/src/Compositor.hpp>
|
||
|
#include <hyprland/src/Window.hpp>
|
||
|
#include <hyprland/src/config/ConfigManager.hpp>
|
||
|
#include <hyprland/src/render/Renderer.hpp>
|
||
|
#undef private
|
||
|
|
||
|
#include "globals.hpp"
|
||
|
|
||
|
// Do NOT change this function.
|
||
|
APICALL EXPORT std::string PLUGIN_API_VERSION() {
|
||
|
return HYPRLAND_API_VERSION;
|
||
|
}
|
||
|
|
||
|
// hooks
|
||
|
inline CFunctionHook* damageHook = nullptr;
|
||
|
inline CFunctionHook* commitHook = nullptr;
|
||
|
typedef void (*origDamage)(void* owner, void* data);
|
||
|
typedef void (*origCommit)(void* owner, void* data);
|
||
|
|
||
|
std::vector<CWindow*> bgWindows;
|
||
|
|
||
|
//
|
||
|
void onNewWindow(CWindow* pWindow) {
|
||
|
static auto* const PCLASS = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprwinwrap:class")->strValue;
|
||
|
|
||
|
if (pWindow->m_szInitialClass != *PCLASS)
|
||
|
return;
|
||
|
|
||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||
|
|
||
|
if (!PMONITOR)
|
||
|
return;
|
||
|
|
||
|
if (!pWindow->m_bIsFloating)
|
||
|
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(pWindow);
|
||
|
|
||
|
pWindow->m_vRealSize.setValueAndWarp(PMONITOR->vecSize);
|
||
|
pWindow->m_vRealPosition.setValueAndWarp(PMONITOR->vecPosition);
|
||
|
pWindow->m_vSize = PMONITOR->vecSize;
|
||
|
pWindow->m_vPosition = PMONITOR->vecPosition;
|
||
|
pWindow->m_bPinned = true;
|
||
|
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
|
||
|
|
||
|
bgWindows.push_back(pWindow);
|
||
|
|
||
|
pWindow->setHidden(true); // so that hl doesn't render this
|
||
|
|
||
|
g_pInputManager->refocus();
|
||
|
|
||
|
Debug::log(LOG, "[hyprwinwrap] new window moved to bg {}", pWindow);
|
||
|
}
|
||
|
|
||
|
void onCloseWindow(CWindow* pWindow) {
|
||
|
std::erase(bgWindows, pWindow);
|
||
|
|
||
|
Debug::log(LOG, "[hyprwinwrap] closed window {}", pWindow);
|
||
|
}
|
||
|
|
||
|
void onRenderStage(eRenderStage stage) {
|
||
|
if (stage != RENDER_PRE_WINDOWS)
|
||
|
return;
|
||
|
|
||
|
for (auto& bgw : bgWindows) {
|
||
|
if (bgw->m_iMonitorID != g_pHyprOpenGL->m_RenderData.pMonitor->ID)
|
||
|
continue;
|
||
|
|
||
|
timespec now;
|
||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||
|
|
||
|
bgw->setHidden(false);
|
||
|
|
||
|
g_pHyprRenderer->renderWindow(bgw, g_pHyprOpenGL->m_RenderData.pMonitor, &now, false, RENDER_PASS_ALL, false, true);
|
||
|
|
||
|
bgw->setHidden(true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void onDamage(void* owner, void* data) {
|
||
|
const auto PWINDOW = (CWindow*)owner;
|
||
|
|
||
|
if (std::find(bgWindows.begin(), bgWindows.end(), PWINDOW) == bgWindows.end()) {
|
||
|
((origDamage)damageHook->m_pOriginal)(owner, data);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PWINDOW->setHidden(false);
|
||
|
|
||
|
((origDamage)damageHook->m_pOriginal)(owner, data);
|
||
|
|
||
|
PWINDOW->setHidden(true);
|
||
|
}
|
||
|
|
||
|
void onCommit(void* owner, void* data) {
|
||
|
const auto PWINDOW = (CWindow*)owner;
|
||
|
|
||
|
if (std::find(bgWindows.begin(), bgWindows.end(), PWINDOW) == bgWindows.end()) {
|
||
|
((origCommit)commitHook->m_pOriginal)(owner, data);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PWINDOW->setHidden(false);
|
||
|
|
||
|
((origCommit)commitHook->m_pOriginal)(owner, data);
|
||
|
|
||
|
PWINDOW->setHidden(true);
|
||
|
}
|
||
|
|
||
|
void onConfigReloaded() {
|
||
|
static auto* const PCLASS = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hyprwinwrap:class")->strValue;
|
||
|
g_pConfigManager->parseKeyword("windowrulev2", "float, class:^(" + *PCLASS + ")$", true);
|
||
|
g_pConfigManager->parseKeyword("windowrulev2", "size 100\% 100\%, class:^(" + *PCLASS + ")$", true);
|
||
|
}
|
||
|
|
||
|
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||
|
PHANDLE = handle;
|
||
|
|
||
|
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(std::any_cast<CWindow*>(data)); });
|
||
|
HyprlandAPI::registerCallbackDynamic(PHANDLE, "closeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onCloseWindow(std::any_cast<CWindow*>(data)); });
|
||
|
HyprlandAPI::registerCallbackDynamic(PHANDLE, "render", [&](void* self, SCallbackInfo& info, std::any data) { onRenderStage(std::any_cast<eRenderStage>(data)); });
|
||
|
HyprlandAPI::registerCallbackDynamic(PHANDLE, "configReloaded", [&](void* self, SCallbackInfo& info, std::any data) { onConfigReloaded(); });
|
||
|
|
||
|
auto fns = HyprlandAPI::findFunctionsByName(PHANDLE, "listener_commitSubsurface");
|
||
|
if (fns.size() < 1)
|
||
|
throw std::runtime_error("hyprwinwrap: listener_commitSubsurface not found");
|
||
|
damageHook = HyprlandAPI::createFunctionHook(PHANDLE, fns[0].address, (void*)&onDamage);
|
||
|
|
||
|
fns = HyprlandAPI::findFunctionsByName(PHANDLE, "listener_commitWindow");
|
||
|
if (fns.size() < 1)
|
||
|
throw std::runtime_error("hyprwinwrap: listener_commitWindow not found");
|
||
|
commitHook = HyprlandAPI::createFunctionHook(PHANDLE, fns[0].address, (void*)&onCommit);
|
||
|
|
||
|
bool hkResult = damageHook->hook();
|
||
|
hkResult = hkResult && commitHook->hook();
|
||
|
|
||
|
if (!hkResult)
|
||
|
throw std::runtime_error("hyprwinwrap: hooks failed");
|
||
|
|
||
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprwinwrap:class", SConfigValue{.strValue = "kitty-bg"});
|
||
|
|
||
|
HyprlandAPI::addNotification(PHANDLE, "[hyprwinwrap] Initialized successfully!", CColor{0.2, 1.0, 0.2, 1.0}, 5000);
|
||
|
|
||
|
return {"hyprwinwrap", "A clone of xwinwrap for Hyprland", "Vaxry", "1.0"};
|
||
|
}
|
||
|
|
||
|
APICALL EXPORT void PLUGIN_EXIT() {
|
||
|
;
|
||
|
}
|