mirror of
https://github.com/hyprwm/hyprland-plugins.git
synced 2024-11-21 18:25:58 +01:00
hyprwinwrap: add new plugin
This commit is contained in:
parent
9ad145a102
commit
8d5c2f60c8
7 changed files with 237 additions and 0 deletions
|
@ -12,6 +12,7 @@ This repo houses official plugins for Hyprland.
|
|||
- csgo-vulkan-fix -> fixes custom resolutions on CS:GO with `-vulkan`
|
||||
- hyprbars -> adds title bars to windows
|
||||
- hyprtrails -> adds smooth trails behind moving windows
|
||||
- hyprwinwrap -> clone of xwinwrap, allows you to put any app as a wallpaper
|
||||
|
||||
# Nix
|
||||
|
||||
|
|
4
hyprwinwrap/Makefile
Normal file
4
hyprwinwrap/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
all:
|
||||
$(CXX) -shared -fPIC --no-gnu-unique main.cpp -o hyprwinwrap.so -g `pkg-config --cflags pixman-1 libdrm hyprland` -std=c++2b -O2
|
||||
clean:
|
||||
rm ./hyprwinwrap.so
|
25
hyprwinwrap/README.md
Normal file
25
hyprwinwrap/README.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# hyprwinwrap
|
||||
|
||||
Clone of xwinwrap for hyprland.
|
||||
|
||||
Example config:
|
||||
```ini
|
||||
plugin {
|
||||
hyprwinwrap {
|
||||
# class is an EXACT match and NOT a regex!
|
||||
class = kitty-bg
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Launch `kitty -c "~/.config/hypr/kittyconfigbg.conf" --class="kitty-bg" "/home/vaxry/.config/hypr/cava.sh"`
|
||||
|
||||
Example script for cava:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
sleep 1 && cava
|
||||
```
|
||||
|
||||
_sleep required because resizing happens a few ms after open, which breaks cava_
|
21
hyprwinwrap/default.nix
Normal file
21
hyprwinwrap/default.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
hyprland,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprwinwrap";
|
||||
version = "0.1";
|
||||
src = ./.;
|
||||
|
||||
inherit (hyprland) nativeBuildInputs;
|
||||
|
||||
buildInputs = [hyprland] ++ hyprland.buildInputs;
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/hyprwm/hyprland-plugins";
|
||||
description = "Hyprland version of xwinwrap";
|
||||
license = licenses.bsd3;
|
||||
platforms = platforms.linux;
|
||||
};
|
||||
}
|
5
hyprwinwrap/globals.hpp
Normal file
5
hyprwinwrap/globals.hpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||
|
||||
inline HANDLE PHANDLE = nullptr;
|
156
hyprwinwrap/main.cpp
Normal file
156
hyprwinwrap/main.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
#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() {
|
||||
;
|
||||
}
|
25
hyprwinwrap/meson.build
Normal file
25
hyprwinwrap/meson.build
Normal file
|
@ -0,0 +1,25 @@
|
|||
project('hyprwinwrap', 'cpp',
|
||||
version: '0.1',
|
||||
default_options: ['buildtype=release'],
|
||||
)
|
||||
|
||||
cpp_compiler = meson.get_compiler('cpp')
|
||||
if cpp_compiler.has_argument('-std=c++23')
|
||||
add_global_arguments('-std=c++23', language: 'cpp')
|
||||
elif cpp_compiler.has_argument('-std=c++2b')
|
||||
add_global_arguments('-std=c++2b', language: 'cpp')
|
||||
else
|
||||
error('Could not configure current C++ compiler (' + cpp_compiler.get_id() + ' ' + cpp_compiler.version() + ') with required C++ standard (C++23)')
|
||||
endif
|
||||
|
||||
globber = run_command('find', '.', '-name', '*.cpp', check: true)
|
||||
src = globber.stdout().strip().split('\n')
|
||||
|
||||
shared_module(meson.project_name(), src,
|
||||
dependencies: [
|
||||
dependency('hyprland'),
|
||||
dependency('pixman-1'),
|
||||
dependency('libdrm'),
|
||||
],
|
||||
install: true,
|
||||
)
|
Loading…
Reference in a new issue