Skip to content

Commit f444ff0

Browse files
committed
hyprfocus: init new plugin
1 parent c0e675d commit f444ff0

File tree

7 files changed

+209
-0
lines changed

7 files changed

+209
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This repo houses official plugins for Hyprland.
77
- csgo-vulkan-fix -> fixes custom resolutions on CS:GO with `-vulkan`
88
- hyprbars -> adds title bars to windows
99
- hyprexpo -> adds an expo-like workspace overview
10+
- hyprfocus -> flashfocus for hyprland
1011
- hyprscrolling -> adds a scrolling layout to hyprland
1112
- hyprtrails -> adds smooth trails behind moving windows
1213
- hyprwinwrap -> clone of xwinwrap, allows you to put any app as a wallpaper

hyprfocus/CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required(VERSION 3.27)
2+
3+
project(hyprfocus
4+
DESCRIPTION "flashfocus for Hyprland"
5+
VERSION 0.1
6+
)
7+
8+
set(CMAKE_CXX_STANDARD 23)
9+
10+
file(GLOB_RECURSE SRC "*.cpp")
11+
12+
add_library(hyprfocus SHARED ${SRC})
13+
14+
find_package(PkgConfig REQUIRED)
15+
pkg_check_modules(deps REQUIRED IMPORTED_TARGET
16+
hyprland
17+
libdrm
18+
libinput
19+
libudev
20+
pangocairo
21+
pixman-1
22+
wayland-server
23+
xkbcommon
24+
)
25+
target_link_libraries(hyprfocus PRIVATE rt PkgConfig::deps)
26+
27+
install(TARGETS hyprfocus)

hyprfocus/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
all:
2+
$(CXX) -shared -fPIC --no-gnu-unique main.cpp -o hyprfocus.so -g `pkg-config --cflags pixman-1 libdrm hyprland pangocairo libinput libudev wayland-server xkbcommon` -std=c++2b -O2
3+
clean:
4+
rm ./hyprfocus.so

hyprfocus/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# hyprfocus
2+
3+
Flashfocus for Hyprland.
4+
5+
## Configuring
6+
7+
### Animations
8+
9+
Hyprfocus exposes two animation leaves: `hyprfocusIn` and `hyprfocusOut`:
10+
```ini
11+
animation = hyprfocusIn, 1, 1.7, myCurve
12+
animation = hyprfocusOut, 1, 1.7, myCurve2
13+
```
14+
15+
### Variables
16+
17+
| name | description | type | default |
18+
| --- | --- | --- | --- |
19+
|mode|which mode to use (flash / bounce / slide) | str | flash |
20+
| fade_opacity | for flash, what opacity to flash to | float | 0.8 |
21+
| bounce_strength | for bounce, what fraction of the window's size to jump to | float | 0.95 |
22+
| slide_height | for slice, how far up to slide | float | 20 |

hyprfocus/globals.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
#include <hyprland/src/plugins/PluginAPI.hpp>
4+
5+
inline HANDLE PHANDLE = nullptr;

hyprfocus/main.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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+
const auto ORIGINAL = CBox{window->m_realPosition->goal(), window->m_realSize->goal()};
58+
59+
window->m_realPosition->setConfig(PIN);
60+
window->m_realSize->setConfig(PIN);
61+
62+
auto box = ORIGINAL.copy().scaleFromCenter(std::clamp(*PBOUNCE, 0.1F, 1.F));
63+
64+
*window->m_realPosition = box.pos();
65+
*window->m_realSize = box.size();
66+
67+
window->m_realSize->setCallbackOnEnd([w = PHLWINDOWREF{window}, POUT, ORIGINAL](WP<CBaseAnimatedVariable> pav) {
68+
if (!w)
69+
return;
70+
w->m_realSize->setConfig(POUT);
71+
w->m_realPosition->setConfig(POUT);
72+
73+
if (w->m_isFloating) {
74+
*w->m_realPosition = ORIGINAL.pos();
75+
*w->m_realSize = ORIGINAL.size();
76+
} else
77+
g_pLayoutManager->getCurrentLayout()->recalculateWindow(w.lock());
78+
79+
w->m_realSize->setCallbackOnEnd(nullptr);
80+
});
81+
} else if (*PMODE == "slide") {
82+
const auto ORIGINAL = window->m_realPosition->goal();
83+
84+
window->m_realPosition->setConfig(PIN);
85+
86+
*window->m_realPosition = ORIGINAL - Vector2D{0.F, std::clamp(*PSLIDE, 0.F, 150.F)};
87+
88+
window->m_realPosition->setCallbackOnEnd([w = PHLWINDOWREF{window}, POUT, ORIGINAL](WP<CBaseAnimatedVariable> pav) {
89+
if (!w)
90+
return;
91+
w->m_realPosition->setConfig(POUT);
92+
93+
if (w->m_isFloating)
94+
*w->m_realPosition = ORIGINAL;
95+
else
96+
g_pLayoutManager->getCurrentLayout()->recalculateWindow(w.lock());
97+
98+
w->m_realPosition->setCallbackOnEnd(nullptr);
99+
});
100+
}
101+
}
102+
103+
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
104+
PHANDLE = handle;
105+
106+
const std::string HASH = __hyprland_api_get_hash();
107+
108+
if (HASH != GIT_COMMIT_HASH) {
109+
HyprlandAPI::addNotification(PHANDLE, "[hyprwinwrap] Failure in initialization: Version mismatch (headers ver is not equal to running hyprland ver)",
110+
CHyprColor{1.0, 0.2, 0.2, 1.0}, 5000);
111+
throw std::runtime_error("[hww] Version mismatch");
112+
}
113+
114+
// clang-format off
115+
static auto P = HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onFocusChange(std::any_cast<PHLWINDOW>(data)); });
116+
// clang-format on
117+
118+
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:mode", Hyprlang::STRING{"flash"});
119+
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:fade_opacity", Hyprlang::FLOAT{0.8F});
120+
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:slide_height", Hyprlang::FLOAT{20.F});
121+
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:bounce_strength", Hyprlang::FLOAT{0.95F});
122+
123+
// this will not be cleaned up after we are unloaded but it doesn't really matter,
124+
// as if we create this again it will just overwrite the old one.
125+
g_pConfigManager->m_animationTree.createNode("hyprfocusIn", "windowsIn");
126+
g_pConfigManager->m_animationTree.createNode("hyprfocusOut", "windowsOut");
127+
128+
return {"hyprfocus", "Flashfocus for Hyprland", "Vaxry", "1.0"};
129+
}
130+
131+
APICALL EXPORT void PLUGIN_EXIT() {
132+
// reset the callbacks to avoid crashes
133+
for (const auto& w : g_pCompositor->m_windows) {
134+
if (!validMapped(w))
135+
continue;
136+
137+
w->m_realSize->setCallbackOnEnd(nullptr);
138+
w->m_realPosition->setCallbackOnEnd(nullptr);
139+
w->m_activeInactiveAlpha->setCallbackOnEnd(nullptr);
140+
}
141+
}

hyprpm.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,12 @@ build = [
100100
"make -C hyprscrolling all",
101101
]
102102
since_hyprland = 6066
103+
104+
[hyprfocus]
105+
description = "Flashfocus for Hyprland"
106+
authors = ["Vaxry"]
107+
output = "hyprfocus/hyprfocus.so"
108+
build = [
109+
"make -C hyprfocus all",
110+
]
111+
since_hyprland = 6066

0 commit comments

Comments
 (0)